TinyLine 2D Programming Guide

3 Coordinate Spaces and Transformations

What is a coordinate space? All geometric shapes and positions are defined in terms of pairs of coordinates. A coordinate pair is a pair of numbers x and y that locates a point horizontally and vertically within a two-dimensional coordinate space.

Therefore, a coordinate space is defined by the following properties:

    1. The location of the origin (0,0)
    2. The orientation of the X and Y axes (directions of axes)
    3. The lengths of the units along each axis (length of a step along axes)

TinyLine 2D supports three coordinate spaces: character space, user space and device space. Transformations between coordinate spaces are defined by transformation matrices, which can specify any linear mapping of two-dimensional coordinates.

3.1 Device space

Coordinates in device space specify a particular pixel on the TinyBuffer object. In TinyLine 2D device space coordinates are integers. The origin of device space coordinate system is at the upper left corner with the positive direction of the y-axis pointing downward, and the positive direction of the x-axis to the right.

devicespace

3.2 User space

User space is the logical coordinate system being used in application programs. Almost all methods in the TinyLine 2D API are using coordinates in user space. In TinyLine 2D user space coordinates are fixed point numbers.

3.3 Character space

Characters glyphs (TinyGlyph) outlines in the TinyFont class are defined in character space. In TinyLine 2D character space coordinates are EM units.

3.4 Relationships among coordinate spaces

spaces

The transformation from user space to device space is specified by the current matrix of the Tiny2D graphics state.

The transformation from character space to user space is defined by a matrix (cmat) returned by the charToUserTransform method of the Tiny2D class.

3.5 Transformations

In TinyLine 2D all coordinate transformations, including transformations from character, user to device space, are represented by TinyMatrix objects.

The TinyMatrix class represents a 2D affine transformation matrix. By modifying a TinyMatrix, objects can be scaled, rotated, translated, or transformed. TinyMatrix is represented by a transformation matrix written as:

  [ a    b   0 ]
  [ c    d   0 ]
  [ tx   ty  1 ]

Here tx and ty are single fixed point numbers and a,b,c,d are double fixed point numbers.

The transformations could be specified as combinations of those listed below:

  • Translation is equivalent to the TinyMatrix [1 0 0 1 tx ty], where tx and ty are the distances to translate coordinates in X and Y.
  • Scaling is equivalent to the TinyMatrix [sx 0 0 sy 0 0]. One unit in the X and Y directions in the new coordinate system equals sx and sy units in the previous coordinate system.
  • Rotation about the origin is equivalent to the TinyMatrix [cos(a) sin(a) -sin(a) cos(a) 0 0], which has the effect of rotating the coordinate system axes by angle a.
  • A skew transformation along the x-axis is equivalent to the TinyMatrix [1 0 tan(a) 1 0 0], which has the effect of skewing X coordinates by angle a.
  • A skew transformation along the y-axis is equivalent to the TinyMatrix [1 tan(a) 0 1 0 0], which has the effect of skewing Y coordinates by angle a.

If several transformations are applied, the order is important. In general, transformations should be done in the following order: translate, rotate, scale.

Coordinate transformations could be expressed as:

                            [  a    b   0 ]
    [x' y' 1 ] = [x  y  1]  [  c    d   0 ]
                            [  tx   ty  1 ]

By carring out the multiplication:


    x' = ax + cy + tx;

    y' = bx + dy + ty;

The transformations can be combined (multiplied) together to produce a single equivalent transformation of the series of transformations.

Example: Transform.java

transform

View the example as applet (Java-enabled browsers only)

The example demonstrates how the transformations can be combined together. To start, we define the first matrix as a translation to the point (50, 50).

       /* Define the matrix1 as  "translate(50,50)"  */
       /* Translation is the TinyMatrix [1 0 0 1 tx ty],
        * where tx and ty are the distances in x and y. */
       matrix1.translate(50<<Tiny2D.FIX_BITS,50<<Tiny2D.FIX_BITS);

When we draw the red line and text, we set the current transformation matrix to the matrix1:

       /* Overwrites the Tiny2D state */
       tstate.matrix   =  matrix1;
       tstate.fillColor = fillColor;
       tstate.strokeColor = redColor;
       tstate.strokeWidth =(4<<Tiny2D.FIX_BITS);
       /* Draws the path */
       t2d.drawPath(path);

       /* Overwrites the Tiny2D state */
       tstate.fillColor = blackColor;
       tstate.strokeColor = TinyColor.NONE;
       /* Draws the text */
       t2d.drawChars(font,
  	             fontSize,
                     engText,0,engText.length,
                     X,
                     Y,
                     Tiny2D.TEXT_ANCHOR_START);

To draw the green line and text we build the second matrix as combination of a translation the point (50, 50) and a rotation to (-45) degrees:


       /* Define the matrix2 as "translate(50,50) + rotate(-45)" */
       matrix2 = new TinyMatrix(matrix1);
       m = new TinyMatrix();
       /* Rotation is TinyMatrix [cos(a) sin(a) -sin(a) cos(a) 0 0],
        * which has the effect of rotating the coordinate system
        * axes by angle a. */
       m.rotate(-(45<<Tiny2D.FIX_BITS),0,0);
       /* Concatenates the m  to the matrix2.
        * [matrix2] = [m] x [matrix2]
        */
       matrix2.preConcatenate(m);

To complicate the things a little when we want to draw the blue line and text we build the third matrix as combination of a translation the point (50, 50) , a rotation to -45 degrees and a translation to the point (-20, 80).


       /* Define the matrix3 as
        * "translate(50,50) + rotate(-45) + translate(-20,80)"  */
       /* Copy the matrix2 to the matrix3 */
       matrix3 = new TinyMatrix(matrix2);
       m = new TinyMatrix();
       /* Translation is the TinyMatrix [1 0 0 1 tx ty],
        * where tx and ty are the distances in x and y. */
       m.translate(-(20<<Tiny2D.FIX_BITS),80<<Tiny2D.FIX_BITS);
       /* Concatenates the m  to the matrix3.
        * [matrix3] = [m] x [matrix3]
        */
       matrix3.preConcatenate(m);

© 2008 TinyLine. All rights reserved.