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>
svgmove

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>
svgmove.out

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.