Beispiel #1
0
 def _should_unwrap_geom_(self, geom):
     # Loop through the polygons determining if any coordinates need to be shifted and flag accordingly.
     ret = False
     for polygon in iter_exploded_geometries(geom):
         coords = np.array(polygon.exterior.coords)
         if np.any(coords[:, 0] < self.center_axis):
             ret = True
             break
     return ret
Beispiel #2
0
    def unwrap(self, geom):
        """
        :param geom: The target geometry to unwrap (i.e. move to 0 to 360 spatial domain).
        :type geom: :class:`shapely.geometry.base.BaseGeometry`
        :rtype: :class:`shapely.geometry.base.BaseGeometry`
        """

        if type(geom) in [MultiPoint, Point]:
            return self._unwrap_point_(geom)

        assert type(geom) in [Polygon, MultiPolygon]

        # Wrap the polygon if requested.
        if self._should_unwrap_geom_(geom):
            # Loop through individual polygon components. Doing this operation on multi-polygons causes unexpected
            # behavior due to potential invalid geometries.
            processed_geometries = []
            for ctr, to_process in enumerate(iter_exploded_geometries(geom)):
                try:
                    assert to_process.is_valid
                except AssertionError:
                    # Attempt a simple buffering trick to make the geometry valid.
                    to_process = to_process.buffer(0)
                    assert to_process.is_valid
                assert isinstance(to_process, Polygon)

                # Intersection with the two regions.
                if self._should_unwrap_geom_(to_process):
                    left = to_process.intersection(self.clip1)
                    right = to_process.intersection(self.clip2)

                    # Pull out the right side polygons.
                    right_polygons = [
                        poly for poly in iter_exploded_geometries(right)
                    ]

                    # Adjust polygons falling the left window.
                    if isinstance(left, Polygon):
                        left_polygons = [self._unwrap_shift_(left)]
                    else:
                        left_polygons = []
                        for polygon in left:
                            left_polygons.append(self._unwrap_shift_(polygon))

                    # Merge polygons into single unit.
                    try:
                        processed = MultiPolygon(left_polygons +
                                                 right_polygons)
                    except TypeError:
                        left = [
                            x for x in left_polygons if type(x) != LineString
                        ]
                        right = [
                            x for x in right_polygons if type(x) != LineString
                        ]
                        processed = MultiPolygon(left + right)

                else:
                    if isinstance(to_process, Polygon):
                        processed = [to_process]
                    else:
                        processed = to_process
                # Return a single polygon if the output multi-geometry has only one component. Otherwise, explode the
                # multi-geometry.

                if len(processed) == 1:
                    processed = [processed[0]]
                else:
                    processed = [i for i in processed]

                # Hold for final adjustment.
                processed_geometries += processed

            # Convert to a multigeometry if there is more than one output.
            if len(processed_geometries) > 1:
                # HACK: Union geometries to avoid some potential issues with multi-geometries.
                # ret = cascaded_union(processed_geometries)
                ret = MultiPolygon(processed_geometries)
                # assert ret.is_valid
            else:
                ret = processed_geometries[0]

        # If polygon does not need adjustment, just return it.
        else:
            ret = geom

        return ret
Beispiel #3
0
    def wrap(self, geom):
        """
        :param geom: The target geometry to adjust.
        :type geom: :class:`shapely.geometry.base.BaseGeometry`
        :rtype: :class:`shapely.geometry.base.BaseGeometry`
        """
        def _shift_(geom):
            try:
                coords = np.array(geom.exterior.coords)
                coords[:, 0] = coords[:, 0] - 360
                ret = Polygon(coords)
            # Likely a MultiPolygon.
            except AttributeError:
                polygons = np.empty(len(geom), dtype=object)
                for ii, polygon in enumerate(geom):
                    coords = np.array(polygon.exterior.coords)
                    coords[:, 0] = coords[:, 0] - 360
                    polygons[ii] = Polygon(coords)
                ret = MultiPolygon(list(polygons))
            return ret

        if isinstance(geom, (Polygon, MultiPolygon)):
            bounds = np.array(geom.bounds)
            # If the polygon column bounds are both greater than 180 degrees shift the coordinates of the entire
            # polygon.
            if np.all([bounds[0] > self.wrap_axis,
                       bounds[2] > self.wrap_axis]):
                new_geom = _shift_(geom)
            # If a polygon crosses the 180 axis, then the polygon will need to be split with intersection and
            # recombined.
            elif bounds[1] <= self.wrap_axis < bounds[2]:
                left = [
                    poly for poly in iter_exploded_geometries(
                        geom.intersection(self.left_clip))
                ]
                right = [
                    poly for poly in iter_exploded_geometries(
                        _shift_(geom.intersection(self.right_clip)))
                ]
                try:
                    new_geom = MultiPolygon(left + right)
                except TypeError:
                    left = [x for x in left if type(x) != LineString]
                    right = [x for x in right if type(x) != LineString]
                    new_geom = MultiPolygon(left + right)
            # Otherwise, the polygon coordinates are not affected by wrapping and the geometry may be passed through.
            else:
                new_geom = geom
        # Likely a point type object.
        else:
            if isinstance(geom, Point):
                if geom.x > 180:
                    new_geom = Point(geom.x - 360, geom.y)
                else:
                    new_geom = geom
            # Likely a MultiPoint.
            elif isinstance(geom, MultiPoint):
                points = [None] * len(geom)
                for ii, point in enumerate(geom):
                    if point.x > 180:
                        new_point = Point(point.x - 360, point.y)
                    else:
                        new_point = point
                    points[ii] = new_point
                new_geom = MultiPoint(points)
            else:
                raise NotImplementedError(geom)

        return new_geom