Skip to content
Back to skills

Spatial Topology

ASecurity

"Build and post-process spatial graphs with city2graph proximity,

  • 247 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 8, 2026
developmentpythongonodegitapi

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 4 files and shows the line behind each finding

Scanned September 8, 2026

npx -y skills add VectorSpaceLab/AREX-Skill --skill spatial-topology --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Spatial Topology?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Spatial Topology
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/vectorspacelab-spatial-topology/badge)](https://www.skillsdirectory.com/skills/vectorspacelab-spatial-topology)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: spatial-topology
description: "Build and post-process spatial graphs with city2graph proximity,
  contiguity, tessellation, isochrone, clipping, dual-graph, and geometry
  utilities."
metadata:
  disco-role: operating
disable-model-invocation: true
license: BSD 3-Clause
---

# Spatial topology

Use this skill when the task is to turn GeoDataFrames into spatial relations or
clean, measure, tessellate, filter, clip, dualize, or plot an existing spatial
graph. It is a GeoPandas/NetworkX-first operating layer. Keep node identifiers
in the GeoDataFrame index, edge identifiers in the first two levels of a
MultiIndex, and preserve a CRS through every operation.

## Route the request

1. **Choose the graph builder.**
   - Points and local neighbours: `knn_graph` or `fixed_radius_graph`.
   - Planar proximity hierarchy: `delaunay_graph`, `gabriel_graph`,
     `relative_neighborhood_graph`, or `euclidean_minimum_spanning_tree`.
   - Random distance-decay edges: `waxman_graph`.
   - Polygon adjacency: `contiguity_graph`.
   - Polygon-to-point containment: `group_nodes`.
   - Typed layer-to-layer proximity: `bridge_nodes`.
2. **Choose the distance model before calling a builder.** Use a projected CRS
   whose coordinate units match the requested radius, weights, buffers, or
   travel thresholds. Select `network` only when a same-CRS line network is
   available and its node positions and edge weights are usable.
3. **Choose post-processing.** Use `filter_graph_by_distance` for a reachable
   subgraph, `create_isochrone` for a polygonal reachable envelope,
   `create_tessellation` for cells, `clip_graph` for an area boundary,
   `dual_graph` for edge-as-node topology, `remove_isolated_components` for
   largest-component cleanup, and `canonicalize_edges`/
   `symmetrize_edges` for undirected edge-table conventions.
4. **Choose output deliberately.** By default builders return `(nodes_gdf,
   edges_gdf)` or typed dictionaries. `as_nx=True` returns NetworkX and is
   retained for compatibility; the builder APIs mark this option deprecated in
   favour of conversion utilities. `duplicate_edges=True` is a GeoDataFrame
   convenience only and is incompatible with directed variants and NetworkX
   output.
5. **Verify the result.** Check CRS, index shape, relation keys, `weight`,
   geometry type, connectedness, and whether infinite network distances or
   empty/degenerate geometries are expected. Read the focused API and
   troubleshooting references before changing defaults:
   - [API reference](references/api-reference.md)
   - [Distance, CRS, and geometry](references/distance-crs-and-geometry.md)
   - [Troubleshooting](references/troubleshooting.md)

## Operating invariants

- A builder uses the input index as node IDs. Its edge GeoDataFrame normally
  has a `(source, target)` MultiIndex and at least `weight` and `geometry`
  columns. Edge geometry represents the relationship path, not necessarily
  the original feature geometry.
- `GraphBuilder` positions ordinary nodes at geometry centroids. A supplied
  `node_geom_col` can override positions for contiguity and grouping; using
  `set_point_nodes=True` also replaces the returned node geometry and stores
  the original geometry as `original_geometry`.
- Euclidean and Manhattan weights are coordinate-unit distances. Manhattan edge
  geometries are L-shaped (`(x1,y1) -> (x2,y1) -> (x2,y2)`); Euclidean edges
  are direct segments. Network weights are shortest-path costs and network
  edge geometry follows the shortest path when available.
- A network metric snaps each sample centroid to its nearest network node; it
  does not project the sample onto a network edge. Unreachable pairs receive
  `inf` and are excluded by bounded neighbour/radius selection. If both sample
  endpoints snap to one network node, or no usable path geometry exists, edge
  geometry falls back to a direct segment.
- Spatial predicates, contiguity, clipping, centroids, tessellation, and
  buffering operate in the coordinates supplied. Geographic longitude/latitude
  is not a substitute for a projected CRS for map-unit distances or areas.
- Empty inputs are generally returned as typed empty GeoDataFrames/graphs.
  Too few points take explicit early exits in the point builders. Delaunay
  family methods still require non-collinear coordinates when they invoke
  SciPy triangulation; preflight collinear data rather than assuming a silent
  fallback.

## Minimal procedure

```python
from city2graph.proximity import fixed_radius_graph
from city2graph.utils import create_isochrone, filter_graph_by_distance, gdf_to_nx

# Reproject all layers to a CRS with metre-like units before measuring.
points = points.to_crs("EPSG:3857")
nodes, edges = fixed_radius_graph(points, radius=500.0)
graph = gdf_to_nx(nodes=nodes, edges=edges)
reachable = filter_graph_by_distance(
    graph, center_point=origin, threshold=1_000.0, edge_attr="weight"
)
```

For a network metric, first reproject `points` and `network_gdf` to the same
projected CRS, confirm the network converts to a graph with `pos` node
attributes, and decide whether geometry length or a numeric `network_weight`
column is the intended cost. For a heterogeneous result, inspect the typed
edge dictionary before conversion: relation direction and layer names are part
of the contract.

## Non-goals and handoff

This skill does not acquire Overture, GTFS, or GBFS data, construct complete
urban morphology workflows, or convert graphs to PyTorch Geometric. Hand those
tasks to the corresponding package workflow after this skill has produced a
clean spatial graph. It does not infer physical units from a CRS or repair
silently wrong coordinates. When evidence is insufficient, return the typed
empty/fallback result only with the warning or omission recorded.

Files in this skill

  • SKILL.md5.7 KB
  • references/api-reference.md11.7 KB
  • references/distance-crs-and-geometry.md10.7 KB
  • references/troubleshooting.md11.9 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.