def setUp(self): """Setup network, see test_routing.jpg""" self.n0 = routing.RoutingNode(0) self.n1 = routing.RoutingNode(1) self.n2 = routing.RoutingNode(2) self.n3 = routing.RoutingNode(3) self.n4 = routing.RoutingNode(4) self.n5 = routing.RoutingNode(5) self.n6 = routing.RoutingNode(6) self.n7 = routing.RoutingNode(7) self.n0.neighbors = {self.n1: 4, self.n2: 1} self.n1.neighbors = {self.n0: 4, self.n2: 1, self.n4: 4} self.n2.neighbors = {self.n0: 1, self.n1: 1, self.n4: 2, self.n3: 1} self.n3.neighbors = {self.n2: 1, self.n6: 1} self.n4.neighbors = {self.n1: 4, self.n2: 2, self.n5: 4} self.n5.neighbors = {self.n4: 4, self.n6: 1, self.n7: 1} self.n6.neighbors = {self.n3: 1, self.n5: 1} self.n7.neighbors = {self.n5: 1} routing.calc([self.n0, self.n1, self.n2, self.n3, self.n4, self.n5, self.n6, self.n7])
def initialize(self, sim, enable_routing=True): """Initializes the model by parsing and manipulating OSM XML data.""" #parse osm file parser = xml.sax.make_parser() handler = OSMXMLFileParser(self) parser.setContentHandler(handler) parser.parse(self.fobj) assert self.bounds["minlon"] < self.bounds["maxlon"] assert self.bounds["minlat"] < self.bounds["maxlat"] # recalculate bounding box as utm self.bounds["min_x"], self.bounds["min_y"] = utm.latlong_to_utm(self.bounds["minlon"], self.bounds["minlat"]) self.bounds["max_x"], self.bounds["max_y"] = utm.latlong_to_utm(self.bounds["maxlon"], self.bounds["maxlat"]) # now fix up all the references - replace NodePlaceHolders with Nodes for way in self.ways.values(): way.nodes = [self.nodes[handler.node_id_map[node_pl.id]] for node_pl in way.nodes] # these maps are on and off needed for debugging # BUG: ok for non_way_nodes, broken for way_nodes #self.map_osmnodeid_nodeid = handler.node_id_map #self.map_nodeid_osmnodeid = {} #for k, v in self.map_osmnodeid_nodeid.iteritems(): # self.map_nodeid_osmnodeid[v] = k # free mem del handler # connect nodes as neighbors and with ways for j, way in enumerate(self.ways.values()): for i in xrange(len(way.nodes)-1): current_node = way.nodes[i] next_node = way.nodes[i+1] # create WaySegments between current neighbors way_segment = WaySegment(current_node, next_node, width=calc_width(way), tags=way.tags) way_segment.id = i + 1000 * j self.add(way_segment) next_node.ways[current_node] = way_segment current_node.ways[next_node] = way_segment # mark nodes as neighbors and calculate their distances current_node.neighbors[next_node] = int(distance(current_node, next_node)) next_node.neighbors[current_node] = int(distance(current_node, next_node)) del self.ways # distinguish between way_nodes and non_way_nodes based on their neighbors self.non_way_nodes = [] self.way_nodes = [] for n in self.nodes.values(): # nodes with neighbors are on ways if n.neighbors: self.way_nodes.append(n) # exclude nodes without neighbors and without any tag elif len(n.tags) > 0: self.non_way_nodes.append(n) t = time.time() # filter objects contained in World for collide.Lines ways = sorted(filter(lambda w: isinstance(w, collide.Line), list(self.obj))) x_min, y_min = self.bounds["min_x"], self.bounds["min_y"] x_max, y_max = self.bounds["max_x"], self.bounds["max_y"] # check for lines colliding with west, east, north and south border for func, arg0, arg1, arg2 in ((collide.Line.collide_vertical_line, x_min, y_min, y_max), # west (collide.Line.collide_vertical_line, x_max, y_min, y_max), # east (collide.Line.collide_horizontal_line, x_min, x_max, y_max), # north (collide.Line.collide_horizontal_line, x_min, x_max, y_min)): # south for way in ways: collision = func(way, arg0, arg1, arg2) colliding = False if collision[0]: # remove WaySegments that intersect two times since they are useless if (self.out_of_bb(way.nodes[0]) and self.out_of_bb(way.nodes[1])): # kind of awkward removal of ways...somehow wrong nodes will be removed otherwise self.obj = set([w for w in self.obj if not w.id == way.id]) #self.obj.remove(way) if way.nodes[0] in self.way_nodes: self.way_nodes.remove(way.nodes[0]) if way.nodes[1] in self.way_nodes: self.way_nodes.remove(way.nodes[1]) if way.nodes[1] in way.nodes[0].neighbors.keys(): del way.nodes[0].neighbors[way.nodes[1]] if way.nodes[0] in way.nodes[1].neighbors.keys(): del way.nodes[1].neighbors[way.nodes[0]] continue for node in way.nodes: # move nodes outside of bounding box onto bounding box if node.x < x_min: node.x = collision[1] node.y = collision[2] colliding = True side = "west" elif node.x > x_max: node.x = collision[1] node.y = collision[2] colliding = True side = "east" if node.y < y_min: node.x = collision[1] node.y = collision[2] colliding = True side = "south" elif node.y > y_max: node.x = collision[1] node.y = collision[2] colliding = True side = "north" if colliding: node.tags["border"] = side break # fix distances and update way (fixes coordinates and angle) start_node = way.nodes[0] end_node = way.nodes[1] dist = int(distance(start_node, end_node)) start_node.neighbors[end_node] = dist end_node.neighbors[start_node] = dist way.update() elif (self.out_of_bb(way.nodes[0]) and self.out_of_bb(way.nodes[1]) and way in self.obj): self.obj.remove(way) # remove nodes outside of bounding box for node in self.way_nodes[:]: # check if node is outside bb if self.out_of_bb(node): self.way_nodes.remove(node) # and check if any neighbors need to be removed # (if not done, routing may break!) for neighbor in node.neighbors.keys(): if self.out_of_bb(neighbor): del node.neighbors[neighbor] # remove non_way_nodes outside of bb (those cannot be reached anyways) for node in self.non_way_nodes[:]: # check if node is outside bb if self.out_of_bb(node): self.non_way_nodes.remove(node) # perform a sanity-check on ways, remove ways with less than two correct nodes ways = sorted(filter(lambda w: isinstance(w, collide.Line), list(self.obj))) for way in ways: if (way.nodes[0] not in self.way_nodes or way.nodes[1] not in self.way_nodes): self.obj = set([w for w in self.obj if not w.id == way.id]) # sort way_nodes and close gaps in IDs self.way_nodes = sorted(self.way_nodes, key=lambda n:n.id) for i, node in enumerate(self.way_nodes): node.id = i pass # replaces next logging statement #logging.debug('created borders %.2f' % (time.time() - t)) if enable_routing: t = time.time() routing.calc(self.way_nodes, self.path[:-4]) #routing.calc(self.nodes, self.path[:-4]+'_exits', setup=True) # setup=True as quick fix for broken routing data after adding exit nodes => TODO: fix later pass # replaces next logging statement #logging.debug('routing.calc 2 %.2fs' % (time.time() - t)) t = time.time() self.calculate_grid(cache_base_path=self.path[:-4]) pass # replaces next logging statement #logging.debug('calculate_grid colliding %.2fs' % (time.time() - t)) if not enable_routing: for node in self.way_nodes: node.neighbors = {} self.way_nodes_by_id = {} for node in self.way_nodes: self.way_nodes_by_id[node.id] = node # these maps are on and off needed # fixed new implementation self.map_nodeid_osmnodeid = {} self.map_osmnodeid_nodeid = {} for n in self.way_nodes: self.map_nodeid_osmnodeid[n.id] = n.osm_id self.map_osmnodeid_nodeid[n.osm_id] = n.id