Fast way to sample geometric points from SVG paths

2020-07-23 03:56发布

问题:

I'm using the excellent svgpathtools library in Python 3 to work with some paths in an SVG file, created in a vector drawing application.

I'd like to create detailed point arrays for each of the paths contained within the SVG, where the points are equidistant along the path. The following does just that but becomes unbearably slow if more than a few thousand samples are taken.

SAMPLES_PER_PX = 1

fname = "/path/to/file.svg"
paths, attributes = svg2paths(fname)

myPaths = {}
for path,attr in zip(paths, attributes):
    myPathList = []
    pathLength = path.length()
    pathColour = attr['stroke']
    numSamples = int(pathLength * SAMPLES_PER_PX)
    for i in range(numSamples):
        #parametric length = ilength(geometric length)
        myPathList.append(path.point(path.ilength(pathLength * i / (numSamples-1))))
    myPaths[pathColour] = np.array(myPathList)

I've always felt that my Python ain't very Pythonic. Is there a way I can take advantage of some Python-ness to speed this up?

回答1:

I had the same problem. My solution was to sample N points using path.point and then interpolate those points using scipy spline and resample from the spline. Something like:

tck, _ = interpolate.splprep(pts, s=0)
result = interpolate.splev(np.linspace(0, 1, 1000), tck)

Where pts is a list of sampled points. The number N depends on how non-uniform the input curve is. Usually N=20 is sufficient for not too crazy cases:-)



标签: python svg