Friday, December 1, 2017

Fit a 4 point bezier curve for desired length

module to draw a simple 4 point Bez curve. 
function for piece-wise length  estimation. 

And a recursive function to fit control points for the length of your pleasure. 

function AdjustBezier(v,l, precision = 0.00001)=
l<norm(v[0]-v[3])?
let(e=echo("Cant be that short, sorry"))[v[0],v[0] ,v[3] ,v[3]]:
let(
current_lenght=len3bz(v),
error=l/current_lenght,
e=echo(l,current_lenght,error),
new_v=[v[0],v[0]+(v[1]-v[0])*error,v[3]+(v[2]-v[3])*error,v[3]]
)
abs(1-error)>precision?AdjustBezier(new_v,l):v;



function len3bz(v, precision = 0.001, t = 0, acc = 0) =
 t > 1 ? acc : 
len3bz(v, precision, t + precision, acc 
+ norm(bez2(t, v) - bez2(t + precision, v)));

function bez2(t, v) = (len(v) > 2) ? bez2(t, [
  for (i = [0: len(v) - 2]) v[i]* (t)  + v[i + 1] * (1 - t)
]): v[0]* (t)  + v[1]* (1 - t) ;

module ShowControl(v) { // translate(t(v[0])) sphere(v[0][3]);
 
    for (i = [1: len(v) - 1]) {
      // vg  translate(t(v[i])) sphere(v[i][3]);
      hull() {
        translate(t(v[i])) sphere(0.5);
        translate(t(v[i - 1])) sphere(0.5);
      }
    }
}

module ShowBezier(v,steps=50) 
{ // translate(t(v[0])) sphere(v[0][3]);
 step=1/steps;
    for (i = [-step:step:  1+step]) {
      // vg  translate(t(v[i])) sphere(v[i][3]);
      hull() {
        translate(t(bez2(clamp(i), v) ))sphere(1);
        translate(t(bez2(clamp(i+step), v))) sphere(1);
      }
    }
}


function t(v) = [v.x, v.y, v.z];
function clamp(a, b = 0, c = 1) = min(max(a, b), c);

MyBezier=[[0,0,0],[0,0,10],[50,0,50],[50,10,50]];
Newlengh=175;

ShowControl(MyBezier) ; 
ShowBezier(MyBezier) ;
echo(len3bz(MyBezier));

MyNewBezier=AdjustBezier(MyBezier,Newlengh) ;

color("red"){
ShowControl(MyNewBezier) ; 
ShowBezier(MyNewBezier) ;
echo(len3bz(MyNewBezier));}

No comments:

Post a Comment