# Chapter 11.  Transforms

Posted on

## Equations

When we move an element from one location to another location on Inkscape canvas, we can also view it as moving an imaginary coordinate system with it. The element stays at the same location in the imaginary coordinate system. Translate, rotate, and scale are three common transforms in Inkscape.

The translate transform is simply moving an object. The coordinate of a point on the object (x, y) will change to (x’, y’). The `a` and `b` values in the equations shown below represent the distances along X and Y axes the object has moved. If we write two equations below in matrix form, we have the third equation.

The two equations below are for rotation and scale. The rotation angle (alpha) is clockwise because the y axis increases from top to bottom. The `a` and `b` of the scale equation represent the scale factor along X and Y.

The above rotation equation is for rotating around the origin (0, 0). If we rotate an element around a coordinate (a, b), the equation becomes like this.

The matrix is in this form when those three transforms are combined.

## Inkscape Transforms

Let’s look at an example to see how transform works in Inkscape. First we draw a rectangle with top left coordinates (10, 10). It has a width of 60 and height of 40. The SVG file has these lines for the element. We can ignore the `id` and `style` attributes for this example.

``````<rect
style="fill:none;stroke:#000000;
stroke-width:0.26458333;stop-color:#000000"
id="rect31"
width="60"
height="40"
x="10"
y="10" />
``````

We will use the transform dialog (Menu `Object -> Transform` or shortcut Ctrl + Shift + M) to see how Inkscape handles a transform. When we move the rectangle 10mm horizontally and 10mm vertically (with Relative move selected), the SVG element coordinates will change.

``````<rect
width="60"
height="40"
x="20"
y="20" />
``````

Next let’s rotate the object 30 degrees clockwise. The element code becomes like this. It will have a new `transform` attribute with `rotate(30)` as its value. The x and y coordinate values change from (20, 20) to (33.3012, -10.3589). The reason is that the rotation is not around the origin (0, 0), instead it is around the center of the rectangle which is (50, 40). How does Inkscape calculate the new coordinates of the top left corner of the rectangle? It is a little complicated, and this numpy python script shows the calculation.

``````<rect
width="60"
height="40"
x="33.30127"
y="-10.358984"
transform="rotate(30)" />
``````

The `rotate` function as the value of the `transform` attribute can also accept two additional arguments as the rotation center. The xml code shown below represents the same rectangle.

``````<rect
width="60"
height="40"
x="20"
y="20"
transform="rotate(30, 50, 30)" />
``````

The SVG specs define other transform functions `translate`, `scale`, `skewX`, `skewY`, and `matrix`. We can also add a transform attribute to a group or a layer.

## Transform in Extension Code

The `transform.py` module in the `inkex` directory has over 1,000 lines of code. But the system extensions do not use this function very often. Only a few system extensions set the `transform` attribute.

Here is a simple extension to test the `transform` attribute of the rectangle element.

``````<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension
xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<name>Transform Element</name>
<id>user.transform</id>
<effect>
<object-type>all</object-type>
</effect>
<script>
<command location="inx" interpreter="python">transform.py</command>
</script>
</inkscape-extension>
``````
``````# transform.py
import inkex
from inkex import Rectangle, Transform

class NewElement(inkex.GenerateExtension):
container_label = 'transform'
container_layer = True

def generate(self):
self.style = {'fill' : 'none', 'stroke' : '#000000',
'stroke-width' : self.svg.unittouu('1px')}
for r in rects:
yield r

el1 = Rectangle(x='10', y='10', width='60', height='40')
el1.style = self.style

el2 = Rectangle.new(20, 20, 60, 40)
el2.style = self.style
tr = Transform('rotate(30)')
el2.transform = tr

el3 = Rectangle.new(20, 20, 60, 40)
el3.style = self.style
tr = Transform('rotate(30, 50, 40)')
el3.transform = tr

el4 = Rectangle.new(20, 20, 60, 40)
el4.style = self.style
tr = Transform('translate(10, 10) rotate(45)')
el4.transform = tr

el5 = Rectangle.new(20, 20, 60, 40)
el5.style = self.style
tr = Transform('scale(2.0) rotate(60)')
el5.transform = tr

el6 = Rectangle.new(20, 20, 60, 40)
el6.style = self.style
tr = Transform('rotate(60)') * Transform('scale(2.0)')
el6.transform = tr

return el1, el2, el3, el4, el5, el6

if __name__ == '__main__':
NewElement().run()
``````

Notice in the above examples, we can combine multiple transforms as the string argument to the `Transform` constructor, or multiply multiple `Transform` objects. The SVG results are shown below.

``````    <rect
x="10"
y="10"
width="60"
height="40"
id="rect1007" />
<rect
x="20"
y="20"
width="60"
height="40"
transform="rotate(30)"
id="rect1009" />
<rect
x="20"
y="20"
width="60"
height="40"
transform="matrix(0.866025 0.5 -0.5 0.866025 26.6987 -19.641)"
id="rect1011" />
<rect
x="20"
y="20"
width="60"
height="40"
transform="matrix(0.707107 0.707107 -0.707107 0.707107 10 10)"
id="rect1013" />
<rect
x="20"
y="20"
width="60"
height="40"
transform="matrix(1 1.73205 -1.73205 1 0 0)"
id="rect1015" />
<rect
x="20"
y="20"
width="60"
height="40"
transform="matrix(1 1.73205 -1.73205 1 0 0)"
id="rect1017" />
``````

## Other Classes

The `transforms` module also includes several other classes and functions. The notable classes are `Vector2d`, `BoundingBox`, and `DirectedLineSegment`. It also defines two functions `cubic_extrema` and `quadratic_extrema`. Those classes and functions are not necessarily related to `transforms`.

The `Vector2d` and `DirectedLineSegment` classes are very useful when we are working on mathematical drawings. We can apply vector algebra to calculate coordinates of points, and draw them as lines or polygons on the canvas.

## References

Anthony J. Pettofrezzo published two math books Vectors and Their Applications and Matrices And Transformations. Both books are relevant to the transforms module discussed in this chapter.

The book Mathematical Illustrations, A Manual Of Geometry and Postscript by Bill Casselman is an excellent reference for math drawings. Here is the link to the book webpage. The pdfs of the book chapters are available on the webpage.

The book Introduction To Computer Graphics by James Foley and others has a Chapter Geometrical Transformations. The transform equations in the book are in the same format as on this web page.