Source: https://gometry.monicz.dev/api/geometry/geometryarray/

# GeometryArray

The immutable columnar geometry container, with NumPy-native results and the same operation names as Geometry.

**Related:** [Arrays & performance](https://gometry.monicz.dev/guide/arrays/)

## GeometryArray

Accepted call forms

```python
GeometryArray(values: Iterable[None], *, crs: CrsInput | None = None, epoch: SupportsFloat | SupportsIndex | FloatScalar | ScalarFloatArray | None = None) -> GeometryArray[Geometry | None]
```

```python
GeometryArray(values: Iterable[GeometryT_co], *, crs: CrsInput | None = None, epoch: SupportsFloat | SupportsIndex | FloatScalar | ScalarFloatArray | None = None) -> GeometryArray[GeometryT_co]
```

```python
GeometryArray(values: Iterable[GeometryT_co | Buffer | Mapping[str, Any] | SupportsGeoInterface], *, crs: CrsInput | None = None, epoch: SupportsFloat | SupportsIndex | FloatScalar | ScalarFloatArray | None = None) -> GeometryArray[Geometry | GeometryT_co]
```

An immutable array of geometries sharing one CRS/epoch frame.

The vectorized counterpart of `Geometry`: methods mirror the scalar
names element-wise (`arr.area`, `(arr).buffer(10.0)`,
`contains(arr, geom)`) and run as batched Rust kernels with no
per-element Python. Homogeneous point, line, and polygon arrays pack into
shared coordinate columns (with CSR offsets where needed) for zero-copy
Arrow and columnar kernels. Build with `GeometryArray(...)` /
`points(...)` or the WKT/WKB/GeoJSON/Arrow importers; index and
slice it like a sequence.
An immutable, vectorized geometry column with one shared CRS/epoch frame.

Homogeneous arrays use packed coordinate storage and batched Rust kernels;
indexing and slicing preserve zero-copy views where possible.

Construct an immutable array from geometry-like rows.

Iterable values are consumed once in input order. `None` creates a
missing row. A single `Geometry` is not a row iterable; wrap it in a
one-item sequence. Rows may be native geometries, WKB byte buffers,
GeoJSON mappings, or objects exposing `__geo_interface__`. `crs=`
attaches shared metadata and never transforms coordinates.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `values` | `Iterable[None] \| Iterable[GeometryT_co] \| Iterable[GeometryT_co \| Buffer \| Mapping[str, Any] \| SupportsGeoInterface]` | One native geometry, WKB buffer, GeoJSON mapping, or object exposing `__geo_interface__` per input position; `None` marks a missing row. | *required* |
| `crs` | `CrsInput \| None` | Shared CRS label. CRS-free rows adopt it; existing CRS values must be equivalent to it. | `None` |
| `epoch` | `SupportsFloat \| SupportsIndex \| FloatScalar \| ScalarFloatArray \| None` | Shared coordinate epoch for a CRS that admits geometry epochs. Existing epochs must agree with it. | `None` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | An immutable, row-aligned array with missing positions preserved. |

Raises:

| Type | Description |
| --- | --- |
| `TypeError` | If `values` is a single geometry or contains an unsupported value. |
| `CRSError` | If `crs` cannot be resolved or an epoch is invalid for its CRS. |
| `CRSMismatchError` | If input CRS or epoch metadata conflicts with the shared frame. |
| `GeometryError` | If `epoch` is non-finite. |
| `ParseError` | If a WKB or GeoJSON row is malformed. |

### area `property`

```python
area: NDArray[float64]
```

Per-row area, measured for the array's CRS.

A geographic CRS gives ellipsoidal square meters for the region bounded
by edges straight in longitude/latitude; a projected CRS gives squared
native linear units; a CRS-free array gives squared raw coordinate units.
Use `to_crs` to change frame.

Each `GeometryCollection` row counts overlapping members once, as
the area of their union. Parts of a valid `MultiPolygon` cannot
overlap.

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | Read-only `float64` `numpy.ndarray` of shape `(n,)`; `0` for points and curves; `nan` for missing rows. |

Raises:

| Type | Description |
| --- | --- |
| `CRSError` | If the CRS lacks linear axis units for a metric result. |

See Also

[length](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.length "length property") : Length/perimeter under the same CRS-aware metric.

### bounds `property`

```python
bounds: NDArray[float64]
```

Per-geometry bounds `(minx, miny, maxx, maxy)` (see
`Geometry.bounds`), as a read-only `(rows, 4)` float64 ndarray.
Empty and missing rows are all-`nan`; use `.is_missing` to distinguish
missing rows.
Geographic longitude intervals may cross the seam, with `minx > maxx`.

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | One `minx, miny, maxx, maxy` row per input geometry. |

### common\_coordinate\_axes `property`

```python
common_coordinate_axes: Literal['XY', 'XYZ', 'XYM', 'XYZM'] | None
```

Ordinate layout shared by every present row, or `None` when rows
differ.

Returns:

| Type | Description |
| --- | --- |
| `str or None` |  |

### coordinate\_axes `property`

```python
coordinate_axes: list[Literal['XY', 'XYZ', 'XYM', 'XYZM'] | None]
```

Per-geometry ordinate layout (see `Geometry.coordinate_axes`), with
`None` at missing rows.

Returns:

| Type | Description |
| --- | --- |
| `list of str or None` | One `'XY'`/`'XYZ'`/`'XYM'`/`'XYZM'` token per row. |

### coords `property`

```python
coords: Coordinates
```

Returns:

| Type | Description |
| --- | --- |
| `Coordinates` | Flattened coordinates from present rows; missing rows contribute no coordinates. This is a vertex stream, not a row-aligned view; use `.row_index` to recover source-row alignment. |

### crosses\_antimeridian `property`

```python
crosses_antimeridian: NDArray[bool_]
```

Element-wise antimeridian-crossing test.

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | One result per input geometry. |

Raises:

| Type | Description |
| --- | --- |
| `CRSError` | If the CRS is projected (a geographic CRS or CRS-free lon/lat is required). |

### crs `property`

```python
crs: CRS | None
```

CRS shared by every geometry in the array, or `None`.

Returns:

| Type | Description |
| --- | --- |
| `CRS or None` |  |

### epoch `property`

```python
epoch: float | None
```

Coordinate epoch shared by the array, if set.

Returns:

| Type | Description |
| --- | --- |
| `float or None` |  |

### geometry\_type `property`

```python
geometry_type: list[Literal['Point', 'MultiPoint', 'LineString', 'MultiLineString', 'Polygon', 'MultiPolygon', 'GeometryCollection'] | None]
```

Per-geometry OGC type name (see `Geometry.geometry_type`), with
`None` at missing rows.

Returns:

| Type | Description |
| --- | --- |
| `list of str or None` | One name per input geometry, e.g. `'Point'` or `'MultiPolygon'`. |

### has\_m `property`

```python
has_m: NDArray[bool_]
```

Whether each geometry carries an M ordinate. Missing rows are false.

Returns:

| Type | Description |
| --- | --- |
| `ndarray` |  |

### has\_z `property`

```python
has_z: NDArray[bool_]
```

Whether each geometry carries a Z ordinate. Missing rows are false.

Returns:

| Type | Description |
| --- | --- |
| `ndarray` |  |

### is\_ccw `property`

```python
is_ccw: NDArray[bool_]
```

Per-geometry counter-clockwise test (see `Geometry.is_ccw`).

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | One result per input geometry. |

### is\_closed `property`

```python
is_closed: NDArray[bool_]
```

Per-geometry closed test (see `Geometry.is_closed`).

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | One result per input geometry. |

### is\_convex `property`

```python
is_convex: NDArray[bool_]
```

Per-geometry polygon convexity test (see `Geometry.is_convex`).

Returns:

| Type | Description |
| --- | --- |
| `ndarray` |  |

### is\_empty `property`

```python
is_empty: NDArray[bool_]
```

Whether each geometry is empty (no points, rings, or parts).

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | One result per input geometry. |

### is\_missing `property`

```python
is_missing: NDArray[bool_]
```

Which rows are missing, as a boolean `numpy.ndarray`.

True marks a missing row (None on access); a dense array
returns all-False.

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | One `bool` per row. |

Examples:

```pycon
>>> import gometry as gm
>>> gm.GeometryArray([gm.Point(0, 0), None]).is_missing.tolist()
[False, True]
```

### is\_ring `property`

```python
is_ring: NDArray[bool_]
```

Per-geometry ring test (see `Geometry.is_ring`).

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | One result per input geometry. |

### is\_simple `property`

```python
is_simple: NDArray[bool_]
```

Per-geometry simplicity test (see `Geometry.is_simple`).

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | One result per input geometry. |

### is\_valid `property`

```python
is_valid: NDArray[bool_]
```

Per-element validity mask (see `Geometry.is_valid`).

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | `True` where the geometry is valid, one entry per row. |

### length `property`

```python
length: NDArray[float64]
```

Per-row length (curves) or perimeter (areal), measured for the array's
CRS.

A geographic CRS gives ellipsoidal meters along edges straight in
longitude/latitude; a projected CRS gives native linear units; a CRS-free
array gives raw coordinate units. Use `to_crs` to change frame.

Geographic polygon perimeter measures straight chart edges and resolves
seam aliases in the CRS-native periodic longitude frame.

Each `GeometryCollection` row sums every member's length or
perimeter, including overlapping members.

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | Read-only `float64` `numpy.ndarray` of shape `(n,)`; `0` for points; `nan` for missing rows. |

Raises:

| Type | Description |
| --- | --- |
| `CRSError` | If the CRS lacks linear axis units for a metric result. |

See Also

[area](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.area "area property") : Area under the same CRS-aware metric.

### length\_3d `property`

```python
length_3d: NDArray[float64]
```

Per-row 3D length of curves with Z, measured for the array's CRS.

Geographic CRSs do not support 3D Euclidean length.

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | Read-only `float64` `numpy.ndarray` of shape `(n,)`; `nan` where Z is missing on a vertex or the row is missing. |

Raises:

| Type | Description |
| --- | --- |
| `CRSError` | If the CRS lacks linear axis units for a metric result. |

### max\_m `property`

```python
max_m: NDArray[float64]
```

Per-row largest M ordinate (`nan` where a geometry carries no M).

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | Read-only `float64` `numpy.ndarray` of shape `(n,)`; `nan` where M is absent or the row is missing. |

### max\_z `property`

```python
max_z: NDArray[float64]
```

Per-row largest Z ordinate (`nan` where a geometry carries no Z).

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | Read-only `float64` `numpy.ndarray` of shape `(n,)`; `nan` where Z is absent or the row is missing. |

### min\_m `property`

```python
min_m: NDArray[float64]
```

Per-row smallest M ordinate (`nan` where a geometry carries no M).

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | Read-only `float64` `numpy.ndarray` of shape `(n,)`; `nan` where M is absent or the row is missing. |

### min\_z `property`

```python
min_z: NDArray[float64]
```

Per-row smallest Z ordinate (`nan` where a geometry carries no Z).

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | Read-only `float64` `numpy.ndarray` of shape `(n,)`; `nan` where Z is absent or the row is missing. |

### nbytes `property`

```python
nbytes: int
```

Logical coordinate payload in bytes (numpy's `nbytes` convention):
the stored `f64` ordinate columns for this array's selected rows.
Slices and fancy-indexed arrays report only their logical rows. Object
headers, CSR offset columns, row maps, prepared-geometry / frame
sidecars and CRS metadata are excluded (`nbytes` is
payload-only, matching NumPy).

Returns:

| Type | Description |
| --- | --- |
| `int` |  |

### num\_coordinates `property`

```python
num_coordinates: ndarray[tuple[int], dtype[int64]] | NDArray[object_]
```

Per-geometry coordinate count. Missing rows are `0`.

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | One coordinate count per input geometry. The array uses `int64` when every count fits; otherwise it uses `object` with exact Python integers. |

### num\_geometries `property`

```python
num_geometries: ndarray[tuple[int], dtype[int64]]
```

Per-geometry top-level part count (see `Geometry.num_geometries`):
`1` for a single point/line/polygon, including a typed empty; the
member count for a multi/collection, and `0` for an empty multipart
or collection. Explicit empty members still count in their multipart's
member count. Missing rows have count `0`; use `.is_missing` to
distinguish them from present empty geometries.

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | One count per input geometry. |

### parts `property` `readonly`

```python
parts: Groups[GeometryArray[Geometry] | None]
```

Top-level parts grouped by source row.

Simple geometries form one-element groups, multipart and collection
geometries expose their immediate members, empty geometries form empty
groups, and missing source rows remain missing groups.

Returns:

| Type | Description |
| --- | --- |
| `Groups` | One group per input row; missing rows yield `None`. |

### topological\_dimension `property`

```python
topological_dimension: ndarray[tuple[int], dtype[int64]]
```

Per-geometry topological dimension — `0` point, `1` curve, `2`
areal (see `Geometry.topological_dimension`). Missing rows use `-1`;
use `.is_missing` to distinguish them from present point-like
geometries.

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | One dimension per input geometry. |

### total\_bounds `property`

```python
total_bounds: tuple[float, float, float, float] | None
```

Combined bounds `(minx, miny, maxx, maxy)` over all geometries, or
`None` if every geometry is empty. Geographic longitude bounds use
the CRS's periodic interval, so `minx > maxx` denotes a seam crossing.

Returns:

| Type | Description |
| --- | --- |
| `tuple or None` |  |

### \_\_bool\_\_

```python
__bool__() -> bool
```

`False` only when the array has zero rows.

Returns:

| Type | Description |
| --- | --- |
| `bool` |  |

### \_\_contains\_\_

```python
__contains__(value: object, /) -> bool
```

Whether a geometry (or missing row via `None`) is present.

Equality is structural (`Geometry.__eq__`): CRS, epoch, and exact
geometry. `None in arr` is true when any row is missing.

Returns:

| Type | Description |
| --- | --- |
| `bool` |  |

### \_\_getitem\_\_

Accepted call forms

```python
__getitem__(index: ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]], /) -> GeometryT_co
```

```python
__getitem__(index: ndarray[tuple[int], dtype[signedinteger[Any] | unsignedinteger[Any]]], /) -> GeometryArray[GeometryT_co]
```

```python
__getitem__(index: ndarray[tuple[int], dtype[bool_]], /) -> GeometryArray[GeometryT_co]
```

```python
__getitem__(index: ndarray[tuple[Any, ...], dtype[signedinteger[Any] | unsignedinteger[Any]]], /) -> GeometryT_co | GeometryArray[GeometryT_co]
```

```python
__getitem__(index: SupportsIndex, /) -> GeometryT_co
```

```python
__getitem__(index: slice, /) -> GeometryArray[GeometryT_co]
```

```python
__getitem__(index: Sequence[bool], /) -> GeometryArray[GeometryT_co]
```

```python
__getitem__(index: Sequence[SupportsIndex] | ndarray[tuple[int], dtype[signedinteger[Any] | unsignedinteger[Any]]] | Buffer, /) -> GeometryArray[GeometryT_co]
```

```python
__getitem__(index: SupportsIndex | slice | ndarray[tuple[int], dtype[bool_]] | Sequence[bool] | (Sequence[SupportsIndex] | ndarray[tuple[int], dtype[signedinteger[Any] | unsignedinteger[Any]]] | Buffer) | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]] | ndarray[tuple[int], dtype[signedinteger[Any] | unsignedinteger[Any]]] | ndarray[tuple[Any, ...], dtype[signedinteger[Any] | unsignedinteger[Any]]], /) -> GeometryT_co | GeometryArray[GeometryT_co]
```

Select rows by integer, slice, or fancy index.

An `int` returns one typed geometry (or raises `IndexError`).
A `slice` or integer sequence / boolean mask returns a gathered
`GeometryArray` (missing rows stay missing).

Returns:

| Type | Description |
| --- | --- |
| `Geometry or GeometryArray` | Scalar geometry for an int index; array for slice/fancy selection. |

### \_\_iter\_\_

```python
__iter__() -> Iterator[GeometryT_co]
```

Iterate geometries in row order (including missing rows as `None`).

Returns:

| Type | Description |
| --- | --- |
| `iterator of Geometry or None` |  |

### \_\_len\_\_

```python
__len__() -> int
```

Number of rows (including missing rows).

Returns:

| Type | Description |
| --- | --- |
| `int` |  |

### \_\_reversed\_\_

```python
__reversed__() -> GeometryArrayIterator[GeometryT_co]
```

Iterate geometries in reverse row order.

Returns:

| Type | Description |
| --- | --- |
| `iterator of Geometry or None` |  |

### affine\_transform

```python
affine_transform(matrix: tuple[float, float, float, float, float, float] | Iterable[float]) -> Self
```

Apply a 2D affine transform `(a, b, d, e, xoff, yoff)` to a geometry.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `matrix` | `sequence of float` | The six affine coefficients (a, b, d, e, xoff, yoff). | *required* |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One transformed geometry per row (kinds preserved). |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If `matrix` is not 6 finite numbers. |

Examples:

```pycon
>>> import gometry as gm
>>> gm.LineString([(0, 0), (1, 1)]).affine_transform([2, 0, 0, 2, 1, 1]).to_wkt()
'LINESTRING (1 1, 3 3)'
```

### boundary

Accepted call forms

```python
boundary() -> GeometryArray[GeometryCollection]
```

```python
boundary() -> GeometryArray[MultiPoint]
```

```python
boundary() -> GeometryArray[MultiPoint | LineString | MultiLineString | GeometryCollection]
```

```python
boundary() -> GeometryArray[GeometryCollection | None]
```

```python
boundary() -> GeometryArray[MultiPoint | None]
```

```python
boundary() -> GeometryArray[MultiPoint | LineString | MultiLineString | GeometryCollection | None]
```

```python
boundary() -> GeometryArray[MultiPoint | LineString | MultiLineString | GeometryCollection]
```

```python
boundary() -> GeometryArray[MultiPoint | LineString | MultiLineString | GeometryCollection | None]
```

Return the topological boundary of the geometry's occupied support.

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One boundary per row, retaining missing rows. |

Notes

Each row is processed independently. Non-missing outputs retain their row's
CRS and coordinate epoch. Output coordinate axes reflect ordinates available
at every emitted vertex.

Raises:

| Type | Description |
| --- | --- |
| `CRSError` | If the declared CRS cannot be resolved to a topology frame. |
| `InvalidGeometryError` | If a geographic coordinate read by boundary is outside its CRS domain. |
| `ResourceLimitError` | If exact work exceeds the generated-item or embedding-search budget. |
| `OverflowError` | If emitted cells cannot preserve the exact topology in binary64. |

Examples:

```pycon
>>> import gometry as gm
>>> gm.box(0, 0, 2, 2).boundary().to_wkt()
'LINESTRING (0 0, 2 0, 2 2, 0 2, 0 0)'
```

### buffer

Accepted call forms

```python
buffer(distance: FloatInput, *, cap_style: Literal['round', 'flat', 'square'] = 'round', join_style: Literal['round', 'miter', 'bevel'] = 'round', quadrant_segments: int = 8, miter_limit: float = 5.0, side: Literal['both', 'left', 'right'] = 'both', unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[Polygon]
```

```python
buffer(distance: FloatInput, *, cap_style: Literal['round', 'flat', 'square'] = 'round', join_style: Literal['round', 'miter', 'bevel'] = 'round', quadrant_segments: int = 8, miter_limit: float = 5.0, side: Literal['both', 'left', 'right'] = 'both', unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[Polygon | None]
```

```python
buffer(distance: float, *, cap_style: Literal['round', 'flat', 'square'] = 'round', join_style: Literal['round', 'miter', 'bevel'] = 'round', quadrant_segments: int = 8, miter_limit: float = 5.0, side: Literal['both', 'left', 'right'] = 'both', unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[Polygon | MultiPolygon]
```

```python
buffer(distance: float, *, cap_style: Literal['round', 'flat', 'square'] = 'round', join_style: Literal['round', 'miter', 'bevel'] = 'round', quadrant_segments: int = 8, miter_limit: float = 5.0, side: Literal['both', 'left', 'right'] = 'both', unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[Polygon | MultiPolygon | None]
```

```python
buffer(distance: FloatInput, *, cap_style: Literal['round', 'flat', 'square'] = 'round', join_style: Literal['round', 'miter', 'bevel'] = 'round', quadrant_segments: int = 8, miter_limit: float = 5.0, side: Literal['both', 'left', 'right'] = 'both', unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[Polygon | MultiPolygon]
```

```python
buffer(distance: FloatInput, *, cap_style: Literal['round', 'flat', 'square'] = 'round', join_style: Literal['round', 'miter', 'bevel'] = 'round', quadrant_segments: int = 8, miter_limit: float = 5.0, side: Literal['both', 'left', 'right'] = 'both', unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[Polygon | MultiPolygon | None]
```

Buffer a geometry by `distance`, returning the offset region (measured for
the CRS).

On a geographic CRS, stored source-chart edges are refined when their projected
curves cannot be certified within the local-frame input budget before the planar
kernel runs. This input-fidelity budget is separate from the 0.1% frame-fit
limit and from round-arc resolution, which `quadrant_segments` controls; it
does not promise an end-to-end ellipsoidal distance error.
For single-sided buffers, chord directions determine endpoint normals, so the
input-fidelity budget does not bound output endpoint displacement.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `distance` | `float or sequence of float` | Buffer radius; negative shrinks areal geometries. CRS-aware: geodesic meters on a geographic CRS, native linear units on a projected CRS, raw coordinate units when CRS-free — a scalar applies to every geometry, or pass one value per geometry. Every distance must be finite. | *required* |
| `cap_style` | `('round', 'flat', 'square')` | End-cap shape at the original first and last vertices of open lines. Closed lines have no end caps. Point inputs always buffer to round discs, and MultiPoint buffers are unions of round discs; `cap_style` does not affect either. Sided buffers always use flat ends, so this parameter applies to `side='both'` only. | `'round'` |
| `join_style` | `('round', 'miter', 'bevel')` | Interior corner style for both two-sided and sided line buffers, including 180-degree reversals. | `'round'` |
| `quadrant_segments` | `int` | Segments used to approximate a quarter-circle join in either buffer mode. | `8` |
| `miter_limit` | `float` | With `join_style='miter'`: how far a mitered corner may reach, in multiples of `distance`; sharper corners are clipped flat at that reach. Applies to both two-sided and sided buffers; must be positive and finite. | `5.0` |
| `side` | `('both', 'left', 'right')` | Which side(s) of lineal input to buffer. `'left'`/`'right'` build the one-sided strip between the line and its offset curve, with flat ends. These sides honor the join parameters: `join_style`, `quadrant_segments`, and `miter_limit`. The distance must be non-negative.  Buffer boundaries are synthesized and therefore returned in XY; Z/M are not fabricated. | `'both'` |
| `unit` | `('planar', 'meters')` | `None` (the default) follows the CRS: geographic shape area and length use ellipsoidal chart-edge measures while point distances use geodesics; projected measurements use native linear units, and CRS-free measurements use raw coordinate units (area results square the corresponding unit). `'planar'` uses Cartesian coordinate space, with geographic coordinates in their native angular units. `'meters'` uses the CRS-aware metric and requires a CRS. | `'planar'` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One offset region per row. |

Raises:

| Type | Description |
| --- | --- |
| `InvalidGeometryError` | If coordinates are non-finite or buffer arithmetic produces a non-finite derived coordinate. |
| `GeometryError` | If `distance`/`quadrant_segments`/style parameters are invalid, or `unit=meters` is requested for a CRS-free geometry. |
| `ResourceLimitError` | If generated output exceeds its budget. |
| `GeometryTypeError` | If `side` is `'left'`/`'right'` and the geometry is not lineal. |

See Also

[offset\_curve](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.offset_curve "offset_curve") : One-sided raw parallel curve of a line.

Examples:

```pycon
>>> import gometry as gm
>>> disc = gm.Point(0, 0).buffer(10)
>>> round(disc.area)  # ~ pi * 10²
312
```

### build\_area

Accepted call forms

```python
build_area() -> GeometryArray[Polygon | MultiPolygon]
```

```python
build_area() -> GeometryArray[Polygon | MultiPolygon | None]
```

```python
build_area() -> GeometryArray[Polygon | MultiPolygon | GeometryCollection]
```

```python
build_area() -> GeometryArray[Polygon | MultiPolygon | GeometryCollection | None]
```

Assemble linework into one areal geometry. Input ordinates are carried
where vertices can be sourced; otherwise the mathematically planar result is XY.
When returned polygons retain different coordinate axes, they remain separate
members of a GeometryCollection rather than being promoted or flattened. The
GeometryArray method processes rows independently; to assemble linework from
several geometries as one area, combine them into one GeometryCollection first.

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One areal geometry per input row; missing rows remain missing. |

Raises:

| Type | Description |
| --- | --- |
| `InvalidGeometryError` | If the area cannot be assembled from the input linework. |

Examples:

```pycon
>>> import gometry as gm
>>> edges = [[(0,0),(2,0)],[(2,0),(0,2)],[(0,2),(0,0)]]
>>> gm.MultiLineString(edges).build_area().to_wkt()
'POLYGON ((0 0, 2 0, 0 2, 0 0))'
```

### centroid

Accepted call forms

```python
centroid() -> GeometryArray[Point]
```

```python
centroid() -> GeometryArray[Point | None]
```

Area/length-weighted center of the geometry. Geographic (lon/lat) input
crossing the antimeridian is auto-split-normalized; no manual
`split_antimeridian` is required. The computed center is an XY point.

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray[Point]` | One centroid per row (area/length-weighted; may lie outside). |

See Also

[point\_on\_surface](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.point_on_surface "point_on_surface") : A representative point guaranteed on the geometry.
[polylabel](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.polylabel "polylabel") : Pole of inaccessibility (best label anchor).

Raises:

| Type | Description |
| --- | --- |
| `InvalidGeometryError` | If a finite centroid cannot be computed. |

Examples:

```pycon
>>> import gometry as gm
>>> (gm.box(0, 0, 2, 4).centroid()).to_wkt()
'POINT (1 2)'
```

### concat

Accepted call forms

```python
concat(other: GeometryArray[GeometryOtherT], /, *others: GeometryArray[GeometryOtherT]) -> GeometryArray[GeometryT_co | GeometryOtherT]
```

```python
concat(other: GeometryArray[GeometryOtherT | None], /, *others: GeometryArray[GeometryOtherT | None]) -> GeometryArray[GeometryT_co | GeometryOtherT | None]
```

```python
concat() -> GeometryArray[GeometryT_co]
```

Concatenate zero or more arrays sharing this array's CRS and epoch.
With no arrays, return this array.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `other` | `GeometryArray` | First array to append; it must share this array's CRS and epoch. | *required* |
| `others` | `GeometryArray` | Additional arrays to append in order; each must share this array's CRS and epoch. | *required* |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` |  |

Examples:

```pycon
>>> import gometry as gm
>>> a = gm.GeometryArray([gm.box(0, 0, 1, 1)])
>>> a.concat(gm.GeometryArray([gm.Point(2, 2)])).to_wkt()
['POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))', 'POINT (2 2)']
```

### concave\_hull

Accepted call forms

```python
concave_hull(*, concavity: FloatInput = 2.0, length_threshold: FloatInput = 0.0, unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[Point | LineString | Polygon]
```

```python
concave_hull(*, concavity: FloatInput = 2.0, length_threshold: FloatInput = 0.0, unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[Point | LineString | Polygon | None]
```

Compute the concave hull of the geometry. CRS-aware via local projection
(approximate) and does NOT auto-split antimeridian-crossing geographic input;
call `split_antimeridian` first. Uses gometry's chi-shape kernel: Delaunay
boundary triangles are peeled from longest edge to shortest. The geometric XY
hull is independent of input point order. Hull vertices are copies of input
vertices, so X/Y/Z/M ordinates are preserved exactly. When several input vertices
share an XY position, the first in storage order is the survivor.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `concavity` | `float or sequence of float` | Sets the peel distance guard: a candidate triangle's opposite vertex must lie within `edge_length / concavity` of its boundary edge. `0` disables this guard. Higher values typically keep more area, but the greedy peel does not guarantee area monotonicity as `concavity` increases — a scalar applies to every geometry, or pass one value per geometry. Each value must be finite and non-negative. | `2.0` |
| `length_threshold` | `float or sequence of float` | Boundary edges at or below this length are kept; each value must be finite and non-negative. For fixed input and `concavity`, a larger threshold always gives a hull that contains the smaller-threshold hull, so area never decreases. Interpreted for the CRS (see `unit`). On a geographic CRS the threshold is evaluated in a local projection, while the output vertices are emitted from the original input coordinates — a scalar applies to every geometry, or pass one value per geometry. | `0.0` |
| `unit` | `('planar', 'meters')` | `None` (the default) follows the CRS: geographic shape area and length use ellipsoidal chart-edge measures while point distances use geodesics; projected measurements use native linear units, and CRS-free measurements use raw coordinate units (area results square the corresponding unit). `'planar'` uses Cartesian coordinate space, with geographic coordinates in their native angular units. `'meters'` uses the CRS-aware metric and requires a CRS. | `'planar'` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One concave hull per row; degenerate inputs reduce dimension. |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If parameters are non-finite or negative, or selected hull vertices have different coordinate axis layouts. |

See Also

[convex\_hull](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.convex_hull "convex_hull") : Smallest convex set containing the geometry (planar).

Examples:

```pycon
>>> import gometry as gm
>>> mp = gm.MultiPoint([(0, 0), (2, 0), (2, 2), (0, 2), (1, 0.2)])
>>> hull = mp.concave_hull(concavity=1.0)
>>> (hull.geometry_type, round(hull.area, 2))
('Polygon', 3.0)
```

### convex\_hull

Accepted call forms

```python
convex_hull() -> GeometryArray[Point | LineString | Polygon]
```

```python
convex_hull() -> GeometryArray[Point | LineString | Polygon | None]
```

Compute the convex hull of the geometry. Operates in planar lon/lat space and does NOT
auto-split antimeridian-crossing geographic input; call
`split_antimeridian` first. Source vertices retained by the hull keep their
ordinates. Geographic hull construction can add chart-support vertices on
producer root edges; see the geometry guide's `Z/M under operations` section
for how their ordinates are carried. When several input vertices share an XY
position, the first in storage order is the copied survivor.

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One convex hull per row. |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If selected hull vertices have different coordinate axis layouts. |

See Also

[concave\_hull](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.concave_hull "concave_hull") : Concave hull that can follow non-convex outlines.

Examples:

```pycon
>>> import gometry as gm
>>> pts = gm.MultiPoint([(0, 0), (2, 0), (1, 1), (0, 2), (2, 2)])
>>> pts.convex_hull().to_wkt()
'POLYGON ((0 0, 2 0, 2 2, 0 2, 0 0))'
```

### count

```python
count(value: object) -> int
```

Number of structurally equal elements (`list.count` semantics, using
`Geometry.__eq__`).

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `value` | `Geometry` | The element to count. | *required* |

Returns:

| Type | Description |
| --- | --- |
| `int` | How many elements equal `value`. |

### destination

Accepted call forms

```python
destination(bearing: float | FloatInput, distance: float | FloatInput, *, path: Literal['geodesic'] = 'geodesic', unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[Point]
```

```python
destination(bearing: float | FloatInput, distance: float | FloatInput, *, path: Literal['rhumb'], unit: None = None) -> GeometryArray[Point]
```

```python
destination(bearing: float | FloatInput, distance: float | FloatInput, *, path: Literal['geodesic'] = 'geodesic', unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[Point | None]
```

```python
destination(bearing: float | FloatInput, distance: float | FloatInput, *, path: Literal['rhumb'], unit: None = None) -> GeometryArray[Point | None]
```

Walk each point along a geodesic or rhumb path. An empty point stays
`POINT EMPTY`.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `bearing` | `float or sequence of float` | Initial azimuth in degrees clockwise from north. | *required* |
| `distance` | `float or sequence of float` | Finite, non-negative distance to travel in CRS-natural units, unless `unit` is set. | *required* |
| `path` | `('geodesic', 'rhumb')` | Route model. Geodesic forms omit `path`; rhumb forms require `path='rhumb'` and a geographic CRS. | `'geodesic'` |
| `unit` | `('planar', 'meters')` | `None` (the default) follows the CRS: geographic shape area and length use ellipsoidal chart-edge measures while point distances use geodesics; projected measurements use native linear units, and CRS-free measurements use raw coordinate units (area results square the corresponding unit). `'planar'` uses Cartesian coordinate space, with geographic coordinates in their native angular units. `'meters'` uses the CRS-aware metric and requires a CRS.  `path='rhumb'` uses meters and does not accept a unit override. | `'planar'` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray[Point]` | One destination point per array row. |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If `bearing` or `distance` is invalid. |
| `CRSError` | If the selected route requires an unavailable CRS metric. |
| `GeometryTypeError` | If an input row is not a point. |
| `InvalidGeometryError` | If a coordinate is outside the longitude/latitude domain. |

Examples:

```pycon
>>> import gometry as gm
>>> points = gm.GeometryArray([
...     gm.Point(0, 0, crs=4326), gm.Point(1, 1, crs=4326)
... ])
>>> points.destination(90, 1000).to_wkt(precision=5)[0]
'POINT (0.00898 0)'
```

### dissolve

Accepted call forms

```python
dissolve(by: Iterable[GroupKeyT]) -> tuple[GeometryArray[Geometry], list[GroupKeyT]]
```

```python
dissolve(by: Iterable[GroupKeyT]) -> tuple[GeometryArray[Geometry | None], list[GroupKeyT]]
```

Dissolve geometries into per-group unions.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `by` | `iterable` | One grouping key per row (same length as the array). | *required* |

Returns:

| Type | Description |
| --- | --- |
| `tuple of (GeometryArray, list)` | One union per distinct key plus the parallel keys in first-occurrence order. |

Examples:

```pycon
>>> import gometry as gm
>>> arr = gm.GeometryArray([gm.box(0, 0, 1, 1), gm.box(1, 0, 2, 1)])
>>> geoms, keys = arr.dissolve(by=[0, 0])
>>> geoms.to_wkt()
['POLYGON ((0 0, 2 0, 2 1, 0 1, 0 0))']
```

### drop\_missing

```python
drop_missing() -> GeometryArray[GeometryT]
```

Return a new array without the missing rows.

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | The present rows, in order; the input unchanged (and returned as-is when dense). |

Examples:

```pycon
>>> import gometry as gm
>>> len(gm.GeometryArray([gm.Point(0, 0), None]).drop_missing())
1
```

### envelope

Accepted call forms

```python
envelope() -> GeometryArray[Point | Polygon]
```

```python
envelope() -> GeometryArray[Point | Polygon | None]
```

```python
envelope() -> GeometryArray[Point | LineString | Polygon]
```

```python
envelope() -> GeometryArray[Point | LineString | Polygon | None]
```

Axis-aligned bounding-box polygon of the geometry, returned in XY.

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One envelope per row. |

Raises:

| Type | Description |
| --- | --- |
| `InvalidGeometryError` | If coordinates are non-finite. |

Examples:

```pycon
>>> import gometry as gm
>>> gm.LineString([(0, 0), (3, 1)]).envelope().to_wkt()
'POLYGON ((0 0, 3 0, 3 1, 0 1, 0 0))'
```

### estimate\_local\_crs

```python
estimate_local_crs() -> CRS
```

Estimate one conformal metric CRS for all present rows.

Missing rows are ignored. The complete present extent is evaluated
against a fixed 0.1% linear scale-error ceiling; empty/all-missing,
CRS-free, or geographically unsafe arrays raise `CRSError`.

Returns:

| Type | Description |
| --- | --- |
| `CRS` |  |

Examples:

```pycon
>>> import gometry as gm
>>> arr = gm.GeometryArray([gm.Point(-122.4, 37.8, crs=4326)])
>>> arr.estimate_local_crs()
CRS("EPSG:32610")
```

### extremes

Accepted call forms

```python
extremes() -> Extremes[GeometryArray[Point]]
```

```python
extremes() -> Extremes[GeometryArray[Point | None]]
```

Return the west, south, east, and north extreme vertices of the
geometry (numeric X/Y; ties keep the first vertex in storage order).

Returns:

| Type | Description |
| --- | --- |
| `Extremes` | Four row-aligned `Point` arrays as `(west, south, east, north)`. Missing rows stay missing in every column; empty rows degrade to an empty point per column. |

Examples:

```pycon
>>> import gometry as gm
>>> extremes = gm.box(0, 0, 2, 4).extremes()
>>> assert extremes is not None  # None only for an empty geometry
>>> (extremes.west.to_wkt(), extremes.north.to_wkt())
('POINT (0 0)', 'POINT (2 4)')
```

### fill\_missing

Accepted call forms

```python
fill_missing(value: GeometryOtherT) -> GeometryArray[GeometryT | GeometryOtherT]
```

```python
fill_missing(value: GeometryArray[GeometryOtherT | None]) -> GeometryArray[GeometryT | GeometryOtherT]
```

Return a new array with every missing row replaced by `value`.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `value` | `Geometry or GeometryArray` | A scalar fill geometry, or a row-aligned array whose values fill the matching missing rows. Only masked rows are consumed from an array fill value; every consumed row must be present. | *required* |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | A dense array (no missing rows); the input unchanged (and returned as-is when already dense). |

Raises:

| Type | Description |
| --- | --- |
| `CRSMismatchError` | If `value`'s CRS or coordinate-epoch metadata conflicts with the array's. |
| `ValueError` | If an array fill value has a different length. |

Examples:

```pycon
>>> import gometry as gm
>>> arr = gm.GeometryArray([gm.Point(0, 0), None])
>>> arr.fill_missing(gm.Point(9, 9)).to_wkt()[1]
'POINT (9 9)'
```

### force\_2d

```python
force_2d() -> Self
```

Drop Z and M ordinates, preserving geometry type and CRS.
Already-2D input is returned unchanged.

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One XY-only geometry per row (kinds preserved). |

See Also

[force\_3d](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.force_3d "force_3d") : Add a Z ordinate, filling missing vertices.

Examples:

```pycon
>>> import gometry as gm
>>> gm.from_wkt('POINT Z (1 2 3)').force_2d().to_wkt()
'POINT (1 2)'
```

### force\_3d

```python
force_3d(z: float = 0.0) -> Self
```

Make each geometry 3D, filling vertices that lack Z with `z`. Vertices
that already carry Z keep it; M passes through.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `z` | `float` | Finite Z to assign where it is missing. | `0.0` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One 3D geometry per row (kinds preserved). |

Raises:

| Type | Description |
| --- | --- |
| `InvalidGeometryError` | If `z` is not finite. |

See Also

[force\_2d](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.force_2d "force_2d") : Drop Z and M to plain XY.
[with\_coordinates](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.with_coordinates "with_coordinates") : Replace individual coordinate ordinates.

Examples:

```pycon
>>> import gometry as gm
>>> arr = gm.GeometryArray([gm.Point(1, 2)])
>>> arr.force_3d().to_wkt()[0]
'POINT Z (1 2 0)'
```

### index

```python
index(value: object, start: int = 0, stop: int | None = None) -> int
```

First index of a structurally equal element in `[start, stop)`
(list.index semantics, using Geometry.**eq**:
same
CRS, epoch,
and exact geometry; negative bounds count from the end).

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `value` | `Geometry` | The element to locate. | *required* |
| `start` | `int` | First position searched. | `0` |
| `stop` | `int` | One past the last position searched (the array length when omitted). | `None` |

Returns:

| Type | Description |
| --- | --- |
| `int` | The first matching position. |

Raises:

| Type | Description |
| --- | --- |
| `ValueError` | If no element in the window equals `value`. |

### interpolate\_m

```python
interpolate_m(start_m: FloatInput, end_m: FloatInput, *, overwrite: bool = False, unit: Literal['planar', 'meters'] | None = None) -> Self
```

Interpolate an M ordinate along the line's arc length (CRS-aware). M runs
from `start_m` at the start to `end_m` at the end, continuously across
multipart linework (the PostGIS `ST_AddMeasure` shape). The stationing
uses ellipsoidal arclength along straight source-chart edges on geographic CRSs
and planar distance otherwise; `unit='planar'` always uses Cartesian
coordinate space. Coordinates are never moved. Geographic length, perimeter,
and LRS use the same chart-edge model with CRS-aware units.

Z is preserved;
existing M requires `overwrite=True`. Every stored vertex is retained; a
zero-length X/Y segment has equal M values at both ends. Empty linework returns
the same empty with an M axis.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `start_m` | `float or sequence of float` | The measure range (finite, `end_m >= start_m`) — a scalar applies to every geometry, or pass one value per geometry. | *required* |
| `end_m` | `float or sequence of float` | The measure range (finite, `end_m >= start_m`) — a scalar applies to every geometry, or pass one value per geometry. | *required* |
| `overwrite` | `bool` | Replace existing M ordinates instead of raising. | `False` |
| `unit` | `('planar', 'meters')` | `None` (the default) follows the CRS: geographic shape area and length use ellipsoidal chart-edge measures while point distances use geodesics; projected measurements use native linear units, and CRS-free measurements use raw coordinate units (area results square the corresponding unit). `'planar'` uses Cartesian coordinate space, with geographic coordinates in their native angular units. `'meters'` uses the CRS-aware metric and requires a CRS. | `'planar'` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One result per row (kinds preserved). |

Raises:

| Type | Description |
| --- | --- |
| `GeometryTypeError` | If the geometry is not lineal. |
| `InvalidGeometryError` | If the linework carries M without `overwrite`. |
| `GeometryError` | If the measure range is invalid. |

See Also

[line\_interpolate](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.line_interpolate "line_interpolate") : Point at a distance or M location along the line.
[line\_substring](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.line_substring "line_substring") : Extract a contiguous portion of the line.
[line\_locate](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.line_locate "line_locate") : Locate the nearest route position on the line.

Examples:

```pycon
>>> import gometry as gm
>>> line = gm.LineString([(0, 0), (10, 0)])
>>> line.interpolate_m(0.0, 100.0).to_wkt()
'LINESTRING M (0 0 0, 10 0 100)'
```

### line\_interpolate

Accepted call forms

```python
line_interpolate(at: Groups[NDArray[float64] | NDArray[int64]], *, basis: Literal['distance'] = 'distance', count: None = None, normalized: bool = False, unit: Literal['planar', 'meters'] | None = None) -> Groups[GeometryArray[Point]]
```

```python
line_interpolate(at: Groups[NDArray[float64] | NDArray[int64] | None], *, basis: Literal['distance'] = 'distance', count: None = None, normalized: bool = False, unit: Literal['planar', 'meters'] | None = None) -> Groups[GeometryArray[Point] | None]
```

```python
line_interpolate(at: Groups[NDArray[float64] | NDArray[int64]], *, basis: Literal['m'], count: None = None, normalized: Literal[False] = False, unit: None = None) -> Groups[GeometryArray[Point]]
```

```python
line_interpolate(at: Groups[NDArray[float64] | NDArray[int64] | None], *, basis: Literal['m'], count: None = None, normalized: Literal[False] = False, unit: None = None) -> Groups[GeometryArray[Point] | None]
```

```python
line_interpolate(at: FloatInput, *, basis: Literal['distance'] = 'distance', count: None = None, normalized: bool = False, unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[Point]
```

```python
line_interpolate(at: FloatInput, *, basis: Literal['distance'] = 'distance', count: None = None, normalized: bool = False, unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[Point | None]
```

```python
line_interpolate(at: None = None, *, count: int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]] | ndarray[tuple[int], dtype[signedinteger[Any] | unsignedinteger[Any]]] | Iterable[int] | Buffer, basis: Literal['distance'] = 'distance', normalized: Literal[False] = False, unit: Literal['planar', 'meters'] | None = None) -> Groups[GeometryArray[Point]]
```

```python
line_interpolate(at: None = None, *, count: int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]] | ndarray[tuple[int], dtype[signedinteger[Any] | unsignedinteger[Any]]] | Iterable[int] | Buffer, basis: Literal['distance'] = 'distance', normalized: Literal[False] = False, unit: Literal['planar', 'meters'] | None = None) -> Groups[GeometryArray[Point] | None]
```

```python
line_interpolate(at: FloatInput, *, count: None = None, basis: Literal['m'], normalized: Literal[False] = False, unit: None = None) -> GeometryArray[Point]
```

```python
line_interpolate(at: FloatInput, *, count: None = None, basis: Literal['m'], normalized: Literal[False] = False, unit: None = None) -> GeometryArray[Point | None]
```

Interpolate point locations along linework. Empty linework yields
`POINT EMPTY` at every location.

Distance-basis routes retain vertices at zero-length X/Y segments. At an
interior prefix shared by such a run, an exact boundary selects its first
stored vertex; normalized `0` and `1` select the first and last stored
vertices. M-basis interpolation follows the stored monotonic measure and keeps
vertices whose active Z/M ordinates differ even when X/Y is equal.

With CRS-aware units (the default on a geographic CRS), each source edge is
straight in the CRS's longitude and latitude chart and distance is ellipsoidal
arclength along that edge. An independently interpolated point uses canonical
longitude; original endpoints retain their stored spelling. `unit='planar'`
instead uses Cartesian distance in the stored coordinate space.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `at` | `float or sequence of float` | One location or many explicit distance-basis locations. Under `basis='m'`, pass one stored M value for a scalar result or a sequence of stored M values for one line; an array accepts one M value per row.  For an array, numeric `Groups` supplies a separate sequence of explicit locations per route, for either basis. Group count must match array length.  Empty station groups produce empty point groups; missing routes or station groups produce missing groups. Empty routes yield one empty point per station. A plain numeric sequence stays flat, including an empty sequence; only `Groups` selects per-route groups. | *required* |
| `count` | `int or iterable of int` | Number of evenly spaced distance-basis samples per row (`>= 1`) along the metric selected by `unit`. A scalar broadcasts; otherwise pass one count per row. Mutually exclusive with `at` and unavailable with `basis='m'`; `normalized=True` is invalid because count already supplies fractional positions. | `None` |
| `basis` | `('distance', 'm')` | Use CRS-aware distance, or the line's monotonic M ordinate. Distance forms omit `basis`; M stationing requires `basis='m'`. Its M fraction selects the same arclength fraction on each edge: ellipsoidal chart-edge arclength on a geographic CRS, planar length otherwise. | `'distance'` |
| `normalized` | `bool` | Interpret distance-basis `at` values as fractions of the route length under the selected metric. Changing `unit` can change their positions. Invalid with `basis='m'`. | `False` |
| `unit` | `('planar', 'meters')` | `None` (the default) follows the CRS: geographic shape area and length use ellipsoidal chart-edge measures while point distances use geodesics; projected measurements use native linear units, and CRS-free measurements use raw coordinate units (area results square the corresponding unit). `'planar'` uses Cartesian coordinate space, with geographic coordinates in their native angular units. `'meters'` uses the CRS-aware metric and requires a CRS.  Available only with `basis='distance'`; invalid with `basis='m'`. | `'planar'` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray[Point] or Groups[GeometryArray[Point]]` | One point per row for scalar or row-aligned `at`; one point group per row for `count` samples or numeric `Groups` of explicit stations. |

