How Caiyun Weather Optimized Administrative Division Lookups Using H3 Indexing
The article chronicles Caiyun Weather’s evolution of geographic lookup—from a naïve nearest‑adcode algorithm to a high‑precision H3‑based system—detailing the evaluation of Geohash, S2, and H3, performance benchmarks, memory trade‑offs, and the final R‑Tree‑augmented point‑in‑polygon solution.
Caiyun Weather’s app and API return real‑time weather alerts for a given latitude and longitude. In China alerts are issued per administrative division down to the county level, so the service must translate coordinates into the corresponding administrative code before fetching alerts.
V1 – Simple Nearest‑Adcode Approach
The initial implementation iterated over all adcode centroids and selected the nearest one. This produced mismatches such as users in Changping receiving Haidian alerts, users near Chaoyang Academy Road receiving Chaoyang alerts that actually belonged to a neighboring district, and users in Chaoyang Dajue City receiving Tongzhou alerts. The team informally estimated correctness at 70‑80% but later measured an accuracy of 56.5% on a validation set.
V2 – Exploring Grid‑Based Indexes
To improve precision the team evaluated three nationwide grid schemes:
Geohash – discarded after a 2018 GopherChina talk highlighted severe area distortion near the equator, making equal‑resolution cells inconsistent across latitudes.
S2 – praised for stability (used in Google Maps) and a strict hierarchy where each parent contains exactly four children, a property later deemed important. However, a complete API existed only for C++, and the Go implementation was immature.
H3 – an open‑source hexagonal indexing system adopted by Uber, Grab and Didi, with ready‑made libraries for many languages. The team chose H3 because its hexagonal cells suit distance‑sensitive, boundary‑tolerant use cases.
What Is H3?
H3 divides the globe into hexagonal cells at multiple resolutions. Example images from the H3 website illustrate its application to Los Angeles, aggregation of US weather stations, and a comparison with US ZIP codes.
Implementation with H3
Polygon files for all administrative divisions were downloaded. Using H3’s Polygon Fill at resolution 9, the polygons were filled with hexagonal cells. The resulting grid shows original cells in red and aggregated cells in blue.
Testing on a validation dataset (latitude, longitude, adcode) showed the first‑generation method achieving roughly 50% correctness, while the H3‑based grid exceeded 90% correctness. The H3 solution was deployed in API version v2.6.
Drawbacks of the H3 approach:
Memory consumption around 200 MB.
Manual generation and maintenance of GeoJSON polygon files and H3‑ID JSON files.
Data files approaching 20 MB without separation of code and data.
V3 – Handling Boundary Edge Cases
In late November 2021 users reported missed alerts near administrative borders. Visual inspection revealed that aggregation caused loss of fine‑grained boundary details, assigning border points to neighboring grids. The hierarchical nature of H3 means upper‑level cells only approximate lower‑level cells, so exact boundaries are not guaranteed.
Increasing the resolution produced finer hexagons but still failed to capture detailed borders without incurring prohibitive memory costs. The team therefore adopted a precise point‑in‑polygon (PIP) check.
The classic PIP algorithm, Ray Casting, determines whether a ray cast from the point intersects the polygon an odd number of times. To achieve high performance the team leveraged Tile38’s geospatial component, which pre‑indexes polygons using an R‑Tree of small quadrilaterals, dramatically accelerating PIP tests.
RFC 7946 was consulted to ensure correct handling of the GeoJSON format used for the polygon data.
During development the team accounted for multi‑polygon regions (e.g., Qing‑shan Lake district), ensuring that all constituent polygons are evaluated.
Performance Comparison
Version v1 accuracy: 56.5%
Version v2 accuracy: 88.8%
Version v3 accuracy: 97.4%
In production the v3 implementation consumes about 728 MB of memory. Startup time increased from 5.2 s to 5.6 s (+0.4 s). API latency rose from 1.5 ms to 1.9 ms (+0.4 ms). A single query costs roughly 100 000 ns. Adding an outer R‑Tree index narrows candidate polygons to a few dozen, reducing overall query time by 80% to approximately 20 000 ns.
References
Geohash – https://en.wikipedia.org/wiki/Geohash
S2 – https://s2geometry.io
H3 – https://h3geo.org
H3 Indexing – https://h3geo.org/docs/highlights/indexing
Point in Polygon – https://en.wikipedia.org/wiki/Point_in_polygon
Ray Casting – https://en.wikipedia.org/wiki/Ray_casting
RFC 7946 – https://www.rfc-editor.org/rfc/rfc7946
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
