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.
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.
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>
<effects-menu>
<submenu name="Custom"/>
</effects-menu>
</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')}
rects = self.add_rect()
for r in rects:
yield r
def add_rect(self):
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" />
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.
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.
11. Transforms