Пример #1
0
 def test_points_too_far(self):
     proj = utils.get_orthographic_projection(180, 180, 45, 45)
     with self.assertRaises(ValueError) as ar:
         proj(90, -45)
     self.assertEqual(ar.exception.message,
                      'some points are too far from the projection '
                      'center lon=180.0 lat=45.0')
Пример #2
0
 def test_points_too_far(self):
     proj = utils.get_orthographic_projection(180, 180, 45, 45)
     with self.assertRaises(ValueError) as ar:
         proj(90, -45)
     self.assertEqual(
         ar.exception.message,
         'some points are too far from the projection '
         'center lon=180.0 lat=45.0')
Пример #3
0
 def test_projection(self):
     # values verified against pyproj's implementation
     proj = utils.get_orthographic_projection(10, 16, -2, 30)
     lons = numpy.array([10., 20., 30., 40.])
     lats = numpy.array([-1., -2., -3., -4.])
     xx, yy = proj(lons, lats)
     exx = [-309.89151465, 800.52541443, 1885.04014687, 2909.78079661]
     eyy = [-1650.93260348, -1747.79256663, -1797.62444771, -1802.28117183]
     self.assertTrue(numpy.allclose(xx, exx, atol=0.01, rtol=0.005))
     self.assertTrue(numpy.allclose(yy, eyy, atol=0.01, rtol=0.005))
Пример #4
0
 def test_projection(self):
     # values verified against pyproj's implementation
     proj = utils.get_orthographic_projection(10, 16, -2, 30)
     lons = numpy.array([10., 20., 30., 40.])
     lats = numpy.array([-1., -2., -3., -4.])
     xx, yy = proj(lons, lats)
     exx = [-309.89151465, 800.52541443, 1885.04014687, 2909.78079661]
     eyy = [-1650.93260348, -1747.79256663, -1797.62444771, -1802.28117183]
     self.assertTrue(numpy.allclose(xx, exx, atol=0.01, rtol=0.005))
     self.assertTrue(numpy.allclose(yy, eyy, atol=0.01, rtol=0.005))
Пример #5
0
 def test_projecting_back_and_forth(self):
     lon0, lat0 = -10.4, 20.3
     proj = utils.get_orthographic_projection(lon0, lat0, lon0, lat0)
     lons = lon0 + (numpy.random.random((20, 10)) * 50 - 25)
     lats = lat0 + (numpy.random.random((20, 10)) * 50 - 25)
     xx, yy = proj(lons, lats, reverse=False)
     self.assertEqual(xx.shape, (20, 10))
     self.assertEqual(yy.shape, (20, 10))
     blons, blats = proj(xx, yy, reverse=True)
     self.assertTrue(numpy.allclose(blons, lons))
     self.assertTrue(numpy.allclose(blats, lats))
Пример #6
0
 def test_projecting_back_and_forth(self):
     lon0, lat0 = -10.4, 20.3
     proj = utils.get_orthographic_projection(lon0, lat0, lon0, lat0)
     lons = lon0 + (numpy.random.random((20, 10)) * 50 - 25)
     lats = lat0 + (numpy.random.random((20, 10)) * 50 - 25)
     xx, yy = proj(lons, lats, reverse=False)
     self.assertEqual(xx.shape, (20, 10))
     self.assertEqual(yy.shape, (20, 10))
     blons, blats = proj(xx, yy, reverse=True)
     self.assertTrue(numpy.allclose(blons, lons))
     self.assertTrue(numpy.allclose(blats, lats))
