DIRECTORY ImagerBox USING [Rectangle], SF USING [Box], Vector2 USING [VEC]; ImagerTransformation: CEDAR DEFINITIONS ~ BEGIN OPEN Vector2; Transformation: TYPE ~ REF TransformationRep; TransformationRep: TYPE ~ RECORD [ a, b, c, d, e, f: REAL, tx, ty: INTEGER ¬ 0, integerTrans: BOOL ¬ FALSE, -- (tx=c AND ty=f) form: NAT ¬ 0 -- identifies special forms of [a, b, d, e] ]; Create: PROC [a, b, c, d, e, f: REAL] RETURNS [Transformation]; Destroy: PROC [m: Transformation]; Copy: PROC [m: Transformation] RETURNS [Transformation]; Scale: PROC [s: REAL] RETURNS [Transformation]; Scale2: PROC [s: VEC] RETURNS [Transformation]; Rotate: PROC [r: REAL] RETURNS [Transformation]; Translate: PROC [t: VEC] RETURNS [Transformation]; Direction: TYPE ~ {left, right, up, down}; ScanMode: TYPE ~ MACHINE DEPENDENT RECORD [slow, fast: Direction]; SFToXY: PROC [scanMode: ScanMode, sSize, fSize: INT] RETURNS [Transformation]; XYToSF: PROC [scanMode: ScanMode, sSize, fSize: INT] RETURNS [Transformation]; Concat: PROC [m, n: Transformation] RETURNS [Transformation]; Cat: PROC [m1, m2, m3, m4: Transformation ¬ NIL] RETURNS [Transformation]; PreScale: PROC [m: Transformation, s: REAL] RETURNS [Transformation]; PreScale2: PROC [m: Transformation, s: VEC] RETURNS [Transformation]; PreRotate: PROC [m: Transformation, r: REAL] RETURNS [Transformation]; PreTranslate: PROC [m: Transformation, t: VEC] RETURNS [Transformation]; PostScale: PROC [m: Transformation, s: REAL] RETURNS [Transformation]; PostScale2: PROC [m: Transformation, s: VEC] RETURNS [Transformation]; PostRotate: PROC [m: Transformation, r: REAL] RETURNS [Transformation]; PostTranslate: PROC [m: Transformation, t: VEC] RETURNS [Transformation]; TranslateTo: PROC [m: Transformation, t: VEC] RETURNS [Transformation]; ApplyPreConcat: PROC [m, p: Transformation]; ApplyPreScale: PROC [m: Transformation, s: REAL]; ApplyPreScale2: PROC [m: Transformation, s: VEC]; ApplyPreRotate: PROC [m: Transformation, r: REAL]; ApplyPreTranslate: PROC [m: Transformation, t: VEC]; ApplySFToXY: PROC [m: Transformation, scanMode: ScanMode, sSize, fSize: INT]; ApplyPostConcat: PROC [m, p: Transformation]; ApplyPostScale: PROC [m: Transformation, s: REAL]; ApplyPostScale2: PROC [m: Transformation, s: VEC]; ApplyPostRotate: PROC [m: Transformation, r: REAL]; ApplyPostTranslate: PROC [m: Transformation, t: VEC]; ApplyXYToSF: PROC [m: Transformation, scanMode: ScanMode, sSize, fSize: INT]; ApplyTranslateTo: PROC [m: Transformation, t: VEC]; ApplyCat: PROC [m: Transformation, m1, m2, m3, m4: Transformation ¬ NIL]; ApplyInvert: PROC [m: Transformation]; Transform: PROC [m: Transformation, v: VEC] RETURNS [VEC]; TransformVec: PROC [m: Transformation, v: VEC] RETURNS [VEC]; InverseTransform: PROC [m: Transformation, v: VEC] RETURNS [VEC]; InverseTransformVec: PROC [m: Transformation, v: VEC] RETURNS [VEC]; DRound: PROC [v: VEC] RETURNS [VEC]; RoundXY: PROC [m: Transformation, v: VEC] RETURNS [VEC]; RoundXYVec: PROC [m: Transformation, v: VEC] RETURNS [VEC]; TransformRectangle: PROC [m: Transformation, r: ImagerBox.Rectangle] RETURNS [ImagerBox.Rectangle]; InverseTransformRectangle: PROC [m: Transformation, r: ImagerBox.Rectangle] RETURNS [ImagerBox.Rectangle]; EasyTransformation: PROC [m: Transformation] RETURNS [BOOL]; EasyTransformBox: PROC [m: Transformation, x, y, w, h: INTEGER, clip: SF.Box] RETURNS [SF.Box]; FactoredTransformation: TYPE ~ RECORD[r1: REAL, s: VEC, r2: REAL, t: VEC]; Factor: PROC [m: Transformation] RETURNS [f: FactoredTransformation]; Invert: PROC [m: Transformation] RETURNS [Transformation]; Singular: PROC [m: Transformation] RETURNS [BOOL]; Equal: PROC [s, t: Transformation] RETURNS [BOOL]; CloseEnough: PROC [s, t: Transformation, range: REAL ¬ 2000.0] RETURNS [BOOL]; CloseToTranslation: PROC [s, t: Transformation, range: REAL ¬ 2000.0] RETURNS [BOOL]; SingularValues: PROC [m: Transformation] RETURNS [VEC]; NumericalInstability: SIGNAL [real: REAL]; CISDeg: PROC [degrees: REAL] RETURNS [VEC]; END. θ ImagerTransformation.mesa Copyright Σ 1985, 1986, 1991 by Xerox Corporation. All rights reserved. Frank Crow, July 31, 1983 3:28 pm Michael Plass, August 17, 1991 0:20 am PDT Doug Wyatt, March 26, 1985 3:37:51 pm PST Creating transformations A two-dimensional affine transformation, using an homogeneous coordinate system. 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. Points are represented by the row matrix [ x y 1 ] and this gets multiplied on the left by a transformation matrix to yield the transformed row vector [ ax+by+c dx+ey+f 1 ]. When SF vectors are mixed with transformations, we use the correspondence s~x and f~y (this may initially be counterintuitive for people accustomed to frame buffers). Creates a new transformation: || a d 0 || || b e 0 || || c f 1 || Asserts the Transformation is available for re-use Returns a copy of m. Creates a transformation which scales by s: || s 0 0 || || 0 s 0 || || 0 0 1 || Creates a transformation which scales x by s.x, y by s.y: || s.x 0 0 || || 0 s.y 0 || || 0 0 1 || Creates a transformation which rotates counterclockwise by r degrees: || cos r sin r 0 || || -sin r cos r 0 || || 0 0 1 || Creates a transformation which translates by t.x, t.y: || 1 0 0 || || 0 1 0 || || t.x t.y 1 || The result transforms [s, f] to [x, y], given the source (e.g., pixel array) scan mode. The result transforms [x, y] to [s, f], given the destination (e.g., display) scan mode. Combining transformations 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 Concatenates up to four transformations. Equivalent to Concat[Scale[s], m]. Equivalent to Concat[Scale2[s], m]. Equivalent to Concat[Rotate[r], m]. Equivalent to Concat[Translate[t], m]. Equivalent to Concat[m, Scale[s]]. Equivalent to Concat[m, Scale2[s]]. Equivalent to Concat[m, Rotate[r]]. Equivalent to Concat[m, Translate[t]]. 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! Equivalent to m^ _ Concat[p, m]. Note the order of p and m! Equivalent to m^ _ Concat[Scale[s], m]. Equivalent to m^ _ Concat[Scale2[s], m]. Equivalent to m^ _ Concat[Rotate[r], m]. Equivalent to m^ _ Concat[Translate[t], m]. Equivalent to m^ _ Concat[SFToXY[scanMode, sSize, fSize], m]. Equivalent to m^ _ Concat[m, p]. Equivalent to m^ _ Concat[m, Scale[s]]. Equivalent to m^ _ Concat[m, Scale2[s]]. Equivalent to m^ _ Concat[m, Rotate[r]]. Equivalent to m^ _ Concat[m, Translate[t]]. Equivalent to m^ _ Concat[m, XYToSF[scanMode, sSize, fSize]]. Equivalent to m^ _ TranslateTo[m, t]. Equivalent to m^ _ Cat[m1, m2, m3, m4]; the initial content of m is ignored. Equivalent to m^ _ Invert[m]. Applying transformations "Point" transformation: [m.a*v.x + m.b*v.y + m.c, m.d*v.x + m.e*v.y + m.f]. "Vector" transformation: [m.a*v.x + m.b*v.y, m.d*v.x + m.e*v.y]. Equivalent to Transform[Invert[m], v]. Equivalent to TransformVec[Invert[m], v]. Rounds both components of v to integers. Equivalent to InverseTransform[m, DRound[Transform[m, v]]]. Equivalent to InverseTransformVec[m, DRound[TransformVec[m, v]]]. Rectangles Returns the smallest rectangle enclosing the transformed vertices of r. 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. ERROR if NOT EasyTransformation[m]. Other operations Represents Cat[Rotate[r1], Scale2[s], Rotate[r2], Translate[t]]. Returns f such that m=Cat[Rotate[f.r1], Scale2[f.s], Rotate[f.r2], Translate[f.t]]. Note: SingularValues[m] = [MAX[ |f.s.x|, |f.s.y| ], MIN[ |f.s.x|, |f.s.y| ]] Returns the inverse of m. Returns TRUE if m may not reasonably be inverted. 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). 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. 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. 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: Κ Ί–(cedarcode) style•StyleDefψBeginStyle (cedarcode) AttachStyle (matrix) "for display of a matrix" {standard FontFamily centered lineFormatting centered lastLineFormatting BreakSize 1 sp .add tabStops BreakSize topLeading BreakSize bottomLeading 1 in keep} StyleRule EndStyle•NewlineDelimiter ™codešœ™Kšœ Οeœ=™HKšœ!™!K™*K™)K™—šΟk ˜ Kšœ žœ ˜Kšžœžœ˜Kšœžœžœ˜—K˜KšΠblœžœž ˜'Kšœžœžœ ˜head™Kšœžœžœ˜-šœžœžœ˜"Kšœžœ˜Kšœžœ˜KšœžœžœΟc Πck ˜.Kšœžœ +˜9Kšœ˜K™oImatrixšΠlxœΟiœ£œ’œ£œ£œ’œ£œ£œ’™#Kšœ^™^K™(Mš’œ£œ£œ’™ K™cMš’œ£œ£œ’œ™Kšœ¦™¦K™—K˜šΟnœžœžœžœ˜?K™Mš’œ£œ£œ’œ£œ£œ’œ£œ£œ’™#K™—š€œžœ˜"Jšœ2™2K™—š€œžœžœ˜8K™K™—š€œžœžœžœ˜/K™+Mš ’œ£œ’œ£œ’œ’™#K˜—š€œžœžœžœ˜/K™9Mš ’œ£œ’œ£œ’œ ’™/K™—š€œžœžœžœ˜0K™EMš’œΠbsœ£œ₯œ£œ’œΠpt₯œ£œ₯œ£œ’œ’™FK™—š€ œžœžœžœ˜2K™6Mš ’œ ’œ ’œ£œ£œ’™+K™—Kšœ žœ˜*š œ žœžœž œžœ˜BK˜—š€œžœ$žœžœ˜NKšœW™WK™—š€œžœ$žœžœ˜NKšœX™XK™——™š€œžœžœ˜=K™Kšœ"™"K™"K™*K™—š€œžœ#žœžœ˜JK™(K™—š€œžœžœžœ˜EKšœ"™"K™—š€ œžœžœžœ˜EKšœ#™#K™—š€ œžœžœžœ˜FKšœ#™#K™—š€ œžœžœžœ˜HKšœ&™&K™—š€ œžœžœžœ˜FKšœ"™"K™—š€ œžœžœžœ˜FKšœ#™#K™—š€ œžœžœžœ˜GKšœ#™#K™—š€ œžœžœžœ˜IKšœ&™&K™—š€ œžœžœžœ˜GK™!Mš’œ£œ£œ’œ£œ£œ’œ£œ£œ’™9——™K™@Kšœ>™>K™š€œžœ˜,Kšœ<™