3D Cardinal Spline

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

3D Cardinal Spline

dinther
I needed a 3D cardinal spline for a ship hull generator. I could not find the kind I wanted so I wrote one. Also a good exercise in functional coding. I thought to share it. Feedback welcome of course.

//  Cardinal Spine adapted from https://github.com/dominictarr/cardinal-spline-3d
//  for openscad
//
//  By: Paul van Dinther
//
//  usage:
//
//  pts = cardinal_spline([[5,0],[3,-4],[0,-5],[-3,-4],[-5,0]], tension = 0.5, numOfSeg=15, close=false);
//  polygon(pts);
//
//  or 3D
//
//  pts = cardinal_spline([[5,0,0],[3,4,2],[0,5,5],[-3,4,2],[-5,0,0]], tension = 0.5, numOfSeg=15, close=true);
//  for (i = [0:1:len(pts)-1]) translate(pts[i]) sphere(r=0.25);
//


function cardinal_spline(points= undef, tension = 0.5, numOfSeg=15, close = false) =
    let(
        count = len(points),
        pts = close? concat([points[count-1]],points, [points[0]]) : concat([points[0]], points,[points[count-1]]),
        echo(pts),
        cachePtr = 4,
        cache = concat([1,0,0,0], [for (i = [1:1:numOfSeg-1]) let(
            st = i/numOfSeg,
            st2 = st * st,
            st3 = st2 * st,
            st23 = st3 * 2,
            st32 = st2 * 3,
            cg = [st23 - st32 + 1, st32 - st23, st3 - 2 * st2 + st,st3-st2]) each cg],[0,1, for (i=[0:1:((numOfSeg + 2)*4)-(numOfSeg*4)-4]) 0 ])
        ) concat(parse(pts=pts, cache=cache, count=count, tension=tension, numOfSeg=numOfSeg), close? parse(pts=[points[count-2],points[count-1], points[0], points[1]],cache=cache, count=2, tension=tension, numOfSeg=numOfSeg) : [points[count-1]]);
               
function parse(pts=undef, cache=undef, count=undef , tension=0.5, numOfSeg=15) =    
    [for( i = [ 1 : 1 : count-1]) let(
        pt1x = pts[i][0],
        pt1y = pts[i][1],
        pt1z = pts[i][2]==undef? 0 : pts[i][2],
        pt2x = pts[i+1][0],
        pt2y = pts[i+1][1],
        pt2z = pts[i+1][2]==undef? 0 : pts[i+1][2],
        t1x = (pt2x - pts[i-1][0]) * tension,
        t1y = (pt2y - pts[i-1][1]) * tension,
        t1z = (pt2z - (pts[i-1][2]==undef? 0 : pts[i-1][2])) * tension,
        echo(pts[i-1][2]),
        t2x = (pts[i+2][0] - pt1x) * tension,
        t2y = (pts[i+2][1] - pt1y) * tension,
        t2z = ((pts[i+2][2]==undef? 0 : pts[i+2][2]) - pt1z) * tension,
        data = [for(t=[0:1:numOfSeg-1]) let(
            c1 = cache[t*4 + 0],
            c2 = cache[t*4 + 1],
            c3 = cache[t*4 + 2],
            c4 = cache[t*4 + 3],
            x = c1 * pt1x + c2 * pt2x + c3 * t1x + c4 * t2x,
            y = c1 * pt1y + c2 * pt2y + c3 * t1y + c4 * t2y,
            z = c1 * pt1z + c2 * pt2z + c3 * t1z + c4 * t2z,
            d = pts[i][2]==undef? [x, y] : [x, y, z]
        ) d]) each data];

Sent from the OpenSCAD mailing list archive at Nabble.com.

_______________________________________________
OpenSCAD mailing list
To unsubscribe send an email to [hidden email]