示例#1
0
    def _readboundarydata(self, name, as_polygons=False):
        from models import aacgm
        from copy import deepcopy
        import _geoslib
        import numpy as np

        if self.coords is 'mag':
            nPts = len(self._boundarypolyll.boundary[:, 0])
            lats, lons, _ = aacgm.aacgmConvArr(
                list(self._boundarypolyll.boundary[:, 1]),
                list(self._boundarypolyll.boundary[:, 0]), [0.] * nPts,
                self.datetime.year, 1)
            b = np.asarray([lons, lats]).T
            oldgeom = deepcopy(self._boundarypolyll)
            newgeom = _geoslib.Polygon(b).fix()
            self._boundarypolyll = newgeom
            out = basemap.Basemap._readboundarydata(self,
                                                    name,
                                                    as_polygons=as_polygons)
            self._boundarypolyll = oldgeom
            return out
        else:
            return basemap.Basemap._readboundarydata(self,
                                                     name,
                                                     as_polygons=as_polygons)
示例#2
0
 def _readboundarydata(self, name, as_polygons=False):
     from copy import deepcopy
     import _geoslib
     import numpy as np
 
     from davitpy.utils import coord_conv
 
     lons, lats = coord_conv(list(self._boundarypolyll.boundary[:, 0]),
                             list(self._boundarypolyll.boundary[:, 1]),
                             self.coords, "geo", altitude=0.,
                             date_time=self.datetime)
     b = np.asarray([lons,lats]).T
     oldgeom = deepcopy(self._boundarypolyll)
     newgeom = _geoslib.Polygon(b).fix()
     self._boundarypolyll = newgeom
     out = basemap.Basemap._readboundarydata(self, name,
                                             as_polygons=as_polygons)
     self._boundarypolyll = oldgeom
     return out
示例#3
0
def cut_prime_meridian(vertices):
    """Cut a polygon across the prime meridian, possibly splitting it into multiple
    polygons.  Vertices consist of (longitude, latitude) pairs where longitude
    is always given in terms of a wrapped angle (between 0 and 2*pi).

    This routine is not meant to cover all possible cases; it will only work for
    convex polygons that extend over less than a hemisphere."""

    out_vertices = []

    # Ensure that the list of vertices does not contain a repeated endpoint.
    if (vertices[0, :] == vertices[-1, :]).all():
        vertices = vertices[:-1, :]

    # Ensure that the longitudes are wrapped from 0 to 2*pi.
    vertices = np.column_stack((wrapped_angle(vertices[:, 0]), vertices[:, 1]))

    def count_meridian_crossings(phis):
        n = 0
        for i in range(len(phis)):
            if crosses_meridian(phis[i - 1], phis[i]):
                n += 1
        return n

    def crosses_meridian(phi0, phi1):
        """Test if the segment consisting of v0 and v1 croses the meridian."""
        # If the two angles are in [0, 2pi), then the shortest arc connecting
        # them crosses the meridian if the difference of the angles is greater
        # than pi.
        phi0, phi1 = sorted((phi0, phi1))
        return phi1 - phi0 > np.pi

    # Count the number of times that the polygon crosses the meridian.
    meridian_crossings = count_meridian_crossings(vertices[:, 0])

    if meridian_crossings % 2:
        # FIXME: Use this simple heuristic to decide which pole to enclose.
        sign_lat = np.sign(np.sum(vertices[:, 1]))

        # If there are an odd number of meridian crossings, then the polygon
        # encloses the pole. Any meridian-crossing edge has to be extended
        # into a curve following the nearest polar edge of the map.
        for i in range(len(vertices)):
            v0 = vertices[i - 1, :]
            v1 = vertices[i, :]
            # Loop through the edges until we find one that crosses the meridian.
            if crosses_meridian(v0[0], v1[0]):
                # If this segment crosses the meridian, then fill it to
                # the edge of the map by inserting new line segments.

                # Find the latitude at which the meridian crossing occurs by
                # linear interpolation.
                delta_lon = abs(reference_angle(v1[0] - v0[0]))
                lat = abs(reference_angle(v0[0])) / delta_lon * v0[1] + abs(
                    reference_angle(v1[0])) / delta_lon * v1[1]

                # Find the closer of the left or the right map boundary for
                # each vertex in the line segment.
                lon_0 = 0. if v0[0] < np.pi else 2 * np.pi
                lon_1 = 0. if v1[0] < np.pi else 2 * np.pi

                # Set the output vertices to the polar cap plus the original
                # vertices.
                out_vertices += [
                    np.vstack((vertices[:i, :], [
                        [lon_0, lat],
                        [lon_0, sign_lat * np.pi / 2],
                        [lon_1, sign_lat * np.pi / 2],
                        [lon_1, lat],
                    ], vertices[i:, :]))
                ]

                # Since the polygon is assumed to be convex, the only possible
                # odd number of meridian crossings is 1, so we are now done.
                break
    elif meridian_crossings:
        # Since the polygon is assumed to be convex, if there is an even number
        # of meridian crossings, we know that the polygon does not enclose
        # either pole. Then we can use ordinary Euclidean polygon intersection
        # algorithms.

        # Construct polygon representing map boundaries in longitude and latitude.
        frame_poly = geos.Polygon(
            np.asarray([[0., np.pi / 2], [0., -np.pi / 2],
                        [2 * np.pi, -np.pi / 2], [2 * np.pi, np.pi / 2]]))

        # Intersect with polygon re-wrapped to lie in [pi, 3*pi).
        poly = geos.Polygon(
            np.column_stack(
                (reference_angle(vertices[:, 0]) + 2 * np.pi, vertices[:, 1])))
        if poly.intersects(frame_poly):
            out_vertices += [
                p.get_coords() for p in poly.intersection(frame_poly)
            ]

        # Intersect with polygon re-wrapped to lie in [-pi, pi).
        poly = geos.Polygon(
            np.column_stack((reference_angle(vertices[:, 0]), vertices[:, 1])))
        if poly.intersects(frame_poly):
            out_vertices += [
                p.get_coords() for p in poly.intersection(frame_poly)
            ]
    else:
        # Otherwise, there were zero meridian crossings, so we can use the
        # original vertices as is.
        out_vertices += [vertices]

    # Done!
    return out_vertices
