Deze week ga ik het wat uittesten in de praktijk.
#!/usr/bin/python
# -*- coding: utf-8 -*-
import xml.sax
import sys
import getopt
import io
import re
import time;
nodeId = -1
'''
This Python 2.7 compliant script will turn WayPoints coming from a Garmin device
into an OSM-compliant file that can be imported with JOSM.
It relies on the syntax used in the name of the waypoints
The following stuff is recognized:
- VB for amenity: waste_basket (Vuilbak)
- BK for amenity: bench (Bank or Zitbank)
- FIREH for emergency: fire_hydrant
- M50/M70/Z70/Z30/Z50 for maxspeeds (Z for zones)
- PIKNIK for tourism: picnic_site
- WSS [name] for historic: wayside_shrine
- CDC for power: cable_distribution_cabinet
- ESS for power: sub_station
- STOP/GW for highway: stop / give_way
- LLI/RLI for highway: street_lamp
- PAAL, KGATE, SWINGGATE, SWGATE, GATE, FBAR for
barrier: bollard / kissing_gate, swing_gate, swing_gate, gate, cycle_barrier
- house number notations, e.g. R10, L10-12, L10+-+20, L10+12---13+15
Execution:
parseWayPoints.py -f
waypoint file has to end on '.gpx'
The output is a file name the same as the waypoint file, but ending on '.osm'
'''
class Node():
def __init__(self, lon, lat):
global nodeId
self.lon = lon
self.lat = lat
self.id = nodeId
nodeId = nodeId - 1
def moveABit(self):
return Node(self.lon + 0.00001, self.lat + 0.00001)
def moveABitMore(self, move):
return Node(self.lon + move, self.lat + move)
class NodePlacer():
def __init__(self, file):
self.file = file
self.updatedText = ''
self.nodeCount = 0
self.node = None
def placeNode(self, node, tags):
self.file.write('')
for kv in tags:
self.file.write('')
self.file.write(' \n')
self.node = node
def placeMovedNode(self, node, tags):
node = node.moveABit()
self.placeNode(node, tags)
class AmenityNode(NodePlacer):
def __init__(self, file):
NodePlacer.__init__(self, file)
def match(self, node, text):
if text.find("BK VB") > -1 or text.find("VB BK") > -1 :
self.placeNode(node, [('amenity', 'waste_basket')] )
self.placeMovedNode(node, [('amenity', 'bench')] )
self.updatedText = text.replace("BK VB", "").replace('VB BK', '')
self.nodeCount = 2
return True
if text.find("VB") > -1:
self.placeNode(node, [('amenity', 'waste_basket')] )
self.updatedText = text.replace('VB', '')
self.nodeCount = 1
return True
if text.find("BK") > -1:
self.placeNode(node, [('amenity', 'bench')] )
self.updatedText = text.replace('BK', '')
self.nodeCount = 1
return True
if text.find("FIREH") > -1:
self.placeNode(node, [('emergency', 'fire_hydrant')] )
self.updatedText = text.replace('FIREH', '')
self.nodeCount = 1
return True
return False
class PicnicNode(NodePlacer):
def __init__(self, file):
NodePlacer.__init__(self, file)
def match(self, node, text):
if text.find("PIKNIK") > -1:
self.placeNode(node, [('tourism', 'picnic_site')] )
self.updatedText.replace('PIKNIK', '')
self.nodeCount = 1
return True
class MaxSpeedNode(NodePlacer):
def __init__(self, file):
NodePlacer.__init__(self, file)
def match(self, node, text):
if text.find("M50") > -1:
self.placeNode(node, [('maxspeed', '50'), ('zone:traffic', 'BE:rural')])
self.nodeCount = 1
self.updatedText = text.replace('M50', '')
if text.find('M70') > -1:
self.placeNode(node, [('maxspeed', '70'), ('zone:traffic', 'BE:rural')])
self.nodeCount = 1
self.updatedText = text.replace('M70', '')
if text.find('Z70') > -1:
self.placeNode(node, [('maxspeed', '70'), ('zone:traffic', 'BE:rural'), ('source:maxspeed', 'zone70')])
self.nodeCount = 1
self.updatedText = text.replace('Z70', '')
if text.find('Z50') > -1:
self.placeNode(node, [('maxspeed', '50'), ('zone:traffic', 'BE:rural'), ("source:maxspeed", "zone50")])
self.nodeCount = 1
self.updatedText = text.replace('Z50', '')
if text.find('Z30') > -1:
self.placeNode(node, [('maxspeed', '30'), ('zone:traffic', 'BE:urban'), ("source:maxspeed", "zone30")])
self.nodeCount = 1
self.updatedText = text.replace('Z30', '')
class WaySideShrineNode(NodePlacer):
def __init__(self, file):
NodePlacer.__init__(self, file)
self.wssPattern = re.compile(r'\A[LR]+[ ]WSS([ A-Za-z0-9]*)')
def match(self, node, text):
wssMatch = self.wssPattern.match(text)
if wssMatch:
if (wssMatch.group(1) == ""):
self.placeNode(node, [('historic', 'wayside_shrine'), ('religion', 'christian'), ('denomination', 'roman_catholic')])
else:
self.placeNode(node, [('historic', 'wayside_shrine'), ('religion', 'christian'), ('denomination', 'roman_catholic'), ('name', wssMatch.group(1).strip())])
self.updatedText = ''
self.nodeCount = 1
return True
return False
class BarrierNode(NodePlacer):
def __init__(self, file):
NodePlacer.__init__(self, file)
def match(self, node, text):
if text.find("PAAL") > -1:
self.placeNode(node, [('barrier', 'bollard'), ('foot','yes'), ('bicycle', 'yes')] )
self.updatedText = text.replace('PAAL', '')
self.nodeCount = 1
return True
if text.find("SWINGGATE") > -1 or text.find("SWGATE") > -1:
self.placeNode(node, [('barrier', 'swing_gate'), ('foot','yes'), ('bicycle', 'yes')] )
self.updatedText = text.replace('SWINGGATE', '').replace('SWGATE', '')
self.nodeCount = 1
return True
if text.find("KGATE") > -1 or text.find("KISSGATE") > -1:
self.placeNode(node, [('barrier', 'kiss_gate'), ('foot','yes'), ('bicycle', 'no')] )
self.updatedText = ''
self.nodeCount = 1
return True
if text.find("GATE") > -1:
self.placeNode(node, [('barrier', 'gate'), ('foot','yes'), ('bicycle', 'yes')] )
self.updatedText = text.replace('GATE', '')
self.nodeCount = 1
return True
if text.find("FBAR") > -1 :
self.placeNode(node, [('barrier', 'cycle_barrier'), ('foot','yes'), ('bicycle', 'yes')] )
self.updatedText = text.replace('FBAR', '')
self.nodeCount = 1
return True
class PowerNode(NodePlacer):
def __init__(self, file):
NodePlacer.__init__(self, file)
def match(self, node, text):
if text == "L ESS" or text == "R ESS" or text == "ESS":
self.placeNode(node, [('power', 'sub_station')] )
self.updatedText = ''
self.nodeCount = 1
return True
if text == "L CDC" or text == "R CDC" or text == "CDC":
self.placeNode(node, [('power', 'cable_distribution_cabinet')] )
self.updatedText = ''
self.nodeCount = 1
return True
class HighwayNode(NodePlacer):
def __init__(self, file):
NodePlacer.__init__(self, file)
def match(self, node, text):
if text == "RLI" or text == "LLI" :
self.placeNode(node, [('highway', 'street_lamp')] )
self.updatedText = ''
self.nodeCount = 1
return True
if text == "STOP" :
self.placeNode(node, [('highway', 'stop')] )
self.updatedText = ''
self.nodeCount = 1
return True
if text.find("GW") == 0:
self.placeNode(node, [('highway', 'give_way')] )
self.updatedText = ''
self.nodeCount = 1
return True
class HouseNumberNode(NodePlacer):
def __init__(self, file):
NodePlacer.__init__(self, file)
self.numberPattern = re.compile('[0-9]')
self.houseNumberPattern = re.compile(r'\A[+-]*([0-9]+[a-zA-Z]*)')
self.terracePattern = re.compile(r'[+-]*([0-9]+[a-zA-Z]*)\+\-\+([0-9]+[a-zA-Z]*)')
def match(self, node, text):
if not ( text.startswith("L") or text.startswith("R")):
return False
numberpart = text.strip('LR ')
terraceMatch = self.terracePattern.match(numberpart)
if terraceMatch:
group1 = int(terraceMatch.group(1))
group2 = int(terraceMatch.group(2))
startNr = min(group1, group2)
endNr = max(group1, group2)
terraceNrs = range(startNr, endNr + 1, 2)
self.nodeCount = 0
for nr in terraceNrs:
self.placeNode(node, [('building', 'house'), ('addr:housenumber', str(nr))])
node = node.moveABitMore(0.00005)
self.nodeCount = self.nodeCount + 1
self.updatedText = 'L' + self.terracePattern.sub('', numberpart, 1)
return True
houseNumberMatch = self.houseNumberPattern.match(numberpart)
if houseNumberMatch:
self.placeNode(node, [('building', 'house'), ('addr:housenumber', houseNumberMatch.group(1).strip())])
self.updatedText = 'L' + self.houseNumberPattern.sub('', numberpart, 1)
self.nodeCount = 1
return True
class WaypointContentHandler(xml.sax.ContentHandler):
def __init__(self, filename):
xml.sax.ContentHandler.__init__(self)
self.nodeCount = 0
self.text = ""
self.f = open(filename, 'w')
self.f.write('\n')
self.f.write('\n')
self.f.write('\n')
self._matchers = [ AmenityNode(self.f), PicnicNode(self.f), HighwayNode(self.f),
BarrierNode(self.f), PowerNode(self.f), HouseNumberNode(self.f), WaySideShrineNode(self.f),
MaxSpeedNode(self.f) ]
def startElement(self, tagname, attrs):
if tagname == "wpt":
self.node = Node(float(attrs.getValue("lon")), float(attrs.getValue("lat")))
if tagname == "name":
self.text = ''
def endElement(self, tagname):
if tagname == "name":
self.tagNode(self.node, self.text.strip())
def endDocument(self):
self.f.write(' \n')
self.f.close()
def characters(self, content):
self.text = self.text + content
def tagNode(self, node, text):
for matcher in self._matchers:
theText = text
matcher.node = None
while matcher.match(node, theText):
theText = matcher.updatedText.strip()
self.nodeCount = self.nodeCount + matcher.nodeCount
if matcher.node is None:
node = node.moveABitMore(0.00005)
else:
node = matcher.node.moveABitMore(0.00005)
class FileNameGenerator():
def generateFileName(self, waypointFile):
outputfile = waypointFile.replace('gpx', 'osm')
return outputfile
def main(argv):
file = ''
try:
opts, args = getopt.getopt(argv,"hf:",["file="])
except getopt.GetoptError:
print 'parseWayPoints.py -f '
sys.exit(2)
for opt, arg in opts:
if opt == '-h':
print 'Usage: parseWayPoints.py -f '
sys.exit(0)
elif opt in ("-f", "--file"):
file = arg
if file == '':
print 'No file specified'
sys.exit(2)
print 'Parsing WayPoint file: ', file
outputfile = FileNameGenerator().generateFileName(file)
print outputfile
waypointHandler = WaypointContentHandler(outputfile)
fileHandle = io.open(file, "r")
xml.sax.parse(fileHandle, waypointHandler)
print 'Wrote ' + outputfile + ' containing ' + str(waypointHandler.nodeCount) + ' nodes.'
if __name__ == "__main__":
main(sys.argv[1:])