def test_no_clip():
    """Geometry is within TilePyramid bounds."""
    tp = TilePyramid("geodetic")
    geometry = box(177.5, 67.5, -177.5, 73.125)

    # no multipart
    out_geom = clip_geometry_to_srs_bounds(geometry, tp)
    assert geometry == out_geom

    # multipart
    out_geom = clip_geometry_to_srs_bounds(geometry, tp, multipart=True)
    assert isinstance(out_geom, list)
    assert len(out_geom) == 1
    assert geometry == out_geom[0]
Exemple #2
0
def read_vector_window(
    input_file,
    tile,
    pixelbuffer=0,
    validity_check=True
    ):
    """
    Reads an input vector dataset with fiona using the tile bounding box as
    filter and clipping geometry. Returns a list of GeoJSON like features.
    """

    try:
        assert os.path.isfile(input_file)
    except:
        raise IOError("input file does not exist: %s" % input_file)

    try:
        assert pixelbuffer >= 0
    except:
        raise ValueError("pixelbuffer must be 0 or greater")

    try:
        assert isinstance(pixelbuffer, int)
    except:
        raise ValueError("pixelbuffer must be an integer")

    # Check if potentially tile boundaries exceed tile matrix boundaries on
    # the antimeridian, the northern or the southern boundary.
    tile_left, tile_bottom, tile_right, tile_top = tile.bounds(pixelbuffer)
    touches_left = tile_left <= tile.tile_pyramid.left
    touches_bottom = tile_bottom <= tile.tile_pyramid.bottom
    touches_right = tile_right >= tile.tile_pyramid.right
    touches_top = tile_top >= tile.tile_pyramid.top
    is_on_edge = touches_left or touches_bottom or touches_right or touches_top
    if pixelbuffer and is_on_edge:
        tile_boxes = clip_geometry_to_srs_bounds(
            tile.bbox(pixelbuffer),
            tile.tile_pyramid,
            multipart=True
            )
        return chain.from_iterable(
            _get_reprojected_features(
                input_file=input_file,
                dst_bounds=bbox.bounds,
                dst_crs=tile.crs,
                validity_check=validity_check
                )
            for bbox in tile_boxes
            )
        for polygon in tile_boxes:
            print polygon

    else:
        return _get_reprojected_features(
            input_file=input_file,
            dst_bounds=tile.bounds(pixelbuffer),
            dst_crs=tile.crs,
            validity_check=validity_check
            )
Exemple #3
0
def _get_warped_edge_array(tile=None,
                           input_file=None,
                           indexes=None,
                           dst_shape=None,
                           resampling=None,
                           src_nodata=None,
                           dst_nodata=None):
    tile_boxes = clip_geometry_to_srs_bounds(tile.bbox,
                                             tile.tile_pyramid,
                                             multipart=True)
    parts_metadata = dict(left=None, middle=None, right=None, none=None)
    # Split bounding box into multiple parts & request each numpy array
    # separately.
    for polygon in tile_boxes:
        # Check on which side the antimeridian is touched by the polygon:
        # "left", "middle", "right"
        # "none" means, the tile touches the edge just on the top and/or
        # bottom boundary
        part_metadata = {}
        left, bottom, right, top = polygon.bounds
        touches_right = left == tile.tile_pyramid.left
        touches_left = right == tile.tile_pyramid.right
        touches_both = touches_left and touches_right
        height = int(round((top - bottom) / tile.pixel_y_size))
        width = int(round((right - left) / tile.pixel_x_size))
        if indexes is None:
            dst_shape = (None, height, width)
        elif isinstance(indexes, int):
            dst_shape = (height, width)
        else:
            dst_shape = (dst_shape[0], height, width)
        part_metadata.update(bounds=polygon.bounds, shape=dst_shape)
        if touches_both:
            parts_metadata.update(middle=part_metadata)
        elif touches_left:
            parts_metadata.update(left=part_metadata)
        elif touches_right:
            parts_metadata.update(right=part_metadata)
        else:
            parts_metadata.update(none=part_metadata)
    # Finally, stitch numpy arrays together into one. Axis -1 is the last axis
    # which in case of rasterio arrays always is the width (West-East).
    return ma.concatenate([
        _get_warped_array(input_file=input_file,
                          indexes=indexes,
                          dst_bounds=parts_metadata[part]["bounds"],
                          dst_shape=parts_metadata[part]["shape"],
                          dst_crs=tile.crs,
                          resampling=resampling,
                          src_nodata=src_nodata,
                          dst_nodata=dst_nodata)
        for part in ["none", "left", "middle", "right"] if parts_metadata[part]
    ],
                          axis=-1)
