Bounding Rectangles Contents Index Overview of Window Facilities




5 Affine Transformations

An affine transformation is a mapping from one coordinate system onto another that preserves straight lines. In other words, if you take a number of points that fall on a straight line and apply an affine transformation to their coordinates, the transformed coordinates will describe a straight line in the new coordinate system. General affine transformations include all the sorts of transformations that CLIM uses, namely, translations, scaling, rotations, and reflections.

5.1 Transformations

transformation[Protocol Class]
The protocol class of all transformations. There are one or more subclasses of transformation with implementation-dependent names that implement transformations. The exact names of these classes is explicitly unspecified. If you want to create a new class that behaves like a transformation, it should be a subclass of transformation. Subclasses of transformation must obey the transformation protocol.All of the instantiable transformation classes provided by CLIM are immutable.

transformationpobject[Predicate]
Returns true if object is a transformation , otherwise returns false .

+identity-transformation+[Constant]
An instance of a transformation that is guaranteed to be an identity transformation, that is, the transformation that ``does nothing''.

5.1.1 Transformation Conditions

transformation-error[Error]
The class that is the superclass of the following three conditions. This class is a subclass of error .

transformation-underspecified[Error]
The error that is signalled when make-3-point-transformation is given three collinear image points. This condition will handle the :points initarg, which is used to supply the points that are in error.

reflection-underspecified[Error]
The error that is signalled when make-reflection-transformation is given two coincident points. This condition will handle the :points initarg, which is used to supply the points that are in error.

singular-transformation[Error]
The error that is signalled when invert-transformation is called on a singular transformation, that is, a transformation that has no inverse. This condition will handle the :transformation initarg, which is used to supply the transformation that is singular.

5.2 Transformation Constructors

The following transformation constructors do not capture any of their inputs. The constructors all create objects that are subclasses of transformation .

make-translation-transformationtranslation-x translation-y[Function]
A translation is a transformation that preserves length, angle, and orientation of all geometric entities.

make-translation-transformation returns a transformation that translates all points by translation-x in the x direction and translation-y in the y direction. translation-x and translation-y must be real numbers.

make-rotation-transformationangle &optional origin[Function]
make-rotation-transformation*angle &optional origin-x origin-y[Function]
A rotation is a transformation that preserves length and angles of all geometric entities. Rotations also preserve one point (the origin) and the distance of all entities from that point.

make-rotation-transformation returns a transformation that rotates all points by angle (which is a real number indicating an angle in radians) around the point origin . If origin is supplied it must be a point; if not supplied it defaults to (0,0). origin-x and origin-y must be real numbers, and default to 0.

make-scaling-transformationscale-x scale-y &optional origin[Function]
make-scaling-transformation*scale-x scale-y &optional origin-x origin-y[Function]
There is no single definition of a scaling transformation. Transformations that preserve all angles and multiply all lengths by the same factor (preserving the ``shape'' of all entities) are certainly scaling transformations. However, scaling is also used to refer to transformations that scale distances in the x direction by one amount and distances in the y direction by another amount.

make-scaling-transformation returns a transformation that multiplies the x-coordinate distance of every point from origin by scale-x and the y-coordinate distance of every point from origin by scale-y . scale-x and scale-y must be real numbers. If origin is supplied it must be a point; if not supplied it defaults to (0,0). origin-x and origin-y must be real numbers, and default to 0.

make-reflection-transformationpoint1 point2[Function]
make-reflection-transformation*x1 y1 x2 y2[Function]
A reflection is a transformation that preserves lengths and magnitudes of angles, but changes the sign (or ``handedness'') of angles. If you think of the drawing plane on a transparent sheet of paper, a reflection is a transformation that ``turns the paper over''.

make-reflection-transformation returns a transformation that reflects every point through the line passing through the points point1 and point2 (or through the positions (x1,y1) and (x2,y2) in the case of the spread version).

make-transformationmxx mxy myx myy tx ty[Function]
Returns a general transformation whose effect is:

x' = mxx x + mxy y + tx
y' = myx x + myy y + ty
where x and y are the coordinates of a point before the transformation and x' and y' are the coordinates of the corresponding point after.

All of the arguments to make-transformation must be real numbers.

make-3-point-transformationpoint-1 point-2 point-3 point-1-image point-2-image point-3-image[Function]
Returns a transformation that takes points point-1 into point-1-image , point-2 into point-2-image and point-3 into point-3-image . Three non-collinear points and their images under the transformation are enough to specify any affine transformation.

