

Randomly displace that vertex by a distance relative to the length of the segment and a “wiggliness” coefficient.Between every two vertices, create a midpoint vertex.We can use a kind of L-system to do this: We can make a more interesting road by simply adding some extra vertices along the way. There’s also a “size” property which is determined by the sizes of the towns at either end: bigger towns cause bigger roads betweens them. A general ratio for the number of roads.How big are the towns (a bigger town has more roads).How near are the towns geographically (closer towns are more likely to connect).The formula I came up with takes a couple of things into account: So, we use the western-most (northern-most to tie-break) of the two towns as the “A” to seed the random number generator. However, there is a trap: our decision for connecting A to B must be the same as that for connecting B to A – and following exactly the same route. For each town, look at all the neighbouring towns (the grid makes this very easy!), and consider whether to connect it with a road. The nice thing about roads is that generally they connect two towns, so we have a great place to start from. Hence create Outer Tonbury, North Hydewell, East Langmont Creek, or Stamrick.Sometimes add a prefix (eg Outer, North, East, or nothing).Add a random ending fragment (eg -bury, -well, -mont, -rick).Take a random starting fragment (eg, Ton-, Hyde-, Lang-, Stam-).We generate town names with the fake-town-name library, which I wrote for this purpose. That is, a cubic distribution so there are far more tiny towns than big ones. For instance, the size of a town (on a scale of 1-5) is: Math.ceil(random() * random() * random() * 5). Interesting townsĪll the properties are just a question of finding formulas with attractive distributions and representing them appropriately. So we have to generate all towns in or next to the vector tile, then crop the ones that end up falling outside it. The random displacement means that we don’t know exactly which towns will end up within the vector tile we’re generating for. By simply pseudo-randomly displacing each town up to half a grid coordinate in any direction, it suddenly looks much better:Īctually managing the grid was a bit fiddly.

How good this looks in practice comes down to how well we disguise the grid. That grid point is also the seed for the random number generator, and hence all the town’s properties (name, size etc) derive from its position. A simple way to do this (actually, the only one I could think of!) is to use a grid that covers the whole world, where each grid point is one town. Instead, we need to create a global, immutable structure that sort of always “exists” and relate each town to that structure. If we were generating the whole world in one go, we could iterate 1,000,000 times, dropping a town in a random location each iteration.

When the user’s browser requests the tile at ZXY coordinates 11/1976/1368, it quickly generates and responds: But I wanted to have a tiny server with no global context. An easier approach might be to, say, first generate some continents and coastlines, then erode some mountains with rivers and dot towns in appropriate locations. The challenge: a procedurally generated map of this alternative Earth, produced on the fly, vector tile by vector tile.