Пример #7
0
    def _get_proj_enclosing_polygon(self):
        """
        See :meth:`Mesh._get_proj_enclosing_polygon`.

        :class:`RectangularMesh` contains an information about relative
        positions of points, so it allows to define the minimum polygon,
        containing the projection of the mesh, which doesn't necessarily
        have to be convex (in contrast to :class:`Mesh` implementation).

        :returns:
            Same structure as :meth:`Mesh._get_proj_convex_hull`.
        """
        if self.lons.size < 4:
            # the mesh doesn't contain even a single cell, use :class:`Mesh`
            # method implementation (which would dilate the point or the line)
            return super(RectangularMesh, self)._get_proj_enclosing_polygon()

        proj = geo_utils.get_orthographic_projection(
            *geo_utils.get_spherical_bounding_box(self.lons, self.lats)
        )
        mesh2d = numpy.array(proj(self.lons.transpose(),
                                  self.lats.transpose())).transpose()
        lines = iter(mesh2d)
        # we iterate over horizontal stripes, keeping the "previous"
        # line of points. we keep it reversed, such that together
        # with the current line they define the sequence of points
        # around the stripe.
        prev_line = lines.next()[::-1]
        polygons = []
        for i, line in enumerate(lines):
            coords = numpy.concatenate((prev_line, line, prev_line[0:1]))
            # create the shapely polygon object from the stripe
            # coordinates and simplify it (remove redundant points,
            # if there are any lying on the straight line).
            stripe = shapely.geometry.LineString(coords) \
                                     .simplify(self.DIST_TOLERANCE) \
                                     .buffer(self.DIST_TOLERANCE, 2)
            polygons.append(shapely.geometry.Polygon(stripe.exterior))
            prev_line = line[::-1]
        # create a final polygon as the union of all the stripe ones
        polygon = shapely.ops.cascaded_union(polygons) \
                             .simplify(self.DIST_TOLERANCE)
        return proj, polygon
Пример #8
0
    def _get_proj_enclosing_polygon(self):
        """
        See :meth:`Mesh._get_proj_enclosing_polygon`.

        :class:`RectangularMesh` contains an information about relative
        positions of points, so it allows to define the minimum polygon,
        containing the projection of the mesh, which doesn't necessarily
        have to be convex (in contrast to :class:`Mesh` implementation).

        :returns:
            Same structure as :meth:`Mesh._get_proj_convex_hull`.
        """
        if self.lons.size < 4:
            # the mesh doesn't contain even a single cell, use :class:`Mesh`
            # method implementation (which would dilate the point or the line)
            return super(RectangularMesh, self)._get_proj_enclosing_polygon()

        proj = geo_utils.get_orthographic_projection(
            *geo_utils.get_spherical_bounding_box(self.lons, self.lats))
        mesh2d = numpy.array(proj(self.lons.transpose(),
                                  self.lats.transpose())).transpose()
        lines = iter(mesh2d)
        # we iterate over horizontal stripes, keeping the "previous"
        # line of points. we keep it reversed, such that together
        # with the current line they define the sequence of points
        # around the stripe.
        prev_line = lines.next()[::-1]
        polygons = []
        for i, line in enumerate(lines):
            coords = numpy.concatenate((prev_line, line, prev_line[0:1]))
            # create the shapely polygon object from the stripe
            # coordinates and simplify it (remove redundant points,
            # if there are any lying on the straight line).
            stripe = shapely.geometry.LineString(coords) \
                                     .simplify(self.DIST_TOLERANCE) \
                                     .buffer(self.DIST_TOLERANCE, 2)
            polygons.append(shapely.geometry.Polygon(stripe.exterior))
            prev_line = line[::-1]
        # create a final polygon as the union of all the stripe ones
        polygon = shapely.ops.cascaded_union(polygons) \
                             .simplify(self.DIST_TOLERANCE)
        return proj, polygon
