Geometry operations
geometry_opPerform geometry calculations and spatial predicates on coordinates and GeoJSON, including distance, area, buffer, and intersection.
Instructions
Geometry math and predicates — one tool, many ops, no Overture scan.
`op` selects the operation; pass only the params it needs (points are
`{"lat": ..., "lon": ...}`; `geometry` is a GeoJSON object):
- `distance(point, point2)` -> `{"distance_m"}` (great-circle haversine distance)
- `bearing(point, point2)` -> `{"bearing_deg"}` (initial compass bearing)
- `destination(point, bearing_deg, distance_m)` -> `{"point"}`
- `midpoint(point, point2)` -> `{"point"}` (great-circle midpoint)
- `area(geometry)` -> `{"area_m2", "area_km2"}` (Polygon/MultiPolygon)
- `length(geometry)` -> `{"length_m"}` (LineString/MultiLineString)
- `bbox(geometry)` -> `{"bbox": [xmin, ymin, xmax, ymax]}` (any geometry)
- `centroid(geometry)` -> `{"point"}` (any geometry)
- `buffer(point, radius_m)` -> `{"geometry"}` (Polygon, ~32-vertex circle approximation)
- `convex_hull(points)` -> `{"geometry"}` (Polygon; points capped at 100)
- `point_in_polygon(points, geometry)` -> `{"results": [bool, ...]}` (Polygon/MultiPolygon,
holes honored; points capped at 100)
- `nearest_point(point, points)` -> `{"index", "distance_m"}` (points capped at 100)
- `nearest_point_on_line(point, geometry)` -> `{"point", "distance_m", "fraction"}` (LineString)
- `union(geometry, geometry2)` -> `{"geometry", "area_km2"}` (Polygon/MultiPolygon, either slot)
- `intersect(geometry, geometry2)` -> `{"geometry", "area_km2"}`, or `{"empty": true, "note"}`
when the two inputs don't overlap
- `difference(geometry, geometry2)` -> `{"geometry", "area_km2"}` (geometry minus geometry2),
or `{"empty": true, "note"}` when geometry2 fully covers geometry
`buffer`, `convex_hull`, and `union`/`intersect`/`difference` are the
ops that return geometry; that output is simplified to fit the same
token budget `simplify_geometry`'s own default targets, so there's no
need to chain a second call. `union`/`intersect`/`difference` run via
the DuckDB spatial extension already loaded for other tools (see
geometry_setops.py) rather than geometry_ops.py's pure-Python math.
An unknown op returns `{"error": "bad_request", ...}` listing valid ops.
Missing/wrong-shaped params for the given op return `{"error":
"bad_request", ...}` naming exactly what that op needs, e.g. "op=buffer
needs point and radius_m". Point-like inputs are range-checked (lat in
[-90, 90], lon in [-180, 180]); `geometry`/`geometry2` get structural
validation only (right type, non-empty numeric coordinates) — see
geometry_ops.py's module docstring for the accuracy notes behind
area/centroid (a local meters projection, not a geodesic computation)
and buffer/convex_hull (planar approximations, fine at city/regional
scale).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| op | Yes | Geometry operation; each takes a different subset of the other arguments — see below. | |
| point | No | ||
| point2 | No | ||
| points | No | ||
| geometry | No | ||
| radius_m | No | ||
| geometry2 | No | ||
| distance_m | No | ||
| bearing_deg | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||