views:

355

answers:

1

Hello,

I have some SVG files which have many text nodes in them.

I would like to get the absolute position of each of the text nodes, within the SVG document (the SVG documents have width="743.75" and height="1052.5").

An example text node looks like this:

 <g>
  <text transform="matrix(1,0,0,-1,106.5,732.5)">
   <tspan x="0 7.8979998 14.003 17.698999" y="0">Date</tspan>
  </text>
 </g>

How can I calculate all of the matrix() transforms to arrive at the positive absolute X and Y values for each text box? Is there a simple recursive function I could use and pass in each matrix in turn?

Thanks!

A: 

I am also trying to solve this problem, except for images. The question of recursion is that you need to dot multiply the transformation matricies. I'm using NumPy. However, my computations are coming up with ostensibly incorrect answers. Maybe you'll have more luck.

http://www.scipy.org/Tentative_NumPy_Tutorial

http://www.w3.org/TR/SVG/coords.html#TransformMatrixDefined

from decimal import Decimal
import xml.dom.minidom as dom
from numpy import *
doc = dom.parse("labels.svg")

def walk(node):
    if node.nodeType != 1:
        return
    if node.tagName == 'image':
        href = node.getAttribute('xlink:href')
        if not href.startswith("labels/"):
            return
        name = (
            href.
            replace('labels/', '').
            replace('.png', '').
            replace('-resized', '').
            replace('-normalized', '')
        )
        left = float(node.getAttribute('x'))
        top = float(node.getAttribute('y'))
        position = matrix([left, top, float(1)])
        width = float(node.getAttribute('width'))
        height = float(node.getAttribute('height'))
        size = matrix([left, top, float(1)])
        transform = node.getAttribute('transform')
        if transform:
            a, b, c, d, e, f = map(float, transform
                .replace('matrix(', '')
                .replace(')', '')
                .split(',')
            )
            transform = matrix([
                [a, c, e],
                [b, d, f],
                [0, 0, 1]
            ])
            left, top, _ = (transform.I * position.T).A1
        print name, (left, top)
    child = node.firstChild
    while child:
        walk(child)
        child = child.nextSibling

walk(doc.documentElement)
Kris Kowal