Raises:

| Type | Description |
| --- | --- |
| `GeometryTypeError` | If the geometry is not lineal. |
| `InvalidGeometryError` | If M values are missing or non-monotonic. Array failures identify the original input row. |
| `GeometryError` | If input forms conflict, a value is non-finite, or a distance-only option is used with `basis='m'`. |
| `ResourceLimitError` | If `count` exceeds the generated-output budget. |

See Also

[line\_locate](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.line_locate "line_locate") : Locate the nearest route position; repeated support makes the inverse non-unique.
[line\_substring](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.line_substring "line_substring") : Extract a contiguous portion of the line.
[interpolate\_m](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.interpolate_m "interpolate_m") : Assign M ordinates along arc length.

Examples:

```pycon
>>> import gometry as gm
>>> line = gm.LineString([(0, 0), (10, 0)])
>>> line.line_interpolate(4).to_wkt()
'POINT (4 0)'
```

### line\_locate

Accepted call forms

```python
line_locate(point: Point | GeometryArray[Point | None], *, basis: Literal['m'], normalized: Literal[False] = False, unit: None = None) -> NDArray[float64]
```

```python
line_locate(point: Point | GeometryArray[Point | None], *, basis: Literal['distance'] = 'distance', normalized: bool = False, unit: Literal['planar', 'meters'] | None = None) -> NDArray[float64]
```

