Osy#betaRun it on Osyrin: osyrin.com

Reference / Types

Geography

Geography Where;

A place, a route or an area on the Earth, as a GeoJSON geometry — longitude/latitude, WGS84. It is exactly the shape a browser map library draws and a warehouse spatial column hands back, and it behaves identically in a server function and in a browser action.

stable1 example compiled by CItypesspatialmapswarehouse

Summary#

A Geography is a GeoJSON geometry: a point, a line, a polygon, or a collection of them, in longitude/latitude. Declare it on an entity, build one with Geography.Point, or read one from text with Geography.Parse.

entity Store {
  [Required] string Name;
  Geography Location;
}

var here = Geography.Point(18.07, 59.33);      // LONGITUDE first — Stockholm
var area = Geography.Parse(polygonGeoJson);    // throws if it is not a valid geometry

Signature#

Geography Geography.Point(double longitude, double latitude)
Geography Geography.Parse(string geoJson)

Description#

Longitude comes first#

GeoJSON orders a position [longitude, latitude], and so does Geography.Point. The opposite order is the most common mistake anyone makes with GeoJSON, and a swapped Stockholm is a perfectly valid-looking point in the wrong country — so a longitude outside ±180 or a latitude outside ±90 is refused, and the message tells you to swap it. That catches the mistake for most of the planet.

One geometry, one text#

Two spellings of the same geometry — keys in another order, 18.0 for 18, extra spaces — are the same Geography. Every value is kept in one canonical form, so == compares places rather than formatting, and a value read back from the database equals the one you stored.

Geography.Parse("{ \"coordinates\": [18.0, 59.330], \"type\": \"Point\" }")
  == Geography.Point(18, 59.33)      // true — the same point, spelled two ways

Convert.ToString(g) gives you that canonical GeoJSON text, ready to hand to a map.

What is refused, and why#

you passwhy it is refused
a Feature or FeatureCollectiona geography is the geometry; a feature carries properties it has nowhere to keep. Pass feature.geometry.
a geometry with a crsGeoJSON is WGS84 longitude/latitude by definition. Coordinates in another system would be read as degrees and land in the wrong place — reproject first.
any other extra memberit would be dropped without a word. (bbox is the exception: it is derived from the coordinates, so nothing is lost.)
a polygon ring that does not end where it starts, or has fewer than 4 positionsnot a closed shape
a line with one positionnot a line

Where it comes from#

A browser map library emits and consumes GeoJSON directly, and so do the warehouses — Snowflake and Databricks both return a spatial column as GeoJSON (ST_ASGEOJSON). A Geography parameter on a function accepts the geometry as a JSON object or as its text, so a map click and a warehouse row arrive the same way.

It is the same value on both sides#

Geography.Point and Geography.Parse give the same text in a server function and in a browser action, number for number. Both runtimes are held to one shared table of cases — including the numbers where .NET's and JavaScript's default formatting disagree.

Examples#

// Record where an order was delivered, from a map click in the browser.
entity Delivery {
  [Required] string Reference;
  Geography DroppedAt;
}

void Deliver(Delivery d, double longitude, double latitude) {
  d.DroppedAt = Geography.Point(longitude, latitude);
}

See also#

  • DateTimeOffset — the other type added for warehouse columns: an instant with its offset
  • bigdecimal — and the third: 38-digit exact decimals
  • Http.* — fetching GeoJSON from a service

Related

DateTimeOffset

An instant *plus the offset it was recorded at*. Use it when the local time something happened is part of the fact — a…

bigdecimal

Exact base-10 arithmetic with 38 significant digits — for warehouse columns and anything else too wide for `decimal`…

Http.*

Make an outbound HTTP call to a URL you build at runtime — a webhook, a third-party API, a discovered endpoint…