Metadata-Version: 2.4
Name: svg-path-to-shapely
Version: 0.1.0
Summary: Library for loading SVG paths into shapely objects.
Author: Max Weiner
Author-email: Max Weiner <max.weiner@posteo.de>
License-Expression: MIT
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Scientific/Engineering
Requires-Dist: numpy>=2.0
Requires-Dist: shapely>=2.0
Requires-Dist: svg-path>=7.0
Requires-Python: >=3.10
Project-URL: Homepage, https://codeberg.org/axtimhaus/svg-path-to-shapely
Project-URL: Repository, https://codeberg.org/axtimhaus/svg-path-to-shapely
Description-Content-Type: text/markdown

# Library for Loading SVG Paths into Shapely Objects

This library provides some utility functions to find all paths in a SVG document and create [`shapely`](https://shapely.readthedocs.io) geometry objects from them.
It uses [`svg.path`](https://github.com/regebro/svg.path), [`shapely`](https://shapely.readthedocs.io) and [`numpy`](https://numpy.org) under the hood.

## Installation

The package is installable via [PyPI](https://pypi.org/project/svg-path-to-shapely).

## Basic Usage

The intended workflow is as follows.

First, load a SVG document and use the `find_all_paths_in_svg` method query the element tree for `path` elements featuring a `d` attribute.
The optional argument `with_namespace` determines, whether the SVG namespace shall respected in the query (if false, all `path` elements no matter what namespace are found).
As the first argument you may give a string containing SVG code (which will be parsed by [`xml.etree.ElementTree`](https://docs.python.org/3/library/xml.etree.elementtree.html)), or already parsed `xml.etree.ElementTree.ElementTree`/`xml.etree.ElementTree.Element` instances.
Alternatively you may read directly from file with `find_all_paths_in_file`.

```python
from svg_path_to_shapely import find_all_paths_in_svg

paths = find_all_paths_in_svg("your svg code...", with_namespace=True)
```

or

```python
from svg_path_to_shapely import find_all_paths_in_svg
from xml.etree.ElementTree import parse

et = parse("some path-like...")
paths = find_all_paths_in_svg(et, with_namespace=True)
```

or

```python
from svg_path_to_shapely import find_all_paths_in_svg
from xml.etree.ElementTree import fromstring

et = fromstring("your svg code...")
paths = find_all_paths_in_svg("your svg code...", with_namespace=True)
```

or

```python
from svg_path_to_shapely import find_all_paths_in_file

paths = find_all_paths_in_file("some path-like...", with_namespace=True)
```

`paths` will then be a list of `xml.etree.ElementTree.Element` instances representing all `path` element in the document.
Then, create [`svg.path.Path`](https://github.com/regebro/svg.path) instances from those by use of `parse_path`.
This step is intentionally left explicit to be able to query for additional attributes as needed (such as `id`) on the path elements.
You may supply the element instance directly or a string with a valid value of the `d` attribute.

```python
from svg_path_to_shapely import parse_path

parsed = [parse_path(p) for p in paths]
```

Last, convert those path instances to [`shapely`](https://shapely.readthedocs.io) geometries using `convert_path_to_line_string`.
This function may return a `LineString`, `LinearRing` or `MultiLineString`, depending on whether the path is open, closed or multi-part (with multiple `M`/`m` directives), respectively.
The optional parameter `count` determines the number of evenly spaced discrete points to approximate arcs and Bezier curves with (as `shapely` does only know linear strings).

```python
from svg_path_to_shapely import convert_path_to_line_string

geoms = [convert_path_to_line_string(p, count=11) for p in parsed]
```

The latter will check if the path is multi-part and split it accordingly.
To spare this effort, if you know the path is single-part, you may use `convert_single_part_path_to_line_string` instead.
This will essentially treat multiple move directives (`M`/`m`) as if they were line directives (`L`/`l`).

The library exports some more of its lower-level functions. 
Have a look into their docstrings for information on how to use them.

## Application Examples

You find example SVG documents and respective code in the `test` directory.

### Powder Particle Shape Analysis

A micrograph of copper powder particles was imported in [Inkscape](https://inkscape.org) and paths were manually drawn around the particles to determine their contours.

![Copper Powder Micrograph with Marked Contours](test/CuPowder.svg)

The paths were extracted and converted to `shapely` geometries to be able to analyse their geometric properties further (for the sake of example just centered at (0, 0) and plotted again).

![Particle Contours Plot as Extracted](test/extracted_particles.svg)

## Building and Testing

Project dependencies and build process are maintained using [`uv`](https://docs.astral.sh/uv).
Build the package using `uv build`.
Test are run using `uv run pytest`.

## License

The software is distributed under the terms of the [MIT License](LICENSE).

## Contributing

Issues and pull requests are welcome without any special contribution guidelines.
