Last active
March 30, 2017 09:21
-
-
Save mathandy/b4d2faf4ea3de7c0640126e2015c7484 to your computer and use it in GitHub Desktop.
An svgpathtools example: computing many points quickly with and numpy arrays
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""The goal of this gist is to show how to compute many points on a path | |
quickly using NumPy arrays. I.e. there's a much faster way than using, say | |
[some_path.point(t) for t in many_tvals]. The example below assumes the | |
`Path` object is composed entirely of `CubicBezier` objects, but this can | |
easily be generalized to paths containing `Line` and `QuadraticBezier` objects | |
also. | |
Note: The relevant matrix transformation for quadratics can be found in the | |
svgpathtools.bezier module.""" | |
import numpy as np | |
from svgpathtools import * | |
class HigherOrderBezier: | |
def __init__(self, bpoints): | |
self.bpts = bpoints | |
def bpoints(self): | |
return self.bpts | |
def point(self, t): | |
return bezier_point(self.bpoints(), t) | |
def __repr__(self): | |
return str(self.bpts) | |
def random_bezier(degree): | |
if degree <= 3: | |
return bpoints2bezier(polynomial2bezier(np.random.rand(degree + 1))) | |
else: | |
return HigherOrderBezier(np.random.rand(degree + 1)) | |
def points_in_each_seg_slow(path, tvals): | |
return [seg.poly()(tvals) for seg in path] | |
def points_in_each_seg(path, tvals): | |
"""Compute seg.point(t) for each seg in path and each t in tvals.""" | |
A = np.matrix([[-1, 3, -3, 1], # transforms cubic bez to standard poly | |
[ 3, -6, 3, 0], | |
[-3, 3, 0, 0], | |
[ 1, 0, 0, 0]]) | |
B = [seg.bpoints() for seg in path] | |
return np.dot(B, np.dot(A, np.power(tvals, [[3],[2],[1],[0]]))) | |
if __name__ == '__main__': | |
num_segs = 1000 | |
testpath = Path(*[random_bezier(3) for dummy in range(num_segs)]) | |
tvals = np.linspace(0, 1, 10) | |
pts = points_in_each_seg(testpath, tvals) | |
pts_check = points_in_each_seg_slow(testpath, tvals) | |
print np.max(pts - pts_check) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment