Skip to content
Commits on Source (4)
Changes
=======
1.0.3 (2018-08-01)
------------------
Bug fixes:
- The input file handler of rio-rasterize has been changed so that it does not
reject GeoJSON files (#1425).
- Linear rings have been added as acceptable input for rio-rasterize and other
commands and functions (#1431).
1.0.2 (2018-07-27)
------------------
......
rasterio (1.0.3-1) unstable; urgency=medium
* Team upload.
* New upstream release.
-- Bas Couwenberg <sebastic@debian.org> Thu, 02 Aug 2018 07:08:13 +0200
rasterio (1.0.2-1) unstable; urgency=medium
* Team upload.
......
......@@ -43,7 +43,7 @@ import rasterio.path
__all__ = ['band', 'open', 'pad', 'Env']
__version__ = "1.0.2"
__version__ = "1.0.3"
__gdal_version__ = gdal_version()
# Rasterio attaches NullHandler to the 'rasterio' logger and its
......
......@@ -584,8 +584,8 @@ cdef class OGRGeomBuilder:
cdef object coordinates
cdef object geometries
valid_types = {'Point', 'MultiPoint', 'LineString', 'MultiLineString',
'Polygon', 'MultiPolygon'}
valid_types = {'Point', 'MultiPoint', 'LineString', 'LinearRing',
'MultiLineString', 'Polygon', 'MultiPolygon'}
if typename in valid_types:
coordinates = geometry.get('coordinates')
......@@ -596,6 +596,8 @@ cdef class OGRGeomBuilder:
return self._buildPoint(coordinates)
elif typename == 'LineString':
return self._buildLineString(coordinates)
elif typename == 'LinearRing':
return self._buildLinearRing(coordinates)
elif typename == 'Polygon':
return self._buildPolygon(coordinates)
elif typename == 'MultiPoint':
......
......@@ -440,8 +440,8 @@ def is_valid_geom(geom):
bool: True if object is a valid GeoJSON geometry type
"""
geom_types = {'Point', 'MultiPoint', 'LineString', 'MultiLineString',
'Polygon', 'MultiPolygon'}
geom_types = {'Point', 'MultiPoint', 'LineString', 'LinearRing',
'MultiLineString', 'Polygon', 'MultiPolygon'}
if 'type' not in geom:
return False
......@@ -473,6 +473,11 @@ def is_valid_geom(geom):
# a coordinate
return len(coords) >= 2 and len(coords[0]) >= 2
if geom_type == 'LinearRing':
# Rings must have at least 4 coordinates and at least x, y for
# a coordinate
return len(coords) >= 4 and len(coords[0]) >= 2
if geom_type == 'MultiLineString':
# Multi lines must have at least one LineString
return (len(coords) > 0 and len(coords[0]) >= 2 and
......
......@@ -21,7 +21,10 @@ import rasterio.shutil
logger = logging.getLogger(__name__)
# Common options used below
def files_handler(ctx, param, value):
"""Process and validate input file names"""
return value
# Unlike the version in cligj, this one doesn't require values.
files_inout_arg = click.argument(
......@@ -29,7 +32,7 @@ files_inout_arg = click.argument(
nargs=-1,
type=click.Path(resolve_path=True),
metavar="INPUTS... OUTPUT",
callback=options.files_inout_handler)
callback=files_handler)
@click.command(short_help='Rasterize features.')
......
......@@ -8,7 +8,7 @@ from affine import Affine
import rasterio
from rasterio.enums import MergeAlg
from rasterio.errors import WindowError, RasterioDeprecationWarning
from rasterio.errors import WindowError
from rasterio.features import (
bounds, geometry_mask, geometry_window, is_valid_geom, rasterize, sieve,
shapes)
......@@ -33,6 +33,12 @@ def test_bounds_line():
assert bounds(MockGeoInterface(g)) == (0, 0, 10, 10)
def test_bounds_ring():
g = {'type': 'LinearRing', 'coordinates': [[0, 0], [10, 10], [10, 0]]}
assert bounds(g) == (0, 0, 10, 10)
assert bounds(MockGeoInterface(g)) == (0, 0, 10, 10)
def test_bounds_polygon():
g = {'type': 'Polygon', 'coordinates': [[[0, 0], [10, 10], [10, 0]]]}
assert bounds(g) == (0, 0, 10, 10)
......@@ -91,6 +97,7 @@ def test_geometry_mask_invert(basic_geometry, basic_image_2x2):
)
)
def test_geometry_invalid_geom():
"""An invalid geometry should fail"""
......@@ -298,6 +305,24 @@ def test_is_valid_geom_polygon(geojson_polygon):
assert not is_valid_geom(geom)
def test_is_valid_geom_ring(geojson_polygon):
"""Properly formed GeoJSON LinearRing is valid"""
geojson_ring = deepcopy(geojson_polygon)
geojson_ring['type'] = 'LinearRing'
# take first ring from polygon as sample
geojson_ring['coordinates'] = geojson_ring['coordinates'][0]
assert is_valid_geom(geojson_ring)
# Empty iterables are invalid
geom = deepcopy(geojson_ring)
geom['coordinates'] = []
assert not is_valid_geom(geom)
geom = deepcopy(geojson_ring)
geom['coordinates'] = [[]]
assert not is_valid_geom(geom)
def test_is_valid_geom_multipolygon(geojson_multipolygon):
"""Properly formed GeoJSON MultiPolygon is valid"""
......@@ -595,6 +620,7 @@ def test_rasterize_all_touched(basic_geometry, basic_image):
)
)
def test_rasterize_merge_alg_add(basic_geometry, basic_image_2x2x2):
"""
Rasterizing two times the basic_geometry with the "add" merging
......
......@@ -35,6 +35,25 @@ def test_rasterize(tmpdir, runner, basic_feature):
assert np.all(data)
def test_rasterize_file(tmpdir, runner, basic_feature):
"""Confirm fix of #1425"""
geojson_file = tmpdir.join('input.geojson')
geojson_file.write(json.dumps(basic_feature))
output = str(tmpdir.join('test.tif'))
result = runner.invoke(
main_group, [
'rasterize', str(geojson_file), output, '--dimensions', DEFAULT_SHAPE[0],
DEFAULT_SHAPE[1]])
assert result.exit_code == 0
assert os.path.exists(output)
with rasterio.open(output) as out:
assert np.allclose(out.bounds, (2, 2, 4.25, 4.25))
data = out.read(1, masked=False)
assert data.shape == DEFAULT_SHAPE
assert np.all(data)
def test_rasterize_bounds(tmpdir, runner, basic_feature, basic_image_2x2):
output = str(tmpdir.join('test.tif'))
result = runner.invoke(
......
......@@ -836,6 +836,13 @@ def test_transform_geom_linestring_precision_iso(polygon_3373):
assert int(result['coordinates'][0][0] * 10) == 7988423
def test_transform_geom_linearring_precision(polygon_3373):
ring = polygon_3373['coordinates'][0]
geom = {'type': 'LinearRing', 'coordinates': ring}
result = transform_geom('EPSG:3373', 'EPSG:4326', geom, precision=1, antimeridian_cutting=True)
assert all(round(x, 1) == x for x in flatten_coords(result['coordinates']))
def test_transform_geom_linestring_precision_z(polygon_3373):
ring = polygon_3373['coordinates'][0]
x, y = zip(*ring)
......