Flutter Geolocator
ArchivedFebruary 1, 2019
A fork of the Flutter Geolocator package — another open-source contribution in the Flutter/Firebase geolocation ecosystem. The real value: a deep understanding of how geographic information systems work, from geohashing and the Haversine formula to R-trees, quadtrees, and Uber's H3 hexagonal index.
Purpose
Forked the Flutter Geolocator package to contribute improvements, continuing the pattern of participating in the open-source geolocation ecosystem. Geolocator handles the device-side problem — getting the user's position via GPS, Wi-Fi, and cell tower triangulation. Combined with GeoFlutterFire for the query-side, these two packages form the full pipeline for location-based features in Flutter apps.
Stack
What I Learned
- Geohashing encodes a latitude/longitude pair into a single string — like "9q8yyk8" — where shared prefixes indicate proximity. The algorithm recursively subdivides the Earth into grid cells: split the globe along longitude, pick left or right (0 or 1), split along latitude, pick top or bottom, repeat. Each bit narrows the cell. The brilliance: proximity in geographic space maps to prefix similarity in string space, so a database range query on a single indexed string column replaces complex queries across two floating-point coordinate columns.
- The Haversine formula calculates the great-circle distance between two points on a sphere — the shortest path along the surface, accounting for Earth's curvature. This powers every "distance from me" feature. It is also the client-side filter step in geohash queries: geohashing gives you candidates within a bounding box, Haversine tells you which are actually within your desired radius, since geohash cells are rectangular and a radius is circular.
- Dijkstra's algorithm finds the shortest path from a source to all nodes in a weighted graph. A* improves on this with a heuristic estimate of remaining distance, preferentially exploring paths toward the goal. Google Maps models the road network as a weighted graph (intersections = nodes, road segments = edges, weights = travel time) and runs optimized A* variants with contraction hierarchies to return routes in milliseconds over billions of edges.
- R-trees are the spatial indexing structure behind fast geographic database queries. Like a B-tree indexes one-dimensional data, an R-tree indexes multi-dimensional data. Each node contains a bounding rectangle enclosing all children. To find restaurants within 1 km, the database walks the tree, pruning branches whose bounding rectangles do not intersect your search area. PostGIS uses R-trees (GiST indexes) as its primary spatial index.
- Quadtrees recursively partition space — start with a square, split into four quadrants when a region has too many objects, repeat. Sparse areas stay as large cells, dense areas subdivide deeply. Used in collision detection, level-of-detail rendering, and map tile loading.
- H3 is Uber's hexagonal hierarchical spatial index — hexagons instead of rectangles at 16 resolutions. Hexagons are superior because every neighbor is equidistant from center (rectangles have diagonal neighbors that are farther). Uber uses H3 for surge pricing zones, driver positioning, and demand forecasting.
- The Firebase/Firestore geo-query pipeline: store a geohash field alongside each document, query by geohash prefix ranges (native Firestore string range queries), filter client-side with Haversine to remove candidates outside your radius. GeoFlutterFire automates this pattern. Geolocator provides device position. Together: Geolocator gets where you are, GeoFlutterFire queries who is near you.
Key Insights
- The geo-algorithm landscape maps directly to apps everyone uses daily. Geohashing powers "near me" searches. Haversine powers distance displays. A* powers navigation. R-trees power spatial databases. Quadtrees power map tile loading. H3 powers Uber's surge pricing. Understanding these transforms you from someone who uses location features to someone who can build them.
- Location-based games like Pokemon Go use nearly all of these simultaneously: geohashing for spawning, Haversine for proximity checks, quadtrees for map rendering, spatial indexing for viewport queries. Any location-based game concept — and Hot Potato Games has considered them — requires this same toolkit.
- For the Potatuhs ecosystem, geolocation opens unexpected doors: localized shipping estimates, nearby pop-up events, or a "Potatuhs spotted in the wild" community map. The pipeline is always the same: get position, index spatially, query by proximity, filter by distance.
- Composability beats completeness. Geolocator solves device positioning. GeoFlutterFire solves Firestore geo-queries. Haversine solves distance calculation. Each is small, focused, and composable. The engineer's job is to understand the problem well enough to know which primitives to compose.
This post was composed through a conversation between Brett Owers and Claude Code (Anthropic). The content reflects Brett's recollection of each project and the lessons drawn from it. Some details may be approximate or omitted — the purpose is to paint an honest picture of a software engineer's development over time, not to serve as a precise historical record.