Graphics Environment: 5.2 Coordinate Space: Coordinate Transformations

Up: GEOS SDK TechDocs| Up | Prev: 5.1 Standard Coordinate Space | Next: 5.3 Precise Coordinates

GEOS provides routines which "transform" the coordinate space. These commands can shift, magnify, or rotate the coordinate grid, or perform several of these changes at once. These transformations affect structures in the GState, and new transformations can be combined with or replace a GState's current transformation.

These transformations apply to the coordinate space, not to individual objects. As a result, if you apply a 200% scaling factor to a drawing not centered on the origin, not only will its size change, but its position will change as well. If you want these operations to affect an object but not its position, you should translate the coordinates so that the origin is at the desired center of scaling or rotation, apply the scaling or rotation, draw the object at the translated origin, then change the coordinates back.

Since they are stored in the GState, these transformations endure--they do not go away after you've drawn your next object. If you apply a 90 degree rotation, you will continue drawing rotated to 90 degrees until you either rotate to some other angle or use another Graphics State. Transformations are also cumulative. If you rotate your space 30°, then translate it up an inch, the result will be a rotated, translated coordinate space. If you want to nullify your last transformation, apply the opposite transformation.

When applying a new transformation to a space which has already been transformed, the old transformations will affect the new one. Be careful, therefore, of the order of your transformations when combining a translation with any other kind of transformation. If you make your transformations in the wrong order, you may not get what you expected.

Simple Transformations

GrApplyRotation(), GrApplyScale(), GrApplyTranslation(), GrSetDefaultTransform(), GrSetNullTransform(), GrInitDefaultTransform(), GrSaveTransform(), GrRestoreTransform()

If you find yourself using transformations at all, they will probably all be rotations, scalings, and translations. The GEOS graphics system includes commands to apply these kinds of transformations to your coordinate system, taking the form GrApplyTransformation() . These commands work with a transformation data structure associated with the Graphics State, so everything drawn in that Graphics State will be suitably transformed.

GrApplyRotation() rotates the coordinate space, turning it counterclockwise around the origin. All objects drawn after the rotation will appear as if someone had turned their drawing surface to a new angle. With a 90° rotation, a shape centered at (1, 1) would draw as if centered at (1, -1). Anything drawn centered at the origin would not change position but would be drawn with the new orientation.

GrApplyScale() resizes the coordinate space; this is useful for zooming in and out. After applying a scale to double the size of everything in the x and y directions, everything will be drawn twice as big, centered twice as far away from the origin. Applying a negative scale causes objects to be drawn with the scale suggested by the magnitude of the scaling factor but "flipped over" to the other side of the coordinate axes.

GrApplyTranslation() causes the coordinate system to be shifted over. After a translation, everything will be drawn at a new position, with no change in orientation or size.

To undo the effects of a transformation, you can apply the opposite transformation: rotate the other way, translate in the opposite direction, or scale with the inverse factor.

To undo the effects of all prior transformations, return to the default transformation matrix using the GrSetDefaultTransform() command. The routine GrSetNullTransform() sets the Graphics State transformation to the null transform--nullifying not only your transformations, but any the system may have imposed as well. For the most part, you should avoid using the GrSetNullTransform() command and use the GrSetDefaultTransform() instead. You can change the default transformation matrix using GrInitDefaultTransform() , but this is generally a bad idea since the windowing system works with the default transformation, and if a geode begins making capricious changes, this can produce strange images.

There are "push" and "pop" operations for transformations. To keep a record of the GState's current transformation, call GrSaveTransform() . To restore the saved transformation, call GrRestoreTransform() .

Complicated Transformations

GrApplyTransform(), GrSetTransform(), GrGetTransform(), GrTransformByMatrix(), GrUntransformByMatrix()

You may want to make some change to the coordinate system that has no simple correspondence to scaling, rotation, or translation. Perhaps you know some linear algebra and want to use your knowledge to combine several transformation functions into a single transformation (thus improving execution speed). All transformations on the coordinate system are expressed in the form of transformation matrices. A GEOS graphics system transformation consists of a matrix containing 6 variables and 3 constants (see figure, below). The six variables allow for standard coordinate transformations. The constants (0, 0, and 1 respectively) allow these transformation matrices to be composed. For example, multiplying a scaling matrix with a rotation matrix creates a matrix which represents a combined scaling and rotation. The six variable matrix elements are stored in a TransMatrix structure.

The GEOS system uses one matrix to store the Graphics State transformation and one to store the Window transformation. When told to apply a new transformation, the graphics system constructs a matrix to represent the requested transformation change and multiplies this matrix by the old transformation matrix. To combine these matrices, GEOS multiplies them together to get the cross-product

If you know that there's a particular combination of transformations you're going to be using a lot, you can do some math in advance to compute your own transformation matrix, then apply the raw matrix as a transformation using GrApplyTransform() . To replace the GState's current transformation matrix with the matrix of your choice, use GrSetTransform() . To find out the current transformation, call GrGetTransform() .

You could combine these steps to pre-compute a transformation that combined a translation and a scaling:

  1. Call GrApplyTranslation() to apply a translation to the GState's coordinate space.
  2. Call GrApplyScale() to apply the scale factor to the GState's coordinate space. The space is now both translated and scaled.
  3. Call GrGetTransform() to get the current GState transformation (stored in a TransMatrix structure).
  4. To apply this transformation to another GState, use the GrApplyTransform() command.

GrTransformByMatrix() returns the results of transforming a passed coordinate pair using an arbitrary transformation matrix. GrUntransformByMatrix() performs the reverse operation, returning the coordinates which would have transformed to the passed coordinates.

Sometimes you have to be careful about the order in which these transformations are supposed to occur. When multiplying transformation matrices together, the transformation that is applied later is the first in the multiplication pair. You can combine any number of rotations and scalings together without having to worry about order: the resulting matrices will be the same. When combining a translation with any other kind of operation, it makes a difference what order you make the transformations and thus makes a difference based on what order you multiply the matrices.


Up: GEOS SDK TechDocs| Up | Prev: 5.1 Standard Coordinate Space | Next: 5.3 Precise Coordinates