Exemple #4
0
 def _reproject_tile_bbox(self, out_crs=None):
     """
     Returns tile bounding box reprojected to source file CRS. If bounding
     box overlaps with antimeridian, a MultiPolygon is returned.
     """
     return reproject_geometry(
         clip_geometry_to_srs_bounds(
             self.tile.bbox(pixelbuffer=self.pixelbuffer),
             self.tile.tile_pyramid
             ),
         self.tile.crs,
         out_crs
         )
Exemple #5
0
def _read_vector_window(input_file, tile, validity_check=True):
    if tile.pixelbuffer and tile.is_on_edge():
        return chain.from_iterable(
            _get_reprojected_features(input_file=input_file,
                                      dst_bounds=bbox.bounds,
                                      dst_crs=tile.crs,
                                      validity_check=validity_check)
            for bbox in clip_geometry_to_srs_bounds(
                tile.bbox, tile.tile_pyramid, multipart=True))
    else:
        features = _get_reprojected_features(input_file=input_file,
                                             dst_bounds=tile.bounds,
                                             dst_crs=tile.crs,
                                             validity_check=validity_check)
        return features
Exemple #6
0
def _get_warped_edge_array(
    tile=None, input_file=None, band_idx=None, resampling="nearest"
):
    LOGGER.debug("read array at pyramid edge")
    tile_boxes = clip_geometry_to_srs_bounds(
        tile.bbox, tile.tile_pyramid, multipart=True)
    parts_metadata = dict(left=None, middle=None, right=None, none=None)
    # Split bounding box into multiple parts & request each numpy array
    # separately.
    for polygon in tile_boxes:
        # Check on which side the antimeridian is touched by the polygon:
        # "left", "middle", "right"
        # "none" means, the tile touches the edge just on the top and/or
        # bottom boundary
        part_metadata = {}
        left, bottom, right, top = polygon.bounds
        touches_right = left == tile.tile_pyramid.left
        touches_left = right == tile.tile_pyramid.right
        touches_both = touches_left and touches_right
        height = int(round((top-bottom)/tile.pixel_y_size))
        width = int(round((right-left)/tile.pixel_x_size))
        affine = Affine.translation(
            left, top) * Affine.scale(
            tile.pixel_x_size, -tile.pixel_y_size)
        part_metadata.update(
            bounds=polygon.bounds, shape=(height, width), affine=affine)
        if touches_both:
            parts_metadata.update(middle=part_metadata)
        elif touches_left:
            parts_metadata.update(left=part_metadata)
        elif touches_right:
            parts_metadata.update(right=part_metadata)
        else:
            parts_metadata.update(none=part_metadata)
    # Finally, stitch numpy arrays together into one.
    return ma.concatenate(
        [
            _get_warped_array(
                input_file=input_file, band_idx=band_idx,
                dst_bounds=parts_metadata[part]["bounds"],
                dst_shape=parts_metadata[part]["shape"],
                dst_affine=parts_metadata[part]["affine"],
                dst_crs=tile.crs, resampling=resampling)
            for part in ["none", "left", "middle", "right"]
            if parts_metadata[part]
        ], axis=1)
