-- CubicImpl.mesa -- Last changed by Maureen Stone, 9-Sep-81 16:21:17 -- Written by Doug Wyatt, September 22, 1980 5:30 PM DIRECTORY Cubic, Vector USING [Vec, Add, Sub, Mul, Div, Min, Max, In]; CubicImpl: PROGRAM IMPORTS Vector EXPORTS Cubic = { OPEN Cubic; CoeffsToBezier: PUBLIC PROCEDURE[c: Coeffs] RETURNS[b: Bezier] = { OPEN Vector,c,b; -- Compute the bezier control points of the cubic -- These points form a convex hull of the curve -- b0 is the starting point, b3 is the ending point -- b0 _ c0; -- b1 _ c0 + c1/3; -- b2 _ c0 + 2*c1/3 + c2/3; [ = b1 + (c1+c2)/3 ] -- b3 _ c0 + c1 + c2 + c3; b0_c0; b1_Add[c0,Div[c1,3]]; b2_Add[b1,Div[Add[c1,c2],3]]; b3_Add[Add[Add[c0,c1],c2],c3]; }; BezierToCoeffs: PUBLIC PROCEDURE[b: Bezier] RETURNS[c: Coeffs] = { OPEN Vector,b,c; temp: Vec; -- Compute the cubic coefficients from the Bezier points. -- c0 _ b0; -- c1 _ 3(b1-b0); -- c2 _ 3(b0-2b1+b2); [ = 3(b2-b1) - c1 ] -- c3 _ -b0 +3(b1-b2) + b3; [ = b3 - (b0 + 3(b2-b1)) ] c0 _ b0; c1 _ Mul[Sub[b1,b0],3]; c2 _ Sub[(temp_Mul[Sub[b2,b1],3]),c1]; c3 _ Sub[b3,Add[b0,temp]]; }; BezierPolygon: PUBLIC PROCEDURE[b: Bezier, epsilon: REAL,Proc: PROCEDURE[Vector.Vec]] = { lvlmax: CARDINAL=10; SubDivide: PROCEDURE[b: Bezier, lvl: CARDINAL] = { IF lvl>=lvlmax OR IsFlat[b,epsilon] THEN Proc[b.b3] ELSE { OPEN Vector; q1,q2,q3,qp1,qp2,q: Vec; bb: Bezier; q1_Mul[Add[b.b0,b.b1],0.5]; q2_Mul[Add[b.b1,b.b2],0.5]; q3_Mul[Add[b.b2,b.b3],0.5]; qp1_Mul[Add[q1,q2],0.5]; qp2_Mul[Add[q2,q3],0.5]; q_Mul[Add[qp1,qp2],0.5]; bb_[b0: b.b0, b1: q1, b2: qp1, b3: q]; SubDivide[bb,lvl+1]; bb_[b0: q, b1: qp2, b2: q3, b3: b.b3]; SubDivide[bb,lvl+1]; }; }; SubDivide[b,1]; }; IsFlat: PROCEDURE[b: Bezier, eps: REAL] RETURNS[BOOLEAN] = INLINE { OPEN Vector; dx,dy: REAL; d1,d2,d,bl,bh: Vec; oh: Vec=[0.5,0.5]; bh_Add[Max[b.b0,b.b3],oh]; bl_Sub[Min[b.b0,b.b3],oh]; IF ~In[b.b1,bl,bh] OR ~In[b.b2,bl,bh] THEN RETURN[FALSE]; d1_Sub[b.b1,b.b0]; d2_Sub[b.b2,b.b0]; d_Sub[b.b3,b.b0]; dx_ABS[d.x]; dy_ABS[d.y]; IF dx+dy < 1 THEN RETURN[TRUE]; IF dy < dx THEN RETURN[ ABS[d2.y-((d.y*d2.x)/d.x)]