Skip to content

Commit

Permalink
lint
Browse files Browse the repository at this point in the history
  • Loading branch information
cpederkoff committed Jun 22, 2024
1 parent bb7a70a commit 507d2c6
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 30 deletions.
30 changes: 21 additions & 9 deletions stltovoxel/polygon_repair.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ def find_polylines(segments): # noqa: C901

return polylines


def find_polyline_endpoints(segs):
start_to_end = dict()
end_to_start = dict()
Expand Down Expand Up @@ -87,30 +88,35 @@ def find_polyline_endpoints(segs):

return start_to_end


def atan_sum(f1, f2):
# Angle sum and difference identity
# atan2(atan_sum(f1, f2)) == atan2(f1) + atan2(f2)
x1,y1 = f1
x2,y2 = f2
x1, y1 = f1
x2, y2 = f2
return ( x1*x2 - y1*y2, y1*x2 + x1*y2)


def atan_neg(f1):
# atan2(atan_neg(f1)) == -atan2(f1)
x,y = f1
return x,-y
x, y = f1
return x, -y


def subtract(s1, s2):
return (s1[0] - s2[0], s1[1] - s2[1])


def add(s1, s2):
return (s1[0] + s2[0], s1[1] + s2[1])


def winding_contour_pole(pos, pt, repel):
# The total winding number of a system is composed of a sum of atan2 functions (one at each point of each line segment)
# The gradient of atan2(y,x) is
# The gradient of atan2(y, x) is
# Gx = -y/(x^2+y^2); Gy = x/(x^2+y^2)
# The contour (direction of no increase) is orthogonal to the gradient, either
# (-Gy,Gx) or (Gy,-Gx)
# (-Gy, Gx) or (Gy, -Gx)
# This is represented by:
# Cx = x/(x^2+y^2); Cy = y/(x^2+y^2) or
# Cx = -x/(x^2+y^2); Cy = -y/(x^2+y^2)
Expand All @@ -124,24 +130,27 @@ def winding_contour_pole(pos, pt, repel):
else:
return (-cx, -cy)


def normalize(pt):
x, y = pt
dist = math.sqrt(x**2 + y**2)
return (x / dist, y / dist)


def distance(p1, p2):
x1, y1 = p1
x2, y2 = p2
return math.sqrt((y2 - y1)**2 + (x2 - x1)**2)


def initial_direction(my_seg, other_segs):
# Computing the winding number of a given point requires 2 angle computations per line segment (one per point).
# This method makes 2 angle computations for every segment in other_segs to compute the winding number at my_seg[1].
# It also makes one angle computation from my_seg[0] to my_seg[1].
# The result is an angle out of my_seg which leads to a winding number of a target value.
# The result is an angle out of my_seg which leads to a winding number of a target value.
# In theory this target winding number can be any value, but here pi radians (180 degrees) is used for simplicity.
# Also, generally angle computation would take the form of [atan2(start-pt)-atan2(end-pt)]+... , but multiple atan2 calls
# can be avoided through use of atan2 identities.
# can be avoided through use of atan2 identities.
# Since the final angle would be converted back into a vector, no atan2 call is required.
pt = my_seg[1]
accum = subtract(my_seg[0], my_seg[1])
Expand All @@ -152,8 +161,9 @@ def initial_direction(my_seg, other_segs):
accum = normalize(accum)
return np.array(accum)


def winding_contour(pos, segs):
accum = (0,0)
accum = (0, 0)
for start, end in segs:
# Starting points attract the vector field
start_vec = winding_contour_pole(pos, start, repel=False)
Expand All @@ -163,6 +173,7 @@ def winding_contour(pos, segs):
accum = add(accum, end_vec)
return normalize(accum)


def winding_number_search(start, ends, segs, polyline_endpoints, max_iterations):
# find the segment I am a part of
my_seg = next(filter(lambda seg: seg[1] == start, segs))
Expand Down Expand Up @@ -190,6 +201,7 @@ def winding_number_search(start, ends, segs, polyline_endpoints, max_iterations)