Locate the position on linework nearest `point`. Empty linework, or
an empty query point, locates to `nan`.

Projection is in X/Y. Zero-length X/Y segments add no distance-basis projection.
Planar distance-basis locate selects the exactly nearest segment; exact ties
prefer an interior projection over an endpoint, then the first segment in route
order, matching planar proximity. Geographic locate applies the same role and
source order when evaluated backend distances compare equal. It ranks available
measurements, including the chart projection trial, rather than asserting an
exact geodesic minimum. With `basis='m'`, the returned M is taken from the
selected projection.

With CRS-aware units on a geographic CRS, locate minimizes geodesic distance to
the straight chart edges and returns cumulative ellipsoidal arclength to the
nearest point. `unit='planar'` instead uses Cartesian distance in the stored
coordinate space.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `point` | `Point or GeometryArray[Point \| None]` | A point to project, or one point per line row. Missing query rows produce `nan` in the result column. | *required* |
| `basis` | `('distance', 'm')` | Return a CRS-aware distance, or the line's monotonic M ordinate. Distance forms omit `basis`; M stationing requires `basis='m'`. M-based projection follows the same chart-edge metric: ellipsoidal arclength on a geographic CRS, planar length otherwise. | `'distance'` |
| `normalized` | `bool` | Return a distance-basis fraction in [0, 1] under the selected metric. Changing `unit` can change the nearest projection and returned fraction. Invalid with `basis='m'`. | `False` |
| `unit` | `('planar', 'meters')` | `None` (the default) follows the CRS: geographic shape area and length use ellipsoidal chart-edge measures while point distances use geodesics; projected measurements use native linear units, and CRS-free measurements use raw coordinate units (area results square the corresponding unit). `'planar'` uses Cartesian coordinate space, with geographic coordinates in their native angular units. `'meters'` uses the CRS-aware metric and requires a CRS.  Available only with `basis='distance'`; invalid with `basis='m'`. | `'planar'` |

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | One location per line row. |

Raises:

| Type | Description |
| --- | --- |
| `CRSError` | If the CRS cannot provide an unambiguous distance metric. |
| `CRSMismatchError` | If operands' CRS or coordinate-epoch metadata differ. |
| `GeometryTypeError` | If the geometry is not lineal. |
| `InvalidGeometryError` | If M values are missing or non-monotonic. Array failures identify the original input row. |
| `GeometryError` | If a distance-only option is used with `basis='m'`. |

See Also

[line\_interpolate](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.line_interpolate "line_interpolate") : Point at a route station; locate/interpolate round-trip only at a unique nearest position.
[line\_substring](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.line_substring "line_substring") : Extract a contiguous portion of the line.
[interpolate\_m](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.interpolate_m "interpolate_m") : Assign M ordinates along arc length.

Examples:

```pycon
>>> import gometry as gm
>>> line = gm.LineString([(0, 0), (10, 0)])
>>> line.line_locate(gm.Point(4, 3))
4.0
```

### line\_merge

Accepted call forms

```python
line_merge(*, directed: bool = False) -> GeometryArray[LineString]
```

```python
line_merge(*, directed: bool = False) -> GeometryArray[LineString | None]
```

```python
line_merge(*, directed: bool = False) -> GeometryArray[LineString | MultiLineString]
```

```python
line_merge(*, directed: bool = False) -> GeometryArray[LineString | MultiLineString | None]
```

Merge connected LineString parts into longer LineStrings.

Joins occur only at degree-two endpoints, never across branching junctions.
With `directed=True`, join only a source end to a source start: no component's
coordinate order is reversed.
Directed merging keeps active-distinct endpoint occurrences at a join, so
different Z/M values at the same X/Y are retained as consecutive vertices.
Geographic endpoints use seam and pole identity. Joining source aliases may
canonicalize their longitude spelling and insert vertices to retain authored
full-period edges; inserted Z/M follow original-source arclength.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `directed` | `bool` | Preserve the direction of every source coordinate sequence. | `False` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One merged linework per row. |

Raises:

| Type | Description |
| --- | --- |
| `GeometryTypeError` | If the geometry is not lineal. |

Examples:

```pycon
>>> import gometry as gm
>>> a, b = [(0, 0), (1, 1)], [(1, 1), (2, 2)]
>>> (gm.MultiLineString([a, b]).line_merge()).to_wkt()
'LINESTRING (0 0, 1 1, 2 2)'
```

