Example #1
0
File: mesh.py Project: pslh/nhlib
    def get_convex_hull(self):
        """
        Get a convex polygon object that contains projections of all the points
        of the mesh.

        :returns:
            Instance of :class:`nhlib.geo.polygon.Polygon` that is a convex
            hull around all the points in this mesh. If the original mesh
            had only one point, the resulting polygon has a square shape
            with a side length of 10 meters. If there were only two points,
            resulting polygon is a stripe 10 meters wide.
        """
        # avoid circular imports
        from nhlib.geo.polygon import Polygon
        # 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, self.lats)).copy()
        multipoint = shapely.geometry.MultiPoint(coords)
        # create a 2d polygon from a convex hull around that multipoint
        polygon2d = multipoint.convex_hull
        # if mesh had only one point, the convex hull is a point. if there
        # were two, it is a line string. we need to return a convex polygon
        # object, so extend that area-less geometries by some arbitrarily
        # small distance, like five meters.
        if isinstance(polygon2d, (shapely.geometry.LineString,
                                  shapely.geometry.Point)):
            polygon2d = polygon2d.buffer(0.005, 1)
        return Polygon._from_2d(polygon2d, proj)
Example #2
0
    def _from_2d(cls, polygon2d, proj):
        """
        Create a polygon object from a 2d polygon and a projection.

        :param polygon2d:
            Instance of ``shapely.geometry.Polygon``.
        :param proj:
            Projection object created
            by :func:`~nhlib.geo._utils.get_orthographic_projection`
            that was used to project ``polygon2d``. That projection
            will be used for projecting it back to get spherical
            coordinates from Cartesian ones.
        :returns:
            New :class:`Polygon` object. Note that spherical coordinates
            of that polygon do not get upsampled even for longer edges.
        """
        # avoid calling class' constructor
        polygon = object.__new__(cls)
        # project polygon2d back on the sphere
        xx, yy = numpy.transpose(polygon2d.boundary.coords)
        # need to cut off the last point -- it repeats the first one
        polygon.lons, polygon.lats = proj(xx[:-1], yy[:-1], reverse=True)
        # initialize the instance (as constructor would do)
        polygon._bbox = utils.get_spherical_bounding_box(polygon.lons,
                                                         polygon.lats)
        polygon._polygon2d = polygon2d
        polygon._projection = proj
        return polygon
Example #3
0
def get_polygon_area(polygon):
    """
	Compute polygon area in squared kilometers.
	"""
    lons = [lon for lon, lat in polygon]
    lats = [lat for lon, lat in polygon]

    west, east, north, south = _utils.get_spherical_bounding_box(lons, lats)
    proj = _utils.get_orthographic_projection(west, east, north, south)
    xx, yy = proj(lons, lats)

    polygon2d = shapely.geometry.Polygon(zip(xx, yy))

    return polygon2d.area
def get_polygon_area(polygon):
	"""
	Compute polygon area in squared kilometers.
	"""
	lons = [lon for lon,lat in polygon]
	lats = [lat for lon,lat in polygon]
	
	west, east, north, south = _utils.get_spherical_bounding_box(lons, lats)
	proj = _utils.get_orthographic_projection(west, east, north, south)
	xx, yy = proj(lons, lats)
	
	polygon2d = shapely.geometry.Polygon(zip(xx, yy))
	
	return polygon2d.area
Example #5
0
File: mesh.py Project: pslh/nhlib
    def get_joyner_boore_distance(self, mesh):
        """
        Compute and return Joyner-Boore distance to each point of ``mesh``.
        Point's depth is ignored.

        See :meth:`nhlib.geo.surface.BaseSurface.get_joyner_boore_distance`
        for definition of this distance.

        :returns:
            numpy array of distances in km of the same shape as ``mesh``.
            Distance value is considered to be zero if a point
            lies inside the polygon enveloping the projection of the mesh
            or on one of its edges.
        """
        bounding_mesh = self._get_bounding_mesh(with_depths=False)
        assert bounding_mesh.depths is None
        lons, lats = bounding_mesh.lons, bounding_mesh.lats
        depths = numpy.zeros_like(lons)
        proj = geo_utils.get_orthographic_projection(
            *geo_utils.get_spherical_bounding_box(lons, lats)
        )
        xx, yy = proj(lons, lats)
        mesh_2d = numpy.array([xx, yy], dtype=float).transpose().copy()
        if len(xx) == 2:
            mesh_2d = shapely.geometry.LineString(mesh_2d)
        elif len(xx) == 1:
            mesh_2d = shapely.geometry.Point(*mesh_2d)
        elif len(xx) > 2:
            mesh_2d = shapely.geometry.Polygon(mesh_2d)
        mesh_lons, mesh_lats = mesh.lons.flatten(), mesh.lats.flatten()
        mesh_xx, mesh_yy = proj(mesh_lons, mesh_lats)

        distances = []
        for i in xrange(len(mesh_lons)):
            point_2d = shapely.geometry.Point(mesh_xx[i], mesh_yy[i])
            dist = mesh_2d.distance(point_2d)
            if dist < 500:
                # if the distance is below threshold of 500 kilometers,
                # consider the distance measured on the projection accurate
                # enough (an error doesn't exceed half km).
                distances.append(dist)
            else:
                # ... otherwise get the precise distance between bounding mesh
                # projection and the point projection using pure numerical way
                distances.append(geodetic.min_distance(
                    lons, lats, depths, mesh_lons[i], mesh_lats[i], 0
                ))
        return numpy.array(distances).reshape(mesh.shape)
Example #6
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))