[Experimental Proof of Concept] Map generation from OpenStreetMap data

The (hypothetical long term) idea would be to generate CDDA maps from real world places.

The current implemention (Github repo) just generates an empty world with roads. It ain’t much, but they are !!!REAL WORLD™ roads!!!

“Demo” results (imgur album):

Right now it’s just a curiosity and would require a lot of work to make something playable. I doubt I could get anywhere near that point, but I couldn’t resist giving it a try when I thought about it. It seemed simple and in the end I was able to make it work with less than 500 lines of real code (excluding constant declarations and alike).

It’s written in python but, given the small size, it would be easy to port to any language.

Tested only on Windows, CDDA Experimental 0.E-10010-gd821da4.

3 Likes

some thoughts/ideas

  • the buildings would need to be procedurally generated to fit the roads
  • alternatively building could be premade at predetermined sizes and slotted in where possible with unused space being filled with procedurally generated stuff like greenery, sidewalks etc
  • building density (urban vs sub urban vs rural) can be approximated by road density in a given area
  • in urban and suburban areas buildings could be put were there is space
  • in rural areas buildings could be placed at regular intervals (determined by density)
  • regardless of density a “building” should be put where there is a dead end (thus explaining why the road is there)
  • it might be wise to put in water (oceans, lakes, rivers etc ) since towns tend to be build by rivers
  • easiest way to identify the rivers would be by its color on the map
  • bridges could be identified by making a box out of the points at the “ends/corners” of river segments that are next to roads, so long as the points are relatively close together
2 Likes

Thanks for the input, good food for thought!

  • the buildings would need to be procedurally generated to fit the roads
  • in urban and suburban areas buildings could be put were there is space

I was indeed thinking of using procgen to generate the buildings. But no need to work hard for the building positions, the OSM data is awesome, not only contains the shapes of the buildings (so no need to guess them), but also the type of the building and there are several subcategorizations with more details: Shops, Crafts, Leisure, Sport, Power.

  • alternatively building could be premade at predetermined sizes and slotted in where possible with unused space being filled with procedurally generated stuff like greenery, sidewalks etc

I will try procgen first. I found several papers about “house generators”. Here is one that is accesible online: http://tede2.pucrs.br/tede2/bitstream/tede/6314/2/474948%20-%20Texto%20Completo.pdf

The good thing with procgen is that, once you have it working, you have infinite content.

  • building density (urban vs sub urban vs rural) can be approximated by road density in a given area

There is some data on the OSM XML about the levels but I don’t know if that would be enough.

  • it might be wise to put in water (oceans, lakes, rivers etc ) since towns tend to be build by rivers

Yeah, that’s the easiest feature to include. I went with the roads for the proof of concept because they are a bit more visual. Having that working, adding the water is super easy.

  • easiest way to identify the rivers would be by its color on the map

Again, OSM XML is your friend. You also have the polygons of water areas.

  • bridges could be identified by making a box out of the points at the “ends/corners” of river segments that are next to roads, so long as the points are relatively close together

Bridges (and tunnels) are the rickiest parts I can think of… I still have no idea how you could manage them. I haven’t looked too much at the OSM XML data in that regard.

1 Like

you seem to have more practical experience then me.
I suspect the following is a bit of a long ramble, but hopefully there are useful ideas in there.

regarding bridges and tunnels involving water:
a potential algorithm for bridges over water:

  1. first label all lakes (identify by large rectangles of water)
  2. then find some water (label as point a) that isn’t very “near” a lake (far enough that you can assume it’s not part of the lake
  3. then go from water at very short increments in a straight line until you find something that isn’t water
  4. if length exceeds some value go back to step 2 but change the direction by 90 degrees (since you went down a straight length of river)
  5. identify the point just before you hit no water as point b and the point outside water as point c
  6. go from point c at a 10 degree angle off bc until you hit water, label water found as point d
  7. repeat step 3 shifted 180 degree
  8. label the resultant point b as e and point d as f
  9. find center point of shape from bdef label as g
  10. average the angles of bd and ef, this is the angle the river is going
  11. the average distance of gb, gd, ge, gf times 2 is the width of the river
  12. travel down the river from g until you hit not water, if a road skip to step 15
  13. go back by half the rivers width
  14. go back to step 3 treating current point as point a
  15. go back by half the rivers width
  16. treat road point as point b and river point as point a
  17. go off point b an small angle (say 0.1 degree) from point a.
  18. if you find water repeat step 17 but increase the angle slightly
  19. the first point that is not water is point c
  20. repeat step 17,18 but going other direction
  21. identify resultant point c as point d
  22. go from a down and past b until you hit water, treat new water point as e
  23. repeat steps 17,18,19,20,21 using point e as point a
  24. label resultant point c as point f and resultant point d as point g
  25. points cdfg label a rectangle that represents a bridge

regarding bridges/tunnels over roads:
a potential algorithm:

  1. identify different roads by their width and urban density
    -small = (0 to 10 meters) (made up numbers)
    -small urban, generate paved
    -small suburban, generate paved
    -small rural, generate paved or gravel/dirt
    -small deep rural, generate gravel/dirt
    -medium= (11 to 20 meters) (again made up numbers)
    -medium (urban,suburban,rural) generate paved
    -large=(21+ meters) (made up numbers)
    -large (urban,suburban,rural) generate paved
  2. if small urban overlaps with:
    -small/medium urban make intersection with lights
    -large make highway on ramp style intersection
  3. if small suburban overlaps with:
    -small suburban make intersection with sign
    -medium suburban make intersection with lights
    -large make highway on ramp style intersection
  4. if small rural overlaps with:
    -small/medium rural make intersection sign
    -large make highway on ramp style intersection
  5. if medium urban overlaps with:
    -medium urban make intersection with lights
    -large make highway on ramp style intersection or bridge
  6. if medium suburban overlaps with:
    -medium suburban make intersection with lights
    -large make highway on ramp style intersection or bridge
  7. if medium rural overlaps with:
    -medium rural make intersection with signs
    -large make highway on ramp style intersection or bridge
  8. if large overlaps large make bridge
2 Likes

Thanks for the input.

This has encourged me to take a look at the OpenStreetData for a bridge and a tunnel, and they are marked on the XML. There could be some ambiguity with more complex cases, but the simpler cases seem doable.

A bridge (<tag k="bridge" v="yes"/>).

 <way id="49312719" visible="true" version="3" changeset="15308499" timestamp="2013-03-09T22:24:02Z" user="sanchi" uid="170106">
  <nd ref="626216644"/>
  <nd ref="626216645"/>
  <tag k="bridge" v="yes"/>
  <tag k="highway" v="service"/>
  <tag k="layer" v="1"/>
 </way>

And a tunnel (<tag k="tunnel" v="yes"/>):

 <way id="144209951" visible="true" version="6" changeset="71486078" timestamp="2019-06-21T15:23:35Z" user="Alfonso RG" uid="3313579">
  <nd ref="6563223459"/>
  <nd ref="1578305796"/>
  <tag k="highway" v="tertiary"/>
  <tag k="layer" v="-1"/>
  <tag k="maxspeed" v="20"/>
  <tag k="oneway" v="yes"/>
  <tag k="tunnel" v="yes"/>
 </way>
3 Likes