### line\_substring

Accepted call forms

```python
line_substring(start: FloatInput, end: FloatInput, *, basis: Literal['m'], normalized: Literal[False] = False, unit: None = None) -> GeometryArray[LineString | Point]
```

```python
line_substring(start: FloatInput, end: FloatInput, *, basis: Literal['m'], normalized: Literal[False] = False, unit: None = None) -> GeometryArray[LineString | Point | None]
```

```python
line_substring(start: FloatInput, end: FloatInput, *, basis: Literal['distance'] = 'distance', normalized: bool = False, unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[LineString | Point]
```

```python
line_substring(start: FloatInput, end: FloatInput, *, basis: Literal['distance'] = 'distance', normalized: bool = False, unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[LineString | Point | None]
```

Return the portion of linework from `start` through `end`. Empty
linework yields `LINESTRING EMPTY`.

Both bounds are inclusive. Stored vertices at zero-length X/Y segments consume
no distance but remain in the result when their active ordinates differ,
including consecutive vertices with identical X/Y. This applies to distance
and M basis.

With CRS-aware units, geographic cut points are inverted by ellipsoidal
arclength along straight source-chart edges. New endpoints embedded in a
retained source edge keep that edge's continuous longitude spelling.
`unit='planar'` instead interpolates in the stored coordinate space.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `start` | `float or sequence of float` | Ordered locations on the selected basis. Distance values follow the CRS; M values are stored route measures. A scalar applies to every array row. | *required* |
| `end` | `float or sequence of float` | Ordered locations on the selected basis. Distance values follow the CRS; M values are stored route measures. A scalar applies to every array row. | *required* |
| `basis` | `('distance', 'm')` | Use CRS-aware distance, or the line's monotonic M ordinate. Distance forms omit `basis`; M stationing requires `basis='m'`. Its M fraction selects the same arclength fraction on each edge: ellipsoidal chart-edge arclength on a geographic CRS, planar length otherwise. | `'distance'` |
| `normalized` | `bool` | Interpret distance-basis positions as fractions of the route length under the selected metric. Changing `unit` can change the cut points. Invalid with `basis='m'`. | `False` |
| `unit` | `('planar', 'meters')` | `None` (the default) follows the CRS: geographic shape area and length use ellipsoidal chart-edge measures while point distances use geodesics; projected measurements use native linear units, and CRS-free measurements use raw coordinate units (area results square the corresponding unit). `'planar'` uses Cartesian coordinate space, with geographic coordinates in their native angular units. `'meters'` uses the CRS-aware metric and requires a CRS.  Available only with `basis='distance'`; invalid with `basis='m'`. | `'planar'` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One substring per row. |

Raises:

| Type | Description |
| --- | --- |
| `GeometryTypeError` | If the geometry is not lineal. |
| `InvalidGeometryError` | If M values are missing or non-monotonic. Array failures identify the original input row. |
| `GeometryError` | If locations are non-finite or out of order, or a distance-only option is used with `basis='m'`. |

See Also

[line\_interpolate](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.line_interpolate "line_interpolate") : Point at a location along the line.
[line\_locate](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.line_locate "line_locate") : Locate the nearest route position on the line.
[interpolate\_m](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.interpolate_m "interpolate_m") : Assign M ordinates along arc length.

Examples:

```pycon
>>> import gometry as gm
>>> line = gm.LineString([(0, 0), (10, 0)])
>>> line.line_substring(2, 6).to_wkt()
'LINESTRING (2 0, 6 0)'
```

### map\_coordinate\_sequences

```python
map_coordinate_sequences(func: Callable[[NDArray[float64]], ArrayLike]) -> Self
```

Map each point, line, or ring sequence independently in row order.

Uses `Geometry.map_coordinate_sequences` admission and callback rules,
preserving each row's grouping, native ordinate schema, CRS, and epoch.
Missing rows remain missing and do not invoke the callback. Errors carry
the source row; callback exceptions retain their original type.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `func` | `callable` | Receives one read-only `(N, D)` float64 matrix at a time and may change N while preserving D. | *required* |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` |  |

### map\_coordinates

```python
map_coordinates(func: Callable[[NDArray[float64]], ArrayLike]) -> Self
```

Apply a vectorized callback to this array's coordinate matrix.

The callback receives a read-only `(N, dims)` float64 matrix for
present rows and must return a matrix with the same shape.
Non-uniform arrays (mixed-axes rows or a heterogeneous
GeometryCollection) use the view's union layout with NaN padding;
each member keeps its native axes on apply.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `func` | `callable` | Function called with the read-only coordinate matrix. | *required* |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` |  |

Examples:

```pycon
>>> import gometry as gm
>>> arr = gm.GeometryArray([gm.LineString([(0, 0), (1, 1)])])
>>> arr.map_coordinates(lambda m: m + 1).to_wkt()
['LINESTRING (1 1, 2 2)']
```

### maximum\_inscribed\_circle

Accepted call forms

```python
maximum_inscribed_circle(*, tolerance: FloatInput | None = None, unit: Literal['planar', 'meters'] | None = None) -> CircleArray[Circle]
```

```python
maximum_inscribed_circle(*, tolerance: FloatInput | None = None, unit: Literal['planar', 'meters'] | None = None) -> CircleArray[Circle | None]
```

Solve the largest circle inscribed in a polygonal geometry.
The returned Circle retains its center and radius independently of polygon
resolution. Read `circle.center` and `circle.radius` directly, or call
`circle.to_polygon(quadrant_segments=16)` for a contained polygonal realization.

Planar/projected input certifies the global inradius gap against `tolerance`;
the radius is the downward-rounded clearance at the retained representable center.
Geographic metric input solves in one retained local projection: the guarantee
applies there, rather than to the ellipsoid or restored source-coordinate polygon.
The center is returned in the source CRS and retains the source coordinate epoch.

Empty input has an empty center and NaN radius. A nonempty polygon with no
filled interior has its stored-bounds midpoint and radius zero.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `tolerance` | `float or sequence of float` | Positive absolute bound on the planar global-inradius gap, either shared or one value per row. Omitted selects a scale-aware tolerance per row. | `None` |
| `unit` | `('planar', 'meters')` | `None` (the default) follows the CRS: geographic shape area and length use ellipsoidal chart-edge measures while point distances use geodesics; projected measurements use native linear units, and CRS-free measurements use raw coordinate units (area results square the corresponding unit). `'planar'` uses Cartesian coordinate space, with geographic coordinates in their native angular units. `'meters'` uses the CRS-aware metric and requires a CRS. | `'planar'` |

Returns:

| Type | Description |
| --- | --- |
| `CircleArray` | Retained circle solutions with vectorized center and radius projections. Missing rows remain missing; empty and missing radii are NaN. |

Raises:

| Type | Description |
| --- | --- |
| `GeometryTypeError` | If the input is not polygonal. |
| `InvalidGeometryError` | If invalid polygonal topology prevents the circle calculation. |
| `GeometryError` | If tolerance is not positive and finite, or meters are requested without a CRS. |
| `OverflowError` | If the requested inradius accuracy has no representable center/radius result. |
| `CRSError` | If a geographic working frame cannot be prepared. |

See Also

[minimum\_bounding\_circle](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.minimum_bounding_circle "minimum_bounding_circle") : Smallest enclosing circle solution.
[polylabel](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.polylabel "polylabel") : Approximate label anchor from a distinct floating-point search.

Examples:

```pycon
>>> import gometry as gm
>>> circle = gm.box(0, 0, 2, 2).maximum_inscribed_circle()
>>> (circle.center.to_wkt(), circle.radius)
('POINT (1 1)', 1.0)
>>> circle.to_polygon().geometry_type
'Polygon'
```

### minimum\_bounding\_circle

Accepted call forms

```python
minimum_bounding_circle(*, unit: Literal['planar', 'meters'] | None = None) -> CircleArray[Circle]
```

```python
minimum_bounding_circle(*, unit: Literal['planar', 'meters'] | None = None) -> CircleArray[Circle | None]
```

Solve the smallest circle enclosing the geometry.
Read `circle.center` and `circle.radius` without constructing a polygon.
`circle.to_polygon(quadrant_segments=16)` creates a circumscribed polygon
whose edges enclose the exact working-frame disk; a zero-radius disk yields
a Point and empty input yields POLYGON EMPTY.

For planar/projected input, the exact support disk is retained. Its center and
radius are rounded independently for numerical access; projected unit conversion
is applied before rounding. The polygon is certified against the exact disk,
not a reconstruction from those rounded values.

Geographic point sets with two distinct sites retain the midpoint of a shortest
ellipsoidal geodesic and half its inverse distance; a single site has radius zero.
This numerical solution remains available across global extents. Its polygon
uses the geographic Point.buffer local-projection approximation and may raise
CRSError when that realization exceeds the projection's accuracy domain.

Other geographic input uses one retained local-projection disk, an approximation
rather than an ellipsoidal optimum. Source-chart edges may be refined before
the projected support calculation.

Geographic radii are in meters; centers and
polygons are in the source CRS.
The center retains the source coordinate epoch. A zero-radius center selected
from an input site preserves the first source point's ordinates and spelling;
computed centers and positive-radius polygon realizations are XY.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `unit` | `('planar', 'meters')` | `None` (the default) follows the CRS: geographic shape area and length use ellipsoidal chart-edge measures while point distances use geodesics; projected measurements use native linear units, and CRS-free measurements use raw coordinate units (area results square the corresponding unit). `'planar'` uses Cartesian coordinate space, with geographic coordinates in their native angular units. `'meters'` uses the CRS-aware metric and requires a CRS. | `'planar'` |

Returns:

| Type | Description |
| --- | --- |
| `CircleArray` | Retained circle solutions. Missing rows remain missing; numeric projections use NaN for empty and missing rows. |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If meters are requested without a CRS. |
| `CRSError` | If a geographic local-projection solution cannot fit its accuracy domain. One-/two-point ellipsoidal solutions do not require a local frame. |
| `OverflowError` | If input coordinates cannot support a finite-coordinate circle calculation. |

Examples:

```pycon
>>> import gometry as gm
>>> circle = gm.MultiPoint([(0, 0), (4, 0)]).minimum_bounding_circle()
>>> (circle.center.to_wkt(), circle.radius)
('POINT (2 0)', 2.0)
```

### minimum\_clearance

```python
minimum_clearance(*, unit: Literal['planar', 'meters'] | None = None) -> NDArray[float64]
```

Smallest distance by which a vertex could move to invalidate the geometry.
On a geographic CRS, the witness is selected in the geometry's best local
projection and then measured geodesically in source coordinates; this is a
local-projection approximation, not an exact ellipsoidal clearance search.
Original vertices remain clearance sites. Refined chart-edge samples improve
boundary support without becoming new sites; an on-edge witness is interpolated
on its original source segment.
Projected CRS and CRS-free geometries measure in the active planar units.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `unit` | `('planar', 'meters')` | `None` (the default) follows the CRS: geographic shape area and length use ellipsoidal chart-edge measures while point distances use geodesics; projected measurements use native linear units, and CRS-free measurements use raw coordinate units (area results square the corresponding unit). `'planar'` uses Cartesian coordinate space, with geographic coordinates in their native angular units. `'meters'` uses the CRS-aware metric and requires a CRS. | `'planar'` |

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | One clearance distance per row. |

Examples:

```pycon
>>> import gometry as gm
>>> gm.box(0, 0, 3, 2).minimum_clearance()
2.0
```

### minimum\_clearance\_line

Accepted call forms

```python
minimum_clearance_line(*, unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[LineString]
```

```python
minimum_clearance_line(*, unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[LineString | None]
```

Two-point line realizing `minimum_clearance`. The metric matches
minimum\_clearance: on a geographic CRS, the witness is selected in the
geometry's best local projection and returned in source coordinates, so it is a
local-projection approximation rather than an exact ellipsoidal clearance
search. Original vertices remain clearance sites; inserted chart-edge support
samples do not become new sites, and an on-edge witness is interpolated on the
original source segment.
`LINESTRING EMPTY` when the clearance is infinite (fewer than two distinct
vertices).

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `unit` | `('planar', 'meters')` | `None` (the default) follows the CRS: geographic shape area and length use ellipsoidal chart-edge measures while point distances use geodesics; projected measurements use native linear units, and CRS-free measurements use raw coordinate units (area results square the corresponding unit). `'planar'` uses Cartesian coordinate space, with geographic coordinates in their native angular units. `'meters'` uses the CRS-aware metric and requires a CRS. | `'planar'` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One realizing line per row. |

See Also

[minimum\_clearance](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.minimum_clearance "minimum_clearance") : The clearance distance itself.

Examples:

```pycon
>>> import gometry as gm
>>> (gm.box(0, 0, 3, 2).minimum_clearance_line()).to_wkt()
'LINESTRING (0 0, 0 2)'
```

### minimum\_rotated\_rectangle

Accepted call forms

```python
minimum_rotated_rectangle() -> GeometryArray[Point | LineString | Polygon]
```

```python
minimum_rotated_rectangle() -> GeometryArray[Point | LineString | Polygon | None]
```

Minimum-area rotated bounding rectangle. A computed areal rectangle is
returned in XY. A degenerate geographic result that follows source-edge support
can retain resolvable Z/M by the original edge's ellipsoidal arclength; see the
geometry guide's `Z/M under operations` section.

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One rotated rectangle per row. |

Raises:

| Type | Description |
| --- | --- |
| `InvalidGeometryError` | If the rotated rectangle cannot be computed. |

Examples:

```pycon
>>> import gometry as gm
>>> rect = gm.box(0, 0, 2, 2).minimum_rotated_rectangle()
>>> gm.equals(rect, gm.box(0, 0, 2, 2))
True
```

### minimum\_width

```python
minimum_width(*, unit: Literal['planar', 'meters'] | None = None) -> NDArray[float64]
```

Width of the narrowest parallel strip enclosing the geometry.
Uses the complete convex hull, including all disconnected components. Holes
do not reduce the width. This is distinct from minimum clearance and from
the shorter side of the minimum-area rotated rectangle. A point or collinear
support has width zero; empty input has width NaN.

Planar/projected input selects antipodal hull supports using exact squared-width
comparisons and rounds the final measurement after unit conversion. Geographic
metric input uses the prepared geometry in one local projection, an approximation
on the ellipsoid. Source-chart edge refinement precedes the hull calculation.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `unit` | `('planar', 'meters')` | `None` (the default) follows the CRS: geographic shape area and length use ellipsoidal chart-edge measures while point distances use geodesics; projected measurements use native linear units, and CRS-free measurements use raw coordinate units (area results square the corresponding unit). `'planar'` uses Cartesian coordinate space, with geographic coordinates in their native angular units. `'meters'` uses the CRS-aware metric and requires a CRS. | `'planar'` |

Returns:

| Type | Description |
| --- | --- |
| `numpy.ndarray of float` | Minimum strip widths; NaN for empty and missing rows. |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If meters are requested without a CRS. |
| `CRSError` | If a geographic working frame cannot fit its accuracy domain. |
| `OverflowError` | If non-finite coordinates prevent the support calculation. |

Examples:

```pycon
>>> import gometry as gm
>>> gm.box(0, 0, 4, 2).minimum_width()
2.0
```

### node

Accepted call forms

```python
node() -> GeometryArray[MultiLineString]
```

```python
node() -> GeometryArray[MultiLineString | None]
```

Node linework by splitting every edge at all intersections. Input
ordinates are carried where possible; unsourceable seam vertices yield XY.

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | Noded linework per row. |

Raises:

| Type | Description |
| --- | --- |
| `OverflowError` | If no adjacent binary64 assignment preserves the exact noded linework. |
| `ResourceLimitError` | If the bounded embedding search is exhausted. |
| `InvalidGeometryError` | If noding fails on the input linework. |

Examples:

```pycon
>>> import gometry as gm
>>> lines = gm.MultiLineString([[(0,0),(2,0)],[(1,-1),(1,1)]])
>>> noded = lines.node()
>>> (noded.num_geometries, noded.length)
(4, 4.0)
```

### normalize

```python
normalize() -> Self
```

Return a geometry in canonical (normalized) form. The canonical form is the
lexicographically smallest equivalent presentation: parts sort ascending,
lines take their smaller direction (closed lines the smallest rotation), and
polygon rings lead with their minimum vertex under RFC 7946 winding
(exterior counter-clockwise, holes clockwise).

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | The canonical form of every element (kinds preserved). |

Examples:

```pycon
>>> import gometry as gm
>>> messy = gm.from_wkt('MULTIPOINT ((1 1), (0 0))')
>>> messy.normalize().to_wkt()
'MULTIPOINT ((0 0), (1 1))'
```

### offset\_curve

Accepted call forms

```python
offset_curve(distance: FloatInput, *, join_style: Literal['round', 'miter', 'bevel'] = 'round', quadrant_segments: int = 8, miter_limit: float = 5.0, unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[LineString]
```

```python
offset_curve(distance: FloatInput, *, join_style: Literal['round', 'miter', 'bevel'] = 'round', quadrant_segments: int = 8, miter_limit: float = 5.0, unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[MultiLineString]
```

```python
offset_curve(distance: FloatInput, *, join_style: Literal['round', 'miter', 'bevel'] = 'round', quadrant_segments: int = 8, miter_limit: float = 5.0, unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[GeometryCollection]
```

```python
offset_curve(distance: FloatInput, *, join_style: Literal['round', 'miter', 'bevel'] = 'round', quadrant_segments: int = 8, miter_limit: float = 5.0, unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[LineString | None]
```

```python
offset_curve(distance: FloatInput, *, join_style: Literal['round', 'miter', 'bevel'] = 'round', quadrant_segments: int = 8, miter_limit: float = 5.0, unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[MultiLineString | None]
```

