All Manuals > CLIM 2.0 User Guide > 3 The CLIM Drawing Environment

3.5 The Transformations Used by CLIM

The type of transformations that CLIM uses are called affine transformations. An affine transformation is a transformation 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 fall on a straight line in the new coordinate system. Affine transformations include translations, scalings, rotations, and reflections.

A translation is a transformation that preserves the length, angle, and orientation of all geometric entities.

A rotation is a transformation that preserves the length and angles of all geometric entities. Rotations also preserve one point and the distance of all entities from that point. You can think of that point as the "center of rotation"; it is the point around which everything rotates.

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.

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".

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 same transformation can often be constructed by a different composition of different 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 this creates a new region, but it does not affect the region argument.

The user interface to transformations is the :transformation option to the drawing functions. Users can create transformations with constructors. See 3.5.1 CLIM Transformation Constructors. The other operators documented in this section are used by CLIM itself, and are not often needed by users.

3.5.1 CLIM Transformation Constructors

The following functions create transformation objects that can be used, for instance, in a call to compose-transformations. The transformation constructors do not capture any of their inputs. The constructors all create objects that are subclasses of transformation.

make-translation-transformation Function

make-translation-transformation translation-x translation-y

Summary: A translation is a transformation that preserves the 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-transformation Function

make-rotation-transformation angle &optional origin

make-rotation-transformation* Function

make-rotation-transformation* angle &optional origin-x origin-y

Summary: A rotation is a transformation that preserves the 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.

make-scaling-transformation Function

make-scaling-transformation scale-x scale-y &optional origin

make-scaling-transformation* Function

make-scaling-transformation* scale-x scale-y &optional origin-x origin-y

Summary: As discussed previously, there is no single definition of a scaling transformation. 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.

make-reflection-transformation Function

make-reflection-transformation point1 point2

make-reflection-transformation* Function

make-reflection-transformation* x1 y1 x2 y2

Summary: 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-transformation Function

make-transformation a b c d u v

Summary: Returns a general transformation whose effect is:

x' = ax+by+u
y' = cx+dy+v

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-transformation Function

make-3-point-transformation point-1 point-2 point-3 point-1-image point-2-image point-3-image

Summary: 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 signaled. 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* Function

make-3-point-transformation* x1 y1 x2 y2 x3 y3 x1-image y1-image x2-image y2-image x3-image y3-image

Summary: 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 signaled. 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.

3.5.2 CLIM Transformation Protocol

transformation Protocol Class

Summary: The protocol class of all transformations. There are one or more subclasses of transformation that implement transformations, the exact names of which are 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 obey the transformation protocol.

All of the instantiable transformation classes provided by CLIM are immutable.

transformationp Function

transformationp object

Summary: Returns t if object is a transformation; otherwise, it returns nil.

+identity-transformation+ Constant

Summary: An instance of a transformation that is guaranteed to be an identity transformation, that is, the transformation that "does nothing".

transformation-error Condition Class

Summary: The class that is the superclass of the following three conditions. This class is a subclass of error.

transformation-underspecified Condition Class

Summary: The error that is signaled when make-3-point-transformation is given three collinear image points.

reflection-underspecified Condition Class

Summary: The error that is signaled when make-reflection-transformation is given two coincident points.

singular-transformation Condition Class

Summary: The error that is signaled when invert-transformation is called on a singular transformation, that is, a transformation that has no inverse.

3.5.3 CLIM Transformation Predicates

The following predicates are provided in order to be able to determine whether or not a transformation has a particular characteristic.

transformation-equal Generic Function

transformation-equal transformation1 transformation2

Summary: Returns t if the two transformations have equivalent effects (that is, are mathematically equal); otherwise, it returns nil.

identity-transformation-p Generic Function

identity-transformation-p transformation

Summary: Returns t if transformation is equal (in the sense of transformation-equal) to the identity transformation; otherwise, it returns nil.

translation-transformation-p Generic Function

translation-transformation-p transformation

Summary: Returns t if transformation is a pure translation, that is, a transformation that moves every point by the same distance in x and the same distance in y. Otherwise, it returns nil.

invertible-transformation-p Generic Function

invertible-transformation-p transformation

Summary: Returns t if transformation has an inverse; otherwise, it returns nil.

reflection-transformation-p Generic Function

reflection-transformation-p transformation

Summary: Returns t if transformation inverts the "handedness" of the coordinate system; otherwise, it returns nil. 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-p Generic Function

rigid-transformation-p transformation

Summary: Returns t if transformation transforms the coordinate system as a rigid object, that is, as a combination of translations, rotations, and pure reflections. Otherwise, it returns nil.

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

even-scaling-transformation-p Generic Function

even-scaling-transformation-p transformation

Summary: Returns t if transformation multiplies all x-lengths and y-lengths by the same magnitude; otherwise, it returns nil. This includes pure reflections through vertical and horizontal lines.

scaling-transformation-p Generic Function

scaling-transformation-p transformation

Summary: Returns t if transformation multiplies all x-lengths by one magnitude and all y-lengths by another magnitude; otherwise, it returns nil. This category includes even scalings as a subset.

rectilinear-transformation-p Generic Function

rectilinear-transformation-p transformation

