Compare commits

...

3 Commits

Author SHA1 Message Date
Andrew Port 026b1dc6e6 updated from master 2020-12-08 19:57:11 -08:00
Andrew Port 2824a26a6c Merge remote-tracking branch 'origin/master' into vectorize-path-point 2020-12-08 19:56:46 -08:00
Andrew Port 8fd4fd73b8 added vectorized implementation of Path.point 2020-12-02 00:34:22 -08:00
2 changed files with 21 additions and 15 deletions

View File

@ -2430,25 +2430,31 @@ class Path(MutableSequence):
self._length = sum(lengths) self._length = sum(lengths)
self._lengths = [each/self._length for each in lengths] self._lengths = [each/self._length for each in lengths]
def point(self, pos): def point(self, T):
# Shortcuts # Shortcuts
if pos == 0.0: if T == 0.0:
return self._segments[0].point(pos) return self._segments[0].point(T)
if pos == 1.0: if T == 1.0:
return self._segments[-1].point(pos) return self._segments[-1].point(T)
self._calc_lengths() self._calc_lengths()
# Find which segment the point we search for is located on: # Find which segment the point we search for is located on:
segment_start = 0 cumulative_relative_lengths = np.cumsum(self._lengths)
for index, segment in enumerate(self._segments):
segment_end = segment_start + self._lengths[index] if hasattr(T, '__iter__'):
if segment_end >= pos: T = np.array(T).reshape(1, len(T))
# This is the segment! How far in on the segment is the point? relevant_seg_indices = np.argmax(cumulative_relative_lengths[:, None] >= T, axis=0)
segment_pos = (pos - segment_start)/( T0, T1 = cumulative_relative_lengths[relevant_seg_indices - 1],\
segment_end - segment_start) cumulative_relative_lengths[relevant_seg_indices]
return segment.point(segment_pos) t = (T - T0) / (T1 - T0)
segment_start = segment_end return [self[i].point(tval) for i, tval in zip(relevant_seg_indices, t)]
else: # assume T is a scalar
relevant_seg_index = np.argmax(cumulative_relative_lengths >= T)
T0, T1 = cumulative_relative_lengths[relevant_seg_index - 1],\
cumulative_relative_lengths[relevant_seg_index]
t = (T - T0) / (T1 - T0)
return self[relevant_seg_index].point(t)
def length(self, T0=0, T1=1, error=LENGTH_ERROR, min_depth=LENGTH_MIN_DEPTH): def length(self, T0=0, T1=1, error=LENGTH_ERROR, min_depth=LENGTH_MIN_DEPTH):
self._calc_lengths(error=error, min_depth=min_depth) self._calc_lengths(error=error, min_depth=min_depth)

2
tags
View File

@ -820,7 +820,7 @@ point build/lib/svgpathtools/path.py /^ def point(self, t):$/;" m class:Cubic
point build/lib/svgpathtools/path.py /^ def point(self, t):$/;" m class:Line point build/lib/svgpathtools/path.py /^ def point(self, t):$/;" m class:Line
point build/lib/svgpathtools/path.py /^ def point(self, t):$/;" m class:QuadraticBezier point build/lib/svgpathtools/path.py /^ def point(self, t):$/;" m class:QuadraticBezier
point examples/compute-many-points-quickly-using-numpy-arrays.py /^ def point(self, t):$/;" m class:HigherOrderBezier point examples/compute-many-points-quickly-using-numpy-arrays.py /^ def point(self, t):$/;" m class:HigherOrderBezier
point svgpathtools/path.py /^ def point(self, pos):$/;" m class:Path point svgpathtools/path.py /^ def point(self, T):$/;" m class:Path
point svgpathtools/path.py /^ def point(self, t):$/;" m class:Arc point svgpathtools/path.py /^ def point(self, t):$/;" m class:Arc
point svgpathtools/path.py /^ def point(self, t):$/;" m class:CubicBezier point svgpathtools/path.py /^ def point(self, t):$/;" m class:CubicBezier
point svgpathtools/path.py /^ def point(self, t):$/;" m class:Line point svgpathtools/path.py /^ def point(self, t):$/;" m class:Line