Source: https://gometry.monicz.dev/api/toplevel/measurement/

# Measurement

Area, length, distance, nearest points, and similarity measures.

**Related:** [CRS, units & measurement](https://gometry.monicz.dev/guide/crs/)

## area

Accepted call forms

```python
area(geom: Geometry, *, unit: Literal['planar', 'meters'] | None = None) -> float
```

```python
area(geom: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], *, unit: Literal['planar', 'meters'] | None = None) -> NDArray[float64]
```

```python
area(geom: Iterable[Geometry | Buffer | Mapping[str, Any] | SupportsGeoInterface | None], *, unit: Literal['planar', 'meters'] | None = None) -> NDArray[float64]
```

```python
area(geom: Geometry | (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None] | Iterable[Geometry | Buffer | Mapping[str, Any] | SupportsGeoInterface | None], *, unit: Literal['planar', 'meters'] | None = None) -> float | NDArray[float64]
```

Compute area in CRS-natural units or with a `unit` override.

For a `GeometryCollection`, overlapping members count once, as the area
of their union. Parts of a valid `MultiPolygon` cannot overlap.

For geographic geometries, area is the ellipsoidal area of the region whose
edges are straight in longitude/latitude.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `geom` | `Geometry, GeometryArray, or iterable of geometry-like values or None` | Input geometry, array, or iterable materialized as a row-preserving array. Missing rows return `nan`. | *required* |
| `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 |
| --- | --- |
| `float or ndarray` | Scalar area or one value per row. |

Raises:

| Type | Description |
| --- | --- |
| `CRSError` | If the CRS lacks linear axis units for a metric result. |
| `GeometryError` | If `unit='meters'` is requested for a CRS-free geometry. |

See Also

[area](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.area "area") : CRS-natural property form.
[length](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.length "length") : Length/perimeter with the same `unit` override.

Examples:

```pycon
>>> import gometry as gm
>>> gm.area(gm.box(0, 0, 2, 2), unit='planar')
4.0
```

## distance

Accepted call forms

```python
distance(left: Point, right: Point, *, path: Literal['rhumb'], unit: None = None) -> float
```

```python
distance(left: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Point | None], right: Point | (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Point | None], *, path: Literal['rhumb'], unit: None = None) -> NDArray[float64]
```

```python
distance(left: Point, right: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Point | None], *, path: Literal['rhumb'], unit: None = None) -> NDArray[float64]
```

```python
distance(left: Point | (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Point | None], right: Point | (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Point | None], *, path: Literal['rhumb'], unit: None = None) -> float | NDArray[float64]
```

```python
distance(left: Geometry, right: Geometry, *, path: Literal['geodesic'] = 'geodesic', unit: Literal['planar', 'meters'] | None = None) -> float
```

```python
distance(left: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], right: Geometry | (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], *, path: Literal['geodesic'] = 'geodesic', unit: Literal['planar', 'meters'] | None = None) -> NDArray[float64]
```

```python
distance(left: Geometry, right: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], *, path: Literal['geodesic'] = 'geodesic', unit: Literal['planar', 'meters'] | None = None) -> NDArray[float64]
```

```python
distance(left: Geometry | (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], right: Geometry | (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], *, path: Literal['geodesic'] = 'geodesic', unit: Literal['planar', 'meters'] | None = None) -> float | NDArray[float64]
```

Compute the minimum distance between `left` and `right`.

CRS-aware: geodesic meters on a geographic CRS, native linear units on a
projected CRS, raw coordinate units when CRS-free. On a geographic CRS,
point-to-point distances use ellipsoidal geodesics, and shape edges are
straight in the CRS's longitude/latitude chart with short-way longitude
across the antimeridian. Filled polygon interiors participate. For two
points, `path='rhumb'` measures the constant-bearing route in meters on a
geographic CRS.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `left` | `Geometry, GeometryArray, or iterable of Geometry or None` | Scalar and sequence operands broadcast pairwise; sequences must have equal length and compatible CRS/epoch frames. | *required* |
| `right` | `Geometry, GeometryArray, or iterable of Geometry or None` | Scalar and sequence operands broadcast pairwise; sequences must have equal length and compatible CRS/epoch frames. | *required* |
| `path` | `('geodesic', 'rhumb')` | Route for point operands. Omit for geodesic distance; rhumb distance requires `path='rhumb'` and a geographic CRS and uses meters. | `'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. | `'planar'` |