If point-1 , point-2 and point-3 are collinear, the transformation-underspecified error will be signalled. If point-1-image , point-2-image and point-3-image are collinear, the resulting transformation will be singular (that is, will have no inverse) but this is not an error.

make-3-point-transformation*x1 y1 x2 y2 x3 y3 x1-image y1-image x2-image y2-image x3-image y3-image[Function]
Returns a transformation that takes the points at the positions (x1 ,y1 ) into (x1-image ,y1-image ), (x2 ,y2 ) into (x2-image ,y2-image ) and (x3 ,y3 ) into (x3-image ,y3-image ). Three non-collinear points and their images under the transformation are enough to specify any affine transformation.

If the positions (x1,y1), (x2,y2) and (x3,y3) are collinear, the transformation-underspecified error will be signalled. If (x1-image ,y1-image ), (x2-image ,y2-image ), and (x3-image ,y3-image ) are collinear, the resulting transformation will be singular but this is not an error.

This is the spread version of make-3-point-transformation .

5.3 The Transformation Protocol

The following subsections describe the transformation protocol. All classes that are subclasses of transformation must implement methods for all of the generic functions in the following subsections.

5.3.1 Transformation Predicates

In all of the functions below, the argument named transformation must be a transformation.

transformation-equaltransformation1 transformation2[Generic function]
Returns true if the two transformations transformation1 and transformation2 have equivalent effects (that is, are mathematically equal), otherwise returns false .

Implementations are encouraged to allow transformations that are not numerically equal due to floating-point roundoff errors to be transformation-equal . An appropriate level of ``fuzziness'' is single-float-epsilon , or some small multiple of single-float-epsilon .

identity-transformation-ptransformation[Generic function]
Returns true if the transformation transformation is equal (in the sense of transformation-equal ) to the identity transformation, otherwise returns false .

invertible-transformation-ptransformation[Generic function]
Returns true if the transformation transformation has an inverse, otherwise returns false .

translation-transformation-ptransformation[Generic function]
Returns true if the transformation transformation is a pure translation, that is, a transformation such that there are two distance components dx and dy and every point (x,y) is moved to (x+dx,y+dy). Otherwise, translation-transformation-p returns false .

reflection-transformation-ptransformation[Generic function]
Returns true if the transformation transformation inverts the ``handedness'' of the coordinate system, otherwise returns false . Note that this is a very inclusive category---transformations are considered reflections even if they distort, scale, or skew the coordinate system, as long as they invert the handedness.

rigid-transformation-ptransformation[Generic function]
Returns true if the transformation transformation transforms the coordinate system as a rigid object, that is, as a combination of translations, rotations, and pure reflections. Otherwise, it returns false .

Rigid transformations are the most general category of transformations that preserve magnitudes of all lengths and angles.

even-scaling-transformation-ptransformation[Generic function]
Returns true if the transformation transformation multiplies all x lengths and y lengths by the same magnitude, otherwise returns false . It does include pure reflections through vertical and horizontal lines.

scaling-transformation-ptransformation[Generic function]
Returns true if the transformation transformation multiplies all x lengths by one magnitude and all y lengths by another magnitude, otherwise returns false . This category includes even scalings as a subset.

rectilinear-transformation-ptransformation[Generic function]
Returns true if the transformation transformation will always transform any axis-aligned rectangle into another axis-aligned rectangle, otherwise returns false . This category includes scalings as a subset, and also includes 90 degree rotations.

Rectilinear transformations are the most general category of transformations for which the bounding rectangle of a transformed object can be found by transforming the bounding rectangle of the original object.


Issue: SWM
Supply this figure.
To be supplied.
Figure 5.1: The predicates for analyzing the mathematical properties of a transformation.

5.3.2 Composition of Transformations

If we transform from one coordinate system to another, then from the second to a third coordinate system, we can regard the resulting transformation as a single transformation resulting from composing the two component transformations. It is an important and useful property of affine transformations that they are closed under composition. Note that composition is not commutative; in general, the result of applying transformation A and then applying transformation B is not the same as applying B first, then A.

Any arbitrary transformation can be built up by composing a number of simpler transformations, but that composition is not unique.

compose-transformationstransformation1 transformation2[Generic function]
Returns a transformation that is the mathematical composition of its arguments. Composition is in right-to-left order, that is, the resulting transformation represents the effects of applying the transformation transformation2 followed by the transformation transformation1 .

invert-transformationtransformation[Generic function]
Returns a transformation that is the inverse of the transformation transformation . The result of composing a transformation with its inverse is equal to the identity transformation.

