# Coordinate Translation Logic in Graphviz2Drawio: Converting SVG Offsets to Absolute Positions

> Learn how graphviz2drawio translates SVG offsets to Draw.io absolute coordinates using the CoordsTranslate class for precise graph conversions.

- Repository: [Harold Martin/graphviz2drawio](https://github.com/hbmartin/graphviz2drawio)
- Tags: internals
- Published: 2026-03-03

---

**Graphviz2Drawio parses the global SVG transform attribute to extract translation offsets and applies them to every coordinate via the CoordsTranslate class, converting relative Graphviz positions into absolute Draw.io coordinates.**

The coordinate translation logic in graphviz2drawio bridges the gap between Graphviz's SVG output format and Draw.io's absolute positioning requirements. When Graphviz generates an SVG diagram, it wraps the entire drawing in a `<g>` element with a global transform attribute that shifts the coordinate system. The hbmartin/graphviz2drawio repository implements a centralized translation utility to handle this offset consistently across nodes, edges, and text elements.

## Understanding the SVG Coordinate Challenge

Graphviz outputs diagrams as SVG where all shape-specific coordinates are **relative to a global offset**. The root `<svg>` element contains a `transform="translate(x y)"` attribute that shifts the entire diagram. Without accounting for this offset, individual elements like rectangles, ellipses, and polygons would be positioned incorrectly relative to the canvas origin.

The library must parse this global transform once and apply it to every subsequent coordinate read from individual SVG nodes. This ensures that the final Draw.io XML contains absolute positions that match the original Graphviz layout.

## The CoordsTranslate Class: Core of the Translation Logic

All coordinate translation functionality is encapsulated in the **`CoordsTranslate`** class located in [[`graphviz2drawio/models/CoordsTranslate.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/models/CoordsTranslate.py)](https://github.com/hbmartin/graphviz2drawio/blob/master/graphviz2drawio/models/CoordsTranslate.py). This class stores the global X and Y offsets and provides methods to apply them to various coordinate types.

### Parsing the Global Transform String

The **`from_svg_transform`** static method extracts the offset values from the SVG transform attribute:

```python
@staticmethod
def from_svg_transform(transform: str) -> "CoordsTranslate":
    x, y = transform.split("translate(")[1].split(")")[0].split(" ")
    return CoordsTranslate(x=float(x), y=float(y))

```

This method receives a string like `"translate(120.0 45.0)"`, parses the numeric values, and returns a `CoordsTranslate` instance initialized with the extracted offsets.

### Applying Offsets to Coordinates

The **`translate`** method shifts raw coordinates by the stored global offset:

```python
def translate(self, x: float | str, y: float | str) -> tuple[float, float]:
    return float(x) + self.x, float(y) + self.y

```

This method accepts both `float` and `str` inputs, converting them automatically before applying the offset. Shape factories call this method for every coordinate extracted from SVG attributes.

For text baseline adjustments, the **`complex_translate`** method handles complex number representations:

```python
def complex_translate(self, cnum: complex) -> complex:
    return complex(cnum.real + self.x, cnum.imag + self.y)

```

This is used specifically for text positioning where offsets are represented as complex numbers.

## Integration Across the Conversion Pipeline

The `CoordsTranslate` instance is created once during SVG parsing and propagated through all factory classes that generate Draw.io elements.

### Root SVG Parsing

In [[`graphviz2drawio/models/SvgParser.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/models/SvgParser.py)](https://github.com/hbmartin/graphviz2drawio/blob/master/graphviz2drawio/models/SvgParser.py), the root `<svg>` element is examined to extract the global transform:

```python
coords = CoordsTranslate.from_svg_transform(root.attrib["transform"])

```

This `coords` object is then passed to all subsequent processing steps.

### Node Coordinate Translation

The `NodeFactory` in [[`graphviz2drawio/mx/NodeFactory.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/mx/NodeFactory.py)](https://github.com/hbmartin/graphviz2drawio/blob/master/graphviz2drawio/mx/NodeFactory.py) receives the `coords` instance and forwards it to `RectFactory` helpers. Inside [[`graphviz2drawio/mx/RectFactory.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/mx/RectFactory.py)](https://github.com/hbmartin/graphviz2drawio/blob/master/graphviz2drawio/mx/RectFactory.py), every shape helper calls `coords.translate` before constructing `Rect` objects:

```python
x, y = coords.translate(attrib["x"], attrib["y"])

```

This ensures that rectangles, images, and ellipses are positioned absolutely on the Draw.io canvas.

### Edge and Curve Translation

Similarly, `EdgeFactory` in [[`graphviz2drawio/mx/EdgeFactory.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/mx/EdgeFactory.py)](https://github.com/hbmartin/graphviz2drawio/blob/master/graphviz2drawio/mx/EdgeFactory.py) passes the `coords` object to `CurveFactory`. The curve factory uses `coords.translate` to shift every control point of Bezier paths, ensuring that edges connect nodes at the correct absolute positions.

### Text Baseline Adjustment

In `NodeFactory._extract_texts`, after reading the first `<text>` element, the code computes a complex offset and applies `coords.complex_translate(complex(x, y))`. This aligns the text baseline with the global SVG origin while maintaining the relative positioning specified by Graphviz.

## Practical Code Examples

### Creating a CoordsTranslate Instance from SVG Transform

```python
from graphviz2drawio.models.CoordsTranslate import CoordsTranslate

transform = "translate(120.0 45.0)"
coords = CoordsTranslate.from_svg_transform(transform)

print(coords.x, coords.y)   # Output: 120.0 45.0

```

### Translating a Point for Shape Construction

```python

# Raw coordinates from SVG polygon point "30,20"

raw_x, raw_y = "30", "20"

# Apply global offset (120.0, 45.0)

x, y = coords.translate(raw_x, raw_y)

# Result: (150.0, 65.0)

print(f"Absolute position: ({x}, {y})")

```

### Using Translation in Node Factory Context

```python
from graphviz2drawio.mx.NodeFactory import NodeFactory
from graphviz2drawio.models.CoordsTranslate import CoordsTranslate

# Initialize with parsed transform

coords = CoordsTranslate.from_svg_transform("translate(10 20)")
node_factory = NodeFactory(coords)

# All nodes created by this factory will have coordinates 

# automatically adjusted by (10, 20)

```

## Summary

- **Global offset extraction**: The `CoordsTranslate.from_svg_transform` method parses the SVG root's `translate(x y)` attribute to capture the global diagram offset.
- **Centralized translation logic**: The `CoordsTranslate` class in [`graphviz2drawio/models/CoordsTranslate.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/models/CoordsTranslate.py) provides typed methods (`translate`, `complex_translate`) that apply offsets to both numeric and string coordinates.
- **Pipeline integration**: The same `CoordsTranslate` instance is propagated from `SvgParser` through `NodeFactory`, `EdgeFactory`, and `RectFactory`, ensuring consistent absolute positioning for nodes, edges, and text.
- **Multi-format support**: The class handles standard `(x, y)` tuples for shapes and complex numbers for text baseline offsets, accommodating all Graphviz SVG output variations.

## Frequently Asked Questions

### Why does Graphviz use a global transform attribute instead of absolute coordinates?

Graphviz generates SVG diagrams with a global `translate` transform to simplify internal coordinate calculations during layout algorithms. This approach allows Graphviz to compute positions relative to a local origin while rendering, then shift the entire diagram to its final viewport position with a single transform attribute. The graphviz2drawio library compensates for this design choice by parsing the transform and applying it to every element.

### What happens if the SVG transform attribute is missing or malformed?

The current implementation in `CoordsTranslate.from_svg_transform` assumes the transform string follows the standard `"translate(x y)"` format. If the attribute is missing or does not contain the expected pattern, the string splitting logic would raise an `IndexError` or `ValueError`. Production usage should validate the SVG structure before parsing, as Graphviz consistently outputs the transform attribute in its SVG generation.

### How does CoordsTranslate handle both string and float inputs?

The `translate` method accepts a union type `float | str` for both x and y parameters. When called, it explicitly converts inputs using `float(x)` and `float(y)` before adding the global offset. This design eliminates the need for callers to pre-convert SVG attribute values (which are always strings in XML) while also supporting numeric inputs from internal calculations. The same flexibility applies to `complex_translate` for text positioning.

### Is the translation logic applied to all SVG elements equally?

Yes, the translation logic is applied consistently across all geometric elements, but through different code paths depending on element type. **Nodes** use `coords.translate` in `RectFactory` for rectangles, images, and ellipses. **Edges** apply the same method in `CurveFactory` for Bezier control points. **Text** elements use `coords.complex_translate` for baseline offsets. This unified approach ensures that nodes, edges, labels, and curves maintain their relative positions while shifting to absolute coordinates on the Draw.io canvas.