Returns:

| Type | Description |
| --- | --- |
| `float or ndarray` | One result per input pair. |

Raises:

| Type | Description |
| --- | --- |
| `CRSError` | If the CRS lacks linear axis units for a metric result. |
| `CRSMismatchError` | If the operands' CRS or coordinate-epoch metadata differ. |
| `GeometryTypeError` | If `path='rhumb'` is used with non-point operands. |
| `CRSError` | If `path='rhumb'` is used without a geographic CRS. |
| `GeometryError` | If `unit='meters'` is requested for a CRS-free geometry or a unit override is supplied with `path='rhumb'`. |

See Also

[dwithin](https://gometry.monicz.dev/api/toplevel/predicates/#gometry.dwithin "dwithin") : Within-distance test.
[nearest\_points](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.nearest_points "nearest_points") : Closest-pair witness points.
[shortest\_line](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.shortest_line "shortest_line") : Connecting line between closest points.
[hausdorff\_distance](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.hausdorff_distance "hausdorff_distance") : Hausdorff (set-to-set) similarity distance.
[frechet\_distance](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.frechet_distance "frechet_distance") : Curve-to-curve similarity (linestrings).

Examples:

```pycon
>>> import gometry as gm
>>> gm.distance(gm.Point(0, 0), gm.Point(3, 4))
5.0
>>> a, b = gm.Point(13.0, 52.0, crs=4326), gm.Point(13.1, 52.0, crs=4326)
>>> round(gm.distance(a, b))  # meters
6868
```

## distance\_3d

Accepted call forms

```python
distance_3d(left: Geometry, right: Geometry, *, unit: Literal['planar', 'meters'] | None = None) -> float
```

```python
distance_3d(left: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], right: Geometry | (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], *, unit: Literal['planar', 'meters'] | None = None) -> NDArray[float64]
```

```python
distance_3d(left: Geometry, right: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], *, unit: Literal['planar', 'meters'] | None = None) -> NDArray[float64]
```

```python
distance_3d(left: Geometry | (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], right: Geometry | (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], *, unit: Literal['planar', 'meters'] | None = None) -> float | NDArray[float64]
```

Compute the minimum 3D (Euclidean) distance between two geometries,
measured for their CRS.

Distance is over linework: points/multipoints as degenerate segments,
polygons via their boundary rings. Part of the 3D Euclidean family with
`length_3d` only — area and perimeter are inherently 2D (XY footprint)
and have no 3D form; the 3D extent is `bounds` with `min_z`/`max_z`.

A projected CRS gives native linear units and a CRS-free geometry gives
raw coordinate units — the same defaults as the 2D `distance`. A geographic
CRS raises under every `unit`: a Euclidean norm cannot combine degrees
with meter heights. Every vertex on both operands must carry a Z ordinate.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `left` | `Geometry, GeometryArray, or iterable of Geometry or None` | Scalar and sequence operands broadcast pairwise; sequences must have equal length and compatible CRS/epoch frames. | *required* |
| `right` | `Geometry, GeometryArray, or iterable of Geometry or None` | Scalar and sequence operands broadcast pairwise; sequences must have equal length and compatible CRS/epoch frames. | *required* |
| `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 |
| --- | --- |
| `float or ndarray` | One result per input pair. |

Raises:

| Type | Description |
| --- | --- |
| `CRSError` | If the CRS lacks linear axis units for a metric result. |
| `CRSMismatchError` | If the operands' CRS or coordinate-epoch metadata differ. |
| `GeometryError` | If `unit='meters'` is requested for a CRS-free geometry. |
| `InvalidGeometryError` | If either operand lacks a Z ordinate on every vertex. |

See Also

[distance](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.distance "distance") : The 2D sibling, with the same `unit` override.
[length\_3d](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.length_3d "length_3d") : Total 3D length under the same metric.

Examples:

```pycon
>>> import gometry as gm
>>> gm.distance_3d(gm.from_wkt('POINT Z (0 0 0)'), gm.from_wkt('POINT Z (0 0 3)'))
3.0
```

## frechet\_distance

Accepted call forms

```python
frechet_distance(left: Geometry, right: Geometry, *, densify: float | None = None, unit: Literal['planar', 'meters'] | None = None) -> float
```

```python
frechet_distance(left: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], right: Geometry | (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], *, densify: FloatInput | None = None, unit: Literal['planar', 'meters'] | None = None) -> NDArray[float64]
```

```python
frechet_distance(left: Geometry, right: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], *, densify: FloatInput | None = None, unit: Literal['planar', 'meters'] | None = None) -> NDArray[float64]
```

```python
frechet_distance(left: Geometry | (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], right: Geometry | (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], *, densify: FloatInput | None = None, unit: Literal['planar', 'meters'] | None = None) -> float | NDArray[float64]
```

Discrete Fréchet distance between two linestrings.

Measured for the CRS like `distance`: geodesic meters on a geographic
CRS, native linear units on a projected CRS, raw coordinate units when CRS-free.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `left` | `Geometry, GeometryArray, or iterable of Geometry or None` | The line operands; scalar and sequence inputs broadcast pairwise. | *required* |
| `right` | `Geometry, GeometryArray, or iterable of Geometry or None` | The line operands; scalar and sequence inputs broadcast pairwise. | *required* |
| `densify` | `float` | Subdivide every segment into pieces no longer than this fraction of its length (in `(0, 1]`) before measuring, tightening the discrete vertex metric toward the continuous one. Omitted measures vertices only. | `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 |
| --- | --- |
| `float or ndarray` | One result per input pair. |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If `densify` is outside `(0, 1]`. |
| `CRSMismatchError` | If the operands' CRS or coordinate-epoch metadata differ. |
| `InvalidGeometryError` | If the linework is empty. |
| `GeometryTypeError` | If either geometry is not a single line. |