Пример #9
0
    def test(self):
        polygon2d = shapely.geometry.Polygon([
            (-12, 0), (0, 14.5), (17.1, 3), (18, 0), (16.5, -3), (0, -10)
        ])
        proj = geo_utils.get_orthographic_projection(0, 0, 0, 0)
        poly = polygon.Polygon._from_2d(polygon2d, proj)
        elons = [-0.10791866, 0., 0.1537842, 0.1618781, 0.14838825, 0.]
        elats = [0., 0.13040175, 0.02697965, 0., -0.02697965, -0.0899322]
        ebbox = [-0.10791866, 0.1618781, 0.13040175, -0.0899322]
        numpy.testing.assert_allclose(poly.lons, elons)
        numpy.testing.assert_allclose(poly.lats, elats)
        numpy.testing.assert_allclose(poly._bbox, ebbox)
        self.assertIs(poly._polygon2d, polygon2d)
        self.assertIs(poly._projection, proj)

        poly = polygon.Polygon._from_2d(poly._polygon2d, poly._projection)
        numpy.testing.assert_allclose(poly.lons, elons)
        numpy.testing.assert_allclose(poly.lats, elats)
        numpy.testing.assert_allclose(poly._bbox, ebbox)
        self.assertIs(poly._polygon2d, polygon2d)
        self.assertIs(poly._projection, proj)
Пример #10
0
    def test(self):
        polygon2d = shapely.geometry.Polygon([
            (-12, 0), (0, 14.5), (17.1, 3), (18, 0), (16.5, -3), (0, -10)
        ])
        proj = geo_utils.get_orthographic_projection(0, 0, 0, 0)
        poly = polygon.Polygon._from_2d(polygon2d, proj)
        elons = [-0.10791866, 0., 0.1537842, 0.1618781, 0.14838825, 0.]
        elats = [0., 0.13040175, 0.02697965, 0., -0.02697965, -0.0899322]
        ebbox = [-0.10791866, 0.1618781, 0.13040175, -0.0899322]
        numpy.testing.assert_allclose(poly.lons, elons)
        numpy.testing.assert_allclose(poly.lats, elats)
        numpy.testing.assert_allclose(poly._bbox, ebbox)
        self.assertIs(poly._polygon2d, polygon2d)
        self.assertIs(poly._projection, proj)

        poly = polygon.Polygon._from_2d(poly._polygon2d, poly._projection)
        numpy.testing.assert_allclose(poly.lons, elons)
        numpy.testing.assert_allclose(poly.lats, elats)
        numpy.testing.assert_allclose(poly._bbox, ebbox)
        self.assertIs(poly._polygon2d, polygon2d)
        self.assertIs(poly._projection, proj)
Пример #11
0
    def to_polygon(self, radius):
        """
        Create a circular polygon with specified radius centered in the point.

        :param radius:
            Required radius of a new polygon, in km.
        :returns:
            Instance of :class:`~nhlib.geo.polygon.Polygon` that approximates
            a circle around the point with specified radius.
        """
        assert radius > 0
        # avoid circular imports
        from nhlib.geo.polygon import Polygon
        # get a projection that is centered in the point
        proj = geo_utils.get_orthographic_projection(
            self.longitude, self.longitude, self.latitude, self.latitude
        )
        # create a shapely object from a projected point coordinates,
        # which are supposedly (0, 0)
        point = shapely.geometry.Point(*proj(self.longitude, self.latitude))
        # extend the point to a shapely polygon using buffer()
        # and create nhlib.geo.polygon.Polygon object from it
        return Polygon._from_2d(point.buffer(radius), proj)
Пример #12
0
    def _init_polygon2d(self):
        """
        Spherical bounding box, projection, and Cartesian polygon are all
        cached to prevent redundant computations.

        If any of them are `None`, recalculate all of them.
        """
        if (self._polygon2d is None or self._projection is None
                or self._bbox is None):
            # resample polygon line segments:
            lons, lats = get_resampled_coordinates(self.lons, self.lats)

            # find the bounding box of a polygon in spherical coordinates:
            self._bbox = utils.get_spherical_bounding_box(lons, lats)

            # create a projection that is centered in a polygon center:
            self._projection = \
                utils.get_orthographic_projection(*self._bbox)

            # project polygon vertices to the Cartesian space and create
            # a shapely polygon object:
            xx, yy = self._projection(lons, lats)
            self._polygon2d = shapely.geometry.Polygon(zip(xx, yy))