Summary: Returns t if transformation will always transform any axis-aligned rectangle into another axis-aligned rectangle; otherwise, it returns nil. 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.

3.5.4 CLIM Transformation Functions

compose-transformations Generic Function

compose-transformations transformation1 transformation2

Summary: 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-transformation Generic Function

invert-transformation transformation

Summary: 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 signals the singular-transformation error for all of these cases.

compose-translation-with-transformation Function

compose-translation-with-transformation transformation dx dy

compose-scaling-with-transformation Function

compose-scaling-with-transformation transformation sx sy &optional origin

compose-rotation-with-transformation Function

compose-rotation-with-transformation transformation angle &optional origin

Summary: 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. They are provided because it is common to build up a transformation as a series of simple transformations.

compose-transformation-with-translation Function

compose-transformation-with-translation transformation dx dy

compose-transformation-with-scaling Function

compose-transformation-with-scaling transformation sx sy &optional origin

compose-transformation-with-rotation Function

compose-transformation-with-rotation transformation angle &optional origin

Summary: 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 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.

The following three functions are no different than using with-drawing-options with the :transformation keyword argument supplied. However, they are sufficiently useful that they are provided as a convenience to programmers.

In order to preserve referential transparency, these three forms apply the translation, rotation, or scaling transformation first, then the rest of the transformation from (medium-transformation medium). That is, the following two forms would return the same transformation (assuming that the medium's transformation in the second example is the identity transformation):

(compose-transformations
 (make-translation-transformation dx dy) 
 (make-rotation-transformation angle)) 
 
(with-translation (medium dx dy) 
  (with-rotation (medium angle)
    (medium-transformation medium))) 

with-translation Macro

with-translation (medium dx dy) &body body

Summary: Establishes a translation on the medium medium that translates by dx in the x direction and dy in the y direction, and then executes body with that transformation in effect.

dx and dy are as for make-translation-transformation.

The medium argument is not evaluated, and must be a symbol that is bound to a sheet or medium. If medium is t, *standard-output* is used. body may have zero or more declarations as its first forms.

with-scaling Macro

with-scaling (medium sx &optional sy origin) &body body

Summary: Establishes a scaling transformation on the medium medium that scales by sx in the x direction and sy in the y direction, and then executes body with that transformation in effect. If sy is not supplied, it defaults to sx. If origin is supplied, the scaling is about that point; if it is not supplied, it defaults to (0, 0).

sx and sy are as for make-scaling-transformation.

The medium argument is not evaluated, and must be a symbol that is bound to a sheet or medium. If medium is t, *standard-output* is used. body may have zero or more declarations as its first forms.

with-rotation Macro

with-rotation (medium angle &optional origin) &body body

Summary: Establishes a rotation on the medium medium that rotates by angle, and then executes body with that transformation in effect. If origin is supplied, the rotation is about that point; if it is not supplied, it defaults to (0, 0).

angle and origin are as for make-rotation-transformation.

The medium argument is not evaluated, and must be a symbol that is bound to a sheet or medium. If medium is t, *standard-output* is used. body may have zero or more declarations as its first forms.

These two functions also compose a transformation into the current transformation of a stream, but have more complex behavior.

with-local-coordinates Macro

with-local-coordinates (medium &optional x y) &body body

Summary: Binds the dynamic environment to establish a local coordinate system on the medium medium with the origin of the new coordinate system at the position (x, y). The "directionality" of the coordinate system is otherwise unchanged. x and y are real numbers, and both default to 0.

The medium argument is not evaluated, and must be a symbol that is bound to a sheet or medium. If medium is t, *standard-output* is used. body may have zero or more declarations as its first forms.

with-first-quadrant-coordinates Macro

with-first-quadrant-coordinates (medium &optional x y) &body body

Summary: Binds the dynamic environment to establish a local coordinate system on the medium medium with the positive x axis extending to the right and the positive y axis extending upward, with the origin of the new coordinate system at the position (x, y). x and y are real numbers, and both default to 0.

The medium argument is not evaluated, and must be a symbol that is bound to a sheet or medium. If medium is t, *standard-output* is used. body may have zero or more declarations as its first forms.

3.5.5 Applying CLIM 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 affect the region argument; it is free to either create a new region or return an existing (cached) region.

These generic functions are implemented for all classes of transformations. Furthermore, all subclasses of region and ink 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.

transform-region Generic Function

transform-region transformation region

Summary: Applies transformation to the region region, and returns the transformed region.

untransform-region Generic Function

untransform-region transformation region

Summary: 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-position Generic Function

transform-position transformation x y

Summary: 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-position Generic Function

untransform-position transformation x y

Summary: 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-distance Generic Function

transform-distance transformation dx dy

Summary: 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-distance Generic Function

untransform-distance transformation dx dy

Summary: 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* Generic Function

transform-rectangle* transformation x1 y1 x2 y2

Summary: Applies the transformation transformation to the rectangle specified by the four coordinate arguments, which are real numbers. The arguments x1, y1, x2, and y2 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 if 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* Generic Function

untransform-rectangle* transformation x1 y1 x2 y2

Summary: 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.


CLIM 2.0 User Guide - 01 Dec 2021 19:38:56