```python
offset_curve(distance: FloatInput, *, join_style: Literal['round', 'miter', 'bevel'] = 'round', quadrant_segments: int = 8, miter_limit: float = 5.0, unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[GeometryCollection | None]
```

```python
offset_curve(distance: FloatInput, *, join_style: Literal['round', 'miter', 'bevel'] = 'round', quadrant_segments: int = 8, miter_limit: float = 5.0, unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[LineString | MultiLineString | GeometryCollection]
```

```python
offset_curve(distance: FloatInput, *, join_style: Literal['round', 'miter', 'bevel'] = 'round', quadrant_segments: int = 8, miter_limit: float = 5.0, unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[LineString | MultiLineString | GeometryCollection | None]
```

Compute a line offset to one side of a linestring by `distance` (measured
for the CRS).

Geographic input uses the same local-frame admission and source-chart edge
refinement as `buffer`. Its input-fidelity budget is separate from the 0.1%
frame-fit limit and round-join resolution, which `quadrant_segments` controls.
Chord directions determine endpoint normals, so the input-fidelity budget does
not bound output endpoint displacement.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `distance` | `float or sequence of float` | Offset; sign selects the side. CRS-aware: geodesic meters on a geographic CRS, native linear units on a projected CRS, raw coordinate units when CRS-free — a scalar applies to every geometry, or pass one value per geometry. The result is the RAW parallel curve: where the input folds back within `distance` the curve can self-intersect; `buffer(side=...)` gives the trimmed area instead. Every distance must be finite. | *required* |
| `join_style` | `('round', 'miter', 'bevel')` | Corner treatment at outside turns: `'round'` inscribes fillet arcs, `'miter'` extends the carriers to their crossing (clipped at `miter_limit`), `'bevel'` connects the offsets directly. | `'round'` |
| `quadrant_segments` | `int` | Segments per quarter circle of every round join. | `8` |
| `miter_limit` | `float` | With `join_style='miter'`: how far a mitered corner may reach, in multiples of `distance`, before it is clipped flat. | `5.0` |
| `unit` | `('planar', 'meters')` | `None` (the default) follows the CRS: geographic shape area and length use ellipsoidal chart-edge measures while point distances use geodesics; projected measurements use native linear units, and CRS-free measurements use raw coordinate units (area results square the corresponding unit). `'planar'` uses Cartesian coordinate space, with geographic coordinates in their native angular units. `'meters'` uses the CRS-aware metric and requires a CRS. | `'planar'` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One offset curve per row. |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If `distance`/`quadrant_segments`/style parameters are invalid. |
| `ResourceLimitError` | If generated output exceeds its budget. |

See Also

[buffer](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.buffer "buffer") : Offset region (optionally one-sided via `side`).

Examples:

```pycon
>>> import gometry as gm
>>> path = gm.LineString([(0, 0), (4, 0)])
>>> (path.offset_curve(1)).to_wkt()
'LINESTRING (0 1, 4 1)'
```

### orient\_polygons

```python
orient_polygons(*, ccw: bool = True) -> Self
```

Orient polygon rings to a consistent winding.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `ccw` | `bool` | `True` (default): exterior CCW, holes CW; `False` flips. | `True` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One reoriented geometry per row (kinds preserved). |

Examples:

```pycon
>>> import gometry as gm
>>> cw = gm.Polygon([(0, 0), (0, 1), (1, 1), (1, 0)])
>>> cw.orient_polygons().exterior.is_ccw
True
```

### point\_on\_surface

Accepted call forms

```python
point_on_surface() -> GeometryArray[Point]
```

```python
point_on_surface() -> GeometryArray[Point | None]
```

Representative point guaranteed to lie on the geometry. Geographic (lon/lat)
input crossing the antimeridian is auto-split-normalized; no manual
`split_antimeridian` is required. The point lies inside or on the geometry,
unlike centroid. Polygonal scanline candidates are checked after rounding; an
uncovered candidate falls back to a source boundary point. The representative
is computed in XY and does not imply a source Z/M. On planar polygonal input,
the first polygon component wins when representative chords have equal width.

See Also

