Beispiel #1
0
    def _build_stop(self, stop, osm_type):
        """Helper function to build a Stop object

        Returns a initiated Stop object from raw data

        """

        if self._is_valid_stop_candidate(stop):

            # Make sure name is not empty
            if "name" not in stop.tags:
                stop.tags["name"] = "[{}]".format(self.stop_no_name)

            # Ways don't have a pair of coordinates and need to be calculated
            if osm_type == "way":
                (stop.lat, stop.lon) = Helper.get_center_of_nodes(
                    stop.get_nodes())

            # Move to Elements class, once attributes with defaults play well
            # with inheritance https://github.com/python-attrs/attrs/issues/38
            osm_url = "https://osm.org/" + str(
                osm_type) + "/" + str(stop.id)

            # Create and return Stop object
            stop = Stop(osm_id=stop.id, osm_type=osm_type, osm_url=osm_url,
                        tags=stop.tags, name=stop.tags['name'], lat=stop.lat,
                        lon=stop.lon)
            return stop

        else:
            logging.warning(
                "Warning: Potential stop is invalid and has been ignored.")
            logging.warning(
                " Check tagging: https://osm.org/%s/%s", osm_type, stop.id)
            return None
Beispiel #2
0
    def _find_best_name_for_unnamed_stop(self, stop):
        """Define name for stop without explicit name based on sourroundings

        """
        api = overpy.Overpass()

        result = api.query("""
        <osm-script>
          <query type="way">
            <around lat="%s" lon="%s" radius="50.0"/>
            <has-kv k="name" />
            <has-kv modv="not" k="highway" v="trunk"/>
            <has-kv modv="not" k="highway" v="primary"/>
            <has-kv modv="not" k="highway" v="secondary"/>
            <has-kv modv="not" k="amenity" v="bus_station"/>
          </query>
          <print order="quadtile"/>
          <query type="node">
            <around lat="%s" lon="%s" radius="50.0"/>
            <has-kv k="name"/>
            <has-kv modv="not" k="highway" v="bus_stop"/>
          </query>
          <print order="quadtile"/>
        </osm-script>
        """ % (stop.lat, stop.lon, stop.lat, stop.lon))

        candidates = []

        # get all node candidates
        for node in result.get_nodes():
            if 'name' in node.tags and node.tags["name"] is not None:
                candidates.append(node)

        # get way node candidates
        for way in result.get_ways():
            if 'name' in way.tags and way.tags["name"] is not None:
                candidates.append(way)

        # leave if no candidates
        if len(candidates) == 0:
            # give stop a different name, so we won't search again without
            # refreshing data
            stop.name = self.stop_no_name
            return

        # find closest candidate
        winner = None
        winner_distance = sys.maxint
        for candidate in candidates:
            if isinstance(candidate, overpy.Way):
                lat, lon = Helper.get_center_of_nodes(
                    candidate.get_nodes(resolve_missing=True))
                distance = util.ApproximateDistance(lat, lon, stop.lat,
                                                    stop.lon)
            else:
                distance = util.ApproximateDistance(candidate.lat,
                                                    candidate.lon, stop.lat,
                                                    stop.lon)
            if distance < winner_distance:
                winner = candidate
                winner_distance = distance

        # take name from winner
        stop.name = winner.tags["name"]
Beispiel #3
0
    def _build_station(self, stop_area, osm_type):
        """Helper function to build Station objects from stop_areas

        The function creates a Station object for the stop_area
        flagged as location_type = 1. This means station, that can
        group stops.

        The members of this relation add this station their parent.

        Returns a initiated Station object from raw data

        """
        # Check relation to be a station or used differently
        if 'route' in stop_area.tags:
            return None
        else:
            # Check tagging whether this is a stop area.
            if 'public_transport' not in stop_area.tags:
                logging.warning(
                    "Potential station has no public_transport tag.")
                logging.warning(" Please fix on OSM: https://osm.org/%s/%s",
                                osm_type, stop_area.id)
                return None
            elif stop_area.tags['public_transport'] != 'stop_area':
                logging.warning(
                    "Warning: Potential station is not tagged as stop_area.")
                logging.warning(" Please fix on OSM: https://osm.org/%s/%s",
                                osm_type, stop_area.id)
                return None

        # Analzyse member objects (stops) of this stop area
        members = {}
        for member in stop_area.members:

            if member.role == "platform":

                if isinstance(member, overpy.RelationNode):
                    member_osm_type = "node"
                elif isinstance(member, overpy.RelationWay):
                    member_osm_type = "way"

                identifier = member_osm_type + "/" + str(member.ref)

                if identifier in self.stops['regular']:

                    # Collect the Stop objects that are members
                    # of this Station
                    members[identifier] = self.stops['regular'][identifier]
                else:
                    logging.error("Station member was not found in data")
                    logging.error(" https://osm.org/relation/%s", stop_area.id)
                    logging.error(" https://osm.org/node/%s", member.ref)

        if len(members) < 1:
            # Stop areas with only one stop, are not stations they just
            # group different elements of one stop together.
            logging.error("Station with no members has been discarted:")
            logging.error(" https://osm.org/relation/%s", stop_area.id)
            return None

        elif len(members) == 1:
            logging.warning(
                "OSM stop area has only one platform and can't be used as a GTFS station:"
            )
            logging.warning(" https://osm.org/relation/%s", stop_area.id)
            return None

        # Check name of stop area
        if 'name' not in stop_area.tags:
            logging.warning(
                "Stop area without name. Please fix in OpenStreetMap:")
            logging.warning(" https://osm.org/relation/%s", stop_area.id)
            stop_area.name = self.stop_no_name
        else:
            stop_area.name = stop_area.tags["name"]

        # Calculate coordinates for stop area based on the center of it's
        # members
        stop_area.lat, stop_area.lon = Helper.get_center_of_nodes(
            members.values())

        # Move to Elements class, once attributes with defaults play well
        # with inheritance https://github.com/python-attrs/attrs/issues/38
        osm_url = "https://osm.org/" + str(osm_type) + "/" + str(stop_area.id)

        # Create and return Station object
        station = Station(osm_id=stop_area.id,
                          osm_type=osm_type,
                          osm_url=osm_url,
                          tags=stop_area.tags,
                          name=stop_area.name,
                          lat=stop_area.lat,
                          lon=stop_area.lon)
        station.set_members(members)

        logging.info(
            "Stop area (OSM) has been used to create a station (GTFS):\n")
        logging.info(" https://osm.org/relation/%s\n", str(stop_area.id))

        return station