See Also

[distance](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.distance "distance") : Minimum pairwise distance.
[hausdorff\_distance](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.hausdorff_distance "hausdorff_distance") : Hausdorff (set-to-set) similarity distance.
[dwithin](https://gometry.monicz.dev/api/toplevel/predicates/#gometry.dwithin "dwithin") : Within-distance test.
[nearest\_points](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.nearest_points "nearest_points") : Closest-pair witness points.
[shortest\_line](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.shortest_line "shortest_line") : Connecting line between closest points.

Examples:

```pycon
>>> import gometry as gm
>>> a = gm.LineString([(0, 0), (10, 0)])
>>> b = gm.LineString([(0, 1), (10, 1)])
>>> gm.frechet_distance(a, b)
1.0
```

## hausdorff\_distance

Accepted call forms

```python
hausdorff_distance(left: Geometry, right: Geometry, *, max_error: float | None = None, unit: Literal['planar', 'meters'] | None = None) -> float
```

```python
hausdorff_distance(left: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], right: Geometry | (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], *, max_error: float | None = None, unit: Literal['planar', 'meters'] | None = None) -> NDArray[float64]
```

```python
hausdorff_distance(left: Geometry, right: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], *, max_error: float | None = None, unit: Literal['planar', 'meters'] | None = None) -> NDArray[float64]
```

```python
hausdorff_distance(left: Geometry | (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], right: Geometry | (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], *, max_error: float | None = None, unit: Literal['planar', 'meters'] | None = None) -> float | NDArray[float64]
```

Compute the continuous Hausdorff (set-to-set) distance between `left`
and `right`.

CRS-aware: geodesic meters on a geographic CRS, native linear units on a
projected CRS, raw coordinate units when CRS-free. Geographic Hausdorff
ranges continuously over straight chart edges and supports point and
linework operands only; filled polygon interiors require `unit='planar'`
or a projected CRS. Planar results use a certified relative bound by
default or a caller-supplied absolute bound.

Planar polygons are filled sets, including their interiors. For example,
a square `[-2, 2] by [-2, 2]` and the same square with a diamond hole at
`(0, 1), (1, 0), (0, -1), (-1, 0)` have filled-set Hausdorff distance
`1 / sqrt(2)`, whereas their boundary Hausdorff distance is `1.5`.
Shapely's discrete and densified Hausdorff forms measure boundaries instead.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `left` | `Geometry, GeometryArray, or iterable of Geometry or None` | Scalar and sequence operands broadcast pairwise; sequences must have equal length and compatible CRS/epoch frames. | *required* |
| `right` | `Geometry, GeometryArray, or iterable of Geometry or None` | Scalar and sequence operands broadcast pairwise; sequences must have equal length and compatible CRS/epoch frames. | *required* |
| `max_error` | `float` | Positive finite scalar absolute error bound in final result units. Planar results default to a certified relative error of at most `1e-9`. Omit it for geographic Hausdorff, which uses a fixed radius-scaled algorithmic gap rather than a caller-requested bound. | `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 |
| --- | --- |
| `float or ndarray` | One result per input pair. A planar result is zero exactly when the operands have equal closed support; unequal positive distances remain positive even when smaller than the effective error bound. An empty operand yields `inf`, as in `distance`. |

Raises:

| Type | Description |
| --- | --- |
| `CRSError` | If the CRS lacks linear axis units for a metric result, or a geographic operand includes a filled polygon interior, or the geographic source frontier cannot close its numerical gap before binary64 parameter refinement stops. |
| `CRSMismatchError` | If the operands' CRS or coordinate-epoch metadata differ. |
| `GeometryError` | If `max_error` is not a positive finite scalar or is supplied for a geodesic result; if `unit='meters'` is requested for a CRS-free geometry; or if a finite planar result cannot be certified within representable output and the available generated-work or memory resources. |

See Also

[distance](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.distance "distance") : Minimum pairwise distance.
[frechet\_distance](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.frechet_distance "frechet_distance") : Curve-to-curve similarity (linestrings).
[dwithin](https://gometry.monicz.dev/api/toplevel/predicates/#gometry.dwithin "dwithin") : Within-distance test.
[nearest\_points](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.nearest_points "nearest_points") : Closest-pair witness points.
[shortest\_line](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.shortest_line "shortest_line") : Connecting line between closest points.

Examples:

```pycon
>>> import gometry as gm
>>> a = gm.LineString([(0, 0), (10, 0)])
>>> b = gm.LineString([(0, 1), (10, 3)])
>>> abs(gm.hausdorff_distance(a, b, max_error=1e-12) - 3.0) <= 1e-12
True
```

## length

Accepted call forms

```python
length(geom: Geometry, *, unit: Literal['planar', 'meters'] | None = None) -> float
```

```python
length(geom: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], *, unit: Literal['planar', 'meters'] | None = None) -> NDArray[float64]
```

```python
length(geom: Iterable[Geometry | Buffer | Mapping[str, Any] | SupportsGeoInterface | None], *, unit: Literal['planar', 'meters'] | None = None) -> NDArray[float64]
```

```python
length(geom: Geometry | (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None] | Iterable[Geometry | Buffer | Mapping[str, Any] | SupportsGeoInterface | None], *, unit: Literal['planar', 'meters'] | None = None) -> float | NDArray[float64]
```

Compute length in CRS-natural units or with a `unit` override.

For a `GeometryCollection`, length sums every member's length or
perimeter, including overlapping members.

For geographic geometries, length and perimeter are measured along edges
straight in longitude/latitude on the CRS ellipsoid.

Geographic polygon perimeter removes chart-cut copies only: within one
ring, antiparallel coincident arcs at different longitude lifts cancel;
on the canonical seam meridian, opposite-interior copies cancel across all
rings, including a ring with itself. Same-side seam duplicates, off-seam
same-lift retraces, and every other stored overlap remain in the perimeter.
This seam convention is tied to the canonical seam: rotating the longitude
origin can change which arcs are seam cuts.

Arc identity uses exact canonical longitudes and admitted latitudes; no
tolerance is applied. Between the two seam spellings, the longitude step is
degenerate; differing latitudes still trace a meridian arc. An explicit
one-period edge between non-seam longitudes follows the full circle. Planar
and projected perimeter rules are unchanged.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `geom` | `Geometry, GeometryArray, or iterable of geometry-like values or None` | Input geometry, array, or iterable materialized as a row-preserving array. Missing rows return `nan`. | *required* |
| `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 |
| --- | --- |
| `float or ndarray` | Scalar length or one value per row. |

