Search code examples
graphicsgdi+qgraphicsview

Transformation matrix for viewing a 2D drawing


I am refactoring a graphic program that shows a drawing. The program uses its own transformation and the code is quite complicated. I'd like to refact the code with a transformation matrix instead.

The window and view coordinates are X to the right and Y to downwards.

The drawing in window uses the top left point as base point (0,0). The view is a screen rectangle area with base point (0,0) at the top left point too.

The view area can by any rectangle on the screen. It shows the drawing inside 80%x80% area leaving some margins around.

The drawing has a size of width x height. The program should show the drawing with the same scale ratio at both directions. The center of the drawing is mapping to the center of the view area. the drawing can be rotated in any angle between 0 ~ 360 degrees.

What is the general transformation matrix for this, given the following data:

  1. width and height of the drawing
  2. Rotation angle
  3. width and height of the view area
  4. Margins around the drawings

Solution

  • First you need the width/height of the box containing the rotated image

    x0 = image_width/2 * cos(angle) + image_height/2 * sin(angle)
    x1 = image_width/2 * cos(angle) - image_height/2 * sin(angle)
    y0 = image_width/2 * sin(angle) + image_height/2 * cos(angle)
    y1 = image_width/2 * sin(angle) - image_height/2 * cos(angle)
    rotated_width = max(abs(x0), abs(x1)) * 2
    rotated_height = max(abs(y0), abs(y1)) * 2
    

    then you need to compute which of the two dimensions will be the scaling constraint

    sf = min((view_width - 2*border) / rotated_width,
             (view_height - 2*border) / rotated_height)
    

    then you can compute the 3x2 transformation matrix

    m11 = sf*cos(angle)
    m12 = sf*sin(angle)
    m21 = -sf*sin(angle)
    m22 = sf*cos(angle)
    m31 = view_width/2 - image_width/2 * m11 - image_height/2 * m21
    m32 = view_height/2 - image_width/2 * m12 - image_height/2 * m22