Working with Geometries
Best practices for working with geometries in Tilebox.
Geometries are a common cause of friction in geospatial data processing. This is especially true when working with geometries that cross the antimeridian or cover a pole. Tilebox is designed to take away most of the friction involved in this, but it’s still recommended to follow the best practices for handling geometries outlined below.
In doing so, you can ensure that no geometry related issues will arise even when interfacing with other libraries and tools that may not properly support non-linearities in geometries.
Best Practices
To ensure expected behavior when working with geometries, it’s recommended to follow these best practices:
- Use language specific geometry libraries for creating, parsing and serializing geometries.
- Polygon exteriors should always be defined in counter-clockwise winding order.
- Polygon holes (interior rings) should always be defined in clockwise winding order.
- Longitude values should always be within the
[-180, 180]
range, and latitude values should always be within the[-90, 90]
range. - Geometries that cross the antimeridian should be cut along the antimeridian into two parts—one for the eastern hemisphere and one for the western hemisphere.
- Geometries that cover a pole need to be defined in a specific way to ensure correct handling.
- When downloading geometries from external sources, such as from STAC Catalogues always make sure to verify that those assumptions are met to avoid unexpected behavior down the road.
Geometry vs Geography
Some systems expose two similar, but different data types related to geometries: Geometry
and Geography
. The main difference lies in how edge interpolation along the antimeridian is handled.
Geometry
represents a geometry in an arbitrary 2D cartesian coordinate system, and does not perform any edge interpolation, while Geography
typically does wrap around the antimeridian by performing edge interpolation, such as converting cartesian coordinates to a 3D spherical coordinate system.
For Geography
types, the x
coordinate is typically limited to the [-180, 180]
range, and the y
coordinate is limited to the [-90, 90]
range, while for Geometry
types no such limitations are imposed.
Tilebox does not make such a distinction between Geometry
and Geography
types. Instead, it provides a query option to specify a coordinate reference system to control whether geometry intersections and containment checks are performed in a 3D spherical coordinate system (which correctly handles antimeridian crossings) or in a standard 2D cartesian lat/lon
coordinate system.
Terminology
Get familiar with some key concepts related to geometries.
A great resource to learn more about these concepts is this blog post by Tom MacWright.
Point
A Point
is a specific location on the Earth’s surface, represented by a longitude
and latitude
coordinate.
Ring
A Ring
is a collection of points that form a closed loop. The order of the points within the ring matter, since that defines the winding order of the ring, which is either clockwise or counter-clockwise.
Every ring should be explicitly closed, meaning that the first and last point should be the same.
Polygon
A Polygon
is a collection of rings. The first ring is called the exterior ring
, and represents the boundary of the polygon. Any other rings are called interior rings
, and represent holes in the polygon.
MultiPolygon
A MultiPolygon
is a collection of polygons.
Geometry libraries and common formats
Geometries can be expressed in many different ways, and many formats exist for representing geometries. To handle these, the Tilebox Client SDKs delegate geometry handling to external, well-known geometry libraries.
Client SDK | Geometry library used by Tilebox |
---|---|
Python | Shapely |
Go | Orb |
Here is an example of how to define a Polygon
geometry, covering the area of the state of Colorado using Tilebox Client SDKs.
Through these libraries, Tilebox also supports some of the most common formats for representing geometries.
GeoJSON
GeoJSON is a geospatial data interchange format based on JavaScript Object Notation (JSON).
Reading such a GeoJSON geometry can be achieved as follows.
Well-Known Text (WKT)
Well-Known Text (WKT) is a text markup language for representing vector geometry objects.
Well-Known Binary (WKB)
Well-Known Binary (WKB) is a binary representation of vector geometry objects, a binary equivalent to WKT.
Given a colorado.wkb
file containing a binary encoding of the Colorado polygon, it can be read as follows.
There is also an extended well known binary format (ewkb) that supports additional information such as specifying a spatial reference system (like EPSG:4326) in the encoded geometry.
Pythons shapely
library supports that out of the box, and the orb
library for Go supports it as well via the github.com/paulmach/orb/encoding/ewkb
package.
Winding Order
The winding order of a ring defines the orientation of the ring, and is either clockwise or counter-clockwise. The winding order of a ring is determined by the order of the points within the ring.
Geometries in Tilebox follow the right hand rule defined by the GeoJSON specification:
A linear ring MUST follow the right-hand rule with respect to the area it bounds, i.e., exterior rings are counterclockwise, and holes are clockwise.
This means that the exterior ring of a polygon has a counter-clockwise winding order, while interior rings have a clockwise winding order.
When this rule is not followed, querying may yield unexpected results, as can be seen in the example below.
Take the following Polygon
consisting of the same exterior ring but in different winding orders.
This is how those two geometries would be interpreted on a sphere.
Correct (counter-clockwise) winding order
Incorrect (clockwise) winding order
Tilebox detects incorrect winding orders and automatically fixes them when ingesting data.
Since such unexpected behavior can cause issues and be hard to debug, Tilebox does detect incorrect winding orders and automatically fixes them when ingesting data.
This means that Geometries that really cover almost the whole globe except a small area cannot be ingested into Tilebox by simply specifying them as a Polygon
with an exterior ring in clockwise winding order.
Instead, such geometries should be defined as a Polygon
consisting of two rings:
- an exterior ring covering the whole globe in counter-clockwise winding order
- an interior ring specifying the hole in clockwise winding order
Such a definition, which Tilebox will interpret as intended, and also is valid according to the GeoJSON specification, is shown below.
To verify the winding order of a geometry, you can use the following code snippets.
Antimeridian Crossings
Geometries that cross the antimeridian are a common occurrence in satellite data, but can cause issues when not handled correctly.
Take the following Polygon
that crosses the antimeridian.
A geometry that crosses the antimeridian
Below are a couple of different ways to express such a geometry.
While this is a valid representation, it causes issues for a lot of libraries that do calculations or visualization in a cartesian coordinate system, since the line from lon=173
to lon=-175
will be interpreted as a line that is 348
degrees long, crossing the null meridian and almost all the way around the globe.
Often times, visualizations of such geometries will look like in the image below.
Incorrect handling of a geometry crossing the antimeridian
To avoid such issues, some tools working in cartesian coordinate space sometimes extend the possible longitude range beyond to usual bounds of [-180, 180]
.
Expressing the geometry in such a way, may look like this.
Or, the exact same area on the globe can also be expressed as a geometry by extending the longitude range below -180
.
While most visualization tools will probably handle such geometries correctly, special care needs to be taken when working with such geometries when it comes to intersection and containment checks.
The below code snippet illustrates this, by constructing a Polygon
that covers the exact same area in the two different methods shown, and checking whether they intersect each other (which they should, since they represent the same area on the globe).
Antimeridian Cutting
Additionally, none of the representations shown are valid according to the GeoJSON specification. The GeoJSON specification does offers a solution for this problem, though, which is Antimeridian Cutting. It suggests always cutting lines and polygons that cross the antimeridian into two parts—one for the eastern hemisphere and one for the western hemisphere.
To achieve this, check out the antimeridian python package, and an implementation of it in Go.
The antimeridian
python package also is a great resource for learning more about possible antimeridian issues, how the cutting algorithm works and edge cases to be aware of.
By cutting geometries along the antimeridian:
- they conform to the GeoJSON specification
- there is no ambiguity about how to correctly interpret the geometry
- they are correctly handled by most visualization tools
- intersection and containment checks yield correct results no matter the coordinate reference system used
- all longitude values are within the valid
[-180, 180]
range, making it easier to work with them
Pole Coverings
Geometries that cover a pole can be especially tricky to handle correctly. No one algorithm that can handle all possible cases correctly, and different libraries and tools may handle them differently. A lot of times, injecting prior knowledge, such as the fact that a geometry is supposed to cover a pole, can help to resolve such issues. For an example of this, check out the relevant section in the antimeridian documentation.
Generally speaking though, there are two approaches that work well:
Approach 1: Cutting out a hole
Define a geometry with an exterior ring that covers the whole globe. Then cut out a hole by defining an interior ring of the area that is not covered by the geometry.
This approach works especially well for geometries that cover both poles, since then the interior ring is guaranteed to not cover any of the poles.
Geometry covering both poles (view of north pole)
Geometry covering both poles (view of south pole)
Approach 2: Splitting into multiple parts
Another approach, that works well for circular caps covering a pole, involves cutting the geometry into multiple parts, but instead of splitting the geometry only at the antimeridian, also splitting it at the null meridian, the 90
and -90
meridians.
For a circular cap covering the north pole, this results in four triangular parts, which can be combined into a MultiPolygon
. Visualization libraries as well as intersection and containment checks done in cartesian coordinate space will then typically handle such a geometry correctly.
A geometry covering the north pole