[Bf-extensions-cvs] SVN commit: /data/svn/bf-extensions [3702] contrib/py/scripts/addons/ io_scene_open_street_map.py: v0.2
Jerome Neo
jerome.le.chat at free.fr
Mon Sep 3 17:05:23 CEST 2012
Revision: 3702
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-extensions&revision=3702
Author: littleneo
Date: 2012-09-03 15:05:22 +0000 (Mon, 03 Sep 2012)
Log Message:
-----------
v0.2
osm tags for nodes and ways as vgroup, UTM projection, bpy access, ps.import_mesh.osm()
more info in the file.
Modified Paths:
--------------
contrib/py/scripts/addons/io_scene_open_street_map.py
Modified: contrib/py/scripts/addons/io_scene_open_street_map.py
===================================================================
--- contrib/py/scripts/addons/io_scene_open_street_map.py 2012-09-03 13:17:31 UTC (rev 3701)
+++ contrib/py/scripts/addons/io_scene_open_street_map.py 2012-09-03 15:05:22 UTC (rev 3702)
@@ -1,4 +1,4 @@
-# ***** BEGIN GPL LICENSE BLOCK *****
+# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@@ -20,8 +20,8 @@
bl_info = {
"name": "Open Street Map (.osm)",
- "author": "Michael Anthrax Schlachter",
- "version": (0, 1),
+ "author": "Michael Anthrax Schlachter, ideasman42, littleneo",
+ "version": (0, 2),
"blender": (2, 6, 3),
"location": "File > Import",
"description": "Load Open Street Map File",
@@ -30,14 +30,72 @@
"category": "Import-Export"}
# originally written for blender 2.4x by (manthrax _at_ hotmail.com),
-# updated by for blender 2.6x by ideasman42
+# updated for blender 2.6x by ideasman42
# If you use it for something cool, send me an email and let me know!
+# littleneo (v0.2 - september 2012) :
+
+## added a lat/lon to UTM conversion option geoToUTM() :
+# the generated mesh now almost match the exported osm image of the same area, just play with scale and rotate a bit.
+
+## added ability to retrieve openstreet tags as vertex groups :
+# add every way id as a vgroup if the tag exists in osmkeys.
+# add nodes id as vgroup if the tag value pair exists in osmvals.
+# any elligible is added in the corresponding osmkeys or value ('_V_...' vgroup
+
+## added bpy access to addon :
+# bpy.ops.import_mesh.osm(filepath="....", scale=100, utm=False, tag=False)
+
+## added custom properties to generated object so it can be used as source for other osm related scripts :
+# osmfile path to osm xml file
+# tagged bool. osm tags included
+# utm bool. default True
+
+# modified the matrix approximation for utm = False
+# ! corrected lat/lon x/y mismatch
+
import bpy
from mathutils import Vector, Matrix
+import math
+from math import radians, sin, cos, tan, sqrt
+## add more osm tags here.
+# http://wiki.openstreetmap.org/wiki/Map_Features
+osmkeys = [
+ 'highway',
+ 'barrier',
+ 'wall',
+ 'cycleway',
+ 'bicycle',
+ 'waterway',
+ 'railway',
+ 'aeroway',
+ 'aerialway',
+ 'power',
+ 'man_made',
+ 'building',
+ 'leisure',
+ 'amenity',
+ 'office',
+ 'shop',
+ 'craft',
+ 'emergency',
+ 'tourism',
+ 'historic',
+ 'landuse',
+ 'military',
+ 'natural',
+]
-def parseBranch(nodes, bm, nmap, scale=100.0):
+# just a try for nodes, for retrieving v tag values.
+# keyname must exists in osmkeys
+osmvals = {'highway':['traffic_signals']}
+
+# vertex group name -> vertex group index lookup
+grouplookup = {}
+
+def parseBranch(nodes, bm, nmap, obj, scale=100.0, tag=False, UTM=False):
+ vgroups = bm.verts.layers.deform.verify()
tidx = 0
inNode = 0
dlat = dlong = clat = clong = minlat = maxlat = minlong = maxlong = 0.0
@@ -58,12 +116,21 @@
dlong = maxlong - minlong
clat = (maxlat + minlat) * 0.5
clong = (maxlong + minlong) * 0.5
+
+ if UTM :
+ dlong, dlat = geoToUTM(dlong, dlat)
+ clong, clat = geoToUTM(clong, clat)
print(dlat, dlong, clat, clong)
if node.localName == "way":
+
+ wayid = node.getAttribute('id')
nid = None
refs = []
+ if tag :
+ group = obj.vertex_groups.new('way_%s'%wayid)
+ gid = len(obj.vertex_groups) -1
'''
if node.hasAttributes():
for i in range(node.attributes.length):
@@ -71,14 +138,27 @@
print(at.name)
'''
+ if tag :
+ metagid = []
+ for ch in node.childNodes:
+ if ch.localName == "tag":
+ key = ch.getAttribute('k')
+ if key in osmkeys :
+ metagid.append(grouplookup[key])
+
for ch in node.childNodes:
if ch.localName == "nd":
for i in range(ch.attributes.length):
at = ch.attributes.item(i)
- #print(at.name)
if at.name == "ref":
- refs.append(int(at.nodeValue))
-
+ vid = int(at.nodeValue)
+ refs.append(vid)
+ if tag :
+ vert = nmap[vid]
+ weigths = vert[vgroups]
+ weigths[gid] = 1.0
+ for mid in metagid : weigths[mid] = 1.0
+
first = 1
for r in refs:
if first == 0:
@@ -92,59 +172,86 @@
if node.localName == "node":
if node.hasAttributes():
- nid = None
- nlong = None
- nlat = None
- logged = 0
- for i in range(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
+ nid = node.getAttribute('id')
+ nlong = node.getAttribute('lon')
+ nlat = node.getAttribute('lat')
- if (nid is not None) and (nlat is not None) and (nlong is not None):
- fla = (float(nlat) - clat) * scale / dlat
- flo = (float(nlong) - clong) * scale / dlat
- vert = bm.verts.new((fla, flo, 0.0))
- nmap[int(nid)] = vert
- logged = 1
- break
+ # is this test necessary ? maybe for faulty .osm files
+ if (nid != '') and (nlat != '') and (nlong != '') :
+
+ if UTM :
+ nlong, nlat = geoToUTM(float(nlong),float(nlat))
+ else :
+ nlat = float(nlat)
+ nlong = float(nlong)
+
+ x = (nlong - clong) * scale / dlat
+ y = (nlat - clat) * scale / dlat
+ vert = bm.verts.new((x, y, 0.0))
+ nmap[int(nid)] = vert
+ if tag :
+ metagid = []
+ for ch in node.childNodes:
+ if ch.localName == "tag":
+ key = ch.getAttribute('k')
+ val = ch.getAttribute('v')
+ if key in osmvals and val in osmvals[key] :
+ metagid.append(grouplookup[key])
+ metagid.append(grouplookup['_V_'+val])
+ weigths = vert[vgroups]
+ group = obj.vertex_groups.new('node_%s'%nid)
+ gid = len(obj.vertex_groups) -1
+ weigths[gid] = 1.0
+ for mid in metagid : weigths[mid] = 1.0
+
+ else : print('node is missing some elements : %s %s %s'%(nid,nlat,nlong))
+
tidx += 1
#if tidx > 1000:
# break
- tidx += parseBranch(node.childNodes, bm, nmap)
+ tidx += parseBranch(node.childNodes, bm, nmap, obj,scale,tag,UTM)
return tidx
-
-def read(context, filepath, scale=100.0):
+def read(context, filepath, scale=100.0, tag=False, utm=False) :
import bmesh
from xml.dom import minidom
+ # create mesh
+ bm = bmesh.new()
+ name = bpy.path.display_name_from_filepath(filepath)
+ me = bpy.data.meshes.new(name)
+ obj = bpy.data.objects.new(name, me)
+
+ # osm tags option
+ if tag :
+ tvid = 0
+ for gid, grname in enumerate(osmkeys) :
+ obj.vertex_groups.new('_'+grname)
+ grouplookup[grname] = gid + tvid
+ if grname in osmvals :
+ for val in osmvals[grname] :
+ tvid += 1
+ obj.vertex_groups.new('_V_'+val)
+ grouplookup['_V_'+val] = gid + tvid
+
+ # get xml then feed bmesh
+ print("Reading xml...")
xmldoc = minidom.parse(filepath)
-
+
print("Starting parse: %r..." % filepath)
- bm = bmesh.new()
-
nmap = {}
- tidx = parseBranch(xmldoc.childNodes, bm, nmap)
+ tidx = parseBranch(xmldoc.childNodes, bm, nmap, obj,scale,tag,utm)
- # create mesh
- name = bpy.path.display_name_from_filepath(filepath)
- me = bpy.data.meshes.new(name)
bm.to_mesh(me)
- obj = bpy.data.objects.new(name, me)
- # scale by 1.5 is odd, need to look into that
- global_matrix = Matrix(((+0.0, +1.0, +0.0, +0.0),
- (+1.5, -0.0, +0.0, +0.0),
- (+0.0, -0.0, -1.0, +0.0),
- (+0.0, +0.0, +0.0, +1.0)))
- me.transform(global_matrix)
+ # fast approximation of utm for not too big area
+ if utm == False :
+ global_matrix = Matrix(((0.65, 0.0, 0.0, 0.0),
+ (0.0, 1.0, 0.0, 0.0),
+ (0.0, 0.0, 1.0, 0.0),
+ (0.0, 0.0, 0.0, 1.0)))
+ me.transform(global_matrix)
# create the object in the scene
scene = context.scene
@@ -152,10 +259,54 @@
scene.objects.active = obj
obj.select = True
+ # entry points for other addons
+ obj['osmfile'] = filepath
+ obj['tagged'] = tag
+ obj['utm'] = utm
+
print("Parse done... %d" % tidx)
return {'FINISHED'}
+# given lat and longitude in degrees, returns x and y in UTM kilometers.
+# accuracy : supposed to be centimeter :)
+# http://fr.wikipedia.org/wiki/Projection_UTM
+# http://fr.wikipedia.org/wiki/WGS_84
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-extensions-cvs
mailing list