1. NodeBox 1
    1. Homepage
    2. NodeBox 3Node-based app for generative design and data visualization
    3. NodeBox OpenGLHardware-accelerated cross-platform graphics library
    4. NodeBox 1Generate 2D visuals using Python code (Mac OS X only)
  2. Gallery
  3. Documentation
  4. Forum
  5. Blog

findpath on close curve

Posted by Edwin on May 03, 2008



Hi all,

I have a closed path and want to smooth it.
If I convert to or come from a pointlist, the closedness (?) of the path is lost. I want to do more than make a circle out of a square but this is the easy example :

points = [(10, 10), (10, 90), (90, 90), (90, 10)] 
nofill()
path = findpath(points, curvature =1)
stroke(0)
drawpath(path)

 

Posted by Tom De Smedt on May 03, 2008

Why not add a closepath() to the BezierPath object before drawing it:

path.closepath()
drawpath(path)

 

Posted by Edwin on May 03, 2008

Thanks for the quick reply.
I didn't use closepath because that will close the path but AFTER the smoothing of the findpath-function. Try and you just get a straight line. I couldn't find a smooth function for a BezierPath?



Posted by Tom De Smedt on May 11, 2008

A closepath in a path will always be a straight line - if it was a curve it would be hard for the algorithm to figure out if the curve was convex or concave. If you want a smoothly closed path, you will have to write your own functionality.

That said, below is my attempt. The result is not perfect but it may give you some ideas on how the get started:

points = [(10, 10), (10, 90), (90, 90), (90, 10)]
 
# close the path with a curve
points.append(points[0]) 
path = findpath(points, curvature=1)
 
# now we need to smooth the close transition
# we could probably accomplish this by 
# reflecting the handle in the starting point
from nodebox.geo import reflect
 
# the first point in the path can be a moveto, something without handles, ...
# it's much safer to calculate a point which is "very near" the start,
# so we are certain it has handles to reflect.
pt = path.point(0.05)
dx, dy = reflect(pt.x, pt.y, pt.ctrl2.x, pt.ctrl2.y, 2)
 
# the result may look better if we omit the first point,
# resulting in "some extra space" for the transition.
points = list(path)[1:]
pt.cmd = MOVETO
points.insert(0, pt)
 
# adjust the handle of the last point
pt = points[-1]
pt.x, pt.y = points[0].x, points[0].y
pt.ctrl2.x = dx
pt.ctrl2.y = dy
 
translate(100, 100)
nofill()
stroke(0)
drawpath(points)