Map work needs volume before it needs accuracy. A clustering algorithm cannot be evaluated with four markers, a store-locator radius query needs enough points to have edge cases, and a rendering performance test needs thousands. Generating them is the obvious answer, and the obvious mistake is to generate coordinates that are uniformly random — which puts most of your markers in the ocean and none of them in the interesting places.
The coordinates here are anchored instead. Each record picks a real city and then offsets from that city's centre by a random amount, so points cluster where cities are, in roughly the density a real customer base has. Generate a thousand and you get a map that looks like a business rather than a scatter plot.
The trade-off is stated plainly because it decides whether this data is right for your test: the point is near the city, not at the address. The street name and house number in the same record are invented, so the pair does not correspond to the address printed beside it, and no geocoder will ever agree that it does.
That makes the split clean. Anything that consumes coordinates — markers, clusters, heat maps, radius filters, viewport fitting, distance sorting — works well with this data. Anything that converts between an address and a coordinate needs real addresses, because the conversion is the thing under test.
What the coordinates are and are not fit for
The offset is a square rather than a circle, applied to latitude and longitude independently around the city centre, so the spread is not a perfect radius and a point can land just outside the city or on water beside a coastal one. For a demo that is usually fine and occasionally funny; for anything that asserts a point is inside a boundary it is disqualifying, and a polygon lookup is what you would need instead.
Radius and nearest-neighbour logic is the interesting middle case. Because the points cluster around real city centres at a realistic spread, a distance query behaves the way it will in production — there are near neighbours, far outliers and ties. Just do not assert exact distances against the address, and remember that a naive distance calculation over raw degrees is wrong at any latitude away from the equator, because a degree of longitude narrows as you move north or south. That is itself a bug worth having a fixture for.
Precision deserves its own note, because it is routinely confused with accuracy. These values are rounded to five decimal places, which resolves to a little over a metre at the equator. The point itself is accurate to a few kilometres. A coordinate can be extremely precise and completely inaccurate, and a UI that prints seven decimal places next to a city-level guess is making a claim it cannot support.
What generated coordinates are fit for
| Task | Fit | Why |
|---|
| Map markers and clustering | Yes | Points cluster around real cities at a realistic density |
| Heat maps and density views | Yes | The spread around each centre is random rather than uniform across the map |
| Radius and nearest-neighbour queries | Yes | Near neighbours, far outliers and ties all occur naturally |
| Rendering and performance tests | Yes | The bulk exporter goes to 100,000 rows |
| Coordinate parsing and precision fixtures | Yes | Five decimal places, real signs, values that survive a CSV round trip |
| Forward geocoding an address to a point | No | The street name and house number are invented |
| Reverse geocoding a point to an address | No | The point is near the city, not at the address in the record |
| Point-in-polygon or boundary assertions | No | The offset is a square around a centre, with no boundary check |
| Routing or turn-by-turn directions | No | There is no real destination to route to |
The dividing line is direction: anything that consumes a coordinate works, anything that converts between an address and a coordinate does not.
Coordinate bugs worth a fixture
Latitude and longitude swaps are the classic, and they are hard to catch because they often produce a valid-looking result. Swapping a pair in the north-eastern United States gives a longitude of 40 and a latitude of -74, and -74 is out of range for a latitude, so the bug is caught. Swapping a pair near 25 degrees north and 25 degrees east gives another perfectly valid pair, in a different country. A test set drawn from several countries catches this; a test set from one city does not.
Signs are the second most common defect. The western hemisphere has negative longitudes, and a system that drops or normalises the sign moves every American point into Central Asia. The related failure is the null island — a record whose coordinates default to zero and zero rather than to nothing, which is why a map with a suspicious cluster off the coast of west Africa usually means missing data rather than customers.
Then there is formatting. Coordinates cross system boundaries as strings more often than anyone would like, and a locale that uses a comma as its decimal separator turns one number into two fields in a CSV. Storing a coordinate as a single-precision float, or in a column with two decimal places, silently rounds a street-level point to a neighbourhood-level one. Both are worth a fixture that carries a value with real decimals in it, which every record here does.
Decimal places and what they resolve to
| Decimal places | Resolution | What it identifies |
|---|
| 1 | About 11 km | A city or a large district |
| 2 | About 1.1 km | A neighbourhood |
| 3 | About 110 m | A block |
| 4 | About 11 m | A building footprint |
| 5 | About 1.1 m | A doorway — the precision used here, well beyond the accuracy of the point |
Approximate ground distance for a decimal degree of latitude. Longitude narrows as you move away from the equator, which is itself worth a fixture.
Generating enough points to be useful
For a rendering or clustering test the volume matters more than any individual point. The bulk exporter goes to 100,000 rows and writes CSV, JSON or SQL, which is the fastest way to get a map full of markers into a local database. For a smaller, stable set, the JSON API takes a seed and returns byte-identical records, so a demo map can be regenerated exactly rather than re-created by hand.
Spread matters as much as volume. Pin the country or the state and you get points clustered around that region's cities; leave it unpinned and you get a national spread. A store-locator demo generally wants the first, and a performance test generally wants the second, so it is worth generating two fixtures rather than compromising with one.
If your demo shows an address beside the pin, remember what the pin means. The city is real, the postal code is real, and the street is not — so a marker's popup should show the city and region rather than imply that the street exists at that exact point. It is a small framing decision that keeps a demo honest.
How these coordinates are generated
Coordinates are derived, not drawn. The generator picks a real city first, then offsets from that city's centre by a random amount within about 0.12 degrees on each axis — roughly 13 kilometres — and rounds the result to five decimal places. When a record is pinned to a state rather than a city, the offset widens to about 0.4 degrees, or 44 kilometres, and the centre is the state's representative city. Values are WGS 84 decimal degrees, the same reference frame that consumer mapping and GPS use.
Because the offset is applied independently to latitude and longitude, the sampled area is a square rather than a circle, and no polygon check is performed afterwards — which is why a point can sit outside the city limits or in water. That is a deliberate simplicity rather than an oversight: a boundary-accurate point would require a licensed boundary dataset, and it would still not make the invented street address real.
The rest of the record is built to the same rules as everywhere else on this site. The city and its region are real, the postal code is genuinely issued for that place, and the street name and house number are both invented — so nothing in the record, coordinates included, points at a specific building.
The whole record is a pure function of its seed: the same seed returns the same coordinates through the API, which is what lets a demo map be committed as a fixture instead of regenerated on every run.