<> <> <> DIRECTORY IPBasic USING [], IPImager USING [Imager, Vars], IPImagerOps USING [], IPImagerBasic USING [Pair, Transformation, TransformationRep], IPReal USING [Round], IPState USING [State, StateRep], IPTransform USING [], RealFns USING [CosDeg, SinDeg]; IPTransformImpl: CEDAR PROGRAM IMPORTS IPReal, RealFns EXPORTS IPTransform, IPImagerOps, IPBasic = BEGIN OPEN IPImagerBasic; State: TYPE = IPState.State; StateRep: PUBLIC TYPE = IPState.StateRep; -- export to IPBasic Imager: TYPE = IPImager.Imager; Vars: TYPE = IPImager.Vars; DRound: PUBLIC PROC[p: Pair] RETURNS[Pair] = { RETURN[[IPReal.Round[p.x], IPReal.Round[p.y]]]; }; <> <> <> <> SetCode: PROC[m: Transformation] = { IF m.b=0 AND m.d=0 THEN { SELECT m.a FROM 1 => SELECT m.e FROM 1 => m.code _ 0; -1 => m.code _ 1; ENDCASE; -1 => SELECT m.e FROM 1 => m.code _ 2; -1 => m.code _ 3; ENDCASE; ENDCASE; m.code _ 8; } ELSE IF m.a=0 AND m.e=0 THEN { SELECT m.b FROM 1 => SELECT m.d FROM 1 => m.code _ 0; -1 => m.code _ 1; ENDCASE; -1 => SELECT m.d FROM 1 => m.code _ 2; -1 => m.code _ 3; ENDCASE; ENDCASE; m.code _ 9; } ELSE m.code _ 10; }; NewT: PROC[rep: TransformationRep] RETURNS[Transformation] = INLINE { m: Transformation = NEW[TransformationRep _ rep]; SetCode[m]; RETURN[m] }; CopyTransformation: PUBLIC PROC[m: Transformation] RETURNS[Transformation] = { RETURN[NEW[TransformationRep _ m^]] }; MakeT: PUBLIC PROC[a, b, c, d, e, f: REAL] RETURNS[Transformation] = { RETURN[NewT[[a: a, b: b, c: c, d: d, e: e, f: f]]]; }; Translate: PUBLIC PROC[x, y: REAL] RETURNS[Transformation] = { RETURN[NewT[[a: 1, b: 0, c: x, d: 0, e: 1, f: y]]]; }; Rotate: PUBLIC PROC[a: REAL] RETURNS[Transformation] = { cos, sin: REAL; SELECT a FROM 90 => { cos _ 0; sin _ 1 }; 180 => { cos _ -1; sin _ 0 }; 270, -90 => { cos _ 0; sin _ -1 }; ENDCASE => { cos _ RealFns.CosDeg[a]; sin _ RealFns.SinDeg[a] }; RETURN[NewT[[a: cos, b: -sin, c: 0, d: sin, e: cos, f: 0]]]; }; Scale: PUBLIC PROC[s: REAL] RETURNS[Transformation] = { RETURN[NewT[[a: s, b: 0, c: 0, d: 0, e: s, f: 0]]]; }; Scale2: PUBLIC PROC[sx, sy: REAL] RETURNS[Transformation] = { RETURN[NewT[[a: sx, b: 0, c: 0, d: 0, e: sy, f: 0]]]; }; Concat: PUBLIC PROC[m, n: Transformation] RETURNS[Transformation] = { RETURN[NewT[[ a: m.a*n.a + m.d*n.b, b: m.b*n.a + m.e*n.b, c: m.c*n.a + m.f*n.b + n.c, d: m.a*n.d + m.d*n.e, e: m.b*n.d + m.e*n.e, f: m.c*n.d + m.f*n.e + n.f ]]]; }; Invert: PUBLIC PROC[m: Transformation] RETURNS[Transformation] = { det: REAL = (m.a*m.e - m.b*m.d); -- determinant RETURN[NewT[[ a: (m.e)/det, b: (-m.b)/det, c: (m.b*m.f-m.c*m.e)/det, d: (-m.d)/det, e: (m.a)/det, f: (m.c*m.d-m.a*m.f)/det ]]]; }; Transform, Tp: PUBLIC PROC[m: Transformation, p: Pair] RETURNS[Pair] = { SELECT m.code FROM 0 => RETURN[[m.c+p.x, m.f+p.y]]; 1 => RETURN[[m.c-p.x, m.f+p.y]]; 2 => RETURN[[m.c+p.x, m.f-p.y]]; 3 => RETURN[[m.c-p.x, m.f-p.y]]; 4 => RETURN[[m.c+p.y, m.f+p.x]]; 5 => RETURN[[m.c-p.y, m.f+p.x]]; 6 => RETURN[[m.c+p.y, m.f-p.x]]; 7 => RETURN[[m.c-p.y, m.f-p.x]]; 8 => RETURN[[m.c+p.x*m.a, m.f+p.y*m.e]]; 9 => RETURN[[m.c+p.y*m.b, m.f+p.x*m.d]]; ENDCASE => RETURN[[m.c+p.x*m.a+p.y*m.b, m.f+p.x*m.d+p.y*m.e]]; }; TransformVec, Tv: PUBLIC PROC[m: Transformation, v: Pair] RETURNS[Pair] = { SELECT m.code FROM 0 => RETURN[[v.x, v.y]]; 1 => RETURN[[-v.x, v.y]]; 2 => RETURN[[v.x, -v.y]]; 3 => RETURN[[-v.x, -v.y]]; 4 => RETURN[[v.y, v.x]]; 5 => RETURN[[-v.y, v.x]]; 6 => RETURN[[v.y, -v.x]]; 7 => RETURN[[-v.y, -v.x]]; 8 => RETURN[[v.x*m.a, v.y*m.e]]; 9 => RETURN[[v.y*m.b, v.x*m.d]]; ENDCASE => RETURN[[v.x*m.a+v.y*m.b, v.x*m.d+v.y*m.e]]; }; InverseTransform, ITp: PUBLIC PROC[m: Transformation, p: Pair] RETURNS[Pair] = { SELECT m.code FROM 0 => RETURN[[p.x-m.c, p.y-m.f]]; 1 => RETURN[[m.c-p.x, p.y-m.f]]; 2 => RETURN[[p.x-m.c, m.f-p.y]]; 3 => RETURN[[m.c-p.x, m.f-p.y]]; 4 => RETURN[[p.y-m.c, p.x-m.f]]; 5 => RETURN[[m.c-p.y, p.x-m.f]]; 6 => RETURN[[p.y-m.c, m.f-p.x]]; 7 => RETURN[[m.c-p.y, m.f-p.x]]; 8 => RETURN[[(p.x-m.c)/m.a, (p.y-m.f)/m.e]]; 9 => RETURN[[(p.y-m.f)/m.b, (p.x-m.c)/m.d]]; ENDCASE => { x: REAL = p.x-m.c; y: REAL = p.y-m.f; D: REAL = (m.a*m.e - m.b*m.d); RETURN[[(x*m.e-y*m.b)/D, (y*m.a-x*m.d)/D]] }; }; InverseTransformVec, ITv: PUBLIC PROC[m: Transformation, v: Pair] RETURNS[Pair] = { SELECT m.code FROM 0 => RETURN[[v.x, v.y]]; 1 => RETURN[[-v.x, v.y]]; 2 => RETURN[[v.x, -v.y]]; 3 => RETURN[[-v.x, -v.y]]; 4 => RETURN[[v.y, v.x]]; 5 => RETURN[[-v.y, v.x]]; 6 => RETURN[[v.y, -v.x]]; 7 => RETURN[[-v.y, -v.x]]; 8 => RETURN[[v.x/m.a, v.y/m.e]]; 9 => RETURN[[v.y/m.b, v.x/m.d]]; ENDCASE => { D: REAL = (m.a*m.e - m.b*m.d); RETURN[[(v.x*m.e-v.y*m.b)/D, (v.y*m.a-v.x*m.d)/D]] }; }; RoundXY: PUBLIC PROC[m: Transformation, p: Pair] RETURNS[Pair] = { q: Pair = Tp[m, p]; r: Pair = DRound[q]; RETURN[ITp[m, r]]; }; RoundXYVec: PUBLIC PROC[m: Transformation, v: Pair] RETURNS[Pair] = { w: Pair = Tv[m, v]; r: Pair = DRound[w]; RETURN[ITv[m, r]]; }; ConcatT: PUBLIC PROC[self: State, m: Transformation] = { imager: Imager = self.imager; vars: Vars = imager.vars; T: Transformation = vars.T; new: TransformationRep = [ a: m.a*T.a + m.d*T.b, b: m.b*T.a + m.e*T.b, c: m.c*T.a + m.f*T.b + T.c, d: m.a*T.d + m.d*T.e, e: m.b*T.d + m.e*T.e, f: m.c*T.d + m.f*T.e + T.f ]; vars.T^ _ new; SetCode[vars.T]; IF m.code#0 THEN { imager.font _ NIL; vars.fontList _ NIL }; }; Move: PUBLIC PROC[self: State] = { imager: Imager = self.imager; vars: Vars = imager.vars; T: Transformation = vars.T; T.c _ vars.p.cpx; T.f _ vars.p.cpy; }; Trans: PUBLIC PROC[self: State] = { imager: Imager = self.imager; vars: Vars = imager.vars; T: Transformation = vars.T; p: Pair = DRound[[vars.p.cpx, vars.p.cpy]]; T.c _ p.x; T.f _ p.y; }; END.