Search code examples
svginkscape

Interpreting svg paths created in inkscape


I am trying to regenerate svg paths in a script using xml files created by inkscape. I understand how to interpret the d tag in the xml file, but I am having trouble with the transformations baked into the file.

My test file has a path on it that I simplified down to a small triangle to make it easier to work with. The simple svg file from inkscape looks like this:

xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   version="1.1"
   id="svg6530"
   viewBox="0 0 33 134"
   height="134"
   width="33">
  <defs
     id="defs6532" />
  <metadata
     id="metadata6535">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
        <dc:title></dc:title>
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <g
     style="display:inline"
     transform="translate(0,-918.36216)"
     id="layer1">
    <path
       id="path7149"
       d="m 0.10475398,1040.2201 1.79370822,0 1.4230759,-1.6612"
       style="fill:#000000" />
  </g>
</svg>

The path is relative (lowercase m)
It has a transform:translate of (0,-918.36216) applied to it.
The view box is 0 0 33 134
height = 134
width = 33
the path is: "m 0.10475398,1040.2201 1.79370822,0 1.4230759,-1.6612"

All units are pixels.

If I look at the path in inkscape I see the following 3 points in the document: 0.105,12.142 1.898,12.142 3.322,13.80

These are the three points I'd like to recreate in a script.

If I start with

"M 0.105,12.142 1.898,12.142 3.322,13.80" 

I get exactly what I want, but I can't figure out how to get to this from:

d="m 0.10475398,1040.2201 1.79370822,0 1.4230759,-1.6612"

Solution

  • The path string:

    m 0.10475398,1040.2201 1.79370822,0 1.4230759,-1.6612
    

    is equivalent to

    M 0.10475398,1040.2201 l 1.79370822,0 l 1.4230759,-1.6612
    

    or a move and two relative lines.

    If we convert the relative line coordinates to absolute (and round to three decimal places for simplicity) we get:

    M 0.105,1040.220 L (0.105+1.794),(1040.220+0) L 0.105+1.794+1.423),(1040.220+0-1.661)
    

    or

    M 0.105,1040.220 L 1.899,1040.220 L 3.322,1038.559
    

    Now you are also applying a transform to the path. It's a translation by (0,-918.362). If if we now apply that to your path, we get:

    M 0.105,(1040.220 - 918.362) L 1.899,(1040.220 - 918.362) L 3.322,(1038.559 - 918.362)
    

    or:

    M 0.105,121.858 L 1.899,121.858 L 3.322,120.197
    

    In its UI, Inkscape is flipping the Y coordinates from the SVG convention, where Y=0 is at the top, to the cartesian convention where Y=0 is at the bottom.

    So for the final step, if we subtract all the Y coordinates from 134 (the height of the document), we get:

    M 0.105,12.142 L 1.899,12.142 L 3.322,13.807
    

    Which is the string you were after (with minor rounding differences).

    tl;dr: Convert to absolute coordinates, apply the transform, flip the Y coords.