# `Expresso.Element.Diagram.Geometry`
[🔗](https://github.com/rellen/expresso/blob/main/lib/expresso/element/diagram/geometry.ex#L1)

The box and the center of an element of an SVG file

The `move_to` option of an `on` entity in a part moves the part to the
center of a different element of the file. This module finds the two
centers from the tree of the file, with no browser. The render of the deck
then writes the distance as `--x` and `--y`, as for `set: [x: ..., y: ...]`.

The box of an element is the smallest rectangle that holds its shape, in
the coordinates of the `svg` element of the file. The module reads the
`transform` attribute of the element and of each parent, so an element in a
moved group gets the correct box. These shapes have a box:

| Element | Box |
| --- | --- |
| `rect`, `image`, `use`, `foreignObject` | `x`, `y`, `width` and `height` |
| `circle` | `cx`, `cy` and `r` |
| `ellipse` | `cx`, `cy`, `rx` and `ry` |
| `line` | the two points |
| `polyline`, `polygon` | each point of `points` |
| `path` | each end point and each control point of `d` |
| `text`, `tspan` | the point of `x` and `y` |
| `g`, `a`, `svg`, `switch` | the box of each child |

The box of a path holds its control points, so a curve can have a box that
is a little larger than its shape. A text has no width without its font, so
its box is the point where the text starts. A text with `text-anchor:
middle` thus has the correct horizontal center.

# `box`

```elixir
@type box() :: {float(), float(), float(), float()}
```

A box: left, top, right, bottom

# `matrix`

```elixir
@type matrix() :: {float(), float(), float(), float(), float(), float()}
```

An affine transform: x' = a·x + c·y + e, y' = b·x + d·y + f

# `box`

```elixir
@spec box(Floki.html_node(), matrix()) :: box() | nil
```

Return the box of an element in the coordinates of the file

`matrix` is the matrix of the parent of the element. The function returns
`nil` for an element with no shape.

# `distance`

```elixir
@spec distance(Floki.html_tree(), String.t(), String.t()) ::
  {:ok, {float(), float()}} | {:error, String.t()}
```

Return the distance from the center of one element to the center of another

`tree` is the tree of the file from `Floki.parse_fragment!/1`. The distance
is in the coordinates of the parent of the element `from`, because a part
moves in the coordinates of its parent. The function returns an error for
an id that the file does not have, and for an element with no shape.

    iex> tree = Floki.parse_fragment!(~s{<svg><rect id="a" x="0" y="0" width="10" height="10"/><g transform="translate(100, 20)"><circle id="b" cx="5" cy="5" r="5"/></g></svg>})
    iex> Expresso.Element.Diagram.Geometry.distance(tree, "a", "b")
    {:ok, {100.0, 20.0}}

---

*Consult [api-reference.md](api-reference.md) for complete listing*
