Druk bezig met andere dingen, dus snel even tussendoor:
Ik heb gisteren een eerste link gelegd tussen een meetstation van de Vlaamse Milieumaatschappij en hun website met meetresultaten.
Via OpenLinkMap kan je dan doorklikken naar de website van de VMM met daarop gedetailleerde gegevens van de luchtkwaliteit en de werking van het station.
Nu nog de ca. 30 andere meetstations in kaart brengen.
p.s. het idee is feitelijk aangebracht door mijn collega, Claes Buckwalter, die een Android app geschreven heeft om te luchtkwaliteit te bekijken.
Showing posts with label OSM. Show all posts
Showing posts with label OSM. Show all posts
Wednesday, April 3, 2013
Luchtkwaliteit
Wednesday, March 27, 2013
Back To The Future
Vandaag ontdekt: een website die de nadruk legt op historische gebouwen zoals kastelen en kapellen. Verder ook aandacht voor beschermde monumenten, grenspalen e.d.
Hieronder een werkende mini-versie, maar je kan beter naar geschichtskarten surfen
Hieronder een werkende mini-versie, maar je kan beter naar geschichtskarten surfen
Monday, March 25, 2013
Over De Lijn
Toen ik me pas aanmeldde op de mailing list voor de Belgische mappers, werd ik direct onder de arm genomen door Polyglot. Dat is de alias waaronder Jo bijdragen levert aan OpenStreetMap. Ik beschouw hem dan ook een beetje als mijn "mentor" :-)
Jo is al jaren bezig om de buslijnen in Vlaanderen op de kaart te zetten. Hij heeft tevens contact gezocht met De Lijn om de gegevens te mogen overzetten van hun databank naar die van OpenStreetMap. Heel lang stootte hij op een njet en ondertussen schonk De Lijn de gegevens dan ook nog eens aan Google. Dus al die bus symbooltjes op Google maps komen van De Lijn.
Er zat dan niets anders op dan alle 40.000 haltes te bezoeken en de gegevens. Jo deed en oproep via de mailing list. Ik vermoed dat hij toch enkele vrijwilligers vond om de haltes te catalogiseren.
We hadden er al zo'n 9000, al dan niet volledig, in kaart gebracht, toen Jo het bericht kreeg dat hij toch over de gegevens mocht beschikken. Hij is dan begonnen met te kijken in hoeverre de gegevens die al in OpenStreetMap zitten afwijken van de gegevens van De Lijn.
Af en toe bleken er toch wel grote verschillen te zijn. Had de mapper de verkeerde positie ingegeven ? Of was de halte daadwerkelijk verplaatst ? De gehele lijst werd door Jo nagekeken en daarna doorgegeven aan De Lijn. Zij kunnen dan zien of ze de verbeteringen willen terugkoppelen. Op deze manier zouden ze er wel zelf nog iets aan hebben ook.
Welke gegevens brengen we nu juist in kaart:
Jo is al jaren bezig om de buslijnen in Vlaanderen op de kaart te zetten. Hij heeft tevens contact gezocht met De Lijn om de gegevens te mogen overzetten van hun databank naar die van OpenStreetMap. Heel lang stootte hij op een njet en ondertussen schonk De Lijn de gegevens dan ook nog eens aan Google. Dus al die bus symbooltjes op Google maps komen van De Lijn.
Er zat dan niets anders op dan alle 40.000 haltes te bezoeken en de gegevens. Jo deed en oproep via de mailing list. Ik vermoed dat hij toch enkele vrijwilligers vond om de haltes te catalogiseren.
We hadden er al zo'n 9000, al dan niet volledig, in kaart gebracht, toen Jo het bericht kreeg dat hij toch over de gegevens mocht beschikken. Hij is dan begonnen met te kijken in hoeverre de gegevens die al in OpenStreetMap zitten afwijken van de gegevens van De Lijn.Af en toe bleken er toch wel grote verschillen te zijn. Had de mapper de verkeerde positie ingegeven ? Of was de halte daadwerkelijk verplaatst ? De gehele lijst werd door Jo nagekeken en daarna doorgegeven aan De Lijn. Zij kunnen dan zien of ze de verbeteringen willen terugkoppelen. Op deze manier zouden ze er wel zelf nog iets aan hebben ook.
Welke gegevens brengen we nu juist in kaart:
- de plaats van de halte
- de naam Je
- het referentie nummer (de 6 cijfers)
- de nummers van de buslijnen
- de zone
Verder worden ook de routes zelf nog in kaart gebracht. Je kan die dan bekijken op de website van OpenStreetMap zelf. Het mooiste resultaat krijg je door de 'Transport Map' te selecteren via het lagen icoon rechtsboven
De ÖPNVKarte website legt zich uitsluitend toe op het mooi in kaart te brengen van alle vormen van openbaar vervoer. Van internationale luchthavens tot de kleinste (bel)bushalte.
Maar we kunnen nog een stapje verder gaan. De Lijn geeft op zijn website in real-time de aankomst tijden van de bussen door. Dus hoe kunnen we die informatie beschikbaar maken via een kaart ?
Wel, via OpenLinkMap worden alle links (URLs of website referenties) beschikbaar gemaakt op een kaart. Alle bushaltes worden voorgesteld door een busje met een cirkel er rond. Klik je daar op, dan krijg een klein venster met daarin bijkomen informatie over de bushalte.
Klik je dan op mijnlijn.be, dan krijg je de pagina van De Lijn met de real-time informatie van de gekozen bushalte.
Ik wens u een voorspoedige busreis.
Sunday, March 24, 2013
Weekend Projectje
Omdat ik behoorlijk wat data verzamel als waypoints in GPX files, duurt het steeds een hele poos vooraleer ik alle data heb verwerkt. Dit weekend heb ik wat tijd besteed aan het schrijven van een Python script om de GPX data om te zetten in OSM-formaat. Het onderstaande script is het resultaat. Het kan nog lang niet alles omzetten, maar is toch al een start.
Deze week ga ik het wat uittesten in de praktijk.
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:])
Wednesday, March 20, 2013
Geef ons brood en spelen
Iedereen kent het probleem wel dat zijn bakker met vakantie is en je op zoek moet naar een andere. In deze tijd van smartphones hoef je je zondag toch niet door te komen zonder koffiekoeken. Richt je smartphone op http://openstreepmap.org en typ "Bakery, Reet" en floep...
... de pistolekes en koffiekoeken komen u tegemoet. Of tenminste toch de adressen waar je er kan kopen.
Je kan de bakkers natuurlijk ook op Google vinden. Maar net zoals OSM hangt google af van vrijwilligers om al die winkels te verzamelen. Waarom zou je dan voor OSM kiezen? Openheid van data is misschien een goede reden. Als je winkels in Google inbrengt, kan je die gegevens enkel via de Google website opvragen. Bij OSM is de data vrij beschikbaar voor iedereen. Je kan er meespelen en zelf een App of website ontwikkelen waarin die gegevens gebruikt worden.
Dus als je niet tevreden bent over de manier waarop je kan zoeken naar bakkers bij openstreetmap.org, kan je ook een menu ontwikkelen waarin je winkels e.d. kan kiezen, zoals de makers van lenz-online gedaan hebben.
Maar ja, 's avonds is die bakker al gesloten en zit je nog zonder brood. Gelukkig heb je in België ook nog zoiets als broodautomaten. Die dingen vind je volgens mij niet terug op Google, maar wel op OSM. Tenminste als er een Gekke Mapper in je buurt woont, die de moeite heeft genomen om die in kaart te brengen.
Deze lijst van broodautomaten is samengesteld via een taaltje dat ontwikkeld is om de databank van OSM te ondervragen. Dit is waarschijnlijk niet voor iedereen weggelegd, maar het laat nog maar eens zien dat de gegevens open zijn en op verschillende manieren kunnen geraadpleegd worden. Voor wie het zelf eens wil proberen, surf naar Overpass Turbo. Dit is de Broodautomaten vraag. Je moet enkel nog op "Run" klikken.
Het is dus best mogelijk dat er bij jou in de buurt nog niet veel gedaan is, ondanks het legertje vrijwilligers dat aan OSM meewerkt.
Dit plaatje is misschien wat misleidend, want veel mensen die zich inschrijven leveren geen of slechts enkele bijdragen. Dus
is een misschien wat realistischere voorstelling. Ik val misschien in herhaling, maar je bent meer dan welkom om mee te komen spelen. En anders, kan je je misschien al amuseren door op neis-one naar mijn mannetje te zoeken terwijl je van je broodje geniet.
... de pistolekes en koffiekoeken komen u tegemoet. Of tenminste toch de adressen waar je er kan kopen.
Je kan de bakkers natuurlijk ook op Google vinden. Maar net zoals OSM hangt google af van vrijwilligers om al die winkels te verzamelen. Waarom zou je dan voor OSM kiezen? Openheid van data is misschien een goede reden. Als je winkels in Google inbrengt, kan je die gegevens enkel via de Google website opvragen. Bij OSM is de data vrij beschikbaar voor iedereen. Je kan er meespelen en zelf een App of website ontwikkelen waarin die gegevens gebruikt worden.
Dus als je niet tevreden bent over de manier waarop je kan zoeken naar bakkers bij openstreetmap.org, kan je ook een menu ontwikkelen waarin je winkels e.d. kan kiezen, zoals de makers van lenz-online gedaan hebben.
Maar ja, 's avonds is die bakker al gesloten en zit je nog zonder brood. Gelukkig heb je in België ook nog zoiets als broodautomaten. Die dingen vind je volgens mij niet terug op Google, maar wel op OSM. Tenminste als er een Gekke Mapper in je buurt woont, die de moeite heeft genomen om die in kaart te brengen.
Deze lijst van broodautomaten is samengesteld via een taaltje dat ontwikkeld is om de databank van OSM te ondervragen. Dit is waarschijnlijk niet voor iedereen weggelegd, maar het laat nog maar eens zien dat de gegevens open zijn en op verschillende manieren kunnen geraadpleegd worden. Voor wie het zelf eens wil proberen, surf naar Overpass Turbo. Dit is de Broodautomaten vraag. Je moet enkel nog op "Run" klikken.
Het is dus best mogelijk dat er bij jou in de buurt nog niet veel gedaan is, ondanks het legertje vrijwilligers dat aan OSM meewerkt.
Dit plaatje is misschien wat misleidend, want veel mensen die zich inschrijven leveren geen of slechts enkele bijdragen. Dus
Subscribe to:
Posts (Atom)










