IITransformation.mesa
Copyright Ó 1985, 1986 by Xerox Corporation. All rights reserved.
Frank Crow, July 31, 1983 3:28 pm
Michael Plass, December 10, 1986 4:05:13 pm PST
Doug Wyatt, March 26, 1985 3:37:51 pm PST
DIRECTORY
IIBox USING [Rectangle],
SF USING [Box],
Vector2 USING [VEC];
IITransformation: CEDAR DEFINITIONS
~ BEGIN
Creating transformations
VEC: TYPE ~ Vector2.VEC;
Transformation: TYPE ~ REF TransformationRep;
TransformationRep: TYPE ~ RECORD [
a, b, c, d, e, f: REAL,
tx, ty: INTEGER ← 0,
integerTrans: BOOLFALSE, -- (tx=c AND ty=f)
form: NAT ← 0 -- identifies special forms of [a, b, d, e]
];
A two-dimensional affine transformation. Represents the 3 by 3 matrix:
 a d 0
 b e 0
 c f 1
The values of a, b, c, d, e, f are always correct. Other fields are performance accelerators.
Create: PROC [a, b, c, d, e, f: REAL] RETURNS [Transformation];
Creates a new transformation:
 a d 0
 b e 0
 c f 1
Destroy: PROC [m: Transformation];
Asserts the Transformation is available for re-use
Copy: PROC [m: Transformation] RETURNS [Transformation];
Returns a copy of m.
Scale: PROC [s: REAL] RETURNS [Transformation];
Creates a transformation which scales by s:
 s 0 0
 0 s 0
 0 0 1
Scale2: PROC [s: VEC] RETURNS [Transformation];
Creates a transformation which scales x by s.x, y by s.y:
 s.x 0 0
 0 s.y 0
 0 0 1
Rotate: PROC [r: REAL] RETURNS [Transformation];
Creates a transformation which rotates counterclockwise by r degrees:
 cos(r) sin(r) 0
 -sin(r) cos(r) 0
 0 0 1
Translate: PROC [t: VEC] RETURNS [Transformation];
Creates a transformation which translates by t.x, t.y:
 1 0 0
 0 1 0
 t.x t.y 1
Direction: TYPE ~ {left, right, up, down};
ScanMode: TYPE ~ RECORD [slow, fast: Direction];
SFToXY: PROC [scanMode: ScanMode, sSize, fSize: INT] RETURNS [Transformation];
The result transforms [s, f] to [x, y], given the source (e.g., pixel array) scan mode.
XYToSF: PROC [scanMode: ScanMode, sSize, fSize: INT] RETURNS [Transformation];
The result transforms [x, y] to [s, f], given the destination (e.g., display) scan mode.
Combining transformations
Concat: PROC [m, n: Transformation] RETURNS [Transformation];
Returns the matrix product mn:
 m.a*n.a+m.d*n.b m.a*n.d+m.d*n.e 0
 m.b*n.a+m.e*n.b m.b*n.d+m.e*n.e 0
 m.c*n.a+m.f*n.b+n.c m.c*n.d+m.f*n.e+n.f 1
Cat: PROC [m1, m2, m3, m4: Transformation ← NIL] RETURNS [Transformation];
Concatenates up to four transformations.
PreScale: PROC [m: Transformation, s: REAL] RETURNS [Transformation];
Equivalent to Concat[Scale[s], m].
PreScale2: PROC [m: Transformation, s: VEC] RETURNS [Transformation];
Equivalent to Concat[Scale2[s], m].
PreRotate: PROC [m: Transformation, r: REAL] RETURNS [Transformation];
Equivalent to Concat[Rotate[r], m].
PreTranslate: PROC [m: Transformation, t: VEC] RETURNS [Transformation];
Equivalent to Concat[Translate[t], m].
PostScale: PROC [m: Transformation, s: REAL] RETURNS [Transformation];
Equivalent to Concat[m, Scale[s]].
PostScale2: PROC [m: Transformation, s: VEC] RETURNS [Transformation];
Equivalent to Concat[m, Scale2[s]].
PostRotate: PROC [m: Transformation, r: REAL] RETURNS [Transformation];
Equivalent to Concat[m, Rotate[r]].
PostTranslate: PROC [m: Transformation, t: VEC] RETURNS [Transformation];
Equivalent to Concat[m, Translate[t]].
TranslateTo: PROC [m: Transformation, t: VEC] RETURNS [Transformation];
Returns m with origin moved to t:
 m.a m.d 0
 m.b m.e 0
 t.x t.y 1
