Exemplo n.º 1
0
 def bbox(self):
     """Compute the smallest rectangle that contains the entire track (border box)."""
     bbox = s2.LatLngRect()
     for line in self.polylines:
         for latlng in line:
             bbox = bbox.union(s2.LatLngRect.from_point(latlng.normalized()))
     return bbox
Exemplo n.º 2
0
def make_clusters(flights: List[api.Flight], view_min: s2sphere.LatLng,
                  view_max: s2sphere.LatLng) -> List[api.Cluster]:
    if not flights:
        return []

    # Make the initial cluster
    points: List[Point] = [
        Point(*geo.flatten(
            view_min,
            s2sphere.LatLng.from_degrees(flight.most_recent_position.lat,
                                         flight.most_recent_position.lng)))
        for flight in flights
    ]
    x_max, y_max = geo.flatten(view_min, view_max)
    clusters: List[Cluster] = [
        Cluster(x_min=0, y_min=0, x_max=x_max, y_max=y_max, points=points)
    ]

    # TODO: subdivide cluster into many clusters

    result: List[api.Cluster] = []
    for cluster in clusters:
        cluster = cluster.randomize()
        p1 = geo.unflatten(view_min, (cluster.x_min, cluster.y_min))
        p2 = geo.unflatten(view_min, (cluster.x_max, cluster.y_max))
        result.append(
            api.Cluster(corners=[
                api.Position(lat=p1.lat().degrees, lng=p1.lng().degrees),
                api.Position(lat=p2.lat().degrees, lng=p2.lng().degrees)
            ],
                        area_sqm=geo.area_of_latlngrect(
                            s2sphere.LatLngRect(p1, p2)),
                        number_of_flights=len(cluster.points)))

    return result
Exemplo n.º 3
0
    def _determine_bbox(self) -> s2sphere.LatLngRect:
        if self._center:
            log.info("Forcing heatmap center to %s", str(self._center))
            dlat, dlng = 0, 0
            if self._radius:
                er = 6378.1
                quarter = er * math.pi / 2
                dlat = 90 * self._radius / quarter
                scale = 1 / math.cos(self._center.lat().radians)
                dlng = scale * 90 * self._radius / quarter
            else:
                for tr in self.poster.tracks:
                    for line in tr.polylines:
                        for latlng in line:
                            d = abs(self._center.lat().degrees -
                                    latlng.lat().degrees)
                            dlat = max(dlat, d)
                            d = abs(self._center.lng().degrees -
                                    latlng.lng().degrees)
                            while d > 360:
                                d -= 360
                            if d > 180:
                                d = 360 - d
                            dlng = max(dlng, d)
            return s2sphere.LatLngRect.from_center_size(
                self._center, s2sphere.LatLng.from_degrees(2 * dlat, 2 * dlng))

        tracks_bbox = s2sphere.LatLngRect()
        for tr in self.poster.tracks:
            tracks_bbox = tracks_bbox.union(tr.bbox())
        return tracks_bbox
Exemplo n.º 4
0
    def bounds(self) -> s2sphere.LatLngRect:
        """Return bounds of object

        :return: bounds of object
        :rtype: s2sphere.LatLngRect
        """
        return s2sphere.LatLngRect()
Exemplo n.º 5
0
 def _compute_bbox(self):
     self._bbox = s2sphere.LatLngRect()
     for segment in self._segments:
         for point in segment:
             b = s2sphere.LatLngRect.from_point(point._lat_lng)
             self._bbox = self._bbox.union(b)
     if not self._bbox.is_empty():
         self._bbox = self._bbox.expanded(
             s2sphere.LatLng.from_degrees(0.01, 0.01))
Exemplo n.º 6
0
 def object_bounds(self):
     if len(self._objects) == 0:
         return None
     bounds = s2.LatLngRect()
     print('bounds ', bounds)
     for obj in self._objects:
         bounds = bounds.union(obj.bounds())
     print('returned bounds ', bounds)
     return bounds
Exemplo n.º 7
0
    def bounds(self) -> s2sphere.LatLngRect:
        """Return bounds of line

        :return: bounds of line
        :rtype: s2sphere.LatLngRect
        """
        b = s2sphere.LatLngRect()
        for latlng in self.interpolate():
            b = b.union(s2sphere.LatLngRect.from_point(latlng.normalized()))
        return b
