<> <> <> 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] = { << 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.>> 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.