DIRECTORY Basics, IntTransDefs, Real; IntTrans: CEDAR PROGRAM IMPORTS Basics, Real EXPORTS IntTransDefs = BEGIN OPEN IntTransDefs; DividedTransform: TYPE = REF DividedTransformRecord _ NIL; DividedTransformRecord: TYPE = RECORD[ type: [ident..translate+rotscale], a11,a21,a12,a22: REAL, a31,a32: INT]; Context: TYPE = IntTransDefs.Transform; T: DividedTransform = NEW[DividedTransformRecord]; contextStack: ContextStack _ NIL; TH: Transform = NEW[TransformRecord]; --Top of current context, in homogeneous form LH: Transform = NEW[TransformRecord]; inTransforms,needsDivision: BOOLEAN; --state flags Identity: TransformRecord = [ type: ident, a11: 1, a21: 0, a31: 0, a12: 0, a22: 1, a32: 0, a33: 1]; InitTransformation: PUBLIC PROCEDURE RETURNS [BOOLEAN] = BEGIN contextStack _ NIL; TH^ _ Identity; LH^ _ Identity; inTransforms _ TRUE; needsDivision _ TRUE; RETURN[TRUE]; END; FinishTransformation: PUBLIC PROCEDURE RETURNS [BOOLEAN] = BEGIN RETURN[TRUE]; END; FreezeContext: PUBLIC PROCEDURE RETURNS[cs: ContextStack] = BEGIN Push[]; cs _ contextStack; contextStack _ NIL; -- I guess... END; SwapContext: PUBLIC PROCEDURE[cs: ContextStack] = BEGIN contextStack _ cs; Pop[]; END; Push: PUBLIC PROCEDURE = BEGIN IF inTransforms THEN Concatenate[LH,TH,TH]; contextStack _ CONS[NEW[TransformRecord _ TH^], contextStack]; LH^ _ Identity; inTransforms _ TRUE; needsDivision _ TRUE; END; Pop: PUBLIC PROCEDURE = BEGIN IF contextStack = NIL THEN ERROR TransformationStackUnderflow; TH^ _ contextStack.first^; contextStack _ contextStack.rest; inTransforms _ FALSE; needsDivision _ TRUE; END; Rotate: PUBLIC PROCEDURE[xRot,yRot: INT] = BEGIN t: REAL; IF ~inTransforms THEN ERROR TransformationBadContext; BEGIN OPEN LH; SELECT TRUE FROM xRot = 0 => BEGIN t _ -a12; a12 _ a11; a11 _ t; t _ -a22; a22 _ a21; a21 _ t; t _ -a32; a32 _ a31; a31 _ t; IF yRot<0 THEN a33 _ -a33; END; yRot = 0 => IF xRot<0 THEN a33 _ -a33; ENDCASE => BEGIN c: REAL = xRot; s: REAL = yRot; t _ a11*c - a12*s; a12 _ a11*s + a12*c; a11 _ t; t _ a21*c - a22*s; a22 _ a21*s + a22*c; a21 _ t; t _ a31*c - a32*s; a32 _ a31*s + a32*c; a31 _ t; a33 _ a33*Real.SqRt[c*c + s*s]; END; type _ Basics.BITOR[type,rotscale]; END; END; Translate: PUBLIC PROCEDURE[xTrans,yTrans: INT] = BEGIN xT: REAL _ xTrans; yT: REAL _ yTrans; IF ~inTransforms THEN ERROR TransformationBadContext; BEGIN OPEN LH; a31 _ a31 + a33*xT; a32 _ a32 + a33*yT; type _ Basics.BITOR[type,translate]; END; END; Mirror: PUBLIC PROCEDURE[coord: CoordName] = BEGIN IF ~inTransforms THEN ERROR TransformationBadContext; BEGIN OPEN LH; SELECT coord FROM x => BEGIN a11 _ -a11; a21 _ -a21; a31 _ -a31; END; y => BEGIN a12 _ -a12; a22 _ -a22; a32 _ -a32; END; ENDCASE; type _ Basics.BITOR[type,rotscale]; END; END; Scale: PUBLIC PROCEDURE[numerator,denominator: INT] = BEGIN num: REAL _ numerator; denom: REAL _ denominator; IF ~inTransforms THEN ERROR TransformationBadContext; BEGIN OPEN LH; a11 _ a11*num; a21 _ a21*num; a31 _ a31*num; a12 _ a12*num; a22 _ a22*num; a32 _ a32*num; a33 _ a33*denom; type _ Basics.BITOR[type,rotscale]; END; END; GetLocal: PUBLIC PROCEDURE RETURNS[localTransform: TransformRecord] = BEGIN RETURN[LH^]; END; local: Transform _ NEW[TransformRecord]; ApplyLocal: PUBLIC PROCEDURE[transform: TransformRecord] = BEGIN IF ~inTransforms THEN ERROR TransformationBadContext; local^ _ transform; Concatenate[LH,local,LH]; END; GetCurrent: PUBLIC PROCEDURE RETURNS[currentTransform: TransformRecord] = BEGIN IF inTransforms THEN BEGIN Concatenate[LH,TH,TH]; inTransforms _ FALSE; END; RETURN[TH^]; END; TransformPoint: PUBLIC PROCEDURE[x,y: INT] RETURNS[xT,yT: INT] = BEGIN SELECT TRUE FROM inTransforms => BEGIN Concatenate[LH,TH,TH]; inTransforms _ FALSE; DivideTransform[TH,T]; needsDivision _ FALSE; END; needsDivision => BEGIN DivideTransform[TH,T]; needsDivision _ FALSE; END; ENDCASE; BEGIN OPEN T; SELECT type FROM ident => BEGIN xT _ x; yT _ y; END; translate => BEGIN xT _ x + a31; yT _ y + a32; END; rotscale => BEGIN X: REAL = x; Y: REAL = y; xT _ Real.Round[X*a11 + Y*a21]; yT _ Real.Round[X*a12 + Y*a22]; END; ENDCASE => BEGIN X: REAL = x; Y: REAL = y; xT _ a31 + Real.Round[X*a11 + Y*a21]; yT _ a32 + Real.Round[X*a12 + Y*a22]; END; END; END; TransformVector: PUBLIC PROCEDURE[x,y: INT] RETURNS[xT,yT: INT] = BEGIN SELECT TRUE FROM inTransforms => BEGIN Concatenate[LH,TH,TH]; inTransforms _ FALSE; DivideTransform[TH,T]; needsDivision _ FALSE; END; needsDivision => BEGIN DivideTransform[TH,T]; needsDivision _ FALSE; END; ENDCASE; BEGIN OPEN T; SELECT type FROM ident, translate => BEGIN xT _ x; yT _ y; END; ENDCASE => BEGIN X: REAL = x; Y: REAL = y; xT _ Real.Round[X*a11 + Y*a21]; yT _ Real.Round[X*a12 + Y*a22]; END; END; END; RTransformPoint: PUBLIC PROCEDURE[x,y: REAL] RETURNS[xT,yT: REAL] = BEGIN IF inTransforms THEN BEGIN Concatenate[LH,TH,TH]; inTransforms _ FALSE; END; BEGIN OPEN TH; SELECT type FROM ident => BEGIN xT _ x; yT _ y; END; translate => BEGIN xT _ x + a31; yT _ y + a32; END; rotscale => BEGIN xT _ (x*a11 + y*a21)/a33; yT _ (x*a12 + y*a22)/a33; END; ENDCASE => BEGIN xT _ (a31 + x*a11 + y*a21)/a33; yT _ (a32 + x*a12 + y*a22)/a33; END; END; END; RTransformVector: PUBLIC PROCEDURE[x,y: REAL] RETURNS[xT,yT: REAL] = BEGIN IF inTransforms THEN BEGIN Concatenate[LH,TH,TH]; inTransforms _ FALSE; END; BEGIN OPEN TH; SELECT type FROM ident, translate => BEGIN xT _ x; yT _ y; END; ENDCASE => BEGIN xT _ (x*a11 + y*a21)/a33; yT _ (x*a12 + y*a22)/a33; END; END; END; Concatenate: PROCEDURE [A,B,C: Transform] = BEGIN SELECT TRUE FROM A.type=ident => IF C#B THEN C^ _ B^; --(not uncommon for ApplyLocal) B.type=ident => IF C#A THEN C^ _ A^; ENDCASE => BEGIN T: TransformRecord; T.a11 _ A.a11*B.a11 + A.a12*B.a21; T.a21 _ A.a21*B.a11 + A.a22*B.a21; T.a31 _ A.a31*B.a11 + A.a32*B.a21 + A.a33*B.a31; T.a12 _ A.a11*B.a12 + A.a12*B.a22; T.a22 _ A.a21*B.a12 + A.a22*B.a22; T.a32 _ A.a31*B.a12 + A.a32*B.a22 + A.a33*B.a32; T.a33 _ A.a33*B.a33; T.type _ Basics.BITOR[A.type,B.type]; C^ _ T; END; END; DivideTransform: PROCEDURE[AH: Transform, A: DividedTransform] = BEGIN IF AH.a33=1 THEN BEGIN A.a11 _ AH.a11; A.a21 _ AH.a21; A.a31 _ Real.Round[AH.a31]; A.a12 _ AH.a12; A.a22 _ AH.a22; A.a32 _ Real.Round[AH.a32]; END ELSE BEGIN ah33: REAL = AH.a33; A.a11 _ AH.a11/ah33; A.a21 _ AH.a21/ah33; A.a31 _ Real.Round[AH.a31/ah33]; A.a12 _ AH.a12/ah33; A.a22 _ AH.a22/ah33; A.a32 _ Real.Round[AH.a32/ah33]; END; A.type _ AH.type; END; TransformationStackUnderflow: PUBLIC ERROR = CODE; TransformationBadContext: PUBLIC ERROR = CODE; END. θFile: IntTrans.mesa Written by Martin Newell, July 1979 Converted to Mesa 6: October 20, 1980 4:34 PM last edited June 10, 1981 4:27 PM Last Edited by: McCreight, January 30, 1985 3:18:29 pm PST Bertrand Serlet May 21, 1987 4:19:25 pm PDT Transformations are held in homogeneous form, in REALs. The current transformation is held locally in two forms - homogeneous (ground truth) and a divided form for application to a set of input vectors. The transformation stack is a doubly-linked list of homogeneous arrays. Define a DividedTransform for internal use in transformaing points and vectors: The current transformation divided (T[3,3]=1) The local transformation Initialize (or re-initialize) Transformation package Create new context based on existing context state Push current transformation - start a new relative coordinate system Pop current transformation - return to previous coordinate system Rotate x axis to direction of (xRot,yRot) Translate by (xTrans,yTrans) Mirror coordinates Scale by numerator/denominator Return incremental transformation built since last Push Apply transformation to current local transformation Return current cummulative transformation Transform the point (x,y) by current cumulative transformation Transform the direction (x,y) by current cumulative transformation Transform the point (x,y) by current cumulative transformation - in REALs Transform the direction (x,y) by current cumulative transformation - in REALs A*B => C, A=C or B=C is OK AH/AH(3,3) => A Κλ˜Jšœ™Jšœ#™#Jšœ.™.Jšœ"™"šœ:™:Icode™+—J˜J˜JšœV™VJšœM™MJšœS™SJšœ™J˜J˜šΟk ˜ Jšœ˜J˜—šœ  ˜Jšœ ˜Jšœ˜Jš˜Jšœ˜J˜JšœO™OJšœœœœ˜:šœœœ˜&J˜"Jšœœ˜Jšœ œ˜J˜—Jšœ œ˜'J˜Jšœœ˜2˜Jšœ-™-—Jšœœ˜!JšœœΟc-˜Sšœœ˜%Jšœ™—Jšœœž ˜2˜J˜ J˜J˜Jšœ˜J˜—J˜Jš Οnœœ œœœ˜8šœ4™4Jš˜Jšœœ˜Jšœ ˜Jšœ ˜Jšœœ˜Jšœœ˜Jšœœ˜ Jšœ˜J˜—š Ÿœœ œœœ˜:Jš˜Jšœœ˜ Jšœ˜J˜—JšŸ œœ œœ˜;šœ2™2Jš˜Jšœ˜Jšœ˜Jšœœž ˜!Jšœ˜J˜—šŸ œœ œ˜1Jš˜Jšœ˜Jšœ˜Jšœ˜J˜—JšŸœœ œ˜šœD™DJš˜Jš œœ œœœ˜+Jšœœœœ˜>Jšœ ˜Jšœœ˜Jšœœ˜Jšœ˜J˜—JšŸœœ œ˜šœA™AJš˜Jšœœœœ˜>Jšœ˜Jšœ!˜!Jšœœ˜Jšœœ˜Jšœ˜J˜—JšŸœœ œ œ˜*šœ)™)Jš˜Jšœœ˜Jšœœœ˜5šœœœ˜Jšœœ˜šœ ˜J˜J˜J˜Jšœœ ˜Jšœ˜—Jšœ œœ ˜&šœ˜Jšœœ œ˜J˜0J˜0J˜0J˜Jšœ˜—Jšœœ˜#—Jšœ˜Jšœ˜J˜—JšŸ œœ œœ˜1šœ™Jš˜Jšœœ ˜Jšœœ ˜Jšœœœ˜5šœœœ˜J˜J˜Jšœœ˜$—Jšœ˜Jšœ˜J˜—JšŸœœ œ˜,šœ™Jš˜Jšœœœ˜5šœœœ˜Jšœ˜šœ˜ J˜ J˜ J˜ Jšœ˜—šœ˜ J˜ J˜ J˜ Jšœ˜—Jšœ˜Jšœœ˜#—Jšœ˜Jšœ˜J˜—JšŸœœ œœ˜5šœ™Jš˜Jšœœ ˜Jšœœ˜Jšœœœ˜5šœœœ˜J˜J˜J˜J˜J˜J˜J˜Jšœœ˜#—Jšœ˜Jšœ˜J˜—JšŸœœ œœ#˜Ešœ7™7Jš˜Jšœœ˜ Jšœ˜J˜—Jšœœ˜(J˜JšŸ œœ œ˜:šœ4™4Jš˜Jšœœœ˜5Jšœ˜Jšœ œœ˜Jšœ˜J˜—JšŸ œœ œœ%˜Išœ)™)Jš˜šœ ˜Jš˜Jšœ œœ˜Jšœœ˜Jšœ˜—Jšœœ˜ Jšœ˜J˜—Jš Ÿœœ œœœœ˜@šœ>™>Jš˜Jšœœ˜šœ˜Jšœ œœœ˜Jšœœ˜Jšœœœ˜Jšœœ˜Jšœ˜—šœ˜Jšœœœ˜Jšœœ˜Jšœ˜—Jšœ˜šœœœ˜ Jšœ˜šœ ˜J˜J˜Jšœ˜—šœ ˜J˜ J˜ Jšœ˜—šœ ˜Jšœœ˜ Jšœœ˜ Jšœœœ˜Jšœœœ˜Jšœ˜—šœ˜Jšœœ˜ Jšœœ˜ Jšœœœ˜%Jšœœœ˜%Jšœ˜——Jšœ˜Jšœ˜J˜—Jš Ÿœœ œœœœ˜AšœB™BJš˜Jšœœ˜šœ˜Jšœ œœœ˜Jšœœ˜Jšœœœ˜Jšœœ˜Jšœ˜—šœ˜Jšœœœ˜Jšœœ˜Jšœ˜—Jšœ˜šœœœ˜ Jšœ˜˜Jš˜J˜J˜Jšœ˜—šœ˜Jšœœ˜ Jšœœ˜ Jšœœœ˜Jšœœœ˜Jšœ˜——Jšœ˜Jšœ˜J˜—Jš Ÿœœ œœœœ˜CšœI™IJš˜Jšœ ˜šœ˜ Jšœ œœœ˜Jšœœ˜Jšœ˜—šœœœ˜Jšœ˜šœ ˜J˜J˜Jšœ˜—šœ ˜J˜ J˜ Jšœ˜—šœ ˜J˜J˜Jšœ˜—šœ˜J˜J˜Jšœ˜——Jšœ˜Jšœ˜J˜—Jš Ÿœœ œœœœ˜DšœM™MJš˜Jšœ ˜šœ˜ Jšœ œœœ˜Jšœœ˜Jšœ˜—šœœœ˜Jšœ˜˜Jš˜J˜J˜Jšœ˜—šœ˜J˜J˜Jšœ˜——Jšœ˜Jšœ˜J˜—JšŸ œ œœœ˜+šœ™Jš˜Jšœœ˜Jšœœœœœœœž˜DJšœœœœœœœ˜$šœ˜ Jš˜Jšœ˜Jš œœœœœ˜"Jš œœœœœ˜"Jšœœœœœœœ˜0Jš œœœœœ˜"Jš œœœœœ˜"Jšœœœœœœœ˜0Jšœœœ˜Jšœœœœ˜%Jšœœ˜Jšœ˜—Jšœ˜J˜—JšŸœ œœ œ˜@šœ™Jš˜Jšœœ˜ šœ˜ Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jš˜—šœ˜ Jšœœœ˜Jšœœ ˜Jšœœ ˜Jšœœ ˜ Jšœœ ˜Jšœœ ˜Jšœœ ˜ Jšœ˜—Jšœœ˜Jšœ˜J˜J˜—Jšœœœœ˜2Jšœœœœ˜.J˜Jšœ˜—J˜—…—Ž.a