Example #1
0
 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])
Example #2
0
File: osm.py Project: bhenne/MoSP
    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