DIRECTORY SV2d, SVCoordSys2d, SVMatrix2d, SVModelTypes, SVVector2d; SVCoordSys2dImpl: CEDAR PROGRAM IMPORTS SVMatrix2d, SVVector2d EXPORTS SVCoordSys2d = BEGIN Matrix3by3: TYPE = SV2d.Matrix3by3; Point2d: TYPE = SV2d.Point2d; Vector2d: TYPE = SVVector2d.Vector2d; CoordSystem2d: TYPE = REF CoordSystem2dObj; CoordSystem2dObj: TYPE = SVModelTypes.CoordSystem2dObj; TellCoordSysAboutPad: PUBLIC PROC [cs: CoordSystem2d] = { cs.localWRTPad _ FindInTermsOfPad[cs]; cs.padWRTLocal _ SVMatrix2d.Inverse[cs.localWRTPad]; }; CreateCoordSys: PUBLIC PROC [mat: Matrix3by3, withRespectTo: CoordSystem2d] RETURNS [newCS: CoordSystem2d] = { newCS _ NEW[CoordSystem2dObj]; newCS.mat _ mat; newCS.localWRTPad _ SVMatrix2d.Identity[]; newCS.padWRTLocal _ SVMatrix2d.Identity[]; newCS.withRespectTo _ withRespectTo; TellCoordSysAboutPad[newCS]; }; PadToScreen: PUBLIC PROC [padPoint: Point2d, screen: CoordSystem2d] RETURNS [screenPoint: Point2d] = { screenPoint _ SVMatrix2d.Update[screen.localWRTPad, padPoint]; }; ScreenToPad: PUBLIC PROC [screenPoint: Point2d, screen: CoordSystem2d] RETURNS [padPoint: Point2d] = { padPoint _ SVMatrix2d.Update[screen.padWRTLocal, padPoint]; }; FindInTermsOfPad: PUBLIC PROC [cs: CoordSystem2d] RETURNS [mat: Matrix3by3] = { thisCS, nextCS: CoordSystem2d; thisCS _ cs; IF thisCS = NIL THEN RETURN [SVMatrix2d.Identity[]]; mat _ cs.mat; UNTIL thisCS.withRespectTo = NIL DO nextCS _ thisCS.withRespectTo; mat _ SVMatrix2d.MatMult[nextCS.mat, mat]; thisCS _ nextCS; ENDLOOP; }; FindAinTermsOfB: PUBLIC PROC [a: CoordSystem2d, b: CoordSystem2d] RETURNS [aInTermsOfb: Matrix3by3] = { aPad, bPad: Matrix3by3; aPad _ FindInTermsOfPad[a]; IF b = NIL THEN bPad _ SVMatrix2d.Identity[] ELSE bPad _ FindInTermsOfPad[b]; aInTermsOfb _ SVMatrix2d.WorldToLocal[bPad,aPad]; }; FindTranslationOfAinTermsOfB: PUBLIC PROC [a: CoordSystem2d, b: CoordSystem2d] RETURNS [displacements: Vector2d] = { aInTermsOfb: Matrix3by3; IF b = NIL THEN aInTermsOfb _ FindInTermsOfPad[a] ELSE aInTermsOfb _ FindAinTermsOfB[a, b]; displacements _ SVMatrix2d.OriginOfMatrix[aInTermsOfb]; }; PutAinTermsOfB: PUBLIC PROC [a: CoordSystem2d, b: CoordSystem2d] RETURNS [aInTermsOfb: Matrix3by3] = { aPad, bPad: Matrix3by3; aPad _ FindInTermsOfPad[a]; IF b = NIL THEN bPad _ SVMatrix2d.Identity[] ELSE bPad _ FindInTermsOfPad[b]; aInTermsOfb _ SVMatrix2d.WorldToLocal[bPad,aPad]; a.withRespectTo _ b; a.mat _ aInTermsOfb; TellCoordSysAboutPad[a]; }; PlaceAwrtB: PUBLIC PROC [a: CoordSystem2d, b: CoordSystem2d _ NIL, aWRTb: Matrix3by3] = { aPad, bPad, withRespectToPad, aInTermsOfWRT: Matrix3by3; withRespectTo: CoordSystem2d; IF b = NIL THEN bPad _ SVMatrix2d.Identity[] ELSE bPad _ FindInTermsOfPad[b]; aPad _ SVMatrix2d.MatMult[bPad, aWRTb]; withRespectTo _ a.withRespectTo; withRespectToPad _ FindInTermsOfPad[withRespectTo]; aInTermsOfWRT _ SVMatrix2d.WorldToLocal[withRespectToPad, aPad]; a.mat _ aInTermsOfWRT; TellCoordSysAboutPad[a]; }; PlaceTranslationAwrtB: PUBLIC PROC [a: CoordSystem2d, b: CoordSystem2d _ NIL, origin: Point2d] = { aWRTb: Matrix3by3 _ FindAinTermsOfB[a, b]; aPad, bPad, withRespectToPad, aInTermsOfWRT: Matrix3by3; withRespectTo: CoordSystem2d; IF b = NIL THEN bPad _ SVMatrix2d.Identity[] ELSE bPad _ FindInTermsOfPad[b]; aWRTb[1][3] _ origin[1]; aWRTb[2][3] _ origin[2]; aPad _ SVMatrix2d.MatMult[bPad, aWRTb]; withRespectTo _ a.withRespectTo; withRespectToPad _ FindInTermsOfPad[withRespectTo]; aInTermsOfWRT _ SVMatrix2d.WorldToLocal[withRespectToPad, aPad]; a.mat _ aInTermsOfWRT; TellCoordSysAboutPad[a]; }; TranslateAwrtB: PUBLIC PROC [a: CoordSystem2d, b: CoordSystem2d _ NIL, tx, ty: REAL] = { aPad, bPad, aInTermsOfb, newAWorld, withRespectToWorld, aInTermsOfWRT: Matrix3by3; withRespectTo: CoordSystem2d; IF b = NIL THEN bPad _ SVMatrix2d.Identity[] ELSE bPad _ FindInTermsOfPad[b]; aPad _ FindInTermsOfPad[a]; aInTermsOfb _ IF a = b THEN SVMatrix2d.Identity[] ELSE SVMatrix2d.WorldToLocal[bPad, aPad]; aInTermsOfb _ SVMatrix2d.Translate[aInTermsOfb, tx, ty]; -- must be a global translate. newAWorld _ SVMatrix2d.MatMult[bPad, aInTermsOfb]; withRespectTo _ a.withRespectTo; withRespectToWorld _ FindInTermsOfPad[withRespectTo]; aInTermsOfWRT _ SVMatrix2d.WorldToLocal[withRespectToWorld, newAWorld]; a.mat _ aInTermsOfWRT; TellCoordSysAboutPad[a]; }; RotateCCWAwrtB: PUBLIC PROC [a: CoordSystem2d, b: CoordSystem2d _ NIL, degrees: REAL] = { aPad, bPad, aInTermsOfb, newAWorld, withRespectToPad, aInTermsOfWRT: Matrix3by3; withRespectTo: CoordSystem2d; IF b = NIL THEN bPad _ SVMatrix2d.Identity[] ELSE bPad _ FindInTermsOfPad[b]; aPad _ FindInTermsOfPad[a]; aInTermsOfb _ IF a = b THEN SVMatrix2d.Identity[] ELSE SVMatrix2d.WorldToLocal[bPad,aPad]; aInTermsOfb _ SVMatrix2d.RotateCCW[aInTermsOfb, degrees]; -- must be a global translate. newAWorld _ SVMatrix2d.MatMult[bPad, aInTermsOfb]; withRespectTo _ a.withRespectTo; withRespectToPad _ FindInTermsOfPad[withRespectTo]; aInTermsOfWRT _ SVMatrix2d.WorldToLocal[withRespectToPad, newAWorld]; a.mat _ aInTermsOfWRT; TellCoordSysAboutPad[a]; }; IndicesOfMax: PRIVATE PROC [v: Vector2d] RETURNS [indices: ARRAY[1..2] OF NAT, negArray: ARRAY[1..2] OF BOOL] = { temp: REAL; tempIndex: NAT; IF v[1] < 0 THEN {negArray[1] _ TRUE; v[1] _ -v[1]} ELSE negArray[1] _ FALSE; IF v[2] < 0 THEN {negArray[2] _ TRUE; v[2] _ -v[2]} ELSE negArray[2] _ FALSE; indices _ [1,2]; IF v[1] < v[2] THEN { temp _ v[1]; v[1] _ v[2]; v[2] _ temp; tempIndex _ indices[1]; indices[1] _ indices[2]; indices[2] _ tempIndex}; }; AlignAwrtB: PUBLIC PROC [a: CoordSystem2d, b: CoordSystem2d _ NIL] = { aPad, bPad, aInTermsOfb, newAPad, withRespectToPad, aInTermsOfWRT: Matrix3by3; withRespectTo: CoordSystem2d; xAxisChoices: ARRAY[1..2] OF NAT; xAxis, newXAxis, yAxis, newYAxis: Vector2d; xNegArray: ARRAY[1..2] OF BOOL; origin: Point2d; angle: REAL; IF b = NIL THEN bPad _ SVMatrix2d.Identity[] ELSE bPad _ FindInTermsOfPad[b]; aPad _ FindInTermsOfPad[a]; aInTermsOfb _ IF a = b THEN SVMatrix2d.Identity[] ELSE SVMatrix2d.WorldToLocal[bPad,aPad]; xAxis _ SVMatrix2d.XAxisOfMatrix[aInTermsOfb]; yAxis _ SVMatrix2d.YAxisOfMatrix[aInTermsOfb]; origin _ SVMatrix2d.OriginOfMatrix[aInTermsOfb]; angle _ SVVector2d.SmallestAngleBetweenVectors[xAxis, yAxis]; [xAxisChoices, xNegArray] _ IndicesOfMax[xAxis];-- Find largest component newXAxis _ [0,0]; newXAxis[xAxisChoices[1]] _ SVVector2d.Magnitude[xAxis]; IF xNegArray[xAxisChoices[1]] THEN newXAxis[xAxisChoices[1]] _ -newXAxis[xAxisChoices[1]]; newYAxis _ SVVector2d.VectorPlusAngle[newXAxis, angle]; newYAxis _ SVVector2d.Scale[newYAxis, SVVector2d.Magnitude[yAxis]]; aInTermsOfb _ SVMatrix2d.MakeMatFromAxes[newXAxis, newYAxis, origin]; newAPad _ SVMatrix2d.MatMult[bPad, aInTermsOfb]; withRespectTo _ a.withRespectTo; withRespectToPad _ FindInTermsOfPad[withRespectTo]; aInTermsOfWRT _ SVMatrix2d.WorldToLocal[withRespectToPad, newAPad]; a.mat _ aInTermsOfWRT; TellCoordSysAboutPad[a]; }; AbutAwrtB: PUBLIC PROC [a: CoordSystem2d, b: CoordSystem2d _ NIL] = { PlaceTranslationAwrtB[a, b, [0, 0]]; }; END. ,File: SVCoordSys2dImpl.mesa Last edited by Bier on January 28, 1987 2:21:11 pm PST Contents: Routines for manipulating coordinate systems with respect to each other in 2 dimensions. Unlike Coordsystems which are told about WORLD and CAMERA at draw time, CoordSystem2d's are told about Pad every time they are updated. This only makes sense if the updated coordsys has no sons. The general case will be implemented later. Finds the matrix and redefines CoordSystem a to be in terms of b from now on. Places a in PAD so that the transform from b to a is aWRTb. Updates a with respect to its immediate reference (a.withRespectTo) accordingly. Places a in PAD so that the rotation from a to b remains as it is, but the translation is set to origin. Updates a with respect to its immediate reference (a.withRespectTo) accordingly. Bubble sort Rotate A as little as possible to align its two axes parallel to two of the axes of B (though not necessarily the same two). This is the new x axis direction. Preserve angle between x axis and y axis Preserve magnitude of axes Equivalent to PlaceTranslationAwrtB where origin = [0, 0] These perform the named transform but do not change the coordinate system with respect to which CoordSystem a is defined. When b is NIL, assumes b = PAD. For local transforms, let b = a. ΚŒ˜Iheadšœ™Jšœ6™6JšœΤ™ΤJ˜šΟk ˜ Jšœ9˜9—J˜Jšœ ˜Jšœ˜Jšœ˜Jš˜˜Jšœ œ˜#Jšœ œ˜Jšœ œ˜%J˜Jšœœœ˜+Jšœœ!˜7J˜—šΟnœœœ˜9Jšœ&˜&Jšœ4˜4Jšœ˜—J˜šžœœœ1œ˜nJšœœ˜Jšœ˜Jšœ*˜*Jšœ*˜*Jšœ$˜$Jšœ˜Jšœ˜—J˜šž œœœ,œ˜fJšœ>˜>Jšœ˜—šž œœœ/œ˜fJšœ;˜;Jšœ˜—J˜šžœœœœ˜OJšœ˜Jšœ ˜ Jšœ œœœ˜4Jšœ ˜ šœœ˜#Jšœ˜Jšœ*˜*Jšœ˜—Jšœ˜Jšœ˜—šžœœœ&œ˜gJšœ˜Jšœ˜Jšœœœ˜,Jšœ˜ Jšœ1˜1Jšœ˜—šžœœœ&œ˜tJšœ˜Jšœœœ"˜1Jšœ%˜)Jšœ7˜7Jšœ˜—J˜šžœœœ&œ˜fJšœM™MJšœ˜Jšœ˜Jšœœœ˜,Jšœ˜ Jšœ1˜1Jšœ˜Jšœ˜Jšœ˜Jšœ˜—J˜šž œœœ'œ˜YJšœ™Jšœ8˜8Jšœ˜Jšœœœ˜,Jšœ˜ Jšœ'˜'Jšœ ˜ Jšœ3˜3Jšœ@˜@Jšœ˜Jšœ˜Jšœ˜—šžœœœ'œ˜bJšœΊ™ΊJšœ*˜*Jšœ8˜8Jšœ˜Jšœœœ˜,Jšœ˜ Jšœ˜Jšœ˜Jšœ'˜'Jšœ ˜ Jšœ3˜3Jšœ@˜@Jšœ˜Jšœ˜Jšœ˜—J˜J˜š žœœœ'œ œ˜XJšœR˜RJšœ˜Jšœœœ˜,Jšœ˜ Jšœ˜Jšœœœ˜1Jšœ%˜)Jšœ9Οc˜WJšœ2˜2Jšœ ˜ Jšœ5˜5JšœG˜GJšœ˜Jšœ˜Jšœ˜—š žœœœ'œ œ˜YJšœP˜PJšœ˜Jšœœœ˜,Jšœ˜ Jšœ˜Jšœœœ˜1Jšœ$˜(Jšœ:Ÿ˜XJšœ2˜2Jšœ ˜ Jšœ3˜3JšœE˜EJšœ˜Jšœ˜Jšœ˜—J˜šž œœœœ œœœ œœœ˜qJšœ ™ Jšœœ˜ Jšœ œ˜Jšœ œœ˜3Jšœœ˜Jšœ œœ˜3Jšœœ˜Jšœ˜šœ œ˜Jšœ&˜&JšœI˜I—Jšœ˜—J˜šž œœœ'œ˜FJšœ|™|JšœN˜NJšœ˜Jšœœœœ˜!Jšœ+˜+Jšœ œœœ˜Jšœ˜Jšœœ˜ Jšœœœ˜,Jšœ˜ Jšœ˜Jšœœœ˜6Jšœ#˜#J˜Jšœ.˜.Jšœ.˜.Jšœ0˜0Jšœ=˜=šœ0Ÿ˜IJšœ!™!—Jšœ˜Jšœ8˜8Jšœ˜Jšœ8˜<šœ7˜7Jšœ(™(—šœC˜CJšœ™—J˜JšœE˜EJšœ˜Jšœ0˜0Jšœ ˜ Jšœ3˜3JšœC˜CJšœ˜Jšœ˜Jšœ˜—šž œœœ'œ˜Ešœ9™9Jšœ$˜$Jšœ˜—J˜J˜Jšœy™yJšœ™Jšœ ™ J˜—J˜Jšœ˜—…—h(