Source: https://gometry.monicz.dev/api/toplevel/constructive-validation/

# Constructive & validation

Split, snap, polygonize, and validate geometry.

**Related:** [Validation & repair](https://gometry.monicz.dev/guide/validation/)

## polygonize\_all

Accepted call forms

```python
polygonize_all(values: Geometry | GeometryArray[Geometry | None] | Iterable[Geometry | Buffer | Mapping[str, Any] | SupportsGeoInterface | None], *, diagnostics: Literal[False] = False) -> GeometryArray[Polygon]
```

```python
polygonize_all(values: Geometry | GeometryArray[Geometry] | Iterable[Geometry | Buffer | Mapping[str, Any] | SupportsGeoInterface], *, diagnostics: Literal[True]) -> PolygonizeResult[Never]
```

```python
polygonize_all(values: Geometry | GeometryArray[Geometry | None] | Iterable[Geometry | Buffer | Mapping[str, Any] | SupportsGeoInterface | None], *, diagnostics: Literal[True]) -> PolygonizeResult[None]
```

```python
polygonize_all(values: Geometry | GeometryArray[Geometry] | Iterable[Geometry | Buffer | Mapping[str, Any] | SupportsGeoInterface], *, diagnostics: bool) -> GeometryArray[Polygon] | PolygonizeResult[Never]
```

```python
polygonize_all(values: Geometry | GeometryArray[Geometry | None] | Iterable[Geometry | Buffer | Mapping[str, Any] | SupportsGeoInterface | None], *, diagnostics: bool) -> GeometryArray[Polygon] | PolygonizeResult[None]
```

Build polygons from pooled linework, optionally returning full diagnostics.

All input geometries' edges are pooled into one linework graph, so a ring can
close across inputs. `diagnostics=False` returns the enclosed polygons;
`diagnostics=True` returns those same polygons together with cut edges,
dangles, and invalid rings grouped by source row. Missing source rows are
`None` groups; present rows with no diagnostic linework are empty groups.

For geographic input, polygon faces and diagnostic lines use the same
classification, so an edge of a returned face is not also reported as an
invalid ring. A closed polar-cap ring with no leftover linework returns a
polygon with empty cut-edge, dangle, and invalid-ring groups. Planar inputs
retain their planar diagnostic classification.

`GeometryArray.polygonize()` instead preserves one result group per input
row, so use this function when different rows' edges should close together.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `values` | `Geometry, GeometryArray, or iterable of Geometry-like values` | One geometry or linework values to node and polygonize together. Array and iterable inputs may contain `None` rows; they are omitted from the pooled linework. | *required* |
| `diagnostics` | `bool` | Return a `PolygonizeResult` containing the pooled polygons and source-row `Groups` for cut edges, dangles, and invalid rings. The diagnostic result form requires `diagnostics=True`; the polygon-only form omits the option. | *required* |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray or PolygonizeResult` | With the default `False`, the polygons enclosed by the pooled linework. With `True`, the same polygons plus the leftover-linework diagnostics. |

Raises:

| Type | Description |
| --- | --- |
| `OverflowError` | If no adjacent binary64 assignment preserves the exact polygonized output. |
| `ResourceLimitError` | If the bounded embedding search is exhausted. |

See Also

[Geometry.polygonize](https://gometry.monicz.dev/api/geometry/geometry/#gometry.Geometry.polygonize "polygonize") : Polygonize one geometry's own linework.
[GeometryArray.polygonize](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.polygonize "polygonize") : Polygonize each array row independently.
[union\_all](https://gometry.monicz.dev/api/toplevel/overlay-dissolve/#gometry.union_all "union_all") : Union of many geometries into one.
[intersection\_all](https://gometry.monicz.dev/api/toplevel/overlay-dissolve/#gometry.intersection_all "intersection_all") : Common region shared by many geometries.

Examples:

```pycon
>>> import gometry as gm
>>> edges = [
...     gm.LineString([(0, 0), (1, 0)]),
...     gm.LineString([(1, 0), (1, 1)]),
...     gm.LineString([(1, 1), (0, 0)]),
... ]
>>> gm.polygonize_all(edges).to_wkt()
['POLYGON ((0 0, 1 0, 1 1, 0 0))']
>>> result = gm.polygonize_all(edges, diagnostics=True)
>>> result.polygons.to_wkt()
['POLYGON ((0 0, 1 0, 1 1, 0 0))']
```

## require

Accepted call forms

```python
require(value: GeometryT, *, crs: CrsInput | None = None, axes: Literal['XY', 'XYZ', 'XYM', 'XYZM'] | None = None) -> GeometryT
```

```python
require(value: GeometryArray[GeometryRowT], *, crs: CrsInput | None = None, axes: Literal['XY', 'XYZ', 'XYM', 'XYZM'] | None = None) -> GeometryArray[GeometryRowT]
```

```python
require(value: Groups[GeometryArray[GeometryRowT]], *, crs: CrsInput | None = None, axes: Literal['XY', 'XYZ', 'XYM', 'XYZM'] | None = None) -> GeometryArray[GeometryRowT]
```

```python
require(value: Groups[GeometryArray[GeometryRowT] | None], *, crs: CrsInput | None = None, axes: Literal['XY', 'XYZ', 'XYM', 'XYZM'] | None = None) -> GeometryArray[GeometryRowT]
```

```python
require(value: str | Buffer | Mapping[str, Any] | SupportsGeoInterface, *, crs: CrsInput | None = None, axes: Literal['XY', 'XYZ', 'XYM', 'XYZM'] | None = None) -> Geometry
```

```python
require(value: Iterable[GeometryRowT], *, crs: CrsInput | None = None, axes: Literal['XY', 'XYZ', 'XYM', 'XYZM'] | None = None) -> GeometryArray[GeometryRowT]
```

```python
require(value: Iterable[Geometry | str | Buffer | Mapping[str, Any] | SupportsGeoInterface | None], *, crs: CrsInput | None = None, axes: Literal['XY', 'XYZ', 'XYM', 'XYZM'] | None = None) -> GeometryArray[Geometry | None]
```

Parse and require a geometry contract at an input boundary.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `value` | `geometry-like or iterable of geometry-like` | One geometry, a `GeometryArray`, a geometry-valued `Groups`, or an iterable. Foreign scalar inputs may be WKT, WKB, GeoJSON mappings/text, or `__geo_interface__` objects. Geometry-valued groups are flattened in group order and return a `GeometryArray`. | *required* |
| `crs` | `CrsInput` | Expected CRS for the result. CRS-free coordinates are stamped with this CRS; coordinates are never transformed. An existing CRS that is operationally equivalent is relabelled to this requested spelling, while a conflicting CRS raises `CRSMismatchError`. When omitted or `None`, no target is required and an existing CRS is preserved. Accepted forms include authority/WKT/PROJ strings, non-boolean integer-like EPSG codes, `(authority, code)` pairs, PROJJSON/CF mappings, objects exposing `to_authority()`, `to_epsg()`, `to_wkt()`, or `to_json()`, and objects whose `crs` or `srs` property contains another accepted form. Coordinate epochs are preserved and revalidated against the resulting CRS. | `None` |
| `axes` | `('XY', 'XYZ', 'XYM', 'XYZM')` | If given, require the geometry's coordinate axes to match exactly, otherwise raise. | `'XY'` |

Returns:

| Type | Description |
| --- | --- |
| `Geometry or GeometryArray` | The validated input. Iterables return a `GeometryArray`. |

Raises:

| Type | Description |
| --- | --- |
| `CRSError` | If `crs` is not a recognized CRS. |
| `ParseError` | If foreign GeoJSON is malformed, or its legacy `crs` member is unsupported or conflicts with `crs` (`format` is `"geojson"`). |
| `CRSMismatchError` | If an already-decoded / native / non-GeoJSON geometry's CRS conflicts with `crs`. EWKT/EWKB embedded SRID conflicts use this error too. |
| `InvalidGeometryError` | If the geometry is invalid, or its axes differ from `axes`. Geographic validity uses exact quotient topology, so longitude aliases and seam cuts do not depend on stored spelling. Out-of-domain latitude is invalid. For quotient-topology issues, the location is a canonical coordinate of the issue's contact set, chosen deterministically by minimum latitude then longitude. Projected and CRS-free geometry remains planar. |

See Also

[Geometry.validate](https://gometry.monicz.dev/api/geometry/geometry/#gometry.Geometry.validate "validate") : Structured validity report.
[Geometry.repair](https://gometry.monicz.dev/api/geometry/geometry/#gometry.Geometry.repair "repair") : Fix the geometry.

Examples:

```pycon
>>> import gometry as gm
>>> gm.require(gm.Point(1, 2, crs=4326), crs=4326).to_wkt()
'POINT (1 2)'
```

## shared\_paths

Accepted call forms

```python
shared_paths(left: Geometry, right: Geometry) -> GeometryCollection
```

```python
shared_paths(left: Geometry, right: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryT]) -> GeometryArray[GeometryCollection]
```

```python
shared_paths(left: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryT], right: Geometry) -> GeometryArray[GeometryCollection]
```

```python
shared_paths(left: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryT], right: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryOtherT]) -> GeometryArray[GeometryCollection]
```

```python
shared_paths(left: Geometry, right: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryT | None]) -> GeometryArray[GeometryCollection | None]
```

```python
shared_paths(left: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryT | None], right: Geometry) -> GeometryArray[GeometryCollection | None]
```

```python
shared_paths(left: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryT | None], right: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryOtherT | None]) -> GeometryArray[GeometryCollection | None]
```

```python
shared_paths(left: Geometry | (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], right: Geometry | (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None]) -> GeometryCollection | GeometryArray[GeometryCollection | None]
```

Shared paths between two lineal geometries.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `left` | `Geometry, GeometryArray, or iterable of Geometry or None` | Two lineal operands. Scalar and sequence inputs broadcast pairwise; sequences must have equal length and compatible CRS/epoch frames. | *required* |
| `right` | `Geometry, GeometryArray, or iterable of Geometry or None` | Two lineal operands. Scalar and sequence inputs broadcast pairwise; sequences must have equal length and compatible CRS/epoch frames. | *required* |

Returns:

| Type | Description |
| --- | --- |
| `Geometry or GeometryArray` | The shared linework. |

Raises:

| Type | Description |
| --- | --- |
| `CRSMismatchError` | If operands' CRS or coordinate-epoch metadata differ. |
| `GeometryTypeError` | If either operand is not lineal. |

Examples:

```pycon
>>> import gometry as gm
>>> gm.shared_paths(gm.LineString([(0, 0), (2, 0)]), gm.LineString([(1, 0), (3, 0)])).to_wkt()
'GEOMETRYCOLLECTION (MULTILINESTRING ((1 0, 2 0)), MULTILINESTRING EMPTY)'
```

## snap

Accepted call forms

```python
snap(geom: GeometryT, reference: Geometry, tolerance: float) -> GeometryT
```

```python
snap(geom: MultiPoint, reference: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryOtherT], tolerance: FloatInput) -> GeometryArray[MultiPoint]
```

```python
snap(geom: MultiPoint, reference: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryOtherT | None], tolerance: FloatInput) -> GeometryArray[MultiPoint | None]
```

```python
snap(geom: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryT], reference: Geometry | (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryOtherT], tolerance: FloatInput) -> GeometryArray[GeometryT]
```

```python
snap(geom: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryT | None], reference: Geometry | (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryOtherT | None], tolerance: FloatInput) -> GeometryArray[GeometryT | None]
```

```python
snap(geom: GeometryT, reference: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryOtherT], tolerance: FloatInput) -> GeometryArray[GeometryT]
```

```python
snap(geom: GeometryT, reference: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryOtherT | None], tolerance: FloatInput) -> GeometryArray[GeometryT | None]
```

```python
snap(geom: Geometry | GeometryArray[Geometry | None], reference: Geometry | GeometryArray[Geometry | None], tolerance: FloatInput) -> Geometry | GeometryArray[Geometry | None]
```

Snap vertices of `geom` onto `reference` within `tolerance`.

Each source vertex snaps independently to its nearest reference vertex at
or below `tolerance`; if none is in range, it stays unchanged. An exact
computed-distance tie goes to the reference vertex with the smaller X,
then Y, using IEEE total order. Multiple source vertices may snap to the
same reference vertex.

On each line segment, every reference vertex whose projection lies in the
open segment, whose segment distance is at or below `tolerance`, and
whose distance from both endpoints is greater than `tolerance` is
inserted at its reference X/Y. Insertions follow segment order; equal
projections are ordered by reference X/Y.

Snapped source vertices retain
their own Z/M. Inserted geographic vertices keep the reference X/Y and use
the source edge's ellipsoidal arclength at the exact projection parameter;
Cartesian vertices interpolate along the source segment.

Consecutive line
coordinates with identical X/Y are emitted once,
keeping the first. If that leaves only one coordinate, the snapped start
and end are retained as two endpoints, which may share X/Y. Closed rings
are reclosed.

Snapping may collapse polygon rings: collapsed holes are dropped and a
collapsed shell produces an empty polygon. Snapping does not validate or
repair topology, so a snapped polygon may be invalid.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `geom` | `Geometry, GeometryArray, or iterable of Geometry or None` | Geometry whose vertices are moved. Missing rows remain missing. | *required* |
| `reference` | `Geometry, GeometryArray, or iterable of Geometry or None` | Target geometry to snap onto. | *required* |
| `tolerance` | `float or sequence of float` | Maximum finite non-negative snap distance in coordinate space: geographic CRSs use native angular units, projected CRSs use native linear units, and CRS-free geometries use raw coordinate units. | *required* |

Returns:

| Type | Description |
| --- | --- |
| `Geometry or GeometryArray` | Snapped result(s), with missing rows preserved. |

Raises:

| Type | Description |
| --- | --- |
| `CRSMismatchError` | If operands' CRS or coordinate-epoch metadata differ. |
| `GeometryError` | If `tolerance` is invalid. |

Examples:

```pycon
>>> import gometry as gm
>>> gm.snap(gm.Point(0.01, 0), gm.Point(0, 0), 0.1).to_wkt()
'POINT (0 0)'
```

## split

Accepted call forms

```python
split(geom: LineString | MultiLineString, splitter: Point | MultiPoint | GeometryArray[Point | MultiPoint | None], *, tolerance: float = 0.0) -> GeometryArray[LineString]
```

```python
split(geom: GeometryArray[LineString | MultiLineString], splitter: Point | MultiPoint | GeometryArray[Point | MultiPoint], *, tolerance: float = 0.0) -> Groups[GeometryArray[LineString]]
```

```python
split(geom: GeometryArray[LineString | MultiLineString | None], splitter: Point | MultiPoint | GeometryArray[Point | MultiPoint], *, tolerance: float = 0.0) -> Groups[GeometryArray[LineString] | None]
```

```python
split(geom: GeometryArray[LineString | MultiLineString], splitter: GeometryArray[Point | MultiPoint | None], *, tolerance: float = 0.0) -> Groups[GeometryArray[LineString] | None]
```

```python
split(geom: GeometryArray[LineString | MultiLineString | None], splitter: GeometryArray[Point | MultiPoint | None], *, tolerance: float = 0.0) -> Groups[GeometryArray[LineString] | None]
```

```python
split(geom: Geometry, splitter: Geometry | GeometryArray[Geometry | None], *, tolerance: float = 0.0) -> GeometryArray[LineString]
```

```python
split(geom: GeometryArray[Geometry], splitter: Geometry | GeometryArray[Geometry], *, tolerance: float = 0.0) -> Groups[GeometryArray[LineString]]
```

```python
split(geom: GeometryArray[Geometry | None], splitter: Geometry | GeometryArray[Geometry | None], *, tolerance: float = 0.0) -> Groups[GeometryArray[LineString] | None]
```

Split lineal geometry by point splitter(s).

Each piece retains source vertices, including consecutive equal-X/Y
vertices whose active Z/M ordinates differ. Inserted geographic Z/M
ordinates follow the original source edge's ellipsoidal arclength.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `geom` | `Geometry or GeometryArray` | Lineal geometry to split. | *required* |
| `splitter` | `Geometry or GeometryArray` | Point or multipoint cutter. | *required* |
| `tolerance` | `(float, keyword - only)` | Coordinate-space distance within which a splitter point counts as on the line and near-equal cut offsets collapse: native angular units on geographic CRSs, native linear units on projected CRSs, and raw coordinate units when CRS-free. The default `0.0` is exact topological membership (a point splits only when it lies exactly on the linework) with identity deduplication. | `0.0` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray or Groups[GeometryArray]` | A scalar line returns all split parts in one `GeometryArray`, even when its cutter is an array of points. A line array returns one `Groups` row per source line; an array cutter is paired row by row. Missing line or cutter rows produce `None` groups; present rows with no split parts produce empty groups. |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If `tolerance` is negative or non-finite. |
| `CRSMismatchError` | If operands' CRS or coordinate-epoch metadata differ. |
| `GeometryTypeError` | If `geom` is not lineal. |

Examples:

```pycon
>>> import gometry as gm
>>> gm.split(gm.LineString([(0, 0), (2, 0)]), gm.Point(1, 0)).to_wkt()
['LINESTRING (0 0, 1 0)', 'LINESTRING (1 0, 2 0)']
>>> pieces = gm.split(gm.GeometryArray([gm.LineString([(0, 0), (2, 0)])]), gm.Point(1, 0))
>>> pieces.offsets.tolist()
[0, 2]
```
