Geospatial types
On this page
The geospatial types hold places and shapes on the Earth: a point, a line, a polygon, a bounding box, a circle, a map tile. All 17 are in WGS84, the coordinate system GPS uses, and every coordinate is a named field, never a pair of numbers whose order you have to remember.
Geospatial covers the work you do with them: the
geo. operations, from measures and predicates to building values with
geo.from_geojson, geo.from_lng_lat, geo.from_lat_lng, and WKT's
geo.from_wkt and geo.to_wkt; storage in PostGIS geography columns;
query conditions and their indexes; and GeoJSON's Feature and
FeatureCollection. Routing and geocoding come from provider packages.
This section describes the types themselves.
Points and coordinates
A Point is a latitude, a longitude, and an altitude that may
be none.
- The latitude and longitude are the standard
LatitudeandLongitude, each aDecimalwith noscale:. Each is held as the shortest decimal of the nearest IEEE double, as PostGIS stores it (Precision and determinism). So51.50720000001234567is kept as51.50720000001235, and every coordinate of up to 15 significant digits is kept unchanged. - A latitude runs from -90 to 90 and a longitude from -180 to 180, both ends included. So -180 and 180 are both the antimeridian, as RFC 7946 takes them.
- The altitude is a
Lengthof either sign: the height above the WGS84 ellipsoid, which is what RFC 7946's third coordinate is.
A Bearing is a direction in degrees clockwise from true north, from
0 to 360, both ends included, since no bound leaves its end out. 360 and
0 are the same direction but different numbers, so an application that
compares bearings writes north one way. A wind's direction is a
Bearing: the direction it comes from, as WMO reports it.
Geometries
A Geometry is a choice of six variants. Each holds its geometry
under the variant's own name: Geometry.polygon { polygon: zone }.
The geometries' parts are objects, so all six are built and read alike:
- a
LineStringand aMultiPointare theirpoints; - a
Polygonis itsouterring and itsholes; - a
MultiLineStringis itslines; - a
MultiPolygonis itspolygons.
No text form
A geometry has no single text form, a Point included. Neither does a
BoundingBox, a Circle, an EastingNorthing or a MapTile.
text.from and text.parse on one are type.mismatch, as on a
PostalAddress. Every text form these have (WKT, the geo: URI, a
tile's z/x/y, a box's four numbers) depends on the order of its
numbers, and an axis order exists only at an edge that names it. WKT is a
format, not a type: only
the two WKT operations (Interop) read and write it.
GeoJSON
A geometry's JSON is GeoJSON (Json::GeoJson), read and written by
jadpo-value's geo module, the one place where [longitude, latitude]
order exists. Each of the five geometries is its RFC 7946 object.
Geometry is the object of the geometry it holds, its type saying
which; it is never the tagged form other choices are sent in
(Enums).
Reading is strict where RFC 7946 says MUST, and refuses what this page leaves out:
- a latitude or a longitude out of range is refused, as
minormaxat its place incoordinates; - a position is two or three numbers. More are refused, because RFC 7946
says not to extend it. A geometry's positions all have an altitude or
none do (
altitudes_agree; see Altitudes are all or nothing); - a line has two points or more, and a ring four or more, closed so that
its last point is its first. Otherwise it is
min_lengthorformat; - a multi-geometry has at least one part, though RFC 7946 allows none, and a polygon has at least its outer ring;
- the members are
type,coordinatesandbbox. Abboxis checked as four or six numbers and otherwise ignored, because a value's box is worked out from its points.crsand any other foreign member areunknown_field, as every input refuses a field it doesn't have, and WGS84 is the only coordinate system; GeometryCollectionis refused. So are aFeatureand aFeatureCollectionwhere a geometry goes. Those two are standard types of their own,Feature<G, P>andFeatureCollection<G, P>, read where one is the type (Interop).
Ring winding. A ring wound either way is read, and rewound to the
right-hand rule: the outer ring counterclockwise and each hole clockwise.
RFC 7946 §3.1.6 asks a parser not to refuse a ring wound the other way.
Every ring is written by the rule, including a polygon built in code. The
winding is found exactly, on the plane of longitude and latitude, each
rounded to 9 places. A ring with no area is kept as it is. Whether the
holes sit inside the outer ring and whether rings cross is the rule
rings_valid
(Polygons are valid when built).
Numbers on the wire. RFC 7946 is I-JSON, so a coordinate is read as
the double it is and held as the shortest decimal that is that double; a
whole number is held exactly. It is written as a JSON number with its
places, and an altitude in metres with no trailing zeros. A Latitude,
Longitude or Bearing on its own is a Decimal, and is sent as text,
as every Decimal is.
Boxes, circles and other types
- A
BoundingBoxis its sides by name,south,west,northandeast, sent as named fields, never as RFC 7946'sbboxarray. Its south is at or below its north, its rulesouth_not_above_north. A west that is east of its east crosses the antimeridian (RFC 7946 §5.2). It is shown from its south-west corner to its north-east one. - A
Circleis acentre, aPoint, and aradius, aLengthnever below 0. It is sent as named fields, its centre as GeoJSON, and shown1,000 m around 51.5072° N, 0.1276° W. - A
Crs, a coordinate reference system, isEPSG:and its code, 1 to 6 digits with no leading zero. WGS84 isEPSG:4326. URNs andOGC:CRS84aren't read. - A
Geohashis 1 to 12 characters of its base 32, in lower case only. - An
H3Cellis a cell of Uber's H3 grid, its index (H3's mode 1) as 15 lower-case hexadecimal digits. Its bits are checked: reserved bits clear, a resolution from 0 to 15, one of the 122 base cells, a digit from 0 to 6 for each resolution it has and 7 for each it hasn't, and no deleted subsequence on a pentagon. An edge's or a vertex's index isn't a cell. - A
MapTileis a tile in OpenStreetMap's XYZ scheme, its row counted from the north, not TMS's. Itszoomis from 0 to 30, which keepsxandywithin a 32-bit integer, as PostGIS'sST_TileEnvelopetakes them. Each ofxandyis below 2 to the power of the zoom, its rulewithin_zoom. It is shown as a tile's URL writes it,10/511/340. - An
EastingNorthingis a position on a national grid: aneastingand anorthing,Decimals held as written, and itsCrs. It is shown with labels,easting 530,000, northing 180,000 (EPSG:27700). It isn't converted to WGS84 (What geospatial leaves out, and what to use instead).
Shown, stored and matched
Shown to people: a latitude or a longitude in the locale's digits,
with a degree sign and its hemisphere's letter, N, S, E or W in
every locale, and no letter for 0. A point is shown as its latitude, then
its longitude, then its altitude. A line or a ring is its points in
brackets, joined by ; , and a geometry made of others is theirs in
brackets, joined by , .
Stored: a geometry is one PostGIS geography column, checked to its
type (Storage::Geography), and a BoundingBox and a Circle are named
columns (Storage). A Latitude, Longitude
or Bearing is one numeric column; a Crs, Geohash or H3Cell one
text column; and a MapTile and an EastingNorthing a column per
part, an easting's and a northing's numeric.
Shapes: type.standard_exists matches Point's shape: a latitude and
a longitude by their common names, each built on Int or Decimal.
LineString's and Polygon's shapes match through a list of a type that
matches Point. They are one shape, so the error names both
(Packages use the standard types).
Not personal data: a position is as often where a depot or a sensor
is as where a person is. To mark a person's position, use the
location category.
What is built: Geospatial says which parts of geospatial work are built.
Markdown for agents: /docs/geospatial-types.md.Built from Jadpo main at a707efb.