CIF/SVG move declaration
A CIF/SVG move declaration can be used to move parts of an SVG image to a certain position, regardless of transformations applied to the elements that are moved, or any surrounding groups and layers, etc. This page explains the technical details of such move declarations. For a concrete example, see the lamps example.
Example
Consider the following SVG file:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
width="400" height="400" id="root" version="1.1">
<g id="grp1">
<rect style="fill:green;" id="rect1" width="20" height="20" x="5" y="10"
transform="translate(15, 20)"/>
</g>
<g id="grp2" transform="scale(5, 2)">
<rect style="fill:blue;" id="rect2" width="20" height="20" x="5" y="10"
transform="translate(15, 20)"/>
</g>
</svg>
It features a group grp1
, with a green rectangle rect1
. It is 20 by 20 pixels in size. Its position is 20 pixels from the left (x
is 5, but the horizontal translation is 15 pixels) and 30 pixels from the top (y
is 10, but the vertical translation is 20 pixels).
Group grp2
and rectangle rect2
are similar. Rectangle rect2
is blue, and group grp2
is scaled 5 times horizontally, and 2 times vertically. This means that rectangle rect2
is 100 by 40 pixels in size (5 times 20, and 2 times 20). It also means that the position of rect2
is 100 pixels from the left (5 times 20) and 60 pixels from the top (2 times 30).
Also consider the following CIF file:
svgfile "svgmove.svg";
svgmove id "rect1" to 10, 10;
svgmove id "rect2" to 10, 50;
The upper left corner of the bounding box of rectangle rect1
is moved to 10 pixels from the left side, and 10 pixels from the top. The upper left corner of the bounding box of rectangle rect2
is moved to 10 pixels from the left side, and 50 pixels from the top. The effect of the move declarations on the SVG image is:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
width="400" height="400" id="root" version="1.1">
<g id="grp1">
<rect style="fill:green;" id="rect1" width="20" height="20" x="5" y="10"
transform="translate(15, 20) translate(-10.000000,-20.000000)"/>
</g>
<g id="grp2" transform="scale(5, 2)">
<rect style="fill:blue;" id="rect2" width="20" height="20" x="5" y="10"
transform="translate(15, 20) translate(-18.000000,-5.000000)"/>
</g>
</svg>
Note the translations that have been added to the transform
attributes of the rectangles. The additional translation for rectangle rect1
is -10 in the x direction and -20 in the y direction, as the rectangle has been moved from position (20, 30) to position (10, 10).
Rectangle rect2
has been moved from position (100, 60) to position (10, 50). You might have expected a horizontal translation of -90 and a vertical translation of -10. However, its added translation is for -18 pixels horizontally, and -5 pixels vertically. This is because the scaling applies to this translation as well, and 5 * 18 = 90, and 2 * 5 = 10.
The scaling of the surrounding group complicates the calculations for the transformations of its children (rect2
in this case). Moving elements to certain positions becomes more and more complicated when the elements themselves have transformations, their parents have transformations, the parents of their parents have transformations, etc. This especially holds for non-translation transformations, such as scale
, rotate
, etc. The CIF/SVG move declarations make moving easy, by allowing you to specify the target position, regardless of the existence of such transformations.
Syntax
The general syntax of CIF/SVG move declarations is:
svgmove id <id> to <x>, <y>;
svgmove id <id> to <x>, <y> file "...";
The svgmove
keyword is followed by a specification of an SVG element id. Every move declaration must specify the id of an SVG element, and an SVG element with that id must exist in the SVG image. The id
indicates the element that is to be moved.
The x and y target coordinates are both mandatory, and indicate the coordinates of the upper left corner of the bounding box of element that is being moved, relative to the upper left corner of the canvas, after the move is completed. Similar to ids, expressions may be used for both the x and y coordinates, as long as they result in a int
or real
typed value when they’re evaluated. That is, the x and y coordinates must be numeric.
In the syntax examples above, we see that it is also allowed to declare a local SVG file declaration, that only applies to that specific move declaration.
Moving graphical elements
In order for an element to be moved, it must have a graphical representation. Elements that have a graphical representation include rectangles, paths, text labels, groups, etc. However, certain elements don’t have a graphical representation, and thus can not be moved. An example of elements that can not be moved are the tspan
sub-elements of text
elements. The tspan
sub-elements don’t have graphical representations of their own, they are part of the text labels, and only the text
elements have graphical representations.
Conflicting transformations
The SVG standard allows for powerful transformations, including the scale
and matrix
transformations. Now assume we use a scale(0, 0)
transformation. Then all coordinates are multiplied by zero, always resulting in zero. As such, the entire image is scaled into zero by zero pixels. In such cases, there is no translation that can be added to an element, that after application of the scaling transformation, moves it to a certain position. Thus, if such conflicting transformations are present, the move can not be accomplished, and the CIF/SVG move declaration is considered illegal. It should be noted however, that such conflicting transformations are rare, and usually indicate an error has been made in those transformations.
Application
Move declarations are only applied once, at the beginning of the simulation, after the copy declarations have been applied. For more information, see the Application order section.