Ejemplo n.º 1
0
    def get_routes(self, refresh=False):
        """The get_routes function returns the data of routes from
        OpenStreetMap converted into usable objects.

        Data about routes is getting obtained from OpenStreetMap through the
        Overpass API, based on the configuration from the config file.

        Then this data gets prepared by building up objects of RouteMaster and
        RouteVariant objects that are related to each other.

        It uses caching to leverage fast performance and spare the Overpass
        API. Special commands are used to refresh cached data.

        :param self: the own object including it's functions and variables
        :param refresh: A simple boolean indicating a data refresh or use of
            caching if possible.

        :return routes: A dictionary of RouteMaster objects with related
            RouteVariant objects constituting the tree of data.

        """
        # Preferably return cached data about routes
        if refresh is False:
            # Check if routes data is already built in this object
            if not self.routes:
                # If not, try to get routes data from file cache
                self.routes = Cache.read_data('routes-' + self.selector)
            # Return cached data if found
            if bool(self.routes):
                return self.routes

        # No cached data was found or refresh was forced
        print("Query and build fresh data for routes")

        # Obtain raw data about routes from OpenStreetMap
        result = self._query_routes()

        # Pre-sort relations by type
        route_masters = {}
        route_variants = {}
        for relation in result.relations:
            if relation.tags["type"] == "route_master":
                route_masters[relation.id] = relation
            else:
                route_variants[relation.id] = relation

        # Build routes from master relations
        for rmid, route_master in route_masters.iteritems():
            members = OrderedDict()

            # Build route variant members
            for member in route_master.members:

                if member.ref in route_variants:
                    rv = route_variants.pop(member.ref)
                    members[rv.id] = self._build_route_variant(rv, result)

                # Route master member was already used before or is not valid
                else:
                    rv = result.get_relations(member.ref)
                    if bool(rv):
                        rv = rv.pop()
                        sys.stderr.write("Route variant was assigned again:\n")
                        sys.stderr.write("http://osm.org/relation/" +
                                         str(rv.id) + "\n")
                        members[rv.id] = self._build_route_variant(rv, result)
                    else:
                        sys.stderr.write(
                            "Member relation is not a valid route variant:\n")
                        sys.stderr.write("http://osm.org/relation/" +
                                         str(member.ref) + "\n")

            rm = self._build_route_master(route_master, members)

            # Make sure ref number is not already taken
            if rm.ref in self.routes:
                sys.stderr.write("'Ref' of route_master already taken\n")
                sys.stderr.write("http://osm.org/relation/" +
                                 str(route_master.id) + "\n")
                sys.stderr.write("Skipped. Please fix in OpenStreetMap\n")
            else:
                self.routes[rm.ref] = rm

        # Build routes from variants (missing master relation)
        for rvid, route_variant in route_variants.iteritems():
            sys.stderr.write("Route (variant) without masters\n")
            rv = self._build_route_variant(route_variant, result)
            # Make sure ref number is not already taken
            if rv.ref in self.routes:
                sys.stderr.write("Route (variant) with existing 'Ref'\n")
                sys.stderr.write("http://osm.org/relation/" +
                                 str(route_variant.id) + "\n")
                sys.stderr.write("Skipped. Please fix in OpenStreetMap\n")
            else:
                self.routes[rv.ref] = rv

        # Cache data
        Cache.write_data('routes-' + self.selector, self.routes)

        return self.routes
Ejemplo n.º 2
0
    def get_stops(self, refresh=False):
        """The get_stops function returns the data of stops and stop areas from
        OpenStreetMap converted into usable objects.

        Data about stops and stop_areas is getting obtained from OpenStreetMap
        through the Overpass API, based on the configuration from the config
        file.

        Then this data gets prepared by building up objects of the class Stops
        and StopArea (when the Stops are members of a stop_area)

        It uses caching to leverage fast performance and spare the Overpass
        API. Special commands are used to refresh cached data.

        :param self: the own object including it's functions and variables
        :param refresh: A simple boolean indicating a data refresh or use of
            caching if possible.

        :return stops: A dictionary of Stops and StopAreas constituting the
            obtained data.

        """

        # Preferably return cached data about stops
        if refresh is False:
            # Check if stops data is already built in this object
            if not self.stops:
                # If not, try to get stops data from file cache
                self.stops = Cache.read_data('stops-' + self.selector)

            if bool(self.stops):

                # Maybe check for unnamed stop names
                if self.auto_stop_names:
                    self._get_names_for_unnamed_stops()

                # Return cached data if found
                return self.stops

        # No cached data was found or refresh was forced
        print("Query and build fresh data for stops")

        # Obtain raw data about routes from OpenStreetMap
        result = self._query_stops()

        # Build stops from ways (polygons)
        for stop in result.ways:
            if self._is_valid_stop_candidate(stop):
                self.stops["way/" + str(stop.id)] = self._build_stop(
                    stop, "way")

        # Build stops from nodes
        for stop in result.nodes:
            if self._is_valid_stop_candidate(stop):
                self.stops["node/" + str(stop.id)] = self._build_stop(
                    stop, "node")

        # Build stop_areas
        for relation in result.relations:
            # valid stop_area candidade?
            if 'public_transport' in relation.tags:
                if relation.tags["public_transport"] == "stop_area":
                    self.stops["relation/" +
                               str(relation.id)] = self._build_stop_area(
                                   relation)

        # Cache data
        Cache.write_data('stops-' + self.selector, self.stops)

        # Maybe check for unnamed stop names
        if self.auto_stop_names:
            self._get_names_for_unnamed_stops()

        # Warning about stops without stop_area
        for ref, elem in self.stops.iteritems():
            if type(elem) is Stop:
                sys.stderr.write("Stop is not member of a stop_area." +
                                 " Please fix in OpenStreetMap\n")
                sys.stderr.write("http://osm.org/" + ref + "\n")

        return self.stops