raise Exception("Failed to repair mesh")


class PolygonRepair():
def __init__(self, segments, dimensions):
# Maps endpoints to the polygon they form
Expand Down
42 changes: 21 additions & 21 deletions test/test_winding_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,60 +37,60 @@ def test_find_polylines_out_of_order(self):
self.assertEqual(actual_polylines, expected_polylines)

def test_get_direction(self):
other_segs = [((1,0),(1,1)),((1,1),(0,1)),]
my_seg = ((0,1),(0,0))
other_segs = [((1, 0), (1, 1)), ((1, 1), (0, 1)), ]
my_seg = ((0, 1), (0, 0))
actual = polygon_repair.initial_direction(my_seg, other_segs)
actual = tuple(actual)
expected = (1.0,0)
expected = (1.0, 0)
self.tuples_almost_equal(actual, expected)

def test_get_direction2(self):
other_segs = [((1,0),(0,0))]
my_seg = ((0,1),(1,1))
other_segs = [((1, 0), (0, 0))]
my_seg = ((0, 1), (1, 1))
actual = polygon_repair.initial_direction(my_seg, other_segs)
actual = tuple(actual)
expected = polygon_repair.normalize((-1,-1))
expected = polygon_repair.normalize((-1, -1))
self.tuples_almost_equal(actual, expected)

def test_get_direction3(self):
other_segs = [((1,1),(1,0))]
my_seg = ((1,0),(0,0))
other_segs = [((1, 1), (1, 0))]
my_seg = ((1, 0), (0, 0))
actual = polygon_repair.initial_direction(my_seg, other_segs)
actual = tuple(actual)
expected = polygon_repair.normalize((1,1))
expected = polygon_repair.normalize((1, 1))
self.tuples_almost_equal(actual, expected)

def test_grad_90_norm(self):
segs = [((0,0),(1,0)), ((1,0),(1,1))]
pos = np.array((1,1)) - np.array((0.1,0.1))
segs = [((0, 0), (1, 0)), ((1, 0), (1, 1))]
pos = np.array((1, 1)) - np.array((0.1, 0.1))
# Treats starts as repellers and ends as attractors
actual = polygon_repair.winding_contour(pos, segs)
expected = polygon_repair.normalize((-1,-1))
expected = polygon_repair.normalize((-1, -1))
self.tuples_almost_equal(actual, expected)


def test_grad_90_norm2(self):
segs = [((0,0),(1,0)), ((1,0),(1,1)), ((1,1),(0,1))]
pos = (0,0.5)
segs = [((0, 0), (1, 0)), ((1, 0), (1, 1)), ((1, 1), (0, 1))]
pos = (0, 0.5)
actual = polygon_repair.winding_contour(pos, segs)
expected = polygon_repair.normalize((0,-1))
expected = polygon_repair.normalize((0, -1))
self.tuples_almost_equal(actual, expected)

pos = (-.5,0.5)
pos = (-.5, 0.5)
actual = polygon_repair.winding_contour(pos, segs)
expected = polygon_repair.normalize((0,-1))
expected = polygon_repair.normalize((0, -1))
self.tuples_almost_equal(actual, expected)

pos = (.5,0.5)
pos = (.5, 0.5)
actual = polygon_repair.winding_contour(pos, segs)
expected = polygon_repair.normalize((0,-1))
expected = polygon_repair.normalize((0, -1))
self.tuples_almost_equal(actual, expected)

def test_grad_90_norm3(self):
segs = [((0,0),(1,0)), ((1,1),(0,1))]
segs = [((0, 0), (1, 0)), ((1, 1), (0, 1))]
pos = (0.00001, 0.00001)
actual = polygon_repair.winding_contour(pos, segs)
expected = polygon_repair.normalize((-1,-1))
expected = polygon_repair.normalize((-1, -1))
self.tuples_almost_equal(actual, expected)


Expand Down

0 comments on commit 507d2c6

Please sign in to comment.