文件
gprMax/toolboxes/STLtoVoxel/perimeter.py
2025-02-04 20:38:27 +00:00

66 行
1.9 KiB
Python

from functools import reduce
def lines_to_voxels(line_list, pixels):
current_line_indices = set()
x = 0
for event_x, status, line_ind in generate_line_events(line_list):
while event_x - x >= 0:
lines = reduce(lambda acc, cur: acc + [line_list[cur]], current_line_indices, [])
paint_y_axis(lines, pixels, x)
x += 1
if status == "start":
assert line_ind not in current_line_indices
current_line_indices.add(line_ind)
elif status == "end":
assert line_ind in current_line_indices
current_line_indices.remove(line_ind)
def slope_intercept(p1, p2):
x1, y1 = p1[:2]
x2, y2 = p2[:2]
slope = (y2 - y1) / (x2 - x1)
intercept = y1 - slope * x1
return slope, intercept
def generate_y(p1, p2, x):
slope, intercept = slope_intercept(p1, p2)
y = slope * x + intercept
return y
def paint_y_axis(lines, pixels, x):
is_black = False
target_ys = sorted(map(lambda line: int(generate_y(line[0], line[1], x)), lines))
if len(target_ys) % 2:
distances = [target_ys[i + 1] - target_ys[i] for i in range(len(target_ys) - 1)]
# https://stackoverflow.com/a/17952763
min_idx = -min((x, -i) for i, x in enumerate(distances))[1]
del target_ys[min_idx]
yi = 0
for target_y in target_ys:
if is_black:
# Bulk assign all pixels between yi -> target_y
pixels[yi:target_y, x] = True
pixels[target_y][x] = True
is_black = not is_black
yi = target_y
assert is_black is False, f"an error has occured at x{x}"
def generate_line_events(line_list):
events = []
for i, line in enumerate(line_list):
first, second = sorted(line, key=lambda pt: pt[0])
events.append((first[0], "start", i))
events.append((second[0], "end", i))
return sorted(events, key=lambda tup: tup[0])