Esempio n. 1
0
    def _get_query(self):
        params = self.request.params
        term = params.get('term', '').strip()
        if term:
            waypoints = re.split('\s+to\s+', term, re.I)
            if len(waypoints) < 2:
                raise InputError(
                    "That doesn't look like a valid directions request")
        else:
            waypoints = params.get('waypoints', '').strip()

            if waypoints:
                waypoints = waypoints.split(';')
                start, *rest = waypoints
                end = rest[-1] if rest else None
            else:
                start = params.get('from', '').strip()
                end = params.get('to', '').strip()

            if start and end:
                waypoints = [start, end]
            elif start:
                raise InputError('Please enter a starting point')
            elif end:
                raise InputError('Please enter a destination')
            else:
                raise InputError('Please enter something to search for')

        return waypoints
Esempio n. 2
0
    def _get(self):
        req = self.request
        params = req.params
        has_directions_params = 'from' in params or 'to' in params

        if 'term'in params:
            if has_directions_params:
                self.request.response.status_int = 400
                raise InputError(
                    'Query service accepts *either* the `term` query parameter *or* the `from` '
                    'and `to` query parameters')
            term = params.get('term', '').strip()
            if DIRECTIONS_RE.match(term):
                view_class = DirectionsResource
            else:
                view_class = LookupResource
        elif has_directions_params:
            view_class = DirectionsResource
        else:
            raise InputError(
                'Query service requires at least one of the following query parameter: '
                '`term`, `from`, or `to`')

        view = view_class(self.request)
        return view.get()
Esempio n. 3
0
    def _get_config(self):
        """Get configuration for service.

        Extract service config from query params and return a dict of
        keyword args that will be passed when constructing the service
        instance.

        Raises:
            InputError: On bad input

        """
        center = self.request.params.get('center', '').strip()
        if center:
            coords = center.split(',')
            coords = tuple(c.strip() for c in coords)
            coords = tuple(c for c in coords if c)
            if not (len(center) == 2 and all(is_coord(c for c in coords))):
                raise InputError('center param must contain exactly 2 numbers (comma separated)')
            center = tuple(float(c) for c in coords)

        bbox = self.request.params.get('bbox', '').strip()
        if bbox:
            coords = bbox.split(',')
            coords = tuple(c.strip() for c in coords)
            coords = tuple(c for c in coords if c)
            if not (len(coords) == 4 and all(is_coord(c for c in coords))):
                raise InputError('bbox param must contain exactly 4 numbers (comma separated)')
            if coords[0] > coords[2]:
                raise InputError('bbox param minx must be less than maxx')
            if coords[1] > coords[3]:
                raise InputError('bbox param miny must be less than maxy')
            bbox = tuple(float(c) for c in coords)
        else:
            bbox = self._default_bbox

        settings = self.request.registry.settings
        mapbox_access_token = settings.get('mapbox.access_token')

        return {
            'center': center or None,
            'bbox': bbox or None,
            'mapbox_access_token': mapbox_access_token,
        }
Esempio n. 4
0
 def match_id(self, s):
     match = ID_RE.search(s)
     if match:
         type_ = match.group('type')
         if type_ not in TYPE_MAP:
             raise InputError('Unknown type: %s' % type_)
         type_ = TYPE_MAP[type_]
         obj = self.session.query(type_).get(match.group('id'))
         if obj is None:
             return None
         if isinstance(obj, Intersection):
             geom = obj.geom
         else:
             length = obj.geom.length
             geom = Point(obj.geom.interpolate(length / 2))
         return LookupResult(s, obj, geom, obj, obj.name, 'byCycle ID')
Esempio n. 5
0
 def get_waypoints(self, q, points=None):
     errors = []
     waypoints = [w.strip() for w in q]
     num_waypoints = len(waypoints)
     points = points or [None] * num_waypoints
     if num_waypoints != len(points):
         errors.append(
             'Number of points does not match number of waypoints')
     if num_waypoints == 0:
         errors.append('Please enter starting point and destination')
     if num_waypoints == 1:
         errors.append('Please enter a destination')
     else:
         if num_waypoints == 2:
             if not waypoints[0]:
                 errors.append('Please enter a starting point')
             if not waypoints[-1]:
                 errors.append('Please enter a destination')
         else:
             for w in waypoints:
                 if not w:
                     errors.append('Destinations cannot be blank')
                     break
     if errors:
         raise InputError(errors)
     lookup_service = LookupService(self.session, **self.config)
     results = []
     raise_multi = False
     for w, point_hint in zip(waypoints, points):
         try:
             result = lookup_service.query(w, point_hint)
         except MultipleLookupResultsError as exc:
             raise_multi = True
             results.append(exc.choices)
         else:
             results.append(result)
     if raise_multi:
         raise MultipleRouteLookupResultsError(choices=results)
     return results
Esempio n. 6
0
 def _get_query(self):
     params = self.request.params
     term = params.get('term', '').strip()
     if not term:
         raise InputError('Please enter something to search for.')
     return term
Esempio n. 7
0
    def find_path(self,
                  start_result: LookupResult,
                  end_result: LookupResult,
                  cost_func: str = None,
                  heuristic_func: str = None):
        client = Client()

        start = start_result.closest_object
        end = end_result.closest_object
        annex_edges = []
        split_ways = {}

        add_between = isinstance(start, Street) and isinstance(
            end, Street) and start.id == end.id

        if isinstance(start, Street):
            start, *start_ways, start_edges = self.split_way(
                start, start_result.geom, -1, -1, -2)
            annex_edges.extend(start_edges)
            split_ways.update({w.id: w for w in start_ways})

        if isinstance(end, Street):
            end, *end_ways, end_edges = self.split_way(end, end_result.geom,
                                                       -2, -3, -4)
            annex_edges.extend(end_edges)
            split_ways.update({w.id: w for w in end_ways})

        if add_between:
            obj = start_result.closest_object
            geom = trim_line(obj.geom, start.geom, end.geom)

            d1 = obj.geom.project(start.geom)
            d2 = obj.geom.project(end.geom)

            if d1 <= d2:
                start_node, end_node = start, end
            else:
                start_node, end_node = end, start

            if obj.base_cost is None:
                base_cost = None
            else:
                fraction = length_in_meters(geom) / obj.meters
                base_cost = obj.base_cost * fraction

            way = obj.clone(id=-3,
                            geom=geom,
                            start_node_id=start_node.id,
                            start_node=start_node,
                            end_node_id=end_node.id,
                            end_node=end_node,
                            base_cost=base_cost)

            way_attrs = (way.id, base_cost, way.name)
            annex_edges.append((start_node.id, end_node.id, way_attrs))
            if not way.oneway_bicycle:
                annex_edges.append((end_node.id, start_node.id, way_attrs))

            split_ways[way.id] = way

        try:
            result = client.find_path(start.id,
                                      end.id,
                                      annex_edges=annex_edges,
                                      cost_func=cost_func,
                                      heuristic_func=heuristic_func,
                                      fields=('nodes', 'edges'))
        except ClientError as exc:
            status_code = exc.response.status_code
            data = exc.response.json()
            detail = data['detail']
            if status_code == 400:
                raise InputError(detail)
            if status_code == 404:
                raise NoRouteError(start_result, end_result)
            raise

        nodes = result['nodes']
        edges = [edge[0] for edge in result['edges']]

        assert nodes[
            0] == start.id, f'Expected route start node ID: {start.id}; got {nodes[0]}'
        assert nodes[
            -1] == end.id, f'Expected route end node ID: {start.id}; got {nodes[-1]}'

        return nodes, edges, split_ways