IPTransformImpl.mesa
Last edited by:
Doug Wyatt, July 7, 1983 11:51 am
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]]];
};
A Transformation represents the following matrix:
a d 0
b e 0
c f 1
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.