<> <> <> DIRECTORY IPCubic USING [Coeffs], IPImagerBasic USING [Bezier, Pair]; IPCubicImpl: CEDAR PROGRAM EXPORTS IPCubic = BEGIN OPEN IPCubic, IPImagerBasic; Add: PROC[a: Pair, b: Pair] RETURNS[Pair] = INLINE { RETURN[[a.x+b.x,a.y+b.y]] }; Sub: PROC[a: Pair, b: Pair] RETURNS[Pair] = INLINE { RETURN[[a.x-b.x,a.y-b.y]] }; Mul: PROC[a: Pair, s: REAL] RETURNS[Pair] = INLINE { RETURN[[a.x*s,a.y*s]] }; Div: PROC[a: Pair, s: REAL] RETURNS[Pair] = INLINE { RETURN[[a.x/s,a.y/s]] }; In: PROC[a: Pair, b: Pair, c: Pair] RETURNS[BOOLEAN] = INLINE { RETURN[a.x IN[b.x..c.x] AND a.y IN[b.y..c.y]] }; Min: PROC[a: Pair, b: Pair] RETURNS[Pair] = INLINE { RETURN[[MIN[a.x,b.x],MIN[a.y,b.y]]] }; Max: PROC[a: Pair, b: Pair] RETURNS[Pair] = INLINE { RETURN[[MAX[a.x,b.x],MAX[a.y,b.y]]] }; Mid: PROC[a: Pair, b: Pair] RETURNS[Pair] = INLINE { RETURN[[(a.x+b.x)/2,(a.y+b.y)/2]] }; CoeffsToBezier: PUBLIC PROC[coeffs: Coeffs] RETURNS[bezier: Bezier] = { <> <> <> <> <> <> <> bezier.b0 _ coeffs.c0; bezier.b1 _ Add[coeffs.c0,Div[coeffs.c1,3]]; bezier.b2 _ Add[bezier.b1,Div[Add[coeffs.c1,coeffs.c2],3]]; bezier.b3 _ Add[Add[Add[coeffs.c0,coeffs.c1],coeffs.c2],coeffs.c3]; RETURN[bezier]; }; BezierToCoeffs: PUBLIC PROC[bezier: Bezier] RETURNS[coeffs: Coeffs] = { <> <> <> <> <> t: Pair _ Mul[Sub[bezier.b2,bezier.b1],3]; coeffs.c0 _ bezier.b0; coeffs.c1 _ Mul[Sub[bezier.b1,bezier.b0],3]; coeffs.c2 _ Sub[t,coeffs.c1]; coeffs.c3 _ Sub[bezier.b3,Add[bezier.b0,t]]; RETURN[coeffs]; }; Split: PUBLIC PROC[bezier: Bezier] RETURNS[Bezier,Bezier] = { a,b,c,ab,bc,p: Pair; a _ Mid[bezier.b0,bezier.b1]; b _ Mid[bezier.b1,bezier.b2]; c _ Mid[bezier.b2,bezier.b3]; ab _ Mid[a,b]; bc _ Mid[b,c]; p _ Mid[ab,bc]; RETURN[[bezier.b0, a, ab, p],[p, bc, c, bezier.b3]]; }; Flat: PUBLIC PROC[bezier: Bezier, epsilon: REAL] RETURNS[BOOLEAN] = { dx,dy: REAL; d1,d2,d,bl,bh: Pair; oh: Pair=[0.5,0.5]; bh _ Add[Max[bezier.b0,bezier.b3],oh]; bl _ Sub[Min[bezier.b0,bezier.b3],oh]; IF ~In[bezier.b1,bl,bh] OR ~In[bezier.b2,bl,bh] THEN RETURN[FALSE]; d1 _ Sub[bezier.b1,bezier.b0]; d2 _ Sub[bezier.b2,bezier.b0]; d _ Sub[bezier.b3,bezier.b0]; dx _ ABS[d.x]; dy _ ABS[d.y]; IF dx+dy < 1 THEN RETURN[TRUE]; IF dy < dx THEN { dydx: REAL _ d.y/d.x; RETURN[ABS[d2.y-d2.x*dydx]