├── LICENSE ├── exampleData.osm └── router └── router.py /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /router/router.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import re, string, sys 4 | import xml.sax as sax 5 | from math import radians, cos, sin, asin, sqrt 6 | 7 | print "Hello, World!"; 8 | 9 | filepath = sys.argv[1] 10 | 11 | #print "Calculating from:"+ fromNode + " to:"+ toNode 12 | 13 | #print sys.argv[1] 14 | 15 | class DictHandler(sax.handler.ContentHandler): 16 | 17 | def __init__(self): 18 | self.ergebnis = {} 19 | self.schluessel = "" 20 | self.wert = "" 21 | self.id = "" 22 | self.lon = "" 23 | self.lat ="" 24 | self.aktiv = None 25 | self.notecount = 0 26 | 27 | def setDb(self, db): 28 | self.db = db 29 | print "DB given to parser" 30 | 31 | def startElement(self, name, attrs): 32 | #searching for nodes and store all relevant information 33 | if name == "node": 34 | self.aktiv = "node" 35 | self.db.addNode(attrs["id"],node(attrs["id"],attrs["lat"],attrs["lon"])) 36 | #searching for ways 37 | if name == "way": 38 | print "<----------------- A new Way Starts here ---------------------------------->" 39 | self.notecount = self.notecount + 1 40 | self.schluessel = "" 41 | self.saveMe = False 42 | self.highway = "" 43 | self.wert = "" 44 | self.lastNode = None 45 | self.streetName = "" 46 | if self.aktiv != None: 47 | print "something is strange in here" 48 | self.aktiv = "way" 49 | self.id = 0 50 | self.id = attrs["id"] 51 | self.nodes = [] 52 | #print "Id des wegs: \t" + attrs["id"] 53 | #self.aktiv = name 54 | #self.lon = eval(attrs["lon"]) 55 | elif (self.aktiv == "way" and name == "nd"): 56 | #self.nodes[attrs["ref"]] = node(attrs["ref"]) 57 | #print "suchen ob es den node " + attrs["ref"] + " schon gibt" 58 | #print "Lon aus DB: " + self.db.getNode(attrs["ref"]).lon 59 | #add connection between nodes if there is a pref node 60 | nowNode = self.db.getNode(attrs["ref"]) 61 | self.nodes.append(nowNode) 62 | if self.lastNode: 63 | #print "found a old node creating connection" 64 | connection(self.id,self.lastNode,nowNode) 65 | else: 66 | print "no old node saved inna here" 67 | self.lastNode = nowNode 68 | elif (self.aktiv == "way" and name == "tag"): 69 | #print "tag found" 70 | if attrs["k"] == "highway": 71 | #mark connections to beeing saved 72 | self.highway = attrs["v"] 73 | self.saveMe = True 74 | if attrs["k"] == "name": 75 | #print "Name des wegs: \t" + attrs["v"] 76 | self.streetName = attrs["v"] 77 | self.streetName.encode('ascii','ignore') 78 | #print "Name des wegs: \t" + streetName.encode('utf8') 79 | 80 | def endElement(self, name): 81 | if name == "way": 82 | #self.ergebnis[self.schluessel] = self.typ(self.wert) 83 | self.aktiv = None 84 | if self.saveMe: 85 | print "Connections should be saved! " 86 | #print "" 87 | #saving connecitons 88 | for i in self.nodes: 89 | i.saveConnections() 90 | print "Nodes:" 91 | print self.nodes 92 | self.saveMe = False 93 | else: 94 | for i in self.nodes: 95 | i.discardChanges() 96 | #print "" 97 | 98 | 99 | class way(): 100 | def __init__(self,id): 101 | self.id = id 102 | print "new way with id: " + self.id + " created" 103 | 104 | class connection(): 105 | def __init__(self,wayId,node1,node2): 106 | self.node1 = node1 107 | self.node2 = node2 108 | self.wayId = wayId 109 | node1.addConnection(self) 110 | node2.addConnection(self) 111 | print " Connection between: " + node1.id + " and " + node2.id + " created" 112 | def printConnection(self): 113 | print "Saved Connection between: " + self.node1.id + " and " + self.node2.id + "! " 114 | #print "" 115 | def getOtherNode(self,node): 116 | if (node == self.node1): 117 | return self.node2 118 | else: 119 | return self.node1 120 | 121 | class node(): 122 | def __init__(self,id,lat,lon): 123 | self.id = id 124 | self.connections = [] 125 | self.tempconnections = [] 126 | self.lat = lat 127 | self.lon = lon 128 | self.cameFrom = None 129 | self.distanceToDest = 0.0 #how the crow flys 130 | self.distanceFromStart = 0.0 131 | self.explored = False 132 | self.known = False 133 | print "new node with id: " + self.id + " created" 134 | print "lat: " + self.lat + " lon: " + self.lon 135 | def addConnection(self,connection): 136 | self.tempconnections.append(connection) 137 | def saveConnections(self): 138 | print "saving connection" 139 | self.connections.extend(self.tempconnections) 140 | #delete tmp elements 141 | self.tempconnections = [] 142 | def discardChanges(self): 143 | print "removing connection from nonway" 144 | self.tempconnections = [] 145 | def numOfConnections(self): 146 | #print "this node has: " + str(self.connections) + " Connections" 147 | return len(self.connections) 148 | def printConnections(self): 149 | print self.id + " has " + str(len(self.connections)) + " connecitons they are:" 150 | for i in self.connections: 151 | print str(i) 152 | print i.printConnection() 153 | #print "back again" 154 | def getScore(self): 155 | if self.known: 156 | return self.distanceFromStart + self.distanceToDest 157 | else: 158 | print "error: !!!NODE NOT KNOW!!!" 159 | return 0.0 160 | def printNextNodes(self): 161 | print "listing other nodes: " 162 | for i in self.connections: 163 | otherNode = i.getOtherNode(self) 164 | print "id: " + otherNode.id + " lat: " + otherNode.lat + " lon: " + otherNode.lon + " distance: " + str(calcDistance(self,otherNode)) 165 | def raiseKnowledge(self,prefNode,destNode): 166 | print "going to know more about: " + self.id + " Score: " + str(self.getScore()) + " prfNode was: " + prefNode.id 167 | distanceFromPrefNode = calcDistance(prefNode,self) 168 | print "\t distanceFromPrefNode: \t" + str(distanceFromPrefNode) 169 | self.distanceFromStart = prefNode.distanceFromStart + distanceFromPrefNode 170 | print "\t distanceFromStart: \t " + str(self.distanceFromStart) 171 | self.distanceToDest = calcDistance(self,destNode) 172 | print "\t distanceToDest: \t" + str(self.distanceToDest) 173 | self.cameFrom = prefNode 174 | self.known = True 175 | 176 | class routingDb(): 177 | def __init__(self): 178 | print "routing DB created" 179 | self.listOfNodes = {} 180 | 181 | def addNode(self,nodeId,node): 182 | self.listOfNodes[nodeId] = node 183 | print "storred Node: " + nodeId + " in list" 184 | 185 | def size(self): 186 | return str(len(self.listOfNodes)) 187 | 188 | 189 | def getNode(self,nodeId): 190 | return self.listOfNodes[nodeId] 191 | 192 | def cleanUp(self): 193 | print "<----------- Cleaning DB ----------------->" 194 | #self.printStatus() 195 | #remove all nodes which dont have anny connection to another 196 | tmpListOfNodes = {} 197 | for i in self.listOfNodes: 198 | if self.listOfNodes[i].numOfConnections() > 0: 199 | print "keeping node: " + str(i) 200 | tmpListOfNodes[i] = self.listOfNodes[i] 201 | self.listOfNodes = tmpListOfNodes 202 | print "<----------- Cleanup Done ---------------->" 203 | self.printStatus() 204 | 205 | def printStatus(self): 206 | print "<------------ Printing Status --------------->" 207 | print "We have: " + self.size() + " Nodes" 208 | for i in self.listOfNodes: 209 | print "Node " + str(i) + " is in da DB it has: " + str(self.listOfNodes[i].numOfConnections()) + " Connection(s)" 210 | self.listOfNodes[i].printConnections() 211 | 212 | 213 | def readDb(dateiname,db): 214 | print dateiname 215 | handler = DictHandler() 216 | handler.setDb(db) 217 | parser = sax.make_parser() 218 | parser.setContentHandler(handler) 219 | parser.parse(dateiname) 220 | print handler.notecount 221 | return handler.ergebnis 222 | 223 | def findNextNodes(node): 224 | node.printConnections() 225 | node.printNextNodes() 226 | nextNodes = [] 227 | for i in node.connections: 228 | nextNodes.append(i.getOtherNode(node)) 229 | print "Next Nodes: " 230 | print nextNodes 231 | return nextNodes 232 | #for i in node.connections: 233 | # otherNode = i.getOtherNode(node) 234 | # print "id: " + otherNode.id + " lat: " + otherNode.lat + " lon: " + otherNode.lon + " distance: " + str(calcDistance(node,otherNode)) 235 | 236 | def calcDistance(node,otherNode): 237 | lat1 = float(node.lat) 238 | lon1 = float(node.lon) 239 | lat2 = float(otherNode.lat) 240 | lon2 = float(otherNode.lon) 241 | 242 | #Code coppied form: http://stackoverflow.com/questions/4913349/haversine-formula-in-python-bearing-and-distance-between-two-gps-points 243 | """ 244 | Calculate the great circle distance between two points 245 | on the earth (specified in decimal degrees) 246 | """ 247 | # convert decimal degrees to radians 248 | lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2]) 249 | 250 | # haversine formula 251 | dlon = lon2 - lon1 252 | dlat = lat2 - lat1 253 | a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2 254 | c = 2 * asin(sqrt(a)) 255 | 256 | # 6367 km is the radius of the Earth 257 | km = 6367 * c 258 | return km 259 | 260 | def findTopNode(knownNodes): 261 | topNode = knownNodes[0] 262 | for i in knownNodes: 263 | if (topNode.getScore() > i.getScore()): 264 | print "comparing: \n\t" + str(topNode.id) + " Score: " + str(topNode.getScore()) + " and: \n\t" + i.id + " Score: " + str(i.getScore()) 265 | topNode = i 266 | print topNode.id + " has the best Score!" 267 | return topNode 268 | 269 | def startRouting(db): 270 | print "<------------ Starting Routing --------------->" 271 | exploredNodes = [] 272 | knownNodes = [] 273 | tmpNodes = [] 274 | startId = "1554790199" 275 | endId = "280095678" 276 | maxSteps = 40 277 | startNode = db.getNode(startId) 278 | endNode = db.getNode(endId) 279 | print "start Ziehl distanz: " + str(calcDistance(startNode,endNode)) 280 | #startNode.printConnections() 281 | 282 | nowNode = startNode 283 | knownNodes.append(nowNode) 284 | 285 | while ((nowNode != endNode) & (len(knownNodes) > 0) & (maxSteps > 0)): 286 | print "<< This is Step: " + str(maxSteps) + " >>" 287 | #maxSteps = maxSteps - 1 288 | knownNodes.remove(nowNode) 289 | exploredNodes.append(nowNode) 290 | nowNode.explored = True 291 | tmpNodes.extend(findNextNodes(nowNode)) 292 | for i in tmpNodes: 293 | # def raiseKnowledge(self,prefNode,destNode): 294 | i.known = True 295 | if (i.explored == False): 296 | i.raiseKnowledge(nowNode,endNode) 297 | if (i in knownNodes): 298 | print i.id + " is allread known" 299 | else: 300 | knownNodes.append(i) 301 | print "I know some Nodes: " 302 | for i in knownNodes: 303 | print i.id 304 | print "I explored some Nodes: " 305 | for i in exploredNodes: 306 | print i.id 307 | 308 | nowNode = findTopNode(knownNodes) 309 | 310 | print "DONE" 311 | 312 | print "I came to " + nowNode.id 313 | while (nowNode.cameFrom != None): 314 | print " via " + nowNode.cameFrom.id + "\t Link: http://www.openstreetmap.org/node/"+nowNode.cameFrom.id 315 | nowNode = nowNode.cameFrom 316 | 317 | 318 | db = routingDb() 319 | print readDb(open(filepath,"r"),db) 320 | db.cleanUp() 321 | startRouting(db) 322 | --------------------------------------------------------------------------------