Raises:

| Type | Description |
| --- | --- |
| `CRSError` | If the CRS lacks linear axis units for a metric result. |
| `GeometryError` | If `unit='meters'` is requested for a CRS-free geometry. |

See Also

[length](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.length "length") : CRS-natural property form.
[area](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.area "area") : Area with the same `unit` override.

Examples:

```pycon
>>> import gometry as gm
>>> gm.length(gm.LineString([(0, 0), (3, 4)]), unit='planar')
5.0
```

## length\_3d

Accepted call forms

```python
length_3d(geom: Geometry, *, unit: Literal['planar', 'meters'] | None = None) -> float
```

```python
length_3d(geom: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], *, unit: Literal['planar', 'meters'] | None = None) -> NDArray[float64]
```

```python
length_3d(geom: Iterable[Geometry | Buffer | Mapping[str, Any] | SupportsGeoInterface | None], *, unit: Literal['planar', 'meters'] | None = None) -> NDArray[float64]
```

```python
length_3d(geom: Geometry | (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None] | Iterable[Geometry | Buffer | Mapping[str, Any] | SupportsGeoInterface | None], *, unit: Literal['planar', 'meters'] | None = None) -> float | NDArray[float64]
```

Compute 3D length in CRS-natural units or with a `unit` override.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `geom` | `Geometry, GeometryArray, or iterable of geometry-like values or None` | Input geometry, array, or iterable materialized as a row-preserving array. Missing rows return `nan`. | *required* |
| `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.  Geographic CRSs are not supported by 3D Euclidean metrics. | `'planar'` |

Returns:

| Type | Description |
| --- | --- |
| `float or ndarray` | Scalar 3D length or one value per row. |

Raises:

| Type | Description |
| --- | --- |
| `CRSError` | If the CRS lacks linear axis units for a metric result. |
| `GeometryError` | If `unit='meters'` is requested for a CRS-free geometry. |
| `InvalidGeometryError` | If a scalar geometry lacks Z on every vertex. |

See Also

[length\_3d](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.length_3d "length_3d") : CRS-natural property form.
[length](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.length "length") : The 2D sibling, with the same `unit` override.
[distance\_3d](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.distance_3d "distance_3d") : Pairwise 3D distance under the same metric.

Examples:

```pycon
>>> import gometry as gm
>>> gm.length_3d(gm.from_wkt('LINESTRING Z (0 0 0, 3 4 0)'), unit='planar')
5.0
```

## nearest\_points

Accepted call forms

```python
nearest_points(left: Geometry, right: Geometry, *, unit: Literal['planar', 'meters'] | None = None) -> tuple[Point, Point]
```

```python
nearest_points(left: Geometry, right: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryT], *, unit: Literal['planar', 'meters'] | None = None) -> tuple[GeometryArray[Point], GeometryArray[Point]]
```

```python
nearest_points(left: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryT], right: Geometry, *, unit: Literal['planar', 'meters'] | None = None) -> tuple[GeometryArray[Point], GeometryArray[Point]]
```

```python
nearest_points(left: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryT], right: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryOtherT], *, unit: Literal['planar', 'meters'] | None = None) -> tuple[GeometryArray[Point], GeometryArray[Point]]
```

```python
nearest_points(left: Geometry, right: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryT | None], *, unit: Literal['planar', 'meters'] | None = None) -> tuple[GeometryArray[Point | None], GeometryArray[Point | None]]
```

```python
nearest_points(left: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryT | None], right: Geometry, *, unit: Literal['planar', 'meters'] | None = None) -> tuple[GeometryArray[Point | None], GeometryArray[Point | None]]
```

```python
nearest_points(left: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryT | None], right: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryOtherT | None], *, unit: Literal['planar', 'meters'] | None = None) -> tuple[GeometryArray[Point | None], GeometryArray[Point | None]]
```

```python
nearest_points(left: Geometry | (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], right: Geometry | (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], *, unit: Literal['planar', 'meters'] | None = None) -> tuple[Point, Point] | tuple[GeometryArray[Point | None], GeometryArray[Point | None]]
```

Return the closest pair of points between two geometries.

Realizes the same minimizer as `distance`: point-to-point distance is
geodesic on a geographic CRS, planar on a projected one, and in coordinate
space when CRS-free. Geographic shape edges are straight in the CRS's
longitude/latitude chart, using short-way longitude across the antimeridian;
filled polygon interiors participate. Planar and projected metrics accept
any geometry pair, not only points (the witness on a polygon/line may be an
edge-interior point). The connecting line is `shortest_line`.

An empty operand yields
`(POINT EMPTY, POINT EMPTY)`, and the pair is dropped to the operands'
common axes so it matches `shortest_line`'s endpoints exactly.

Equal-distance witnesses prefer an interior projection over a point or
endpoint, then source order. Geographic metrics apply this order only to
equal evaluated backend distances; analytic branches retain their available
candidate. This does not assert an exact geodesic minimum.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `left` | `Geometry, GeometryArray, or iterable of Geometry or None` | Scalar and sequence operands broadcast pairwise; sequences must have equal length and compatible CRS/epoch frames. Unpack order is point on `left`, then on `right`. | *required* |
| `right` | `Geometry, GeometryArray, or iterable of Geometry or None` | Scalar and sequence operands broadcast pairwise; sequences must have equal length and compatible CRS/epoch frames. Unpack order is point on `left`, then on `right`. | *required* |
| `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 |
| --- | --- |
| `tuple of Point or tuple of GeometryArray` | A `(left_point, right_point)` pair for scalar inputs, or a `(left, right)` pair of parallel witness point columns when either operand is a `GeometryArray`. |

