DIRECTORY CharacterizeCubic, Cubic2 USING [Bezier], Imager USING [VEC], ImagerTransformation USING [Transformation, Create, ApplyPreTranslate]; CharacterizeCubicImpl: CEDAR PROGRAM IMPORTS ImagerTransformation EXPORTS CharacterizeCubic ~ BEGIN Bezier: TYPE ~ Cubic2.Bezier; VEC: TYPE ~ Imager.VEC; Type: TYPE ~ CharacterizeCubic.Type; GetType: PUBLIC PROC [bezier: Bezier] RETURNS [Type] = { pt: VEC ¬ GetCanonicalPoint[bezier ! Colinear => GOTO degenerate]; RETURN[GetTypeFromMapped[pt]]; EXITS degenerate => RETURN[degenerate]; }; GetTypeFromMapped: PUBLIC PROC [pt: VEC] RETURNS [Type] = { cuspVal, loopVal: REAL; IF pt.y > 1 OR (pt.y =1 AND pt.x > 1) THEN RETURN[singleInflection]; IF pt.x>1 OR (pt.x>0 AND pt.y<0) THEN RETURN[vanilla]; cuspVal ¬ pt.x*pt.x+4*pt.y-2*pt.x-3; IF cuspVal=0 THEN RETURN[cusp]; IF cuspVal > 0 THEN RETURN[doubleInflection]; loopVal ¬ IF pt.y > 0 THEN (pt.x*pt.x+pt.y*pt.y+pt.x*pt.y-3*pt.x) ELSE (pt.x*pt.x-3*pt.x+3*pt.y); IF loopVal >= 0 THEN RETURN[loop] ELSE RETURN[vanilla]; }; GetCanonicalPoint: PUBLIC PROC [bezier: Bezier] RETURNS [pt: VEC] ~ { tryAgain: BOOLEAN ¬ FALSE; a,b,d,e: REAL; t: VEC; FastSixPoints: PROC[from0,from1, from2, to0, to1, to2: VEC] RETURNS[a,b,d,e: REAL, t: VEC] = { dp0, dp1, dp2, dp3: VEC; del: REAL; dp0.x ¬ from1.x-from0.x; dp0.y ¬ from1.y-from0.y; dp1.x ¬ from2.x-from0.x; dp1.y ¬ from2.y-from0.y; dp2.x ¬ to1.x-to0.x; dp2.y ¬ to1.y-to0.y; dp3.x ¬ to2.x-to0.x; dp3.y ¬ to2.y-to0.y; del ¬ dp0.x*dp1.y-dp1.x*dp0.y; IF del=0 THEN SIGNAL Colinear; a ¬ (dp2.x*dp1.y-dp3.x*dp0.y)/del; b ¬ (dp0.x*dp3.x-dp1.x*dp2.x)/del; d ¬ (dp2.y*dp1.y-dp3.y*dp0.y)/del; e ¬ (dp0.x*dp3.y-dp1.x*dp2.y)/del; t.x¬ to0.x-from0.x; t.y¬ to0.y-from0.y; }; pt ¬ bezier.b3; [a,b,d,e,t] ¬ FastSixPoints[bezier.b0, bezier.b1, bezier.b2, [0,0],[0,1],[1,1] ! Colinear => {tryAgain ¬ TRUE; CONTINUE}]; IF tryAgain THEN { [a,b,d,e,t] ¬ FastSixPoints[bezier.b3, bezier.b2, bezier.b1, [0,0],[0,1],[1,1]]; pt ¬ bezier.b0; }; pt ¬ [pt.x+t.x, pt.y+t.y]; pt ¬ [pt.x*a + pt.y*b, pt.x*d + pt.y*e]; }; Colinear: PUBLIC SIGNAL = CODE; SixPoints: PUBLIC PROC[from0,from1, from2, to0, to1, to2: VEC] RETURNS[transform: ImagerTransformation.Transformation] = { dp0, dp1, dp2, dp3: VEC; a,b,d,e: REAL; del: REAL; xform: ImagerTransformation.Transformation; dp0.x ¬ from1.x-from0.x; dp0.y ¬ from1.y-from0.y; dp1.x ¬ from2.x-from0.x; dp1.y ¬ from2.y-from0.y; dp2.x ¬ to1.x-to0.x; dp2.y ¬ to1.y-to0.y; dp3.x ¬ to2.x-to0.x; dp3.y ¬ to2.y-to0.y; del ¬ dp0.x*dp1.y-dp1.x*dp0.y; IF del=0 THEN SIGNAL Colinear; a ¬ (dp2.x*dp1.y-dp3.x*dp0.y)/del; b ¬ (dp0.x*dp3.x-dp1.x*dp2.x)/del; d ¬ (dp2.y*dp1.y-dp3.y*dp0.y)/del; e ¬ (dp0.x*dp3.y-dp1.x*dp2.y)/del; xform ¬ ImagerTransformation.Create[a: a, b: b, c: to0.x, d: d, e: e, f: to0.y]; ImagerTransformation.ApplyPreTranslate[xform, [x: -from0.x, y: -from0.y]]; RETURN[xform]; }; END. Ξ CharacterizeCubicImpl.mesa Copyright Σ 1987, 1992 by Xerox Corporation. All rights reserved. Maureen Stone, January 18, 1988 5:28:54 pm PST Package for analyzing the characteristics of cubic segments Determines the type of Bezier curve Cull the vanilla region. We now know that y <= 1 We now know x <=1, y <=1 Now choose between the loop and the last vanilla case. We now know that x <1, y < 1 Transform such that three points are on a unit square Κ·•NewlineDelimiter –(cedarcode) style™code•Mark outsideHeaderšœ™Kšœ Οeœ7™BKšœ.™.K™K™;K™—šΟk ˜ Kšœ˜Kšœžœ ˜Kšœžœžœ˜Kšœžœ-˜G—K˜KšΠblœžœž˜$Kšžœ˜Kšžœ˜šœž˜K˜Kšœžœ˜Kšžœžœ žœ˜Kšœžœžœ˜$K˜šΟnœž œžœ ˜8Kšœžœ*žœ ˜BKšžœ˜Kšžœžœ ˜'K˜K˜—š œž œžœžœ ˜;K™#Kšœžœ˜Kš žœ žœ žœ žœžœ˜EK™1Kš žœžœ žœ žœžœ ˜6K™K˜$Kšžœ žœžœ˜Kšžœ žœžœ˜-K™T˜ Kšžœ žœ'˜7Kšžœ˜—Kš žœžœžœžœžœ ˜7K˜—K˜š ΠbnΟb œž œžœžœ˜EK™5Kšœ žœžœ˜Kšœ žœ˜Kšœžœ˜š   œžœ$žœžœ žœžœ˜^Kšœžœ˜Kšœžœ˜ K˜K˜K˜K˜K˜K˜K˜K˜K˜K˜Kšžœžœžœ ˜K˜"K˜"K˜"K˜"K˜K˜K˜K˜—K˜Kšœižœžœ˜zšžœ žœ˜K˜PK˜K˜—K˜K˜(K˜—K˜Kš œž œžœ˜K˜š  œž œ$žœžœ4˜zKšœžœ˜Kšœ žœ˜Kšœžœ˜ Kšœ+˜+K˜K˜K˜K˜K˜K˜K˜K˜K˜K˜Kšžœžœžœ ˜K˜"K˜"K˜"K˜"K˜PKšœJ˜JKšžœ˜K˜K˜—K™—K˜Kšžœ˜—…— "§