In every sense, squares seem to be much easier to reason about and easier to hierarchically partition than hexagons are.
There are certain advantages to hexagons in certain contexts, like six degrees of movement instead of four in board games, but I don't see how any of those advantages translate here for geographical indexing.
I'd love to understand why hexagons as opposed to squares in this context are a superior solution rather than unnecessary complexity?
I get that you're saying hexes are almost always a better representation. I still don't see a concrete example of why, for geographical indexing specifically.
[Edit: sibling reply explained that at the end of the day, it's not about indexing but rather route planning.]
sometimes roads go diagonal
>The cell shape of that grid system is an important consideration. For simplicity, it should be a polygon that tiles regularly: the triangle, the square, or the hexagon. Of these, triangles and squares have neighbors with different distances. Triangles have three different distances, and squares have two different distances. For hexagons, all neighbors are equidistant
And
>This property allows for simpler analysis of movement. Hexagons have the property of expanding rings of neighbors approximating circles
>Hexagons are also optimally space-filling. On average, a polygon may be filled with hexagon tiles with a smaller margin of error than would be present with square tiles.
Hierarchical partitioning with exact containment is useful when aggregating but that's not always the most critical property.
One of the use case Uber was trying to solve here, was to show which regions had surge pricing - on the uber app for the drivers. With h3 and hexagons you can argue it looks a teensy bit better with smoother gradients https://h3geo.org/docs/comparisons/s2.
I am not sure whether Uber uses h3 for other use cases like - finding the closest drivers next to a location.
See this presentation from Uber on this: https://www.youtube.com/watch?v=ay2uwtRO3QE
[1] https://github.com/Filimoa/polars-h3
[2] https://drive.google.com/file/d/18jIVEbE_1QbwTbHdMqj0AVqguf2...
From there you're just trying to optimize uniformity in distance to neighbors, how big the adjustments to the irregular polygons need to be to get them to tile on the surface are, how easy the polygon is to split up into smaller similarly shaped variants of itself as sub tiles, and trying to be somewhat close to a circle in shape as that means the average distance to the center of the area defined by the index is as close to as it can be.
If you chunk through those you'll find quadrangles aren't attractively simple anymore and hexagons tend to optimize the parameters very well. H3 actually uses both hexagons and the occasional pentagon (12 total, no matter the zoom level). It all comes down to "tiling isn't going to be perfect - what is the most optimal answer for the purpose of the tiling".
While squares have superior properties for analytical geospatial data processing that H3 doesn't have, such as congruency, they really only work for Euclidean spaces and the surface of a 2-sphere is non-Euclidean. Any system using squares will be a poor approximation of "equal area" relative to hexagons, which makes them poor for visualization. To use squares for indexing, you need an extra step that allows non-Euclidean space to be addressable from Euclidean space. There are two main ways of doing this.
First, one can project the surface of the sphere onto the surface of a Euclidean cube. Second, one can use an embedding, indexing the 2-sphere in Euclidean 3-space. Both of these can be trivially projected to a hexagonal system like H3 for visualization purposes and commonly are.
If you primarily need visualization and your data is small, using H3 eliminates the step where you need to figure out how to map non-Euclidean data models to Euclidean data models. If you are doing large-scale geospatial processing, it becomes worth the effort for both scalability and performance reasons.
Has Uber figured out a way to do it with just hexagons?
Hexagons. Are the bestagons. https://m.youtube.com/watch?v=thOifuHs6eY
- This data independence property is VERY important for distributed or streaming queries. For example, if you want to join datasets using Spark or other big data tools, each team can add a column for h3 cells independently and join somewhat efficiently. For large volumes of data, constructing the rtree is just not feasible, or more precisely, very disconnected from the rest of the "data ecosystem".
- It doesn't work with any coordinate reference system other than EPSG 4326 (which you may want if you only work on specific geographies to get more precision in your floats)
- It's clearly built with points in mind. Polygons, curves, or lines are an afterthought. For example, the polygonToCells function returns a set of cells that are entirely within the polygon. If you want to join, you'd need to also have the set of all cells that entirely contain the polygon. I've never found a reliable way to get that.
That being said, it's not bad at all, but if you don't have so much data that you can't compute rtree indices, just stick with PostGIS.
With v4 of h3 they (finally) have a clean syntax for this with polygonToCellsExperimental[0].
Now there’s options for
- Cell center is contained in the shape (default) - Cell is fully contained in the shape - Overlapping (covering): Cell overlaps the shape at any point - BBOX: Cell bounding box overlaps shape
Makes life a fair bit easier if you’ve gotta deal with H3 polys. And if you’re working locally, DuckDB Spatial’s r-tree indexing[1] can make for a nice stand-in for PostGIS as a quick point-in-polygon solution without the need to spin up a service.
[0]: https://h3geo.org/docs/api/regions/#polygontocellsexperiment... [1]: https://duckdb.org/docs/stable/extensions/spatial/r-tree_ind...
As for DuckDB & rtree, it's alas not a replacement of postgis yet and the indices cannot be used (yet) in joins. In fact, I even have workflows where I iterate over rows in python and run duckdb queries one after the other rather than joining in just one query because of this very issue.
There are some nice things with this. It contains cells at different levels (sizes). So you can use very small cells if you care about small areas, or large cells if you care more about larger areas. Those are given here https://h3geo.org/docs/core-library/restable/#average-area-i...
From a coordinate it is fast to get the cell at any level, so it's fast to group coordinates at whatever level you want.
If is less about comparing two coordinates, it is more about bering able to group large numbers of coordinates such that they go into non-overlapping groups, where everything in the same group is 'close' to each other.
H3 doesn't have that property between levels. Cells at a level don't overlap. But the the seven children of a cell might overlap with neighboring parent cells.
Of course rectangles aren't rectangular when projected on a sphere. Because there are no straight lines. Rectangles and hexagons are 2d shapes that are applied to the 2d projections of spheres. They only look like rectangles or hexagons in 2D.
Thus most screen projections are derived from wgs84. The idea behind h3 (as I see it) that when moving the map to lets say top-right, you'd need to fetch 1 leaf comparing to 3 leafs with rtree
Each hex can be divided into smaller hexes until you get to the level of feet/meters as opposed to miles/kilometers.
[0]: https://steamtunnel.blogspot.com/2009/12/in-praise-of-6-mile...
Hexagonal tessellations are optimized for display and visualization because they approximate equal surface areas on a sphere. They have poor properties for scalable and efficient analytical data processing because they are not congruent.
Indexing for scalable analytical processing on a sphere requires congruent equal volume decomposition, even if you only care about the surface. You can trivially project it to the surface later if needed. Binary space decomposition, of which space-filling curves are a subset, are strongly preferable for this type of indexing.
In practice, a lot of data processing systems will render data as an H3 tiles only for visualization as a final step. That conversion is fast and trivial and it makes pretty pictures. It is not as commonly used to index the underlying data model because scalability and performance is prohibitive unless the data is small.
The purpose is to be able to predictably map any coordinate to its associated hexagon.
In database applications this makes it easier to query all data associated with a hexagonal area.
It’s the same reason soccer balls aren’t covered in squares/rectangles but rather hexagons.