Пример #13
0
    def _init_polygon2d(self):
        """
        Spherical bounding box, projection, and Cartesian polygon are all
        cached to prevent redundant computations.

        If any of them are `None`, recalculate all of them.
        """
        if (self._polygon2d is None or self._projection is None
            or self._bbox is None):
            # resample polygon line segments:
            lons, lats = get_resampled_coordinates(self.lons, self.lats)

            # find the bounding box of a polygon in spherical coordinates:
            self._bbox = utils.get_spherical_bounding_box(lons, lats)

            # create a projection that is centered in a polygon center:
            self._projection = \
                utils.get_orthographic_projection(*self._bbox)

            # project polygon vertices to the Cartesian space and create
            # a shapely polygon object:
            xx, yy = self._projection(lons, lats)
            self._polygon2d = shapely.geometry.Polygon(zip(xx, yy))
Пример #14
0
    def _get_proj_convex_hull(self):
        """
        Create a projection centered in the center of this mesh and define
        a convex polygon in that projection, enveloping all the points
        of the mesh.

        :returns:
            Tuple of two items: projection function and shapely 2d polygon.
            Note that the result geometry can be line or point depending
            on number of points in the mesh and their arrangement.
        """
        # create a projection centered in the center of points collection
        proj = geo_utils.get_orthographic_projection(
            *geo_utils.get_spherical_bounding_box(self.lons, self.lats))
        # project all the points and create a shapely multipoint object.
        # need to copy an array because otherwise shapely misinterprets it
        coords = numpy.transpose(proj(self.lons.flatten(),
                                      self.lats.flatten())).copy()
        multipoint = shapely.geometry.MultiPoint(coords)
        # create a 2d polygon from a convex hull around that multipoint.
        polygon2d = multipoint.convex_hull

        return proj, polygon2d
Пример #15
0
    def to_polygon(self, radius):
        """
        Create a circular polygon with specified radius centered in the point.

        :param radius:
            Required radius of a new polygon, in km.
        :returns:
            Instance of :class:`~nhlib.geo.polygon.Polygon` that approximates
            a circle around the point with specified radius.
        """
        assert radius > 0
        # avoid circular imports
        from nhlib.geo.polygon import Polygon
        # get a projection that is centered in the point
        proj = geo_utils.get_orthographic_projection(self.longitude,
                                                     self.longitude,
                                                     self.latitude,
                                                     self.latitude)
        # create a shapely object from a projected point coordinates,
        # which are supposedly (0, 0)
        point = shapely.geometry.Point(*proj(self.longitude, self.latitude))
        # extend the point to a shapely polygon using buffer()
        # and create nhlib.geo.polygon.Polygon object from it
        return Polygon._from_2d(point.buffer(radius), proj)
Пример #16
0
    def _get_proj_convex_hull(self):
        """
        Create a projection centered in the center of this mesh and define
        a convex polygon in that projection, enveloping all the points
        of the mesh.

        :returns:
            Tuple of two items: projection function and shapely 2d polygon.
            Note that the result geometry can be line or point depending
            on number of points in the mesh and their arrangement.
        """
        # create a projection centered in the center of points collection
        proj = geo_utils.get_orthographic_projection(
            *geo_utils.get_spherical_bounding_box(self.lons, self.lats)
        )
        # project all the points and create a shapely multipoint object.
        # need to copy an array because otherwise shapely misinterprets it
        coords = numpy.transpose(proj(self.lons.flatten(),
                                      self.lats.flatten())).copy()
        multipoint = shapely.geometry.MultiPoint(coords)
        # create a 2d polygon from a convex hull around that multipoint.
        polygon2d = multipoint.convex_hull

        return proj, polygon2d