-- File: SVCoordSys2dImpl.mesa -- Last edited by Bier on December 18, 1982 1:29 am -- Author: Eric Bier on November 22, 1982 9:35 pm -- 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. DIRECTORY SV2d, SVCoordSys2d, SVMatrix2d, SVVector2d; SVCoordSys2dImpl: PROGRAM IMPORTS SVMatrix2d, SVVector2d EXPORTS SVCoordSys2d = BEGIN Matrix3by3: TYPE = SVMatrix2d.Matrix3by3; Point2d: TYPE = SV2d.Point2d; Vector2d: TYPE = SVVector2d.Vector2d; CoordSystem2d: TYPE = REF CoordSystem2dObj; CoordSystem2dObj: TYPE = SVCoordSys2d.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] = { -- finds the matrix and redefines CoordSystem a to be in terms of b from now on. 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] = { -- 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. 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] = { -- bubble sort 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] = { -- 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). 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 -- this is the new x axis direction. 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]; -- preserve angle between x axis and y axis newYAxis _ SVVector2d.Scale[newYAxis, SVVector2d.Magnitude[yAxis]]; -- preserve magnitude of axes 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] = { -- equivalent to PlaceTranslationAwrtB where origin = [0, 0] PlaceTranslationAwrtB[a, b, [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. END. ĘP˜JšĪcĩœ ›˜ŨJš‡œĪk œEžœžœžœžœžœBžœ(žœžœ%žœ$Īnœžœžœ|Ÿœžœžœ1žœ%žœĮŸ œžœžœ,žœbŸ œžœžœ/žœ[Ÿœžœžœžœ‹žœžœžœcžœŸœžœžœ&žœŨŸœžœžœ&žœ:žœžœžœ$žœdŸœžœžœ&žœ Qœ†Ÿ œžœžœ'žœ‘œĨŸœžœžœ'žœžœŸœžœžœ'žœ žœõžœžœžœ`œŸœžœžœ'žœ žœķžœžœžœ`œŠŸ œžœžœžœ žœžœžœ žœžœžœœžœžœžœ žœžœžœžœžœ žœžœžœžœžœ žœ~Ÿ œžœžœ'žœ€œ~žœžœžœ;žœžœžœžžœžœžœ­œ%œNžœžœr,œGœĶŸ œžœžœ'žœ=œ,Äœžœ˜É?—…—!Ē$