/*--Output data set will only have the bezier coordinates and the group--*/ /*--First and last segments have half straight lines--*/ %macro BezierMacro (data=, x=, y=, group=, out=, outX=, outY=, outG=, n=20); data &out; retain count x1 y1 x2 y2 x3 y3 xp yp; keep &outX &outY &outG count; set &data; by &group; &outg=&group; /*--First half of first segment is a straight line--*/ if first.&group then count=1; else count+1; if count=1 then do; &outx=&x; &outy=&y; xp=&x; yp=&y; output; end; else if count=2 then do; x1=(xp+&x)/2; y1=(yp+&y)/2; x2=&x; y2=&y; end; else if count=3 then do; x3=(&x+x2)/2; y3=(&y+y2)/2; xp=&x; yp=&y; end; else if count > 3 then do; x1=x3; y1=y3; x2=xp; y2=yp; x3=(&x+x2)/2; y3=(&y+y2)/2; xp=&x; yp=&y; end; /*--Compute bezier--*/ if count > 2 then do; do t=0 to 1 by 1/&n; &outx = (1 - t) * (1 - t) * x1 + 2 * (1 - t) * t * x2 + t * t * x3; &outy = (1 - t) * (1 - t) * y1 + 2 * (1 - t) * t * y2 + t * t * y3; output; end; end; if last.&group then do; &outx=&x; &outy=&y; output; end; run; %mend;