示例#4
0
def cut_dateline(vertices):
    """Cut a polygon across the dateline, possibly splitting it into multiple
    polygons.  Vertices consist of (longitude, latitude) pairs where longitude
    is always given in terms of a reference angle (between -pi and pi).

    This routine is not meant to cover all possible cases; it will only work for
    convex polygons that extend over less than a hemisphere."""

    out_vertices = []

    # Ensure that the list of vertices does not contain a repeated endpoint.
    if (vertices[0, :] == vertices[-1, :]).all():
        vertices = vertices[:-1, :]

    def count_dateline_crossings(phis):
        n = 0
        for i in range(len(phis)):
            if crosses_dateline(phis[i - 1], phis[i]):
                n += 1
        return n

    def crosses_dateline(phi0, phi1):
        """Test if the segment consisting of v0 and v1 croses the meridian."""
        phi0, phi1 = sorted((phi0, phi1))
        return phi1 - phi0 > np.pi

    dateline_crossings = count_dateline_crossings(vertices[:, 0])
    if dateline_crossings % 2:
        # FIXME: Use this simple heuristic to decide which pole to enclose.
        sign_lat = np.sign(np.sum(vertices[:, 1]))

        # Determine index of the (unique) line segment that crosses the dateline.
        for i in range(len(vertices)):
            v0 = vertices[i - 1, :]
            v1 = vertices[i, :]
            if crosses_dateline(v0[0], v1[0]):
                delta_lat = abs(reference_angle(v1[0] - v0[0]))
                lat = (np.pi - abs(v0[0])) / delta_lat * v0[1] + (
                    np.pi - abs(v1[0])) / delta_lat * v1[1]
                out_vertices += [
                    np.vstack((vertices[:i, :], [
                        [np.sign(v0[0]) * np.pi, lat],
                        [np.sign(v0[0]) * np.pi, sign_lat * np.pi / 2],
                        [-np.sign(v0[0]) * np.pi, sign_lat * np.pi / 2],
                        [-np.sign(v0[0]) * np.pi, lat],
                    ], vertices[i:, :]))
                ]
                break
    elif dateline_crossings:
        frame_poly = geos.Polygon(
            np.asarray([[-np.pi, np.pi / 2], [-np.pi, -np.pi / 2],
                        [np.pi, -np.pi / 2], [np.pi, np.pi / 2]]))
        poly = geos.Polygon(
            np.column_stack((vertices[:, 0] % (2 * np.pi), vertices[:, 1])))
        if poly.intersects(frame_poly):
            out_vertices += [
                p.get_coords() for p in poly.intersection(frame_poly)
            ]
        poly = geos.Polygon(
            np.column_stack((vertices[:, 0] % (-2 * np.pi), vertices[:, 1])))
        if poly.intersects(frame_poly):
            out_vertices += [
                p.get_coords() for p in poly.intersection(frame_poly)
            ]
    else:
        out_vertices += [vertices]

    return out_vertices