-
Notifications
You must be signed in to change notification settings - Fork 4
Absolute Measurements
SVG stands for scalable vector graphics. The authors of the first SVG standard took the scalable part very seriously and specified the format in a way that makes it impossible to determine an absolute scale for shapes declared in an SVG document. Coordinates in an SVG document can be specified using a number of unit suffixes [0].
- m: One meter, as defined by the SI.
- cm: 1 m / 100.
- mm: 1 m / 1000.
- km: 1 m * 1000.
- in: One inch, defined as 25.4 mm.
- pc: 1 in / 6.
- pt: 1 in / 72.
- ft: 1 in * 12.
- yd: 1 in * 36.
- px: One pixel.
In this list, only px has no defined size in SVG 1.1. SVG 1.1 does hint at a size of 1 in / 90. Later, SVG 2 defined it to be 1 in / 96. But the harm had already been done. Inscape took the value of 1 in / 90 and produces and reads documents using that interpretation. The latest snapshots of version 0.92 changed this to 1 in / 96, making documents incompatible between older and newer versions.
SVG also allows sizes to be declared without specifying a unit, which is what e.g. Inkscape does when writing files. Guess which of the above units is used when no unit is specified.
To make matters more complicated, the SVG standard adds a way to specify the absolute size of the image represented by a document. This defines sort of a scaling factor between the measurements used in the document and the actual sizes those objects will have (I.e. one mm will not be equal to one mm anymore). To make matters even more complicated, this scaling factor is defined using four attributes on the root svg
element, height
, width
, viewBox
and preserveAspectRatio
. And to make this ordeal ultimately pointless again, this "absolute size" can again be specified using the px
unit, making it not absolute again. Inkscape does not even implement preserveAspectRatio
and thus neither does the converter of this project.
[0]: SVG uses the units defined by CCS 3, which are just cm
, mm
, in
, px
, pt
and pc
. But inkex.py
in the Inkscape distribution also includes conversion factors for yd
, ft
, m
and km
, which makes me believe that Inkscape also supports those, thus I included them in the list.
Because the differences introduced by the different interpretations of the px
unit are very frustrating (a scale difference of 15/16 is usually not noticed until the finished part is printed and then does not fit where it should), the converter using in this project employs some checks for documents which lack the necessary information to be converted consistently. Depending on the problem, different error messages are printed. Those error messages look like this:
[inkscape] src/test-1.dxf
Error: While processing src/test-1.svg: SVG document has no viewBox attribute. See https://github.com/Feuermurmel/openscad-template/wiki/Absolute-Measurements
Makefile:92: recipe for target 'src/test-1.dxf' failed
make: *** [src/test-1.dxf] Error 1
Because Inkscape writes all coordinates using the px
units, the converter tries to determine the absolute size of a pixel using the height
and viewBox
attributes. Simply speaking, the height
specifies an absolute value for the height of the whole document while the viewBox
defines the same length as a number of pixels.
For example, in the following SVG document, the viewBox defines 100 pixels in the document to be equal to 100 mm in the real world. The width
attribute is also specified, but it is ignored by the converter:
<svg
xmlns:svg="http://www.w3.org/2000/svg"
width="200mm"
height="100mm"
viewBox="0 0 200 100"
...
The following error messages are produced:
-
SVG document has no height attribute.: Add a
height
attribute to the rootsvg
element, specifying the height of the document in an absolute unit like mm or pt. An appropriatewidth
attribute should also be added. -
Height of SVG document is not an absolute measure.: Add an absolute unit to the
height
attribute of the rootsvg
element (i.e. anything other thanpx
). -
SVG document has no viewBox attribute.: Add a
viewBox
attribute to the document, specifying the size of the document as a number of pixels.
The viewBox
attribute is a sequence of four numbers, without units. To construct the attribute, set the first two values to 0
and compute the two following numbers from the width
and height
attributes of your document by converting the absolute measures of those attributes to pixels. For this, you should probably use a value of 90 or 96 pixels per inch. The following table gives the conversion factors for all SVG units. E.g. a height of 10 cm would be translated to 10 * 37.7953 = 377.953 pixels:
Unit | 90 px / in | 96 px/in |
---|---|---|
1 m | 3543.31 | 3779.53 |
1 cm | 35.4331 | 37.7953 |
1 mm | 3.54331 | 3.77953 |
1 km | 3543310 | 3779530 |
1 in | 90 | 96 |
1 pc | 15 | 16 |
1 pt | 1.25 | 1.33333 |
1 ft | 1080 | 1152 |
1 yd | 3240 | 3456 |
Most may have noticed that this article is written in a very sarcastic and maybe a bit angry tone, which reflects the feelings I have, working on these subjects. I'd like to state here very clearly that I do not want to belittle the work that people have done for the specifications and software projects I mentioned. Both SVG and Inkscape are enormous projects, and especially in Inkscape, and even somewhat and SVG, units are small part of the whole ordeal, insignificant to most people (most people are satisfied when they draw a circle in Inkscape, save it and open it in their browser and its still a circle, both projects together do solve that problem). And all the different requirements arising from different use-cases certainly complicate these matters.
But units … I can live with people wanting to use inches. Even here in Europe, as one example, most of the piping dimensions are specified in inches ("Zoll" as we call it in German). It works because we know that an inch is exactly 2.54 centimeters (OTOH e.g miles, barrels, ounces and pounds are probably a different story because they're ambiguous, but I was not yet exposed to those units in a context where it would have mattered to me).
But when I get into contact with a file format that gets these things slightly wrong, I tend to get very angry. SVG 1.1 got units right 90%, figuratively. The problem is that getting something like that 90% right makes it still completely unusable for when it matters. When I want to have absolute measurements of an object, it's either always correct or I don't want to work with it. And thus I'd like to tell the people working on file formats which may be used to describe object in the real world: Also do the last 10%! Have balls and stand up in your committee and shout: "NO! All measurements have an absolute unit! And it's always millimeters!" (or inches, if you must). I will thank you and the users that don't care won't be the wiser.