spakin / SimpInkScr

Simple Inkscape Scripting
https://inkscape.org/~pakin/%E2%98%85simple-inkscape-scripting
GNU General Public License v3.0
330 stars 32 forks source link

Scatter along object along path #17

Closed g2go4now closed 2 years ago

g2go4now commented 2 years ago

Is it possible to scatter objects along a path? Example: 103

ajrou commented 2 years ago

This should work: https://www.youtube.com/watch?v=svCRPo0K6Lw

spakin commented 2 years ago

@ajrou: I wouldn't have thought to use markers for this purpose. I ought to add those to Simple Inkscape Scripting at some point.

@g2go4now: One approach is to use inkex.bezier to compute positions and slopes at various time offsets along a Bézier curve. Here's an initial attempt at that to give you something from which to start experimenting:

import inkex.bezier

base_rect = rect((-25, -50), (25, 50), fill='red')
p = inkex.Path('M 63.988928,368.75004 C 159.98893,208.75004 255.98893,224.75004 383.98893,384.75004 511.98893,544.75004 591.98893,544.75004 703.98893,432.75004 815.98893,320.75004 863.98893,288.75004 959.98893,352.75004')
path(p, stroke_width=4, stroke='red')

steps = 3
first = inkex.Vector2d(p[0].x, p[0].y)
prev = first
for pe in p[1:]:
    try:
        bez = [list(prev)] + pe.to_bez()
        for s in range(steps):
            pos = inkex.bezier.bezierpointatt(bez, s/steps)
            slope = inkex.bezier.bezierslopeatt(bez, s/steps)
            rad = atan2(slope[1], slope[0])
            xform = inkex.Transform()
            xform.add_translate(pos)
            xform.add_rotate(rad*180/pi)
            clone(base_rect, transform=xform)
    except AttributeError:
        pass
    prev = pe.end_point(first, prev)

pos = inkex.bezier.bezierpointatt(bez, 1)
slope = inkex.bezier.bezierslopeatt(bez, 1)
rad = atan2(slope[1], slope[0])
xform = inkex.Transform()
xform.add_translate(pos)
xform.add_rotate(rad*180/pi)
clone(base_rect, transform=xform)