Raises:

| Type | Description |
| --- | --- |
| `CRSMismatchError` | If the operands' CRS or coordinate-epoch metadata differ. |

See Also

[distance](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.distance "distance") : Minimum pairwise distance.
[shortest\_line](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.shortest_line "shortest_line") : Connecting line between closest points.
[dwithin](https://gometry.monicz.dev/api/toplevel/predicates/#gometry.dwithin "dwithin") : Within-distance test.
[hausdorff\_distance](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.hausdorff_distance "hausdorff_distance") : Hausdorff (set-to-set) similarity distance.
[frechet\_distance](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.frechet_distance "frechet_distance") : Curve-to-curve similarity (linestrings).

Examples:

```pycon
>>> import gometry as gm
>>> square = gm.box(0, 0, 1, 1)
>>> a, b = gm.nearest_points(square, gm.Point(3, 0.5))
>>> (a.to_wkt(), b.to_wkt())
('POINT (1 0.5)', 'POINT (3 0.5)')
```

## shortest\_line

Accepted call forms

```python
shortest_line(left: Geometry, right: Geometry, *, unit: Literal['planar', 'meters'] | None = None) -> LineString
```

```python
shortest_line(left: Geometry, right: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryT], *, unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[LineString]
```

```python
shortest_line(left: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryT], right: Geometry, *, unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[LineString]
```

```python
shortest_line(left: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryT], right: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryOtherT], *, unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[LineString]
```

```python
shortest_line(left: Geometry, right: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryT | None], *, unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[LineString | None]
```

```python
shortest_line(left: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryT | None], right: Geometry, *, unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[LineString | None]
```

```python
shortest_line(left: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryT | None], right: (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[GeometryOtherT | None], *, unit: Literal['planar', 'meters'] | None = None) -> GeometryArray[LineString | None]
```

```python
shortest_line(left: Geometry | (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], right: Geometry | (GeometryArray[GeometryRowT] | Iterable[GeometryRowT])[Geometry | None], *, unit: Literal['planar', 'meters'] | None = None) -> LineString | GeometryArray[LineString | None]
```

Return the shortest connecting line between two geometries (CRS-aware).

`nearest_points` as a connecting `LineString` — degenerate when the
geometries touch. Planar and projected metrics accept any geometry pair, not
only points, and the witness is the closest approach, so an endpoint may
land on an edge interior rather than a vertex.

On a geographic CRS,
point-to-point separation uses ellipsoidal geodesics. Shape edges are
straight in the CRS-native periodic longitude/latitude chart: admitted
ordinary edges use their shortest periodic step, while an explicitly stored
full-period circle edge retains its full turn. See the [CRS guide's
polar-ring and full-turn-edge rules](https://gometry.monicz.dev/guide/crs/#polar-rings-and-full-turn-edges).
Filled polygon interiors participate.

The returned line follows the chart-edge model. With the CRS-aware
geographic metric, its ellipsoidal length is no shorter than the witness
separation in exact geometry, subject to binary64 rounding. If
`unit='planar'` overrides the metric, measure the line with the same
`unit` when comparing lengths. Publication may add vertices to preserve
the computed chart edge; do not assume the line always stores exactly two
coordinates.

An empty operand yields
`LINESTRING EMPTY` (the output-type sentinel, like
`distance`'s `inf`). Output ordinates are the operands' common axes (an
XYZM line versus an XY point gives an XY line). See `nearest_points` for
the witnesses and `distance` for their metric separation.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `left` | `Geometry, GeometryArray, or iterable of Geometry or None` | Scalar and sequence operands broadcast pairwise; sequences must have equal length and compatible CRS/epoch frames. | *required* |
| `right` | `Geometry, GeometryArray, or iterable of Geometry or None` | Scalar and sequence operands broadcast pairwise; sequences must have equal length and compatible CRS/epoch frames. | *required* |
| `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 |
| --- | --- |
| `Geometry or GeometryArray` | One connecting `LineString` per input pair. |

Raises:

| Type | Description |
| --- | --- |
| `CRSMismatchError` | If the operands' CRS or coordinate-epoch metadata differ. |

See Also

[distance](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.distance "distance") : Minimum pairwise distance.
[nearest\_points](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.nearest_points "nearest_points") : Closest-pair witness points.
[dwithin](https://gometry.monicz.dev/api/toplevel/predicates/#gometry.dwithin "dwithin") : Within-distance test.
[hausdorff\_distance](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.hausdorff_distance "hausdorff_distance") : Hausdorff (set-to-set) similarity distance.
[frechet\_distance](https://gometry.monicz.dev/api/toplevel/measurement/#gometry.frechet_distance "frechet_distance") : Curve-to-curve similarity (linestrings).

Examples:

```pycon
>>> import gometry as gm
>>> square = gm.box(0, 0, 1, 1)
>>> gm.shortest_line(square, gm.Point(3, 0.5)).to_wkt()
'LINESTRING (1 0.5, 3 0.5)'
>>> # The near point can fall mid-edge, not on a vertex:
>>> a = gm.from_wkt('POLYGON ((0 0, 2 0, 2 2, 0 2, 0 0))')
>>> b = gm.from_wkt('POLYGON ((4 1, 5 0, 6 1, 5 2, 4 1))')
>>> gm.shortest_line(a, b).to_wkt()
'LINESTRING (2 1, 4 1)'
```
