Hello Tom!
Last night I happened to hack together a Blender python script that does some of what you are looking for.
As yet, It only imports the raw node and way data, but can be used as a starting point for a full geometry exporter/generator.
I was drawn to this problem after reading a blog from the author of CityEngine, on how he use OSM data as a basis for some of his city synthesis projects.
Currently, this will generate only the raw edges that define the map, but if you go into edit mode, and select the region of the map you like, and do an “extrude”, moving the new set of vertices about a roads width, diagonally, this gives you faces you can see in a render.
Please reply/contact me if you are still interested/need help in this!
I am interested in improving and extending this script to do more stuff!
# written by manthrax at hotmail.com. If you use it for something cool, send me an email and let me know!
from Blender import Scene, Mesh, Window, sys, Group, Object, Draw
from Blender.Mathutils import Matrix, Vector, ProjectVecs, DotVecs, AngleBetweenVecs, TranslationMatrix
import Blender,BPyMessages
from xml.dom import minidom
fileName = 'C:/dev/art/map (2).osm' # Replace this path with the full path to your datafile!
xmldoc = minidom.parse(fileName)
cache = []
tidx=0
nmap={}
scl=100.0
def parseBranch(nodes,nme):
global tidx
global nmap
global scl
inNode = 0
dlat = dlong = clat = clong = minlat = maxlat = minlong = maxlong = 0.0
for node in nodes:
if node.localName == "bounds":
if node.hasAttributes():
for i in range(0,node.attributes.length):
at=node.attributes.item(i)
if at.name == "minlat":
minlat = float(at.nodeValue)
elif at.name == "minlon":
minlong = float(at.nodeValue)
elif at.name == "maxlat":
maxlat = float(at.nodeValue)
elif at.name == "maxlon":
maxlong = float(at.nodeValue)
dlat = maxlat-minlat
dlong = maxlong-minlong
clat = (maxlat+minlat)*0.5
clong = (maxlong+minlong)*0.5
print dlat,dlong, clat, clong
if node.localName == "way":
nid=None
refs=[]
#if node.hasAttributes():
#for i in range(0,node.attributes.length):
# at=node.attributes.item(i)
# print at.name
for ch in node.childNodes:
if ch.localName=="nd":
for i in range(0,ch.attributes.length):
at=ch.attributes.item(i)
#print at.name
if at.name == "ref":
refs.append(long(at.nodeValue))
first = 1
for r in refs:
if first==0:
nme.faces.extend(nmap[pr],nmap[r],nmap[r])
else: first = 0
pr=r
if node.localName == "node":
if node.hasAttributes():
nid=None
nlong=None
nlat=None
logged = 0
for i in range(0,node.attributes.length):
at=node.attributes.item(i)
#print at.name
if at.name == "id":
nid = at.nodeValue
elif at.name == "lon":
nlong = at.nodeValue
elif at.name == "lat":
nlat = at.nodeValue
if nid!=None and nlat!=None and nlong != None:
fla = (float(nlat)-clat)*scl/dlat
flo = (float(nlong)-clong)*scl/dlat
nme.verts.extend(Vector(fla,flo,0.0))
nmap[long(nid)]=nme.verts[-1]
logged=1
break
tidx+=1
#if tidx > 1000:
# break
parseBranch(node.childNodes,nme)
print "Starting parse..."
nme = Mesh.New()
parseBranch(xmldoc.childNodes,nme)
print nme.verts
part = Object.New('Mesh', 'mapMesh')
part.link(nme)
nme.update()
sce = Scene.GetCurrent()
sce.link(part)
print "Parse done... %d" % tidx