[centroid](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.centroid "centroid") : Area/length-weighted center (may fall outside).
[polylabel](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.polylabel "polylabel") : Pole of inaccessibility (best label anchor).

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray[Point]` | One point inside or on each row's geometry. |

Raises:

| Type | Description |
| --- | --- |
| `InvalidGeometryError` | If a finite representative point cannot be computed. |

Examples:

```pycon
>>> import gometry as gm
>>> square = gm.box(0, 0, 2, 2)
>>> gm.within(square.point_on_surface(), square)
True
```

### polygonize

Accepted call forms

```python
polygonize() -> Groups[GeometryArray[Polygon]]
```

```python
polygonize() -> Groups[GeometryArray[Polygon] | None]
```

Build polygons from a geometry's own linework, automatically noding
crossings and overlaps. Each geometry is polygonized in isolation; to reconstruct
polygons from a pile of edges pooled across many geometries, use free function
`polygonize_all` on an iterable of
values. Input ordinates are carried where possible; unsourceable noding seams
yield XY.

Returns:

| Type | Description |
| --- | --- |
| `Groups of GeometryArray` | One ragged group of polygons per input geometry, in input order; missing rows yield `None` groups and present empty rows yield empty groups. Each input's OWN linework is polygonized independently (row `i` is `self[i].polygonize()`). To pool ALL rows' edges into one graph so a ring can close across inputs, use the free function `polygonize_all`. |

See Also

[polygonize\_all](https://gometry.monicz.dev/api/toplevel/constructive-validation/#gometry.polygonize_all "polygonize_all") : Pool linework across all supplied geometries.

Raises:

| Type | Description |
| --- | --- |
| `OverflowError` | If no adjacent binary64 assignment preserves the exact polygonized output. |
| `ResourceLimitError` | If the bounded embedding search is exhausted. |
| `InvalidGeometryError` | If polygons cannot be assembled from the linework. |

Examples:

```pycon
>>> import gometry as gm
>>> a, b = [(0, 0), (1, 0)], [(1, 0), (1, 1)]
>>> edges = gm.MultiLineString([a, b, [(1, 1), (0, 0)]])
>>> edges.polygonize().to_wkt()[0]
'POLYGON ((0 0, 1 0, 1 1, 0 0))'
```

### polylabel

Accepted call forms

```python
polylabel(*, tolerance: FloatInput | None = None, unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[Point]
```

```python
polylabel(*, tolerance: FloatInput | None = None, unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[Point | None]
```

Pole of inaccessibility: an approximate most-distant interior point
for label placement. Uses a floating-point cell search with `tolerance` as
its absolute stopping target. For a certified planar global-inradius gap,
use `maximum_inscribed_circle(...).center` instead.
Geographic line and ring boundaries may be refined in the local projection
before the search; `tolerance` controls the search, not the separate
input-refinement budget.
For a nonempty polygon with no filled interior, returns the midpoint of its
stored bounds with radius zero, including when its rings cancel the entire
support.
Empty geometries return `POINT EMPTY`.

See Also

[maximum\_inscribed\_circle](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.maximum_inscribed_circle "maximum_inscribed_circle") : Certified circle solution with direct center access.
[centroid](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.centroid "centroid") : Area/length-weighted center (may fall outside).
[point\_on\_surface](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.point_on_surface "point_on_surface") : A representative point guaranteed on the geometry.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `tolerance` | `float or sequence of float` | Positive absolute stopping target for the approximate label search, interpreted for the CRS (see `unit`) — a scalar applies to every geometry, or pass one value per geometry. Omitted selects a scale-aware tolerance independently for each geometry. | `None` |
| `unit` | `('planar', 'meters')` | `None` (the default) follows the CRS: geographic shape area and length use ellipsoidal chart-edge measures while point distances use geodesics; projected measurements use native linear units, and CRS-free measurements use raw coordinate units (area results square the corresponding unit). `'planar'` uses Cartesian coordinate space, with geographic coordinates in their native angular units. `'meters'` uses the CRS-aware metric and requires a CRS. | `'planar'` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray[Point]` | One point per row. |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If an explicit `tolerance` is not positive and finite. |
| `InvalidGeometryError` | If the pole of inaccessibility cannot be computed. |

Examples:

```pycon
>>> import gometry as gm
>>> gm.box(0, 0, 2, 2).polylabel().to_wkt()
'POINT (1 1)'
```

### quantize

```python
quantize(precision: int) -> Self
```

Round coordinates to a fixed number of decimal places.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `precision` | `int` | Decimal places to keep. Negative values round to tens, hundreds, and so on. Every present X/Y/Z/M ordinate is rounded independently, with ties to even, as with Python's `round`. The decimal result is rounded once to binary64. | *required* |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One rounded geometry per row (kinds preserved). |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If a rounded coordinate is outside the finite binary64 range. |

Examples:

```pycon
>>> import gometry as gm
>>> gm.Point(2.3479218, 48.8589321).quantize(3).to_wkt()
'POINT (2.348 48.859)'
```

### remove\_repeated\_points

```python
remove_repeated_points(*, tolerance: FloatInput = 0.0) -> Self
```

Drop consecutive duplicate coordinates within `tolerance`.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `tolerance` | `float or sequence of float` | Finite non-negative coordinate-space tolerance — native angular units for geographic CRSs, native linear units for projected CRSs, and raw coordinate units when CRS-free. A scalar applies to every geometry, or pass one value per geometry. | `0.0` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One deduplicated geometry per row (kinds preserved). |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If `tolerance` is negative or non-finite. |

Examples:

```pycon
>>> import gometry as gm
>>> stuttery = gm.LineString([(0, 0), (0, 0), (1, 1)])
>>> stuttery.remove_repeated_points().to_wkt()
'LINESTRING (0 0, 1 1)'
```

### repair

Accepted call forms

```python
repair(*, method: Literal['linework', 'structure'] = 'linework') -> GeometryArray[Point]
```

```python
repair(*, method: Literal['linework', 'structure'] = 'linework') -> GeometryArray[MultiPoint]
```

```python
repair(*, method: Literal['linework', 'structure'] = 'linework') -> GeometryArray[Point | MultiPoint | LineString | MultiLineString | GeometryCollection]
```

```python
repair(*, method: Literal['linework', 'structure'] = 'linework') -> GeometryArray[GeometryCollection]
```

```python
repair(*, method: Literal['linework', 'structure'] = 'linework') -> GeometryArray[Point | LineString | MultiLineString]
```

```python
repair(*, method: Literal['linework', 'structure'] = 'linework') -> GeometryArray[Polygon | MultiPolygon]
```

```python
repair(*, method: Literal['linework', 'structure'] = 'linework') -> GeometryArray[Point | None]
```

```python
repair(*, method: Literal['linework', 'structure'] = 'linework') -> GeometryArray[MultiPoint | None]
```

```python
repair(*, method: Literal['linework', 'structure'] = 'linework') -> GeometryArray[Point | MultiPoint | LineString | MultiLineString | GeometryCollection | None]
```

```python
repair(*, method: Literal['linework', 'structure'] = 'linework') -> GeometryArray[GeometryCollection | None]
```

```python
repair(*, method: Literal['linework', 'structure'] = 'linework') -> GeometryArray[Point | LineString | MultiLineString | None]
```

```python
repair(*, method: Literal['linework', 'structure'] = 'linework') -> GeometryArray[Polygon | MultiPolygon | None]
```

```python
repair(*, method: Literal['linework', 'structure'] = 'linework') -> GeometryArray[Geometry]
```

```python
repair(*, method: Literal['linework', 'structure'] = 'linework') -> GeometryArray[Geometry | None]
```

Repair invalid geometry, returning corrected result(s) (OGC). Already-valid
input is returned unchanged at validation cost. Geographic repair checks exact
quotient validity before rebuilding; when output construction needs seam
vertices it splits the source while preserving traceable Z/M ordinates.
Projected and CRS-free geometry remains planar. A collapsed LineString becomes
a Point at its first coordinate. Collapsed MultiLineString members become a
Point or MultiPoint, combined with surviving linework in a GeometryCollection
when both dimensions remain.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `method` | `('linework', 'structure')` | Repair strategy: `linework` nodes all boundary linework and selects regions from each original ring occurrence's winding modulo two before recombining each polygon's shell minus its holes; distinct polygon members are unioned. `structure` rebuilds each ring's nonzero-winding enclosed area and recombines it as shells minus holes.  Z/M are carried at vertices traceable to the input; a rebuild that needs unsourceable vertices returns the mathematically natural XY result. | `'linework'` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One valid geometry per row. |

Raises:

| Type | Description |
| --- | --- |
| `OverflowError` | If no adjacent binary64 assignment preserves the exact repaired geometry. |
| `ResourceLimitError` | If the bounded embedding search is exhausted. |
| `InvalidGeometryError` | If the geometry cannot be repaired. |

See Also

[validate](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.validate "validate") : Structured validity report.
[is\_valid](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.is_valid "is_valid property") : Boolean-only test.

Examples:

```pycon
>>> import gometry as gm
>>> bowtie = gm.from_wkt('POLYGON ((0 0, 2 2, 2 0, 0 2, 0 0))')
>>> fixed = bowtie.repair()
>>> (fixed.is_valid, fixed.geometry_type)
(True, 'MultiPolygon')
```

### reverse

```python
reverse() -> Self
```

Reverse the vertex order of a geometry. Linework retains every stored
vertex and its active Z/M ordinates, including equal-X/Y vertices, in reverse
order.

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One reversed geometry per row (kinds preserved). |

Examples:

```pycon
>>> import gometry as gm
>>> line = gm.LineString([(0, 0), (1, 1), (2, 2)])
>>> line.reverse().to_wkt()
'LINESTRING (2 2, 1 1, 0 0)'
```

### rotate

```python
rotate(angle: float, *, origin: Origin = 'centroid', radians: bool = False) -> Self
```

Rotate a geometry about an origin.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `angle` | `float` | Rotation angle (degrees by default; radians if `radians=True`). | *required* |
| `origin` | `str or sequence of float` | Transform origin: `'centroid'` (default), `'center'`, or an `(x, y)` point. | `'centroid'` |
| `radians` | `bool` | Interpret `angle` in radians instead of degrees. | `False` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One transformed geometry per row (kinds preserved). |

Examples:

```pycon
>>> import gometry as gm
>>> gm.Point(1, 0).rotate(90, origin=(0, 0)).to_wkt(precision=6)
'POINT (0 1)'
```

### sample\_points

Accepted call forms

```python
sample_points(count: int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]] | ndarray[tuple[int], dtype[signedinteger[Any] | unsignedinteger[Any]]] | Iterable[int] | Buffer, *, seed: int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]] | ndarray[tuple[int], dtype[signedinteger[Any] | unsignedinteger[Any]]] | Iterable[int] | Buffer | Generator | None = None, unit: Literal['planar', 'meters'] | None = None) -> Groups[GeometryArray[Point]]
```

```python
sample_points(count: int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]] | ndarray[tuple[int], dtype[signedinteger[Any] | unsignedinteger[Any]]] | Iterable[int] | Buffer, *, seed: int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]] | ndarray[tuple[int], dtype[signedinteger[Any] | unsignedinteger[Any]]] | Iterable[int] | Buffer | Generator | None = None, unit: Literal['planar', 'meters'] | None = None) -> Groups[GeometryArray[Point] | None]
```

Random points on the geometry. The sample space is its highest
dimension: area weighted for areal input, length
weighted for lineal input, and equal weight across point atoms.

Geographic
lines follow each retained longitude branch, while geographic areas are split
into seam- and pole-aware chart parts before sampling. Geographic defaults are
uniform in ellipsoid surface area and arclength on the straight source-chart
edges, not in a local projection or along geodesic replacement edges.

`unit='planar'` instead uses native chart measure; for example, a
degree-based 170° to -170° line follows its retained +20° path, contributing
20° rather than the raw 340° chord. Seam-crossing polygons use their seam-split
chart area, not the complementary raw-coordinate span.

Each logical
member contributes separately, so overlapping members retain their sampling
multiplicity. A zero-area polygon falls back to its linework, and zero-length
linework falls back to vertices, like centroid.

An integer `seed` reproduces
the same points for the same input and measure. Array rows draw distinct streams derived
from `seed` and the row index, and a scalar geometry IS row 0 — so
`arr.sample_points(n, seed=s)[0]` and
`arr[0].sample_points(n, seed=s)` agree.

An empty geometry has nothing to sample and yields no points. Results retain
the input CRS and coordinate epoch. Sampled points are new XY locations, so
they have no source Z/M.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `count` | `int or iterable of int` | Number of points to draw per row (`>= 0`). A scalar broadcasts; otherwise pass one count per row. | *required* |
| `seed` | `int, iterable of int, numpy.random.Generator, or None` | Seed for the deterministic sample stream. A scalar derives a distinct stream for every row; otherwise pass one explicit seed per row. A Generator advances once per call. `None` uses fresh entropy. | `None` |
| `unit` | `('meters', 'planar')` | `None` uses ellipsoidal area/length on geographic input and coordinate measures otherwise. `'planar'` uses chart measures. `'meters'` requires a CRS. | `'meters'` |

Returns:

| Type | Description |
| --- | --- |
| `Groups` | One `GeometryArray` of `count` sampled points per row. |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If `count` or `seed` is invalid. |
| `ResourceLimitError` | If `count` exceeds the generated-output budget. |

Examples:

```pycon
>>> import gometry as gm
>>> square = gm.box(0, 0, 10, 10)
>>> pts = square.sample_points(5, seed=42)
>>> (len(pts), all(p is not None and gm.within(p, square) for p in pts))
(5, True)
```

### scale

```python
scale(x_factor: float, y_factor: float | None = None, *, origin: Origin = 'centroid') -> Self
```

Scale a geometry about an origin.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `x_factor` | `float` | Scale factors along the X and Y axes; `y_factor` defaults to `x_factor`. | *required* |
| `y_factor` | `float` | Scale factors along the X and Y axes; `y_factor` defaults to `x_factor`. | *required* |
| `origin` | `str or sequence of float` | Transform origin: `'centroid'` (default), `'center'`, or an `(x, y)` point. | `'centroid'` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One transformed geometry per row (kinds preserved). |

Examples:

```pycon
>>> import gometry as gm
>>> gm.box(0, 0, 1, 1).scale(2, 2, origin=(0, 0)).bounds
(0.0, 0.0, 2.0, 2.0)
```

### segmentize

Accepted call forms

```python
segmentize(max_length: FloatInput, /, *, fraction: None = None, path: None = None, unit: Literal['planar', 'meters'] | None = None) -> Self
```

```python
segmentize(max_length: FloatInput, /, *, fraction: None = None, path: Literal['geodesic', 'rhumb'], unit: None = None) -> Self
```

```python
segmentize(max_length: None = None, /, *, fraction: FloatInput, path: Literal['geodesic', 'rhumb'] | None = None, unit: None = None) -> Self
```

Densify linework by inserting vertices so no segment exceeds
`max_length` (or a fraction of its length).

By default, each geographic edge keeps its stored shape: the straight line
between its longitude/latitude vertices. `max_length` is measured along that
edge on the ellipsoid. `path='geodesic'` or `path='rhumb'` instead places
new vertices along the shortest ellipsoidal route or the constant-bearing route
between each pair of endpoints. The result remains a polyline with straight
longitude/latitude edges, so its length approaches the selected route length as
the pieces get shorter.

Projected geometries use native linear units, and
CRS-free geometries use raw coordinate units.

Every original vertex survives
unchanged — this operation only inserts. Consecutive equal-X/Y vertices with
distinct active Z/M ordinates remain in their stored order; their zero-length
segments are not subdivided.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `max_length` | `float or sequence of float` | Positive maximum segment length, interpreted for the CRS (see `unit`) — a scalar applies to every geometry, or pass one value per geometry. Pass this positional argument or use `fraction`, but not both. | `None` |
| `fraction` | `float or sequence of float` | Fraction in `(0, 1]` of each source segment. Keyword-only; a scalar applies to every geometry, or pass one value per geometry. | *required* |
| `path` | `('geodesic', 'rhumb')` | Route for inserted geographic vertices. `None` keeps each stored edge; `'geodesic'` follows the shortest ellipsoidal route and is planar for projected or CRS-free inputs; `'rhumb'` follows a constant-bearing route and requires a geographic CRS. `fraction` is measured along the selected route. | `'geodesic'` |
| `unit` | `('planar', 'meters')` | `None` (the default) follows the CRS: geographic shape area and length use ellipsoidal chart-edge measures while point distances use geodesics; projected measurements use native linear units, and CRS-free measurements use raw coordinate units (area results square the corresponding unit). `'planar'` uses Cartesian coordinate space, with geographic coordinates in their native angular units. `'meters'` uses the CRS-aware metric and requires a CRS.  The override applies only to `max_length`; `fraction` has no unit and cannot be combined with `unit`. `path` cannot be combined with `unit`; geographic route distances are meters. | `'planar'` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One segmentized geometry per row (kinds preserved). |

Raises:

| Type | Description |
| --- | --- |
| `CRSError` | If `unit='meters'` is requested and the CRS lacks linear axis units, or `path='rhumb'` is requested without a geographic CRS, or the selected geodesic route has multiple shortest paths. |
| `GeometryError` | If neither or both constraints are supplied, `max_length` is not a positive finite number, `fraction` is outside `(0, 1]`, `unit` is combined with `fraction`, `path` is combined with `unit`, `unit='meters'` is requested for a CRS-free geometry. |
| `OverflowError` | If endpoint-preserving binary64 output cannot satisfy `max_length`. |
| `ResourceLimitError` | If generated coordinates exceed the output budget. |

Examples:

```pycon
>>> import gometry as gm
>>> gm.LineString([(0, 0), (4, 0)]).segmentize(2).to_wkt()
'LINESTRING (0 0, 2 0, 4 0)'
>>> # On a geographic CRS the bound is meters along the ellipsoid.
>>> line = gm.LineString([(0, 0), (1, 0)], crs=4326)
>>> len(list(line.segmentize(20_000).coords))
7
```

### segments

Accepted call forms

```python
segments() -> Groups[GeometryArray[LineString]]
```

```python
segments() -> Groups[GeometryArray[LineString] | None]
```

Consecutive vertex pairs per source geometry.

Each group contains that row's line and ring segments, including closing
edges, without joining parts or rings. Point and empty rows have empty
groups; missing rows remain missing. Ordinates, CRS, and epoch are retained.

Returns:

| Type | Description |
| --- | --- |
| `Groups[GeometryArray[LineString] \| None]` |  |

### self\_intersections

Accepted call forms

```python
self_intersections() -> Groups[GeometryArray[Point]]
```

```python
self_intersections() -> Groups[GeometryArray[Point] | None]
```

Return points where the geometry coincides with itself. Reports proper linework
self-crossings, non-adjacent touches, the endpoints of collinear overlaps
(spikes and backtracks), contact between distinct parts, and duplicate point
coordinates; legal adjacent shared vertices, ring closures, and removable
repeated consecutive vertices are not nodes. For point/lineal input the
result is non-empty exactly when is\_simple is `False`; areal input
diagnoses its rings' linework, and collections are diagnosed recursively.
Geographic diagnostics follow the CRS longitude quotient; projected and
CRS-free geometry remains planar. Points are XY only.

Returns:

| Type | Description |
| --- | --- |
| `Groups` | One `GeometryArray` of distinct self-intersection points per element; missing rows yield `None` groups. |

Examples:

```pycon
>>> import gometry as gm
>>> cross = gm.from_wkt('LINESTRING (0 0, 1 1, 1 0, 0 1)')
>>> cross.self_intersections().to_wkt()
['POINT (0.5 0.5)']
```

### simplify

```python
simplify(tolerance: FloatInput, *, method: Literal['vw', 'dp'] = 'vw', preserve_topology: bool = True, unit: Literal['planar', 'meters'] | None = None) -> Self
```

Simplify a geometry, dropping vertices below a tolerance. Two
algorithms, selected by `method`, both reading `tolerance` on the
same distance scale:

- `'vw'` (Visvalingam-Whyatt, the default) removes the least visually
  significant vertices first — the smallest effective triangle spanned
  with its two neighbors — for a smoother, more natural cartographic
  result. The effective-area threshold is `tolerance**2 / 2`.
- `'dp'` (Douglas-Peucker) compares exact distances to the closed retained
  chord against `tolerance`. Equal maximum distances select the earliest
  source vertex.

On geographic input, metre tolerances are conservatively converted to chart
units using the ellipsoid's global maximum principal radius and the angular
axes. This has no local-projection extent limit, but can retain extra detail,
especially near the poles. Selection still uses source-chart distances and
effective triangle areas, not geodesic replacement edges. VW is an effective-
area criterion, not a maximum-displacement guarantee. Original selected
vertices, including their Z/M ordinates, survive unchanged.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `tolerance` | `float or sequence of float` | Distance scale of removable detail — metres for geographic CRSs, native linear units for projected CRSs, and raw coordinate units when CRS-free. A scalar applies to every geometry, or pass one value per geometry. | *required* |
| `method` | `('vw', 'dp')` | `'vw'` is area-based (Visvalingam-Whyatt); `'dp'` is distance- based (Douglas-Peucker). | `'vw'` |
| `preserve_topology` | `bool` | Preserve topology within each geometry checked: valid polygonal components stay valid and non-collapsed, and simple lineal components stay simple. A `GeometryCollection` is checked child by child; relationships between separate children are not preserved. The raw algorithm runs first (the fast path); a guarded pass only runs when a component fails those checks. `False` skips the guarded check; collapsed areal rings are still removed. | `True` |
| `unit` | `('meters', 'planar')` | Override the CRS-natural tolerance scale. `'planar'` uses native chart units, including angular units on geographic input. `'meters'` requires a CRS and converts projected linear units to metres. | `'meters'` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One simplified geometry per row (kinds preserved). |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If `tolerance` is negative or non-finite. |
| `CRSError` | If a physical metric cannot be resolved, or geographic coordinates are outside their native latitude domain. |

See Also

[coverage\_simplify](https://gometry.monicz.dev/api/toplevel/coverage-polygonal/#gometry.coverage_simplify "coverage_simplify") : Topology-preserving simplification across a polygonal coverage.

Examples:

```pycon
>>> import gometry as gm
>>> wiggly = gm.LineString([(0, 0), (1, 0.1), (2, -0.1), (3, 0)])
>>> (wiggly.simplify(1.0)).to_wkt()
'LINESTRING (0 0, 3 0)'
```

### skew

```python
skew(x_angle: float = 0.0, y_angle: float = 0.0, *, origin: Origin = 'centroid', radians: bool = False) -> Self
```

Skew (shear) a geometry about an origin.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `x_angle` | `float` | Shear angles along the X and Y axes (degrees by default; radians if `radians=True`). | `0.0` |
| `y_angle` | `float` | Shear angles along the X and Y axes (degrees by default; radians if `radians=True`). | `0.0` |
| `origin` | `str or sequence of float` | Transform origin: `'centroid'` (default), `'center'`, or an `(x, y)` point. | `'centroid'` |
| `radians` | `bool` | Interpret `x_angle`/`y_angle` in radians instead of degrees. | `False` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One transformed geometry per row (kinds preserved). |

Examples:

```pycon
>>> import gometry as gm
>>> gm.Point(0, 2).skew(x_angle=45, origin=(0, 0)).to_wkt(precision=6)
'POINT (2 2)'
```

### smooth

```python
smooth(*, iterations: int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]] | ndarray[tuple[int], dtype[signedinteger[Any] | unsignedinteger[Any]]] | Iterable[int] | Buffer = 2, method: Literal['chaikin', 'catmull_rom'] = 'chaikin', keep_endpoints: bool = True) -> Self
```

Smooth line and polygon boundary linework (planar).
Two algorithms, selected by `method`:

- `'chaikin'` (the default) applies corner-cutting quadratic B-spline
  refinement. Each iteration replaces every edge with points at
  one-quarter and three-quarters along it (~doubling vertices). Open
  lines honor `keep_endpoints`; polygon rings are always treated as
  cyclic.
- `'catmull_rom'` subdivides each segment with a centripetal Catmull-Rom
  cubic that passes through every original vertex. `iterations` sets the
  per-segment sample count as `2**iterations` (`0` is identity).
  It always interpolates endpoints, so `keep_endpoints=False` is rejected.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `iterations` | `int or sequence of int` | Smoothing strength — a scalar applies to every geometry, or pass one value per geometry. `0` returns the input unchanged. | `2` |
| `method` | `('chaikin', 'catmull_rom')` | `'chaikin'` corner-cuts every edge; `'catmull_rom'` subdivides with a centripetal interpolating cubic. | `'chaikin'` |
| `keep_endpoints` | `bool` | For open lines under `'chaikin'`, hold the first and last vertices fixed. Rings are cyclic; Catmull-Rom requires `True`. | `True` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One smoothed geometry per row (kinds preserved). |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If `iterations` is negative. |
| `ResourceLimitError` | If smoothing would generate more coordinates than its output budget allows. |

Examples:

```pycon
>>> import gometry as gm
>>> square = gm.box(0, 0, 1, 1)
>>> square.smooth(iterations=1).area < square.area
True
```

### snap\_to\_grid

Accepted call forms

```python
snap_to_grid(grid_size: float | tuple[float, float] | Iterable[float], *, origin: GridOrigin = (0.0, 0.0), repair: Literal[False] = False) -> GeometryArray[GeometryT]
```

```python
snap_to_grid(grid_size: float | tuple[float, float] | Iterable[float], *, origin: GridOrigin = (0.0, 0.0), repair: bool) -> GeometryArray[Point]
```

```python
snap_to_grid(grid_size: float | tuple[float, float] | Iterable[float], *, origin: GridOrigin = (0.0, 0.0), repair: bool) -> GeometryArray[MultiPoint]
```

```python
snap_to_grid(grid_size: float | tuple[float, float] | Iterable[float], *, origin: GridOrigin = (0.0, 0.0), repair: bool) -> GeometryArray[MultiLineString]
```

```python
snap_to_grid(grid_size: float | tuple[float, float] | Iterable[float], *, origin: GridOrigin = (0.0, 0.0), repair: bool) -> GeometryArray[GeometryCollection]
```

```python
snap_to_grid(grid_size: float | tuple[float, float] | Iterable[float], *, origin: GridOrigin = (0.0, 0.0), repair: bool) -> GeometryArray[LineString | MultiLineString]
```

```python
snap_to_grid(grid_size: float | tuple[float, float] | Iterable[float], *, origin: GridOrigin = (0.0, 0.0), repair: bool) -> GeometryArray[Polygon | MultiPolygon]
```

```python
snap_to_grid(grid_size: float | tuple[float, float] | Iterable[float], *, origin: GridOrigin = (0.0, 0.0), repair: Literal[False] = False) -> GeometryArray[GeometryT | None]
```

```python
snap_to_grid(grid_size: float | tuple[float, float] | Iterable[float], *, origin: GridOrigin = (0.0, 0.0), repair: bool) -> GeometryArray[Point | None]
```

```python
snap_to_grid(grid_size: float | tuple[float, float] | Iterable[float], *, origin: GridOrigin = (0.0, 0.0), repair: bool) -> GeometryArray[MultiPoint | None]
```

```python
snap_to_grid(grid_size: float | tuple[float, float] | Iterable[float], *, origin: GridOrigin = (0.0, 0.0), repair: bool) -> GeometryArray[MultiLineString | None]
```

```python
snap_to_grid(grid_size: float | tuple[float, float] | Iterable[float], *, origin: GridOrigin = (0.0, 0.0), repair: bool) -> GeometryArray[GeometryCollection | None]
```

```python
snap_to_grid(grid_size: float | tuple[float, float] | Iterable[float], *, origin: GridOrigin = (0.0, 0.0), repair: bool) -> GeometryArray[LineString | MultiLineString | None]
```

```python
snap_to_grid(grid_size: float | tuple[float, float] | Iterable[float], *, origin: GridOrigin = (0.0, 0.0), repair: bool) -> GeometryArray[Polygon | MultiPolygon | None]
```

```python
snap_to_grid(grid_size: float | tuple[float, float] | Iterable[float], *, origin: GridOrigin = (0.0, 0.0), repair: bool = False) -> GeometryArray[Geometry]
```

```python
snap_to_grid(grid_size: float | tuple[float, float] | Iterable[float], *, origin: GridOrigin = (0.0, 0.0), repair: bool = False) -> GeometryArray[Geometry | None]
```

Snap every coordinate onto a regular grid and clean the result. X/Y move to
the nearest `origin + k * grid_size` grid node; consecutive duplicate vertices
collapse, and parts that degenerate below their minimum become empty (the
PostGIS `ST_SnapToGrid` shape — output may be non-simple). Z/M ride on
surviving vertices. quantize is the decimal-rounding, vertex-preserving
sibling.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `grid_size` | `float or tuple of float` | Positive finite coordinate-space grid spacing — native angular units for geographic CRSs, native linear units for projected CRSs, and raw coordinate units when CRS-free. Pass one value for a square grid or `(sx, sy)`. Zero is invalid here; `coverage_clean(grid_size=0)` instead disables snapping. | *required* |
| `origin` | `tuple of float` | A grid node anchoring the lattice. | `(0.0, 0.0)` |
| `repair` | `bool` | If `True`, guarantee a valid result: snap, linework-repair, and re- snap to a fixpoint. The geometry kind may change (a `Polygon` whose snapped shell pinches splits into a `MultiPolygon`). Geographic `repair=True` validates the exact quotient result; projected and CRS-free geometry remains planar. | `False` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One snapped geometry per row. |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If `grid_size` or `origin` is invalid, or the grid is too fine for the coordinate magnitude. |
| `InvalidGeometryError` | If `repair=True` and repair would have to invent Z/M ordinates, or the snap-repair loop cannot converge. |

Examples:

```pycon
>>> import gometry as gm
>>> jittery = gm.LineString([(0.12, 0.88), (2.49, 1.51)])
>>> jittery.snap_to_grid(grid_size=0.5).to_wkt()
'LINESTRING (0 1, 2.5 1.5)'
```

### sort\_by\_spatial\_key

```python
sort_by_spatial_key(*, curve: Literal['hilbert', 'morton'] = 'hilbert', level: int = 16, bounds: Iterable[float] | None = None) -> Self
```

Return the array reordered along a space-filling curve.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `curve` | `('hilbert', 'morton')` | `hilbert` prioritizes locality; `morton` uses Z-order. | `'hilbert'` |
| `level` | `int` | Curve depth (`1`-`32`). | `16` |
| `bounds` | `iterable[float]` | Ordered `(minx, miny, maxx, maxy)` rectangle for keying. When omitted, uses the present rows' minimum and maximum stored coordinates without periodic wrapping. Geographic `total_bounds` may wrap, so it is not necessarily a curve frame. | `None` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | A new array with the same rows in curve-key order; empty and missing rows sort last. |

Examples:

```pycon
>>> import gometry as gm
>>> arr = gm.GeometryArray([gm.Point(1, 0), gm.Point(0, 0)])
>>> arr.sort_by_spatial_key().to_wkt()
['POINT (0 0)', 'POINT (1 0)']
```

### spatial\_key

```python
spatial_key(*, curve: Literal['hilbert', 'morton'] = 'hilbert', level: int = 16, bounds: Iterable[float] | None = None) -> NDArray[uint64]
```

Space-filling-curve key of each geometry's bbox center.
Discretizes centers into a `2^level x 2^level` grid over `bounds`
and returns distances along the selected curve.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `curve` | `('hilbert', 'morton')` | `hilbert` prioritizes locality; `morton` uses Z-order. | `'hilbert'` |
| `level` | `int` | Grid order (`1` to `32`); 16 matches GeoPandas/DuckDB. | `16` |
| `bounds` | `tuple of float` | Ordered `(minx, miny, maxx, maxy)` rectangle for keying. When omitted, uses the present rows' minimum and maximum stored coordinates without periodic wrapping. Geographic `total_bounds` may wrap, so it is not necessarily a curve frame. Keys compare across geometries only against a *shared* frame — pass the same `bounds` when keying separate geometries. | `None` |

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | One result per row. Empty and missing rows use `uint64.max` and therefore sort last. |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If `level` or `bounds` is invalid. |

Examples:

```pycon
>>> import gometry as gm
>>> keys = gm.GeometryArray([gm.Point(0, 0), gm.Point(10, 10)]).spatial_key(bounds=(0, 0, 10, 10))
>>> bool(keys[0] != keys[1])
True
```

### split\_antimeridian

Accepted call forms

```python
split_antimeridian() -> GeometryArray[Point]
```

```python
split_antimeridian() -> GeometryArray[MultiPoint]
```

```python
split_antimeridian() -> GeometryArray[MultiLineString]
```

```python
split_antimeridian() -> GeometryArray[MultiPolygon]
```

```python
split_antimeridian() -> GeometryArray[GeometryCollection]
```

```python
split_antimeridian() -> GeometryArray[LineString | MultiLineString]
```

```python
split_antimeridian() -> GeometryArray[Polygon | MultiPolygon]
```

```python
split_antimeridian() -> GeometryArray[Point | None]
```

```python
split_antimeridian() -> GeometryArray[MultiPoint | None]
```

```python
split_antimeridian() -> GeometryArray[MultiLineString | None]
```

```python
split_antimeridian() -> GeometryArray[MultiPolygon | None]
```

```python
split_antimeridian() -> GeometryArray[GeometryCollection | None]
```

```python
split_antimeridian() -> GeometryArray[LineString | MultiLineString | None]
```

```python
split_antimeridian() -> GeometryArray[Polygon | MultiPolygon | None]
```

```python
split_antimeridian() -> GeometryArray[Geometry]
```

```python
split_antimeridian() -> GeometryArray[Geometry | None]
```

Split at the antimeridian. CRS-free input is treated as CRS84; a tagged
geographic CRS supplies its own longitude frame and ellipsoid. Parts that cross
come back as multiple parts
whose edges follow the seam — each side keeping its own seam sign — so the
result remains a coordinate-planar longitude/latitude chart for topology.

Inserted seam vertices keep the affine chart crossing in X/Y; eligible Z/M
follow ellipsoidal arclength along the retained source edge. An authored
full-period edge is retained with quarter witnesses before its longitudes are
canonicalized. The two seam aliases and a displacement of multiple periods do
not imply a full-period edge.

When a seam split needs polar closure, it follows
the ring's enclosed pole; a pole-free band does not acquire a polar cap.

Geometries that do not cross are returned unchanged. A split
`LineString` becomes a `MultiLineString` and a split `Polygon` a
`MultiPolygon`, like repair. On a geographic CRS, the split subdivides
existing chart edges, so ellipsoidal area and perimeter are conserved to
rounding.

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One seam-split geometry per row. |

Raises:

| Type | Description |
| --- | --- |
| `CRSError` | If the CRS is projected (CRS-free lon/lat and geographic CRS are accepted), or a coordinate is outside the longitude/latitude domain. |
| `InvalidGeometryError` | If stitching fails, or pole closure would have to invent Z/M ordinates. |

Examples:

```pycon
>>> import gometry as gm
>>> line = gm.LineString([(170, 0), (-170, 0)], crs=4326)
>>> split = line.split_antimeridian()
>>> (split.geometry_type, len(split.parts))
('MultiLineString', 2)
```

### subdivide

Accepted call forms

```python
subdivide(*, max_vertices: int = 256) -> Groups[GeometryArray[Geometry]]
```

```python
subdivide(*, max_vertices: int = 256) -> Groups[GeometryArray[Geometry] | None]
```

Split geometry into parts of bounded complexity. Recursively clips
across the longer axis until every part has at most `max_vertices`
coordinates (the PostGIS `ST_Subdivide` shape). Linework with no
representable rectangular cut is divided between source vertices. Parts cover
the input up to binary64 rounding at constructed cut vertices. Source
ordinates are carried where meaningful; synthesized clip vertices use the
operation's natural XY result. On geographic input, recursively generated cut
vertices remain traced to their original source edges, including across seam
pieces; they are not re-interpolated from an edge fragment created by an earlier
cut.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `max_vertices` | `int` | Maximum coordinates per part (at least `8`). | `256` |

Returns:

| Type | Description |
| --- | --- |
| `Groups of GeometryArray` | One ragged group of parts per input geometry, in input order (row `i` is `self[i].subdivide(...)`). |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If `max_vertices` is below `8`. |
| `OverflowError` | If exact partitioning cannot produce parts within the requested bound, or no adjacent binary64 assignment preserves the exact subdivision. |
| `ResourceLimitError` | If generated output or the bounded embedding search exceeds its budget. |

Examples:

```pycon
>>> import gometry as gm
>>> parts = gm.LineString([(i, 0) for i in range(20)]).subdivide(max_vertices=8)
>>> len(parts)
4
```

### swap\_xy

```python
swap_xy() -> Self
```

Swap the X and Y ordinate of every coordinate (Z/M untouched). The axis-
order repair for data delivered latitude-first: gometry is always `(x, y)`
= `(lon, lat)`, so latitude-ordered input swaps once on ingest.

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One swapped geometry per row (kinds preserved). |

Examples:

```pycon
>>> import gometry as gm
>>> latitude_first = gm.Point(52.5, 13.4)
>>> latitude_first.swap_xy().to_wkt()
'POINT (13.4 52.5)'
```

### to\_arrow

```python
to_arrow(*, encoding: Literal['auto', 'wkb'] = 'auto') -> PyArrowArray
```

Export the array as a `GeoArrow` array.

Geographic export follows `Geometry.to_arrow` finite-drawing rules.
A cut can promote a homogeneous line or polygon column to its multi-part
family. Missing rows, CRS and coordinate epoch are retained.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `encoding` | `('auto', 'wkb')` | `auto` exports homogeneous arrays as their native GeoArrow layout and falls back to WKB for mixed geometry types; `wkb` always exports a GeoArrow WKB array. | `'auto'` |

Returns:

| Type | Description |
| --- | --- |
| `object` | A GeoArrow-compatible array. |

See Also

[from\_arrow](https://gometry.monicz.dev/api/toplevel/io-interop/#gometry.from_arrow "from_arrow") : Decode a GeoArrow array into a `GeometryArray`.

Examples:

```pycon
>>> import gometry as gm
>>> type(gm.GeometryArray([gm.Point(1, 2)]).to_arrow()).__name__
'ExtensionArray'
```

### to\_crs

```python
to_crs(crs: CrsInput, *, area_of_interest: CrsAreaInput | None = None, epoch: SupportsFloat | SupportsIndex | FloatScalar | ScalarFloatArray | None = None, authority: str | None = None, accuracy: float | None = None, allow_ballpark: bool | None = None, only_best: bool | None = None, force_over: bool = False) -> Self
```

Reproject all geometries to a target CRS.
The source coordinate epoch is the array's own `epoch` metadata
(stamp it with `with_epoch` first when the operation needs one);
`epoch` here labels the *output* coordinate epoch.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `crs` | `CRS - like` | Any supported CRS-like input. | *required* |
| `area_of_interest` | `sequence of float` | Bounding `(west, south, east, north)` to pick the best transform. | `None` |
| `epoch` | `numeric scalar or 0-D numeric array` | Output coordinate epoch (decimal year) to tag on the result. Omitted keeps the source epoch when the CRS is unchanged or the target admits geometry epochs; otherwise the output has no epoch. | `None` |
| `authority` | `str` | Restrict candidate coordinate operations to this authority (e.g. `'EPSG'`). | `None` |
| `accuracy` | `float` | Maximum acceptable operation accuracy, in meters. | `None` |
| `allow_ballpark` | `bool` | Allow low-accuracy ballpark operations when no precise one exists. | `None` |
| `only_best` | `bool` | Use only the single best operation; no fallback. | `None` |
| `force_over` | `bool` | Keep coordinates on the source side of the antimeridian instead of wrapping into `[-180, 180]` (PROJ `FORCE_OVER=YES`). Like `only_best`, this also collapses operation selection to a single candidate, so enumerating surfaces return exactly one operation. | `False` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` |  |

Raises:

| Type | Description |
| --- | --- |
| `TransformError` | If no transform exists between the frames or it fails to apply. |
| `CRSError` | If a CRS is invalid or the source is missing. |
| `GeometryError` | If `epoch` is not a finite decimal year. |

Examples:

```pycon
>>> import gometry as gm
>>> arr = gm.GeometryArray([gm.Point(1, 2, crs=4326)])
>>> round(float(arr.to_crs(3857).coords.x[0]), 2)
111319.49
```

### to\_geojson

Accepted call forms

```python
to_geojson(*, drop_epoch: bool = False) -> list[str]
```

```python
to_geojson(*, drop_epoch: bool = False) -> list[str | None]
```

Serialize to `GeoJSON` text. GeoJSON uses OGC:CRS84 longitude/latitude
order under RFC 7946 and carries no source CRS label. CRS-tagged input must use
the 2D WGS 84 geographic family
(`EPSG:4326` or `OGC:CRS84`) or the 3D longitude/latitude/height family
(`EPSG:4979` or `OGC:CRS84h`); reproject other CRS values first. CRS-free
input is explicitly assumed to already be WGS84 longitude/latitude:
coordinates outside longitude `[-180, 180]` or latitude `[-90, 90]` are
rejected, and antimeridian-crossing geometry is split according to RFC 7946.
If CRS-free coordinates have projected or other planar semantics, transform
them or choose another format.

Unsupported Z/M axes raise an error rather than being silently discarded. Remove them explicitly with `force_2d()`, `with_coordinates(z=None)`, or `with_coordinates(m=None)`.

GeoJSON cannot represent M; drop it with `with_coordinates(m=None)` (or `force_2d()`).

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `drop_epoch` | `bool` | Permit losing coordinate-epoch metadata, which GeoJSON cannot encode. | `False` |

Returns:

| Type | Description |
| --- | --- |
| `list of str` | One `GeoJSON` geometry string per row; missing rows yield `None`. |

Raises:

| Type | Description |
| --- | --- |
| `CRSError` | If the input carries a CRS outside the 2D/3D WGS84 longitude/latitude family. |
| `InvalidGeometryError` | If input carries M ordinates; drop them with `with_coordinates(m=None)` (or `force_2d()`). |
| `GeometryError` | If input carries a coordinate epoch and `drop_epoch` is false. |

See Also

[from\_geojson](https://gometry.monicz.dev/api/toplevel/io-interop/#gometry.from_geojson "from_geojson") : Parse `GeoJSON` back into a geometry.

Examples:

```pycon
>>> import gometry as gm
>>> gm.Point(1, 2).to_geojson()
'{"type":"Point","coordinates":[1.0,2.0]}'
```

### to\_geopandas

```python
to_geopandas(*, drop_epoch: bool = False) -> GeoPandasSeries
```

Convert this array to a GeoPandas GeoSeries through vectorized WKB.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `drop_epoch` | `bool` | Permit losing coordinate-epoch metadata, which GeoPandas cannot represent. | `False` |

Returns:

| Type | Description |
| --- | --- |
| `object` | A GeoPandas GeoSeries carrying this array's CRS. |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If the array carries a coordinate epoch and `drop_epoch` is false. |
| `ModuleNotFoundError` | If GeoPandas is not installed. |

Examples:

```pycon
>>> import gometry as gm
>>> type(gm.GeometryArray([gm.Point(1, 2, crs=4326)]).to_geopandas()).__name__
'GeoSeries'
```

### to\_geoparquet

```python
to_geoparquet(path: str | PathLike[str] | BinaryIO | PyArrowNativeFile, *, attributes: PyArrowTable | Mapping[str, Any] | None = None, encoding: Literal['wkb', 'geoarrow', 'geometry'] = 'wkb', **kwargs: Any) -> None
```

Write this array to a GeoParquet file, optionally as a feature table.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `path` | `str, path-like, or binary stream` | Output Parquet path or caller-owned binary writable stream. Text streams are not supported; the writer leaves streams open. | *required* |
| `attributes` | `Table or mapping` | Per-row attribute columns written beside the geometry column (lengths must match). | `None` |
| `encoding` | `str` | `'wkb'` (portable default) and `'geoarrow'` (separated coordinates for homogeneous arrays) write GeoParquet 1.1 with a bbox covering. `'geometry'` writes native Parquet GEOMETRY with GeoParquet 2.0 metadata, including M ordinates. Geographic conversion may canonicalize longitude aliases, split parts and add rounded vertices or pole closures. All modes use finite planar drawings, not geodesic curves or a promise of identical source-point incidence. | `"wkb"` |
| `kwargs` | `mapping` | Additional options forwarded to `pyarrow.parquet.write_table`. | `{}` |

Returns:

| Type | Description |
| --- | --- |
| `None` |  |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If the encoding is unknown, attributes clash with the geometry column or mismatch the row count, or a GeoParquet 1.1 encoding carries M. Use `encoding='geometry'` to preserve M, or explicitly remove it with `with_coordinates(m=None)`. |

Examples:

```pycon
>>> import gometry as gm
>>> import tempfile, os
>>> path = tempfile.mktemp(suffix='.parquet')
>>> gm.GeometryArray([gm.Point(1, 2, crs=4326)]).to_geoparquet(path)
>>> os.path.getsize(path) > 0
True
```

### to\_numpy

```python
to_numpy() -> NDArray[object_]
```

Export the array as a `numpy.ndarray` of typed geometry objects.

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | One typed leaf geometry per row. |

Examples:

```pycon
>>> import gometry as gm
>>> gm.GeometryArray([gm.Point(1, 2)]).to_numpy()[0].to_wkt()
'POINT (1 2)'
```

### to\_pandas

```python
to_pandas(*, index: Any | None = None, name: Hashable | None = None) -> PandasSeries
```

Build a pandas Series backed by gometry's concrete extension dtype.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `index` | `sequence or Index` | Forwarded to `pandas.Series`. | `None` |
| `name` | `hashable` | Series name. | `None` |

Returns:

| Type | Description |
| --- | --- |
| `object` | A pandas Series sharing this geometry array. |

Examples:

```pycon
>>> import gometry as gm
>>> type(gm.GeometryArray([gm.Point(1, 2, crs=4326)]).to_pandas()).__name__
'Series'
```

### to\_polars

```python
to_polars(*, name: str = 'geometry', drop_epoch: bool = False, drop_crs: bool = False) -> PolarsSeries
```

Encode this array as a Polars binary (E)WKB Series.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `name` | `str` | Output Series name. | `"geometry"` |
| `drop_epoch` | `bool` | Permit losing coordinate-epoch metadata, which WKB cannot encode. | `False` |
| `drop_crs` | `bool` | Permit losing a CRS that EWKB cannot embed (no EPSG authority code); restore it via `from_polars(..., crs=...)`. EPSG SRIDs are always embedded when available. | `False` |

Returns:

| Type | Description |
| --- | --- |
| `object` | A Polars Series containing WKB or EWKB values. |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If coordinate epoch metadata or a CRS that cannot be embedded as an EWKB SRID would be lost without `drop_epoch` or `drop_crs`. |
| `ModuleNotFoundError` | If Polars is not installed. |

Examples:

```pycon
>>> import gometry as gm
>>> type(gm.GeometryArray([gm.Point(1, 2, crs=4326)]).to_polars()).__name__
'Series'
```

### to\_polyline

Accepted call forms

```python
to_polyline(*, precision: int = 5, drop_epoch: bool = False) -> list[str]
```

```python
to_polyline(*, precision: int = 5, drop_epoch: bool = False) -> list[str | None]
```

Encode every `LineString` or `Point` row as Google polyline text (see
`Geometry.to_polyline`).
Unsupported Z/M axes raise an error rather than being silently discarded. Remove them explicitly with `force_2d()`, `with_coordinates(z=None)`, or `with_coordinates(m=None)`.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `precision` | `int` | Decimal digits encoded per ordinate (`0` to `11`). | `5` |
| `drop_epoch` | `bool` | Permit losing coordinate-epoch metadata, which polyline cannot encode. | `False` |

Returns:

| Type | Description |
| --- | --- |
| `list of str or None` | One encoded polyline per row, with `None` at missing rows. |

Raises:

| Type | Description |
| --- | --- |
| `GeometryTypeError` | If a row is not a `LineString` or `Point`. |
| `CRSError` | If the CRS is set and is not EPSG:4326 longitude/latitude. |
| `InvalidGeometryError` | If a row carries Z/M, or a coordinate is outside the longitude/latitude domain. Flatten explicitly with `force_2d()`. |
| `GeometryError` | If `precision` is out of range, or the array carries a coordinate epoch and `drop_epoch` is false. |

See Also

[from\_polyline](https://gometry.monicz.dev/api/toplevel/io-interop/#gometry.from_polyline "from_polyline") : Decode Google polyline text into geometries.

Examples:

```pycon
>>> import gometry as gm
>>> gm.GeometryArray([gm.LineString([(0, 0), (1, 1)])]).to_polyline()
['??_ibE_ibE']
```

### to\_wkb

Accepted call forms

```python
to_wkb(*, include_srid: bool = False, precision: int | integer[Any] | None = None, drop_epoch: bool = False) -> list[bytes]
```

```python
to_wkb(*, include_srid: bool = False, precision: int | integer[Any] | None = None, drop_epoch: bool = False) -> list[bytes | None]
```

Serialize to Well-Known Binary.

Unsupported Z/M axes raise an error rather than being silently discarded. Remove them explicitly with `force_2d()`, `with_coordinates(z=None)`, or `with_coordinates(m=None)`.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `include_srid` | `bool` | Embed the EPSG code as an EWKB SRID. The PostGIS wire aliases `OGC:CRS84` to SRID 4326 and `OGC:CRS84h` to SRID 4979; decoding either alias yields that EPSG identity. | `False` |
| `precision` | `int` | Decimal places to round coordinates to (omit for full precision). Uses `quantize` rounding, including negative precision and ties to even. | `None` |
| `drop_epoch` | `bool` | Permit losing coordinate-epoch metadata, which (E)WKB cannot encode. | `False` |

Returns:

| Type | Description |
| --- | --- |
| `list of bytes` | One WKB payload per row; missing rows yield `None`. |

Notes

The coordinate epoch is not representable in (E)WKB and does not survive a
round-trip; use Arrow interchange when the epoch matters.

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If a rounded coordinate overflows, or the geometry carries a coordinate epoch and `drop_epoch` is false. |
| `CRSError` | If `include_srid` is set and the CRS has no EPSG code. |

See Also

[from\_wkb](https://gometry.monicz.dev/api/toplevel/io-interop/#gometry.from_wkb "from_wkb") : Parse WKB/EWKB back into a geometry.

Examples:

```pycon
>>> import gometry as gm
>>> pt = gm.Point(1, 2)
>>> pt.to_wkt() == gm.from_wkb(pt.to_wkb()).to_wkt()
True
```

### to\_wkt

Accepted call forms

```python
to_wkt(*, include_srid: bool = False, precision: int | integer[Any] | None = None, drop_epoch: bool = False) -> list[str]
```

```python
to_wkt(*, include_srid: bool = False, precision: int | integer[Any] | None = None, drop_epoch: bool = False) -> list[str | None]
```

Serialize to Well-Known Text.

Unsupported Z/M axes raise an error rather than being silently discarded. Remove them explicitly with `force_2d()`, `with_coordinates(z=None)`, or `with_coordinates(m=None)`.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `include_srid` | `bool` | Embed the EPSG code as an EWKT `SRID=<code>;` prefix. The PostGIS wire aliases `OGC:CRS84` to SRID 4326 and `OGC:CRS84h` to SRID 4979; decoding either alias yields that EPSG identity. | `False` |
| `precision` | `int` | Decimal places to round coordinates to (omit for full precision). Uses `quantize` rounding, including negative precision and ties to even. | `None` |
| `drop_epoch` | `bool` | Permit losing coordinate-epoch metadata, which WKT cannot encode. | `False` |

Returns:

| Type | Description |
| --- | --- |
| `list of str` | One WKT string per row; missing rows yield `None`. |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If a rounded coordinate overflows, or the geometry carries a coordinate epoch and `drop_epoch` is false. |
| `CRSError` | If `include_srid` is set and the CRS has no EPSG code. |

See Also

[from\_wkt](https://gometry.monicz.dev/api/toplevel/io-interop/#gometry.from_wkt "from_wkt") : Parse WKT back into a geometry.

Examples:

```pycon
>>> import gometry as gm
>>> gm.Point(1.5, 2.5).to_wkt()
'POINT (1.5 2.5)'
>>> gm.GeometryArray([gm.Point(1.5, 2.5)]).to_wkt()
['POINT (1.5 2.5)']
```

### translate

```python
translate(x_offset: float, y_offset: float) -> Self
```

Translate a geometry by `(x_offset, y_offset)`.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `x_offset` | `float` | Offsets along the X and Y axes. | *required* |
| `y_offset` | `float` | Offsets along the X and Y axes. | *required* |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One transformed geometry per row (kinds preserved). |

Examples:

```pycon
>>> import gometry as gm
>>> gm.Point(1, 2).translate(10, 20).to_wkt()
'POINT (11 22)'
```

### triangulate

Accepted call forms

```python
triangulate(*, method: Literal['earcut'], min_angle: None = None, max_area: None = None) -> Groups[GeometryArray[Polygon]]
```

```python
triangulate(*, method: Literal['earcut'], min_angle: None = None, max_area: None = None) -> Groups[GeometryArray[Polygon] | None]
```

```python
triangulate(*, method: Literal['delaunay'], min_angle: None = None, max_area: None = None) -> Groups[GeometryArray[Polygon]]
```

```python
triangulate(*, method: Literal['delaunay'], min_angle: None = None, max_area: None = None) -> Groups[GeometryArray[Polygon] | None]
```

```python
triangulate(*, method: Literal['constrained'], min_angle: FloatInput | None = None, max_area: FloatInput | None = None) -> Groups[GeometryArray[Polygon]]
```

```python
triangulate(*, method: Literal['constrained'], min_angle: FloatInput | None = None, max_area: FloatInput | None = None) -> Groups[GeometryArray[Polygon] | None]
```

Triangulate each geometry with an explicit algorithm.

Geographic Delaunay and constrained triangulation use a CRS-native chart
for seam-crossing input without a preliminary split. Delaunay triangulates point
sites in that coordinate chart; it is not a spherical mesh. Constrained
triangulation preserves polygon boundaries and the pole selected by a polar
cap. Earcut follows polygon XY rings; call `split_antimeridian` first when a
geographic polygon crosses the seam or encloses a pole.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `method` | `('earcut', 'delaunay', 'constrained')` | Required triangulation algorithm. Delaunay methods resolve exact cocircular ties with a canonical rule keyed by lexicographic XY coordinates, independent of insertion order. | `'earcut'` |
| `min_angle` | `float or sequence of float` | Minimum triangle angle in degrees; each value must be positive, finite, and at most 30. Valid only with `method='constrained'`. | `None` |
| `max_area` | `float or sequence of float` | Maximum triangle area in coordinate space; each value must be positive and finite. Geographic CRSs use squared native angular units, projected CRSs use squared native linear units, and CRS-free inputs use squared raw coordinate units. Valid only with `method='constrained'`.  Setting either option enables refinement; inserted Steiner vertices return uniform XY.  Scalar and array rows use quality-first refinement: angle violations by circumradius-to-shortest-edge ratio, then area when both options are set; triangles meeting the angle target follow in descending area. Equal priorities use sorted numeric XY corners. Refinement is independent of insertion order and input ring rotation or reversal. Scalar and array rows use the same first-occurrence source-site and ordinate policy.  Each boundary Steiner vertex is the nearest binary64 coordinate pair to its exact position on the source edge, so the triangles cover the source polygon up to that rounding. | `None` |

Returns:

| Type | Description |
| --- | --- |
| `Groups of GeometryArray[Polygon]` | One ragged triangle group per input geometry. Delaunay methods return counter-clockwise triangles starting at their smallest XY corner, sorted by corner coordinates within each group. |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If a quality constraint is invalid or method-specific options are used with the wrong algorithm. |
| `OverflowError` | If a boundary Steiner point cannot be represented at float resolution; `operation` is `'triangulate'`. |
| `ResourceLimitError` | If refinement exceeds the generated-output budget. |
| `InvalidGeometryError` | If an input polygon is invalid or its triangulation cannot be constructed. |

Examples:

```pycon
>>> import gometry as gm
>>> groups = gm.GeometryArray([gm.box(0, 0, 2, 2)]).triangulate(method='earcut')
>>> groups[0].to_wkt()
['POLYGON ((0 2, 0 0, 2 0, 0 2))', 'POLYGON ((2 2, 0 2, 2 0, 2 2))']
```

### unique\_points

Accepted call forms

```python
unique_points() -> GeometryArray[MultiPoint]
```

```python
unique_points() -> GeometryArray[MultiPoint | None]
```

```python
unique_points() -> GeometryArray[MultiPoint | GeometryCollection]
```

```python
unique_points() -> GeometryArray[MultiPoint | GeometryCollection | None]
```

Distinct vertices in first-occurrence order. Vertices compare by exact
structural identity (every active ordinate by bit pattern, the
`equals_identical` notion), so XYZ points that differ only in Z stay
distinct.

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | One distinct-vertex result per row: a `MultiPoint` for homogeneous rows or a `GeometryCollection` of ordered `Point` members for heterogeneous rows. |

Notes

A heterogeneous result follows ordinary `GeometryCollection` semantics:
`is_simple` is false by convention and structural equality remains type-sensitive.
Mixed-axis and collection exports use WKB for Arrow interchange; see
[Arrow & storage](https://gometry.monicz.dev/ecosystem/arrow/).


See Also

[remove\_repeated\_points](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.remove_repeated_points "remove_repeated_points") : Collapse consecutive duplicate vertices in place, keeping the geometry kind.

Examples:

```pycon
>>> import gometry as gm
>>> loop = gm.LineString([(0, 0), (1, 1), (0, 0), (2, 2)])
>>> loop.unique_points().to_wkt()
'MULTIPOINT ((0 0), (1 1), (2 2))'
```

### validate

Accepted call forms

```python
validate() -> list[ValidationReport]
```

```python
validate() -> list[ValidationReport | None]
```

Structured validity report in the geometry's coordinate frame.
Geographic validity reads exact quotient topology, so period aliases and seam
cuts do not depend on their stored longitude spelling. An out-of-domain
latitude is reported as `latitude_out_of_range`; geographic operations that
require coordinate admission still raise.

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 uses ordinary
planar OGC validity. A nonempty LineString with fewer than two distinct XY
positions is invalid and reports `line_collapsed`.

Returns:

| Type | Description |
| --- | --- |
| `list of ValidationReport` | One report per row; missing rows are `None`. |

See Also

[is\_valid](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.is_valid "is_valid property") : Boolean-only test.
[repair](https://gometry.monicz.dev/api/geometry/geometryarray/#gometry.GeometryArray.repair "repair") : Fix what the report diagnoses.

Examples:

```pycon
>>> import gometry as gm
>>> bowtie = gm.from_wkt('POLYGON ((0 0, 2 2, 2 0, 0 2, 0 0))')
>>> report = bowtie.validate()
>>> (report.valid, report.reason)
(False, 'exterior ring has a self-intersection')
```

### voronoi

Accepted call forms

```python
voronoi(*, output: Literal['polygons'] = 'polygons', tolerance: float = 0.0, clip: Literal['padded', 'envelope'] | Polygon = 'padded') -> Groups[GeometryArray[Polygon]]
```

```python
voronoi(*, output: Literal['polygons'] = 'polygons', tolerance: float = 0.0, clip: Literal['padded', 'envelope'] | Polygon = 'padded') -> Groups[GeometryArray[Polygon] | None]
```

```python
voronoi(*, output: Literal['edges'], tolerance: float = 0.0, clip: Literal['padded', 'envelope'] | Polygon = 'padded') -> Groups[GeometryArray[LineString]]
```

```python
voronoi(*, output: Literal['edges'], tolerance: float = 0.0, clip: Literal['padded', 'envelope'] | Polygon = 'padded') -> Groups[GeometryArray[LineString] | None]
```

Construct a Voronoi diagram from the geometry's vertices. Geographic
sites and a supplied clip polygon use a CRS-native chart for seam crossings;
publication retains chart cuts and polar-cap edge roles without a preliminary
`split_antimeridian`. The construction is planar in longitude/latitude
coordinates, not a geodesic or spherical Voronoi diagram.

Collinear vertices
divide the clip region into strips at their
perpendicular bisectors, and a lone vertex owns the whole clip polygon; the
padded and envelope frames of a lone vertex, or the envelope of a horizontal
or vertical row, bound no cells.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `output` | `('polygons', 'edges')` | Return clipped Voronoi cells or the internal Voronoi edges. The polygon form omits `output`; edge output requires `output='edges'` and excludes the clip polygon's exterior boundary. | `'polygons'` |
| `tolerance` | `float` | Finite non-negative coordinate-space tolerance: native angular units for geographic CRSs, native linear units for projected CRSs, and raw coordinate units when CRS-free. | `0.0` |
| `clip` | `('padded', 'envelope')` | How to bound the unbounded outer cells: a padded box, the input envelope, or a `Polygon` to clip the diagram to. Diagram vertices are synthesized and returned in XY. Rounded clip incidences need not lie on the source polygon under overlay membership. | `'padded'` |

Returns:

| Type | Description |
| --- | --- |
| `Groups[GeometryArray[Polygon]] or Groups[GeometryArray[LineString]]` | One ragged group of the selected output per input geometry, in input order. |

Raises:

| Type | Description |
| --- | --- |
| `OverflowError` | If the output cannot be represented in binary64. `operation` is `'voronoi_cells'` for polygon output and `'voronoi_edge_lines'` for edges. |
| `ResourceLimitError` | If generated output or the embedding search exceeds its budget. |
| `InvalidGeometryError` | If the clip polygon is invalid or exact Voronoi construction fails. |

Examples:

```pycon
>>> import gometry as gm
>>> sites = gm.MultiPoint([(0, 0), (2, 0), (1, 2)])
>>> len(sites.voronoi())
3
>>> len(sites.voronoi(output='edges'))
3
```

### with\_coordinates

Accepted call forms

```python
with_coordinates(coordinates: Sequence[Sequence[float]] | ndarray[tuple[int, int], dtype[floating[Any] | signedinteger[Any] | unsignedinteger[Any] | bool_]] | Coordinates, /) -> Self
```

```python
with_coordinates(coordinates: None = None, /, *, x: FloatScalar | ScalarFloatArray | FloatColumn = ..., y: FloatScalar | ScalarFloatArray | FloatColumn = ..., z: FloatScalar | ScalarFloatArray | FloatColumn | None = ..., m: FloatScalar | ScalarFloatArray | FloatColumn | None = ...) -> Self
```

Return an array with selected coordinate ordinates replaced.

Pass one `(N, dims)` matrix (including a `Coordinates` view), or
replace any of `x=`, `y=`, `z=`, and `m=` by a scalar or a
column over the flattened coordinate sequence. Omitted ordinates are
preserved. `z=None` and `m=None` remove those dimensions; X and Y
cannot be removed. Missing rows contribute no coordinates and remain
missing. Matrix and column modes cannot be mixed. Calling without
arguments returns an unchanged value.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `coordinates` | `sequence of float` | Replacement `(N, dims)` coordinate matrix, including a `Coordinates` view. | `None` |
| `x` | `float, sequence of float, or None` | Replace one ordinate by a scalar broadcast over vertices or a column with one value per coordinate. Omitted ordinates are preserved. `None` removes Z or M and is not valid for X or Y. | `...` |
| `y` | `float, sequence of float, or None` | Replace one ordinate by a scalar broadcast over vertices or a column with one value per coordinate. Omitted ordinates are preserved. `None` removes Z or M and is not valid for X or Y. | `...` |
| `z` | `float, sequence of float, or None` | Replace one ordinate by a scalar broadcast over vertices or a column with one value per coordinate. Omitted ordinates are preserved. `None` removes Z or M and is not valid for X or Y. | `...` |
| `m` | `float, sequence of float, or None` | Replace one ordinate by a scalar broadcast over vertices or a column with one value per coordinate. Omitted ordinates are preserved. `None` removes Z or M and is not valid for X or Y. | `...` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` |  |

Examples:

```pycon
>>> import gometry as gm
>>> arr = gm.GeometryArray([gm.LineString([(0, 0), (1, 1)])])
>>> arr.with_coordinates([(5, 5), (6, 6)]).to_wkt()
['LINESTRING (5 5, 6 6)']
```

### with\_crs

```python
with_crs(crs: CrsInput | None, *, overwrite: bool = False) -> Self
```

Relabel the CRS of all geometries without moving coordinates (see
`Geometry.with_crs`; replacing a different declared CRS requires
`overwrite=True`).

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `crs` | `CRS - like` | Any supported CRS-like input. | *required* |
| `overwrite` | `bool` | Allow replacing an existing, different CRS label. | `False` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` |  |

Raises:

| Type | Description |
| --- | --- |
| `CRSError` | If `crs` is not a recognized CRS, or it would silently replace a different declared CRS without `overwrite`. |

Examples:

```pycon
>>> import gometry as gm
>>> gm.GeometryArray([gm.Point(1, 2)]).with_crs(4326).crs
CRS("EPSG:4326")
```

### with\_epoch

```python
with_epoch(epoch: SupportsFloat | SupportsIndex | FloatScalar | ScalarFloatArray | None, *, overwrite: bool = False) -> Self
```

Declare (or clear) the array's coordinate epoch (see
`Geometry.with_epoch`). The CRS frame must admit an epoch. `None`
clears it; changing a present epoch needs `overwrite=True`.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `epoch` | `numeric scalar, 0-D numeric array, or None` | Decimal year, or `None` to clear. | *required* |
| `overwrite` | `bool` | Allow replacing an existing, different epoch. | `False` |

Returns:

| Type | Description |
| --- | --- |
| `GeometryArray` | A copy carrying the new epoch. |

Raises:

| Type | Description |
| --- | --- |
| `CRSError` | If the CRS frame cannot carry an epoch or a present epoch would change without `overwrite=True`. |
| `GeometryError` | If `epoch` is not a finite decimal year. |

Examples:

```pycon
>>> import gometry as gm
>>> arr = gm.GeometryArray([gm.Point(-122.4, 37.8, crs=4326)])
>>> arr.with_epoch(2015.0).epoch
2015.0
```
