fixed problem with path joints becoming discontious after transformation
parent
561c89ad47
commit
091394b5e3
|
@ -12,6 +12,7 @@ except ImportError:
|
||||||
from warnings import warn
|
from warnings import warn
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
from itertools import tee
|
||||||
|
|
||||||
# these imports were originally from math and cmath, now are from numpy
|
# these imports were originally from math and cmath, now are from numpy
|
||||||
# in order to encourage code that generalizes to vector inputs
|
# in order to encourage code that generalizes to vector inputs
|
||||||
|
@ -132,6 +133,7 @@ def polygon(*points):
|
||||||
return Path(*[Line(points[i], points[(i + 1) % len(points)])
|
return Path(*[Line(points[i], points[(i + 1) % len(points)])
|
||||||
for i in range(len(points))])
|
for i in range(len(points))])
|
||||||
|
|
||||||
|
|
||||||
# Conversion###################################################################
|
# Conversion###################################################################
|
||||||
|
|
||||||
def bpoints2bezier(bpoints):
|
def bpoints2bezier(bpoints):
|
||||||
|
@ -180,6 +182,16 @@ def bez2poly(bez, numpy_ordering=True, return_poly1d=False):
|
||||||
|
|
||||||
|
|
||||||
# Geometric####################################################################
|
# Geometric####################################################################
|
||||||
|
def transform_segments_together(path, transformation):
|
||||||
|
"""Makes sure that, if joints were continuous, they're kept that way."""
|
||||||
|
transformed_segs = [transformation(seg) for seg in path]
|
||||||
|
joint_was_continuous = [sa.end == sb.start for sa, sb in path.joints()]
|
||||||
|
|
||||||
|
for i, (sa, sb)in enumerate(path.joints()):
|
||||||
|
if sa.end == sb.start:
|
||||||
|
transformed_segs[i].end = transformed_segs[(i + 1) % len(path)].start
|
||||||
|
return Path(*transformed_segs)
|
||||||
|
|
||||||
|
|
||||||
def rotate(curve, degs, origin=None):
|
def rotate(curve, degs, origin=None):
|
||||||
"""Returns curve rotated by `degs` degrees (CCW) around the point `origin`
|
"""Returns curve rotated by `degs` degrees (CCW) around the point `origin`
|
||||||
|
@ -196,7 +208,8 @@ def rotate(curve, degs, origin=None):
|
||||||
origin = curve.point(0.5)
|
origin = curve.point(0.5)
|
||||||
|
|
||||||
if isinstance(curve, Path):
|
if isinstance(curve, Path):
|
||||||
return Path(*[rotate(seg, degs, origin=origin) for seg in curve])
|
transformation = lambda seg: rotate(seg, degs, origin=origin)
|
||||||
|
return transform_segments_together(curve, transformation)
|
||||||
elif is_bezier_segment(curve):
|
elif is_bezier_segment(curve):
|
||||||
return bpoints2bezier([transform(bpt) for bpt in curve.bpoints()])
|
return bpoints2bezier([transform(bpt) for bpt in curve.bpoints()])
|
||||||
elif isinstance(curve, Arc):
|
elif isinstance(curve, Arc):
|
||||||
|
@ -214,7 +227,8 @@ def translate(curve, z0):
|
||||||
"""Shifts the curve by the complex quantity z such that
|
"""Shifts the curve by the complex quantity z such that
|
||||||
translate(curve, z0).point(t) = curve.point(t) + z0"""
|
translate(curve, z0).point(t) = curve.point(t) + z0"""
|
||||||
if isinstance(curve, Path):
|
if isinstance(curve, Path):
|
||||||
return Path(*[translate(seg, z0) for seg in curve])
|
transformation = lambda seg: translate(seg, z0)
|
||||||
|
return transform_segments_together(curve, transformation)
|
||||||
elif is_bezier_segment(curve):
|
elif is_bezier_segment(curve):
|
||||||
return bpoints2bezier([bpt + z0 for bpt in curve.bpoints()])
|
return bpoints2bezier([bpt + z0 for bpt in curve.bpoints()])
|
||||||
elif isinstance(curve, Arc):
|
elif isinstance(curve, Arc):
|
||||||
|
@ -255,7 +269,8 @@ def scale(curve, sx, sy=None, origin=0j):
|
||||||
return poly2bez(p)
|
return poly2bez(p)
|
||||||
|
|
||||||
if isinstance(curve, Path):
|
if isinstance(curve, Path):
|
||||||
return Path(*[scale(seg, sx, sy, origin) for seg in curve])
|
transformation = lambda seg: scale(seg, sx, sy, origin)
|
||||||
|
return transform_segments_together(curve, transformation)
|
||||||
elif is_bezier_segment(curve):
|
elif is_bezier_segment(curve):
|
||||||
return scale_bezier(curve)
|
return scale_bezier(curve)
|
||||||
elif isinstance(curve, Arc):
|
elif isinstance(curve, Arc):
|
||||||
|
@ -286,7 +301,9 @@ def transform(curve, tf):
|
||||||
return v.item(0) + 1j * v.item(1)
|
return v.item(0) + 1j * v.item(1)
|
||||||
|
|
||||||
if isinstance(curve, Path):
|
if isinstance(curve, Path):
|
||||||
return Path(*[transform(segment, tf) for segment in curve])
|
transformation = lambda seg: transform(seg, tf)
|
||||||
|
return transform_segments_together(curve, transformation)
|
||||||
|
|
||||||
elif is_bezier_segment(curve):
|
elif is_bezier_segment(curve):
|
||||||
return bpoints2bezier([to_complex(tf.dot(to_point(p)))
|
return bpoints2bezier([to_complex(tf.dot(to_point(p)))
|
||||||
for p in curve.bpoints()])
|
for p in curve.bpoints()])
|
||||||
|
@ -3012,6 +3029,18 @@ class Path(MutableSequence):
|
||||||
arc_required = int(ceil(abs(segment.delta) / sweep_limit))
|
arc_required = int(ceil(abs(segment.delta) / sweep_limit))
|
||||||
self[s:s+1] = list(segment.as_quad_curves(arc_required))
|
self[s:s+1] = list(segment.as_quad_curves(arc_required))
|
||||||
|
|
||||||
|
def joints(self):
|
||||||
|
"""returns generator of segment joints
|
||||||
|
|
||||||
|
I.e. Path(s0, s1, s2, ..., sn).joints() returns generator
|
||||||
|
(s0, s1), (s1, s2), ..., (sn, s0)
|
||||||
|
|
||||||
|
credit: https://docs.python.org/3/library/itertools.html#recipes
|
||||||
|
"""
|
||||||
|
a, b = tee(self)
|
||||||
|
next(b, None)
|
||||||
|
return zip(a, b)
|
||||||
|
|
||||||
def _tokenize_path(self, pathdef):
|
def _tokenize_path(self, pathdef):
|
||||||
for x in COMMAND_RE.split(pathdef):
|
for x in COMMAND_RE.split(pathdef):
|
||||||
if x in COMMANDS:
|
if x in COMMANDS:
|
||||||
|
|
Loading…
Reference in New Issue