> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bijection.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Geospatial data

> Geometry values, spatial queries and maps in your app, and what runs in your own compute

Bijection stores points and shapes as ordinary validated values, answers spatial
questions with exact reads, commits geofence transitions with the observations that
caused them, and draws your data on the workspace map under your read rules. Bulk
and specialist geospatial computation runs in your own infrastructure and comes back
through [customer compute](/datasets/customer-compute).

## Geometry values

Declare a geometry like any other field:

```ts bijection/schema.ts theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
import { defineSchema, defineTable } from "bijection/server";
import { geoPoint, geoShape } from "@bijection/datasets/geometry";
import { v } from "bijection/values";

export default defineSchema({
  depots: defineTable({ name: v.string(), location: geoPoint() }),
  zones: defineTable({
    name: v.string(),
    area: geoShape({ types: ["Polygon", "MultiPolygon"], size: "large" }),
  }),
});
```

Values are GeoJSON in WGS84, longitude first. Every write, function argument and
synced record is checked: an empty, unclosed or self-intersecting shape, or one in
another coordinate system, is refused rather than repaired. The standard size holds
up to 512 positions; `size: "large"` holds up to 40,960. `geoShape({ profile:
"wgs84-3d-hae-linear-sphere-v1" })` adds heights above the WGS84 ellipsoid.

## What runs where

| Bijection | Your compute |
| - | - |
| Validating every geometry, and converting other coordinate systems at the boundary | Converting Shapefile, FileGDB, GeoPackage, GeoTIFF and other formats (GeoJSON, WKT, WKB, KML, KMZ and Geobuf are read natively) |
| Region, nearest-object and cell queries, region totals and drawn-region filters over spatial indexes | Spatial joins, nearest-neighbour and distance joins, and aggregation over large inputs |
| Small per-row geometry steps in [pipelines](/publications/pipelines) | Raster mosaics, reprojection, tiling and analytics |
| Tracks, current positions and geofences, committed with their observations | Map matching, road networks, routing engines and route optimization |
| The workspace map: layers, styling, timeline, drawing, saved and shared maps | Vector tiles for layers too large to draw from your records |
| Publishing geometry to your lake as GeoParquet at exact snapshots | Models, forecasts and simulations |

Your compute reads geometry from a [dataset](/datasets/overview) as ISO WKB in
OGC:CRS84. Distances on the map are great-circle distances; edges are straight lines
in longitude and latitude, as GeoJSON defines them.

## Bring computed shapes onto the map

A job writes its result to an [external dataset](/datasets/customer-compute) and
submits it. A collection sync then keeps one of your collections equal to the latest
accepted version: each row's geometry is admitted again and given its spatial index
cell, so the map can filter it by region.

```ts bijection/areas.ts theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
import { defineCollectionSync } from "@bijection/datasets/collectionSync";
import { shapeCell } from "@bijection/datasets/geoIndex";
import type { Area } from "@bijection/datasets/geometry";
import { internal } from "./_generated/api";

export const areaSync = defineCollectionSync({
  collection: "ServiceArea",
  source: "areaRows",
  generations: "areaGenerations",
  retirements: "areaRetirements",
  byKey: "generation_feature",
  key: "feature",
  retire: internal.areas.retire,
  row: (values) => ({
    ...values,
    cell: shapeCell(values.area as Area),
  }),
});
export const retire = areaSync.retireMutation;
```

Each accepted version replaces the previous one in a single commit; no reader sees a
mix of two versions.

## Tiles from your compute

Layers too large to draw from records, and imagery, are tiled in your compute as
PMTiles archives: vector tiles with one layer named `features`
(`tippecanoe -l features`), or PNG, JPEG or WebP images; uncompressed or gzip. Your
app declares the archive with `defineMapArchives` from
`@bijection/datasets/map-archive` and adds its `upload` and `record` functions to the
producer route. Your job records each archive as the archive's next version with the
same producer grant, naming the dataset versions it was built from, and the workspace
map draws it with the dataset's read rule checked on every tile request. A tile URL from your own server can also be added
as a map layer, but it is fetched directly by the browser and carries none of your
app's access rules, so use it only for public reference layers.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.