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

# Coordinates, parts & groups

Coordinate views, multipart views, and grouped results.

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

## Coordinates

Flat, indexable coordinate sequence behind `geom.coords`:
coordinates flattened depth-first across parts/rings, with per-axis columns.

Index or iterate without first copying all vertices into a list.

For `GeometryArray.coords`, missing rows contribute no vertices. The view is
a flattened vertex stream, not a row-aligned container; use `.row_index`
when you need source-row indexes.

### coordinate\_axes `property`

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

Coordinate layout: `'XY'`, `'XYZ'`, `'XYM'`, or `'XYZM'` — the
`select`-forced layout when set, else the union of the present axes.

Returns:

| Type | Description |
| --- | --- |
| `CoordinateAxes` | The exact ordinate layout visible through this coordinate view. |

### m `property`

```python
m: NDArray[float64]
```

The M ordinates as a read-only `float64` `numpy.ndarray` of view
length (`NaN` when no coordinate carries M).

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | One read-only value per vertex in view order; missing M ordinates are `NaN`. M is a measure ordinate, not a CRS unit; absent columns are materialized. |

### nbytes `property`

```python
nbytes: int
```

Logical coordinate payload in bytes (numpy's `nbytes` convention):
the stored `f64` ordinate values behind this view only. Slices and
array-backed views report only their logical rows. Temporary NumPy
matrices from `numpy.asarray(coords)` and any lazy prepared-geometry
or membership sidecars on the parent geometry/array are not included —
those live on the owner, not on this view.

Returns:

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

### row\_index `property`

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

Per-coordinate source geometry row (all `0` for a scalar geometry);
the source row for each vertex of a `GeometryArray`.

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | A materialized, read-only int64 array in flat coordinate order, one source-row label per vertex. |

### x `property`

```python
x: NDArray[float64]
```

The X ordinates as a read-only `float64` `numpy.ndarray`.

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | One read-only value per vertex in view order, in the geometry's native coordinate units (raw coordinate units when CRS-free). The array shares the immutable coordinate column when one is available. |

### y `property`

```python
y: NDArray[float64]
```

The Y ordinates as a read-only `float64` `numpy.ndarray`.

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | One read-only value per vertex in view order, in the geometry's native coordinate units (raw coordinate units when CRS-free). The array shares the immutable coordinate column when one is available. |

### z `property`

```python
z: NDArray[float64]
```

The Z ordinates as a read-only `float64` `numpy.ndarray` of view
length (`NaN` when no coordinate carries Z).

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | One read-only value per vertex in view order; missing Z ordinates are `NaN`. Values remain in the geometry's native coordinate units; absent columns are materialized. |

### \_\_contains\_\_

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

Whether a coordinate tuple appears among the vertices.

Returns:

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

### \_\_getitem\_\_

Accepted call forms

```python
__getitem__(index: SupportsIndex, /) -> tuple[float | None, ...]
```

```python
__getitem__(index: slice, /) -> list[tuple[float | None, ...]]
```

```python
__getitem__(index: SupportsIndex | slice, /) -> tuple[float | None, ...] | list[tuple[float | None, ...]]
```

Select vertices by integer or slice.

An `int` returns one coordinate tuple `(x, y[, z[, m]])`.
A `slice` returns a `list` of those tuples.

Returns:

| Type | Description |
| --- | --- |
| `tuple or list of tuple` |  |

### \_\_iter\_\_

```python
__iter__() -> CoordinatesIterator
```

Iterate coordinate tuples in vertex order.

Returns:

| Type | Description |
| --- | --- |
| `iterator of tuple` |  |

### \_\_len\_\_

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

Number of vertices in this coordinate view.

Returns:

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

### \_\_reversed\_\_

```python
__reversed__() -> CoordinatesIterator
```

Iterate coordinate tuples in reverse vertex order.

Returns:

| Type | Description |
| --- | --- |
| `iterator of tuple` |  |

### count

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

Number of coordinates equal to `value` under the visible layout
(same representation as iteration / `select`).

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `value` | `object` | The coordinate value to count. | *required* |

Returns:

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

### index

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

First index of an equal coordinate in `[start, stop)`.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `value` | `object` | The coordinate value to locate. | *required* |
| `start` | `int` | First position searched. | `0` |
| `stop` | `int` | One past the last position searched. | `None` |

Returns:

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

Raises:

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

### select

```python
select(axes: Literal['XY', 'XYZ', 'XYM', 'XYZM']) -> Coordinates
```

Return a view of the same coordinates in a fixed `coordinate_axes` layout
(`'XY'`/`'XYZ'`/`'XYM'`/`'XYZM'`). This layout defines the schema
of coordinate tuples, nested output, matrices, dictionaries, and equality.
Tuple/nested output uses `None` where a coordinate lacks the requested
Z/M; matrices and dictionary columns use `NaN` there. Axis accessors
use the selected layout too: excluded Z/M columns contain `NaN`.
Selection does not change the geometry.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `axes` | `('XY', 'XYZ', 'XYM', 'XYZM')` | The layout every tuple and column should take. | `'XY'` |

Returns:

| Type | Description |
| --- | --- |
| `Coordinates` | The same coordinates with the selected view layout. |

Examples:

```pycon
>>> import gometry as gm
>>> coords = gm.LineString([(0, 0), (1, 1)]).coords
>>> coords.select('XYZ').to_nested()
[(0.0, 0.0, None), (1.0, 1.0, None)]
```

### to\_dict

Accepted call forms

```python
to_dict(*, index: Literal[False] = False) -> dict[str, NDArray[float64]]
```

```python
to_dict(*, index: Literal[True]) -> dict[str, NDArray[float64] | ndarray[tuple[int], dtype[int64]]]
```

Return a dependency-free column dict — `{'x': ndarray, 'y': ndarray, …}` — ready
for `pandas`/`polars` (`pd.DataFrame(coords.to_dict())`).
`z`/`m` columns appear when carried by the view or selected layout,
with `NaN` for rows that lack an ordinate; `index=True` adds the
source-geometry row column.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `index` | `bool` | Add an `'index'` column with each coordinate's source row when `True`; the `False` form omits that column. | *required* |

Returns:

| Type | Description |
| --- | --- |
| `dict` | One read-only ndarray per axis (plus `'index'` when requested). |

Examples:

```pycon
>>> import gometry as gm
>>> gm.LineString([(0, 0), (1, 1)]).coords.to_dict()['x'].tolist()
[0.0, 1.0]
```

### to\_nested

```python
to_nested() -> NestedCoordinates
```

Return the coordinates as a nested structure mirroring the geometry's topology
(point → `[x, y]`, line → list of tuples, polygon → list of rings;
arrays → one entry per geometry row) — the `__geo_interface__`-style
nesting, as Python lists. A selected view layout determines each
coordinate's ordinates; absent selected Z/M values are `None`. Missing
array rows remain `None`. The flat columns do not preserve this shape.

Returns:

| Type | Description |
| --- | --- |
| `list` | Nested Python lists and coordinate tuples matching the topology. |

Examples:

```pycon
>>> import gometry as gm
>>> gm.LineString([(0, 0), (1, 1)]).coords.to_nested()
[(0.0, 0.0), (1.0, 1.0)]
```

## GeometryParts

Lazy view over one geometry's immediate parts.

Returned by `.parts` on every geometry. Simple geometries expose a
singleton view of themselves; multipart and collection geometries expose
their immediate members. Scalar indexing and iteration materialize one
typed geometry at a time via `part_at`; slice indexing may still build a
list up front.

### nbytes `property`

```python
nbytes: int
```

Logical coordinate payload retained by the source geometry.

Returns:

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

### \_\_contains\_\_

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

Whether a geometry equals one of the component parts.

Returns:

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

### \_\_getitem\_\_

Accepted call forms

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

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

```python
__getitem__(index: SupportsIndex | slice, /) -> GeometryT_co | list[GeometryT_co]
```

Select parts by integer or slice.

An `int` returns one component geometry. A `slice` returns a
`list` of component geometries.

Returns:

| Type | Description |
| --- | --- |
| `Geometry or list of Geometry` |  |

### \_\_iter\_\_

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

Iterate component geometries.

Returns:

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

### \_\_len\_\_

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

Number of component parts.

Returns:

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

### \_\_reversed\_\_

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

Iterate component geometries in reverse order.

Returns:

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

### count

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

Number of parts equal to `value`.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `value` | `object` | The geometry value to count. | *required* |

Returns:

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

### index

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

First index of an equal part in `[start, stop)`.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `value` | `object` | The geometry value to locate. | *required* |
| `start` | `int` | First position searched. | `0` |
| `stop` | `int` | One past the last position searched. | `None` |

Returns:

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

Raises:

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

## Groups

Accepted call forms

```python
Groups(values: GroupValuesT, offsets: ndarray[tuple[int], dtype[signedinteger[Any] | unsignedinteger[Any]]] | Iterable[int | integer[Any]], *, missing: None = None) -> Groups[GroupValuesT]
```

```python
Groups(values: GroupValuesT, offsets: ndarray[tuple[int], dtype[signedinteger[Any] | unsignedinteger[Any]]] | Iterable[int | integer[Any]], *, missing: ndarray[tuple[int], dtype[bool_]] | Iterable[bool] | None) -> Groups[GroupValuesT | None]
```

Shared CSR ragged container: one flat `values` payload plus row `offsets`.
The values payload keeps its actual type (int64, float64, geometry array, or cell
array). A contiguous values window may share backing; offsets for a window
starting after row zero are rebased, and counts are materialized.

Group a flat typed values array using CSR row boundaries.

The values kind is explicit even when empty. Numeric values are copied,
retaining int64 versus float64; geometry and cell arrays share immutable
storage. Integer values remain exact int64 values.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `values` | `GroupValuesT` | Flat payload. Numeric arrays must be one-dimensional int64 or float64. | *required* |
| `offsets` | `ndarray[tuple[int], dtype[signedinteger[Any] \| unsignedinteger[Any]]] \| Iterable[int \| integer[Any]]` | Nondecreasing boundaries, starting at zero and ending at len(values). | *required* |
| `missing` | `None \| ndarray[tuple[int], dtype[bool_]] \| Iterable[bool] \| None` | One flag per group. Missing groups must have empty values windows. | `varies by call form` |

Returns:

| Type | Description |
| --- | --- |
| `Groups` | A row-grouped view over the supplied values and offsets. |

### counts `property`

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

Per-group element counts (`offsets[i + 1] - offsets[i]`). Missing
groups have count zero; `.is_missing` distinguishes them from present
groups with no values.

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | A materialized, read-only int64 count for each group in row order. |

### is\_missing `property`

```python
is_missing: ndarray[tuple[int], dtype[bool_]]
```

Missing source groups, distinct from present groups with no outputs.

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | A read-only boolean mask in group order. |

### nbytes `property`

```python
nbytes: int
```

Logical CSR payload in bytes: the selected flat values payload, the
`len(self) + 1` int64 offsets column, and a row-validity bitmap when
any group is missing. For geometry-valued groups this uses the values
`GeometryArray.nbytes` and excludes geometry structural offsets,
matching NumPy's payload-only convention.

Returns:

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

### offsets `property`

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

The `len(self) + 1` row boundaries into `values` (CSR offsets
column): row `i` is `values[offsets[i]:offsets[i + 1]]`.

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | A read-only int64 array of row boundaries. Slices are rebased to start at zero; a slice starting after row zero owns a rebased copy. |

### values `property` `readonly`

```python
values: ndarray[(Any, Any)] | GeometryArray[Any] | CellArray[Any]
```

The logical flat payload window (numeric ndarray, `GeometryArray`, or
`CellArray`), with values in group order. A contiguous source window
can share backing; gathered values may be materialized.

Returns:

| Type | Description |
| --- | --- |
| `Group values` | The selected flat payload window. Numeric values are read-only; geometry and cell payloads retain their immutable array types. |

### \_\_reversed\_\_

```python
__reversed__() -> GroupsIterator[GroupRowT_co]
```

Iterate row groups in reverse order.

Returns:

| Type | Description |
| --- | --- |
| `iterator` |  |

### count

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

Number of rows equal to `value`.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `value` | `object` | The row value to count. | *required* |

Returns:

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

### index

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

First index of an equal row in `[start, stop)`.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `value` | `object` | The row value to locate. | *required* |
| `start` | `int` | First position searched. | `0` |
| `stop` | `int` | One past the last position searched. | `None` |

Returns:

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

Raises:

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

### to\_list

Accepted call forms

```python
to_list() -> list[list[int]]
```

```python
to_list() -> list[list[int] | None]
```

```python
to_list() -> list[list[GeometryT_co]]
```

```python
to_list() -> list[list[GeometryT_co] | None]
```

```python
to_list() -> list[list[CellT_co]]
```

```python
to_list() -> list[list[CellT_co] | None]
```

Copy into a plain nested Python list.

Returns:

| Type | Description |
| --- | --- |
| `list` | Materialized rows of the grouped values; missing rows are `None`. |

Examples:

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

### to\_pairs

```python
to_pairs() -> tuple[ndarray[tuple[int], dtype[int64]], ndarray[tuple[int], dtype[int64]]]
```

Expand integer CSR rows into parallel `(row_ids, values)` columns.

The right column is a zero-copy read-only view of the flat CSR values;
only the repeated row-id column is materialized. Row ids are positions
in this logical `Groups` object, so sliced groups start again at zero.

Returns:

| Type | Description |
| --- | --- |
| `tuple of numpy.ndarray` | Parallel read-only int64 `(row_ids, values)` columns. |

Raises:

| Type | Description |
| --- | --- |
| `TypeError` | If the groups contain geometry or cell rows rather than integers. |

Examples:

```pycon
>>> import gometry as gm
>>> idx = gm.SpatialIndex([
...     gm.box(0, 0, 2, 2), gm.box(1, 1, 3, 3), gm.box(10, 10, 11, 11)])
>>> row_ids, values = idx.query(
...     gm.GeometryArray([gm.Point(1.5, 1.5), gm.Point(10.5, 10.5)])
... ).to_pairs()
>>> (row_ids.tolist(), values.tolist())
([0, 0, 1], [0, 1, 2])
```
