How can I split a path into multiple segments?
-
Hello,
please, as title questions.. How can I distribute points along a path? Let's say I have a path with two points and I need to equally place 20 points on it, how can I achieve it? Thanks, Jan!!
-
hello @jansindl3r,
see Plot objects along a path (there’s a link to an example)
-
Thanks @gferreira !
I see that this is not ideal, you can only have one segment for this formula. Though in this result some of the segments seem a bit off.I am sharing result that works fine with use of svg.path, code is included. It is used outside of DrawBot IDE, because I didn't want to bother finding out how to install it there... sorry for that quick dirty parse of the SVG path from string...
import cmath import drawBot as db from svg.path import parse_path path = parse_path('M 300 100 C 100 100 200 200 200 300 L 250 350 L100 950') def points(): for i in range(10 + 1): i = i * 0.1 num = complex(path.point(i)) x, y = num.real, num.imag yield (x, y) db.newDrawing() x, y = [1000] * 2 db.newPage(x, y) db.fill(1) db.rect(0,0,x,y) db.fill(None) db.stroke(0) bezier = db.BezierPath() bezier.moveTo((300, 100)) bezier.curveTo((100, 100), (200, 200), (200, 300)) bezier.lineTo((250, 350)) bezier.lineTo((100, 950)) db.drawPath(bezier) db.fill(0) _points = points() for order, point in enumerate(_points): db.oval(*[val - 5 for val in point], 10, 10) db.saveImage('testje.png')
-
hello @jansindl3r,
thanks for the example, I didn’t know about
svg.path
. (in order to use it inside DrawBot, you have to install it for Python 3.6 – see some problems importing noise module)you can only have one segment for this formula
a contour is made out of several segments, so you need to loop over the contour and get
(p1, p2, p3, p4)
for each segment.here’s an example, using the same
getPoint()
function from the gist:steps = 13 r = 5 B = BezierPath() B.text('a', (90, 120), fontSize=1400) fill(0, 1, 1) drawPath(B) fill(1, 0, 0) for contour in B.contours: for i, segment in enumerate(contour): if i == 0 and contour.open: continue # the first point in a segment # is the last point from the previous segment # tip: use modulo division! p1 = contour[(i-1) % len(contour)][-1] # curve segment if len(segment) == 3: p2, p3, p4 = segment # line segment else: p2 = p1 p3 = p4 = segment[0] # draw steps for i in range(steps): t = i * 1.0 / (steps - 1) x, y = getPoint(t, p1, p2, p3, p4) oval(x-r, y-r, r*2, r*2)
hope this helps!
-
Hi @gferreira such distribution is not very even. I am sending result using svg.path, I will try to have a look on it. It seems like an interesting excercise for my drawBot class.
Thanks, Jan
-
@jansindl3r keep in mind that in a Bezier curve time and distance do not correlate. if you construct a point at time .1 it will not be at one tenth of the curve length.
afaik the most common technique to get similar distances is to calculate lots of points on the curve(s), calculate some distances and select the closest points.
this link has some very helpful information.
good luck.
-
you can also use a FlattenPen from fontPens
https://github.com/robotools/fontPens/blob/master/Lib/fontPens/flattenPen.py#L9
-
there’s an example of
FlattePen
+BezierPath
here