[remove_colinear_vertices / Path] add preserve_uturns and use it for paths
This commit is contained in:
parent
495babf837
commit
ea93a7ef37
3 changed files with 56 additions and 19 deletions
|
|
@ -323,9 +323,30 @@ class Path(Shape):
|
|||
) -> list['Polygon']:
|
||||
extensions = self._calculate_cap_extensions()
|
||||
|
||||
v = remove_colinear_vertices(self.vertices, closed_path=False)
|
||||
v = remove_colinear_vertices(self.vertices, closed_path=False, preserve_uturns=True)
|
||||
dv = numpy.diff(v, axis=0)
|
||||
dvdir = dv / numpy.sqrt((dv * dv).sum(axis=1))[:, None]
|
||||
norms = numpy.sqrt((dv * dv).sum(axis=1))
|
||||
|
||||
# Filter out zero-length segments if any remained after remove_colinear_vertices
|
||||
valid = (norms > 1e-18)
|
||||
if not numpy.all(valid):
|
||||
# This shouldn't happen much if remove_colinear_vertices is working
|
||||
v = v[numpy.append(valid, True)]
|
||||
dv = numpy.diff(v, axis=0)
|
||||
norms = norms[valid]
|
||||
|
||||
if dv.shape[0] == 0:
|
||||
# All vertices were the same. It's a point.
|
||||
if self.width == 0:
|
||||
return [Polygon(vertices=numpy.zeros((3, 2)))] # Area-less degenerate
|
||||
if self.cap == PathCap.Circle:
|
||||
return Circle(radius=self.width / 2, offset=v[0]).to_polygons(num_vertices=num_vertices, max_arclen=max_arclen)
|
||||
if self.cap == PathCap.Square:
|
||||
return [Polygon.square(side_length=self.width, offset=v[0])]
|
||||
# Flush or CustomSquare
|
||||
return [Polygon(vertices=numpy.zeros((3, 2)))]
|
||||
|
||||
dvdir = dv / norms[:, None]
|
||||
|
||||
if self.width == 0:
|
||||
verts = numpy.vstack((v, v[::-1]))
|
||||
|
|
@ -448,16 +469,11 @@ class Path(Shape):
|
|||
rotated_vertices = numpy.vstack([numpy.dot(rotation_matrix_2d(-rotation), v)
|
||||
for v in normed_vertices])
|
||||
|
||||
# Reorder the vertices so that the one with lowest x, then y, comes first.
|
||||
x_min_val = rotated_vertices[:, 0].min()
|
||||
x_min_inds = numpy.where(rotated_vertices[:, 0] == x_min_val)[0]
|
||||
if x_min_inds.size > 1:
|
||||
y_min_val = rotated_vertices[x_min_inds, 1].min()
|
||||
tie_breaker = numpy.where(rotated_vertices[x_min_inds, 1] == y_min_val)[0][0]
|
||||
start_ind = x_min_inds[tie_breaker]
|
||||
# Canonical ordering for open paths: pick whichever of (v) or (v[::-1]) is smaller
|
||||
if tuple(rotated_vertices.flat) > tuple(rotated_vertices[::-1].flat):
|
||||
reordered_vertices = rotated_vertices[::-1]
|
||||
else:
|
||||
start_ind = x_min_inds[0]
|
||||
reordered_vertices = numpy.roll(rotated_vertices, -start_ind, axis=0)
|
||||
reordered_vertices = rotated_vertices
|
||||
|
||||
width0 = self.width / norm_value
|
||||
|
||||
|
|
@ -496,7 +512,7 @@ class Path(Shape):
|
|||
Returns:
|
||||
self
|
||||
"""
|
||||
self.vertices = remove_colinear_vertices(self.vertices, closed_path=False)
|
||||
self.vertices = remove_colinear_vertices(self.vertices, closed_path=False, preserve_uturns=True)
|
||||
return self
|
||||
|
||||
def _calculate_cap_extensions(self) -> NDArray[numpy.float64]:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue