[Path.to_polygons] Use linalg.solve() where possible; fallback to lstsq if singular

This commit is contained in:
jan 2026-03-09 02:41:15 -07:00
commit 25b8fe8448

View file

@ -344,8 +344,18 @@ class Path(Shape):
bs = v[1:-1] - v[:-2] + perp[1:] - perp[:-1] bs = v[1:-1] - v[:-2] + perp[1:] - perp[:-1]
ds = v[1:-1] - v[:-2] - perp[1:] + perp[:-1] ds = v[1:-1] - v[:-2] - perp[1:] + perp[:-1]
rp = numpy.linalg.lstsq(As, bs[:, :, None], rcond=1e-12)[0][:, 0, 0] try:
rn = numpy.linalg.lstsq(As, ds[:, :, None], rcond=1e-12)[0][:, 0, 0] # Vectorized solve for all intersections
# solve supports broadcasting: As (N-2, 2, 2), bs (N-2, 2, 1)
rp = numpy.linalg.solve(As, bs[:, :, None])[:, 0, 0]
rn = numpy.linalg.solve(As, ds[:, :, None])[:, 0, 0]
except numpy.linalg.LinAlgError:
# Fallback to slower lstsq if some segments are parallel (singular matrix)
rp = numpy.zeros(As.shape[0])
rn = numpy.zeros(As.shape[0])
for ii in range(As.shape[0]):
rp[ii] = numpy.linalg.lstsq(As[ii], bs[ii, :, None], rcond=1e-12)[0][0, 0]
rn[ii] = numpy.linalg.lstsq(As[ii], ds[ii, :, None], rcond=1e-12)[0][0, 0]
intersection_p = v[:-2] + rp[:, None] * dv[:-1] + perp[:-1] intersection_p = v[:-2] + rp[:, None] * dv[:-1] + perp[:-1]
intersection_n = v[:-2] + rn[:, None] * dv[:-1] - perp[:-1] intersection_n = v[:-2] + rn[:, None] * dv[:-1] - perp[:-1]