If transformation is singular, invert-transformation will signal the singular-transformation error, with a named restart that is invoked with a transformation and makes invert-transformation return that transformation. This is to allow a drawing application, for example, to use a generalized inverse to transform a region through a singular transformation.

Note that with finite-precision arithmetic there are several low-level conditions that might occur during the attempt to invert a singular or ``almost singular'' transformation. (These include computation of a zero determinant, floating-point underflow during computation of the determinant, or floating-point overflow during subsequent multiplication.) invert-transformation must signal the singular-transformation error for all of these cases.

compose-translation-with-transformationtransformation dx dy[Function]
compose-scaling-with-transformationtransformation sx sy &optional origin[Function]
compose-rotation-with-transformationtransformation angle &optional origin[Function]
These functions create a new transformation by composing the transformation transformation with a given translation, scaling, or rotation, respectively. The order of composition is that the translation, scaling, or rotation ``transformation'' is first, followed by transformation .

dx and dy are as for make-translation-transformation . sx and sy are as for make-scaling-transformation . angle and origin are as for make-rotation-transformation .

Note that these functions could be implemented by using the various constructors and compose-transformations . They are provided, because it is common to build up a transformation as a series of simple transformations.

compose-transformation-with-translationtransformation dx dy[Function]
compose-transformation-with-scalingtransformation sx sy &optional origin[Function]
compose-transformation-with-rotationtransformation angle &optional origin[Function]
These functions create a new transformation by composing a given translation, scaling, or rotation, respectively, with the transformation transformation . The order of composition is transformation is first, followed by the translation, scaling, or rotation ``transformation''.

dx and dy are as for make-translation-transformation . sx and sy are as for make-scaling-transformation . angle and origin are as for make-rotation-transformation .

Note that these functions could be implemented by using the various constructors and compose-transformations . They are provided, because it is common to build up a transformation as a series of simple transformations.

5.3.3 Applying Transformations

Transforming a region applies a coordinate transformation to that region, thus moving its position on the drawing plane, rotating it, or scaling it. Note that transforming a region does not side-effect the region argument; it is free to either create a new region or return an existing (cached) region.

These generic functions must be implemented for all classes of transformations. Furthermore, all subclasses of region and design must implement methods for transform-region and untransform-region . That is, methods for the following generic functions will typically specialize both the transformation and region arguments.

Note that, if the extended region classes are not implemented, the following functions are not closed, that is, they may return results that are not CLIM regions.

transform-regiontransformation region[Generic function]
Applies transformation to the region region , and returns the transformed region.

untransform-regiontransformation region[Generic function]
This is exactly equivalent to
(transform-region (invert-transformation transformation ) region ) .

CLIM provides a default method for untransform-region on the transformation protocol class that does exactly this.

transform-positiontransformation x y[Generic function]
Applies the transformation transformation to the point whose coordinates are the real numbers x and y , and returns two values, the transformed x coordinate and the transformed y coordinate.

transform-position is the spread version of transform-region in the case where the region is a point.

untransform-positiontransformation x y[Generic function]
This is exactly equivalent to
(transform-position (invert-transformation transformation ) x y ) .

CLIM provides a default method for untransform-position on the transformation protocol class that does exactly this.

transform-distancetransformation dx dy[Generic function]
Applies the transformation transformation to the distance represented by the real numbers dx and dy , and returns two values, the transformed dx and the transformed dy .

A distance represents the difference between two points. It does not transform like a point.

untransform-distancetransformation dx dy[Generic function]
This is exactly equivalent to
(transform-distance (invert-transformation transformation ) dx dy ) .

CLIM provides a default method for untransform-distance on the transformation protocol class that does exactly this.

transform-rectangle*transformation x1 y1 x2 y2[Generic function]
Applies the transformation transformation to the rectangle specified by the four coordinate arguments, which are real numbers. The arguments x1 , y1 , x2 , and y1 are canonicalized in the same way as for make-bounding-rectangle . Returns four values that specify the minimum and maximum points of the transformed rectangle in the order min-x , min-y , max-x , and max-y .

It is an error is transformation does not satisfy rectilinear-transformation-p .

transform-rectangle* is the spread version of transform-region in the case where the transformation is rectilinear and the region is a rectangle.

untransform-rectangle*transformation x1 y1 x2 y2[Generic function]
This is exactly equivalent to
(transform-rectangle* (invert-transformation transformation ) x1 y1 x2 y2 ) .

CLIM provides a default method for untransform-rectangle* on the transformation protocol class that does exactly this.



Bounding Rectangles Contents Index Overview of Window Facilities