# Geography

> 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.

<!-- id: types-geography · area: types · stability: stable · html: https://osysharp.com/reference/types/geography/ -->

## Summary        {#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`.

```osy syntax
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      {#signature}

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

## Description    {#description}

### Longitude comes first   {#longitude-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   {#canonical}

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.

```osy syntax
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   {#refused}

| you pass | why it is refused |
|---|---|
| a `Feature` or `FeatureCollection` | a geography is the *geometry*; a feature carries properties it has nowhere to keep. Pass `feature.geometry`. |
| a geometry with a `crs` | GeoJSON 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 member | it 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 positions | not a closed shape |
| a line with one position | not a line |

### Where it comes from   {#sources}

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   {#parity}

`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       {#examples}

```osy test app=geography-delivery
// 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       {#see-also}
- [DateTimeOffset](https://osysharp.com/reference/types/datetimeoffset/) — the other type added for warehouse columns: an instant with its offset
- [bigdecimal](https://osysharp.com/reference/types/bigdecimal/) — and the third: 38-digit exact decimals
- [Http.*](https://osysharp.com/reference/http/facade/) — fetching GeoJSON from a service