Exemple #7
0
def read_vector_window(input_file, tile, validity_check=True):
    """
    Read a window of an input vector dataset.

    Also clips geometry.

    Parameters:
    -----------
    input_file : string
        path to vector file
    tile : ``Tile``
        tile extent to read data from
    validity_check : bool
        checks if reprojected geometry is valid and throws ``RuntimeError`` if
        invalid (default: True)

    Returns
    -------
    features : list
      a list of reprojected GeoJSON-like features
    """
    # Check if potentially tile boundaries exceed tile matrix boundaries on
    # the antimeridian, the northern or the southern boundary.
    tile_left, tile_bottom, tile_right, tile_top = tile.bounds
    touches_left = tile_left <= tile.tile_pyramid.left
    touches_bottom = tile_bottom <= tile.tile_pyramid.bottom
    touches_right = tile_right >= tile.tile_pyramid.right
    touches_top = tile_top >= tile.tile_pyramid.top
    is_on_edge = touches_left or touches_bottom or touches_right or touches_top
    if tile.pixelbuffer and is_on_edge:
        tile_boxes = clip_geometry_to_srs_bounds(tile.bbox,
                                                 tile.tile_pyramid,
                                                 multipart=True)
        return chain.from_iterable(
            _get_reprojected_features(input_file=input_file,
                                      dst_bounds=bbox.bounds,
                                      dst_crs=tile.crs,
                                      validity_check=validity_check)
            for bbox in tile_boxes)
    else:
        features = _get_reprojected_features(input_file=input_file,
                                             dst_bounds=tile.bounds,
                                             dst_crs=tile.crs,
                                             validity_check=validity_check)
        return features
def test_antimeridian_clip(invalid_geom):
    """Clip on antimeridian."""
    tp = TilePyramid("geodetic")
    tp_bounds = box(tp.left, tp.bottom, tp.right, tp.top)

    # extends on the western side
    geometry = box(-183.125, 67.5, -177.5, 73.125)
    # get GeometryCollection
    out_geom = clip_geometry_to_srs_bounds(geometry, tp)
    assert out_geom.geom_type == "GeometryCollection"
    # get list
    out_geom = clip_geometry_to_srs_bounds(geometry, tp, multipart=True)
    assert isinstance(out_geom, list)
    for sub_geom in out_geom:
        assert sub_geom.within(tp_bounds)

    # extends on the eastern side
    geometry = box(177.5, 67.5, 183.125, 73.125)
    # get GeometryCollection
    out_geom = clip_geometry_to_srs_bounds(geometry, tp)
    assert out_geom.geom_type == "GeometryCollection"
    # get list
    out_geom = clip_geometry_to_srs_bounds(geometry, tp, multipart=True)
    assert isinstance(out_geom, list)
    for sub_geom in out_geom:
        assert sub_geom.within(tp_bounds)

    # extends on both sides
    geometry = box(-183.125, 67.5, 183.125, 73.125)
    # get GeometryCollection
    out_geom = clip_geometry_to_srs_bounds(geometry, tp)
    assert out_geom.geom_type == "GeometryCollection"
    # get list
    out_geom = clip_geometry_to_srs_bounds(geometry, tp, multipart=True)
    assert isinstance(out_geom, list)
    for sub_geom in out_geom:
        assert sub_geom.within(tp_bounds)
    assert len(out_geom) == 3

    # fail on invalid geometry
    with pytest.raises(ValueError):
        clip_geometry_to_srs_bounds(invalid_geom, tp)
Exemple #9
0
def read_vector_window(input_file, tile, validity_check=True):
    """
    Read a window of an input vector dataset.

    Also clips geometry.

    Parameters:
    -----------
    input_file : string
        path to vector file
    tile : ``Tile``
        tile extent to read data from
    validity_check : bool
        checks if reprojected geometry is valid and throws ``RuntimeError`` if
        invalid (default: True)

    Returns
    -------
    features : list
      a list of reprojected GeoJSON-like features
    """
    if tile.pixelbuffer and tile.is_on_edge():
        tile_boxes = clip_geometry_to_srs_bounds(
            tile.bbox, tile.tile_pyramid, multipart=True
        )
        return chain.from_iterable(
            _get_reprojected_features(
                input_file=input_file, dst_bounds=bbox.bounds,
                dst_crs=tile.crs, validity_check=validity_check
            )
            for bbox in tile_boxes)
    else:
        features = _get_reprojected_features(
            input_file=input_file, dst_bounds=tile.bounds, dst_crs=tile.crs,
            validity_check=validity_check
        )
        return features