Modifying transformations
These operations change the value of an existing Transformation.
Do not apply these to any Transformation that might be shared!
ApplyPreConcat: PROC [m, p: Transformation];
Equivalent to m^ ← Concat[p, m]. Note the order of p and m!
ApplyPreScale: PROC [m: Transformation, s: REAL];
Equivalent to m^ ← Concat[Scale[s], m].
ApplyPreScale2: PROC [m: Transformation, s: VEC];
Equivalent to m^ ← Concat[Scale2[s], m].
ApplyPreRotate: PROC [m: Transformation, r: REAL];
Equivalent to m^ ← Concat[Rotate[r], m].
ApplyPreTranslate: PROC [m: Transformation, t: VEC];
Equivalent to m^ ← Concat[Translate[t], m].
ApplySFToXY: PROC [m: Transformation, scanMode: ScanMode, sSize, fSize: INT];
Equivalent to m^ ← Concat[SFToXY[scanMode, sSize, fSize], m].
ApplyPostConcat: PROC [m, p: Transformation];
Equivalent to m^ ← Concat[m, p].
ApplyPostScale: PROC [m: Transformation, s: REAL];
Equivalent to m^ ← Concat[m, Scale[s]].
ApplyPostScale2: PROC [m: Transformation, s: VEC];
Equivalent to m^ ← Concat[m, Scale2[s]].
ApplyPostRotate: PROC [m: Transformation, r: REAL];
Equivalent to m^ ← Concat[m, Rotate[r]].
ApplyPostTranslate: PROC [m: Transformation, t: VEC];
Equivalent to m^ ← Concat[m, Translate[t]].
ApplyXYToSF: PROC [m: Transformation, scanMode: ScanMode, sSize, fSize: INT];
Equivalent to m^ ← Concat[m, XYToSF[scanMode, sSize, fSize]].
ApplyTranslateTo: PROC [m: Transformation, t: VEC];
Equivalent to m^ ← TranslateTo[m, t].
ApplyCat: PROC [m: Transformation, m1, m2, m3, m4: Transformation ← NIL];
Equivalent to m^ ← Cat[m1, m2, m3, m4]; the initial content of m is ignored.
ApplyInvert: PROC [m: Transformation];
Equivalent to m^ ← Invert[m].
Applying transformations
Transform: PROC [m: Transformation, v: VEC] RETURNS [VEC];
"Point" transformation: [m.a*v.x + m.b*v.y + m.c, m.d*v.x + m.e*v.y + m.f].
TransformVec: PROC [m: Transformation, v: VEC] RETURNS [VEC];
"Vector" transformation: [m.a*v.x + m.b*v.y, m.d*v.x + m.e*v.y].
InverseTransform: PROC [m: Transformation, v: VEC] RETURNS [VEC];
Equivalent to Transform[Invert[m], v].
InverseTransformVec: PROC [m: Transformation, v: VEC] RETURNS [VEC];
Equivalent to TransformVec[Invert[m], v].
DRound: PROC [v: VEC] RETURNS [VEC];
Rounds both components of v to integers.
RoundXY: PROC [m: Transformation, v: VEC] RETURNS [VEC];
Equivalent to InverseTransform[m, DRound[Transform[m, v]]].
RoundXYVec: PROC [m: Transformation, v: VEC] RETURNS [VEC];
Equivalent to InverseTransformVec[m, DRound[TransformVec[m, v]]].
Rectangles
TransformRectangle: PROC [m: Transformation, r: IIBox.Rectangle] RETURNS [IIBox.Rectangle];
Returns the smallest rectangle enclosing the transformed vertices of r.
InverseTransformRectangle: PROC [m: Transformation, r: IIBox.Rectangle] RETURNS [IIBox.Rectangle];
Returns the smallest rectangle enclosing the inverse-transformed vertices of r.
Easy Transformations
Easy transformations map each source pixel exactly onto one destination pixel, and vice-versa. Most operations in this interface already have faster special cases for such transformations; for an easy transformation, it makes sense to transform integer rectangles onto integer rectangles. For the purposes of these calls, s~x, f~y.
EasyTransformation: PROC [m: Transformation] RETURNS [BOOL] ~ INLINE { RETURN[m.form>=3 AND m.integerTrans] };
EasyTransformBox: PROC [m: Transformation, x, y, w, h: INTEGER, clip: SF.Box] RETURNS [SF.Box];
ERROR if NOT EasyTransformation[m].
Other operations
FactoredTransformation: TYPE ~ RECORD[r1: REAL, s: VEC, r2: REAL, t: VEC];
Represents Cat[Rotate[r1], Scale2[s], Rotate[r2], Translate[t]].
Factor: PROC [m: Transformation] RETURNS [f: FactoredTransformation];
Returns f such that m=Cat[Rotate[f.r1], Scale2[f.s], Rotate[f.r2], Translate[f.t]].
Invert: PROC [m: Transformation] RETURNS [Transformation];
Returns the inverse of m.
Singular: PROC [m: Transformation] RETURNS [BOOL];
Returns TRUE if m may not reasonably be inverted.
Equal: PROC [s, t: Transformation] RETURNS [BOOL];
Returns (s.a=t.a AND s.b=t.b AND s.c=t.c AND s.d=t.d AND s.e=t.e AND s.f=t.f).
CloseEnough: PROC [s, t: Transformation, range: REAL ← 2000.0] RETURNS [BOOL];
Returns TRUE if for all points p such that Transform[s, p] is in [0, 0, range, range], Transform[s, p] and Transform[t, p] differ by at most 1/4 in x and y.
CloseToTranslation: PROC [s, t: Transformation, range: REAL ← 2000.0] RETURNS [BOOL];
Returns TRUE if for all points p such that TransformVec[s, p] is in [0, 0, range, range], TransformVec[s, p] and TransformVec[t, p] differ by at most 1/4 in x and y.
SingularValues: PROC [m: Transformation] RETURNS [VEC];
Returns the singular values of the non-translation portion of m. These are the square roots of the eigenvalues of the symmetric matrix MMT, where M is the non-translation portion. The x component is the larger of the two. These correspond to the maximum and minimum magnitudes that the image of a unit vector can achieve. May raise:
NumericalInstability: SIGNAL [real: REAL];
END.