Exemplo n.º 8
0
    def _determine_zoom(self, width: int, height: int,
                        b: typing.Optional[s2sphere.LatLngRect],
                        c: s2sphere.LatLng) -> typing.Optional[int]:
        if b is None:
            b = s2sphere.LatLngRect(c, c)
        else:
            b = b.union(s2sphere.LatLngRect(c, c))
        assert b
        if b.is_point():
            return self._clamp_zoom(15)

        pixel_margin = self.extra_pixel_bounds()

        w = (width - pixel_margin[0] -
             pixel_margin[2]) / self._tile_provider.tile_size()
        h = (height - pixel_margin[1] -
             pixel_margin[3]) / self._tile_provider.tile_size()
        # margins are bigger than target image size => ignore them
        if w <= 0 or h <= 0:
            w = width / self._tile_provider.tile_size()
            h = height / self._tile_provider.tile_size()

        min_y = (1.0 - math.log(
            math.tan(b.lat_lo().radians) +
            (1.0 / math.cos(b.lat_lo().radians)))) / (2 * math.pi)
        max_y = (1.0 - math.log(
            math.tan(b.lat_hi().radians) +
            (1.0 / math.cos(b.lat_hi().radians)))) / (2 * math.pi)
        dx = (b.lng_hi().degrees - b.lng_lo().degrees) / 360.0
        if dx < 0:
            dx += math.ceil(math.fabs(dx))
        if dx > 1:
            dx -= math.floor(dx)
        dy = math.fabs(max_y - min_y)

        for zoom in range(1, self._tile_provider.max_zoom()):
            tiles = 2**zoom
            if (dx * tiles > w) or (dy * tiles > h):
                return self._clamp_zoom(zoom - 1)
        return self._clamp_zoom(15)
Exemplo n.º 9
0
def test_bounds() -> None:
    context = staticmaps.Context()
    assert context.object_bounds() is None

    context.add_object(staticmaps.Marker(staticmaps.create_latlng(48, 8)))
    bounds = context.object_bounds()
    assert bounds is not None
    assert bounds.is_point()

    context.add_object(staticmaps.Marker(staticmaps.create_latlng(47, 7)))
    assert context.object_bounds() is not None
    assert context.object_bounds() == s2sphere.LatLngRect(
        staticmaps.create_latlng(47, 7), staticmaps.create_latlng(48, 8))

    context.add_object(staticmaps.Marker(staticmaps.create_latlng(47.5, 7.5)))
    assert context.object_bounds() is not None
    assert context.object_bounds() == s2sphere.LatLngRect(
        staticmaps.create_latlng(47, 7), staticmaps.create_latlng(48, 8))

    context.add_bounds(
        s2sphere.LatLngRect(staticmaps.create_latlng(46, 6),
                            staticmaps.create_latlng(49, 9)))
    assert context.object_bounds() is not None
    assert context.object_bounds() == s2sphere.LatLngRect(
        staticmaps.create_latlng(46, 6), staticmaps.create_latlng(49, 9))

    context.add_bounds(
        s2sphere.LatLngRect(staticmaps.create_latlng(47.5, 7.5),
                            staticmaps.create_latlng(48, 8)))
    assert context.object_bounds() is not None
    assert context.object_bounds() == s2sphere.LatLngRect(
        staticmaps.create_latlng(47, 7), staticmaps.create_latlng(48, 8))
Exemplo n.º 10
0
    def object_bounds(self) -> typing.Optional[s2sphere.LatLngRect]:
        """return maximum bounds of all objects

        :return: maximum of all object bounds
        :rtype: s2sphere.LatLngRect
        """
        bounds = None
        if len(self._objects) != 0:
            bounds = s2sphere.LatLngRect()
            for obj in self._objects:
                assert bounds
                bounds = bounds.union(obj.bounds())
        return self._custom_bounds(bounds)
Exemplo n.º 11
0
 def determine_center_zoom(self, width, height):
     if self._center is not None:
         if self._zoom is not None:
             return self._center, self.clamp_zoom(self._zoom)
     b = self.object_bounds()
     if b is None:
         return self._center, self.clamp_zoom(self._zoom)
     if self._zoom is not None:
         return b.get_center(), self.clamp_zoom(self._zoom)
     if self._center is not None:
         b = b.union(s2.LatLngRect(self._center, self._center))
     if b.is_point():
         return b.get_center(), None
     tile_size = self._tile_provider.tile_size()
     # TODO: + extra margin pixels
     margin = 4
     w = (width - 2.0 * margin) / tile_size
     h = (height - 2.0 * margin) / tile_size
     minX = (b.lng_lo().degrees + 180.0) / 360.0
     maxX = (b.lng_hi().degrees + 180.0) / 360.0
     minY = (1.0 - math.log(
         math.tan(b.lat_lo().radians) +
         (1.0 / math.cos(b.lat_lo().radians))) / math.pi) / 2.0
     maxY = (1.0 - math.log(
         math.tan(b.lat_hi().radians) +
         (1.0 / math.cos(b.lat_hi().radians))) / math.pi) / 2.0
     print('in context determine zoom w h minX maxX minY maxY', w, h, minX,
           maxX, minY, maxY)
     dx = maxX - minX
     if dx < 0:
         dx += math.ceil(math.fabs(dx))
     if dx > 1:
         dx -= math.floor(dx)
     dy = math.fabs(maxY - minY)
     for zoom in range(1, self._tile_provider.max_zoom()):
         tiles = 2**zoom
         if (dx * tiles > w) or (dy * tiles > h):
             print('111 b.get_center(), zoom - 1 ', b.get_center(),
                   zoom - 1)
             return b.get_center(), zoom - 1
     print('222 b.get_center(), zoom - 1 ', b.get_center(), zoom - 1)
     return b.get_center(), self._tile_provider.max_zoom()
Exemplo n.º 12
0
 def bounds(self):
     return s2.LatLngRect()