BUG: fix geometry methods to handle single MultiGeoms output (#1134)

This commit is contained in:
Joris Van den Bossche
2019-09-21 19:36:15 +02:00
committed by GitHub
parent 8903e754cc
commit 3f110dcc05
2 changed files with 57 additions and 19 deletions
+30 -19
View File
@@ -112,8 +112,9 @@ def from_wkb(data):
geom = None
out.append(geom)
out = np.array(out, dtype=object)
return GeometryArray(out)
aout = np.empty(n, dtype=object)
aout[:] = out
return GeometryArray(aout)
def to_wkb(geoms):
@@ -146,8 +147,9 @@ def from_wkt(data):
geom = None
out.append(geom)
out = np.array(out, dtype=object)
return GeometryArray(out)
aout = np.empty(n, dtype=object)
aout[:] = out
return GeometryArray(aout)
def to_wkt(geoms):
@@ -197,8 +199,9 @@ def points_from_xy(x, y, z=None):
if z is not None:
z = np.asarray(z, dtype="float64")
out = _points_from_xy(x, y, z)
out = np.array(out, dtype=object)
return GeometryArray(out)
aout = np.empty(len(x), dtype=object)
aout[:] = out
return GeometryArray(aout)
# -----------------------------------------------------------------------------
@@ -384,14 +387,16 @@ def _affinity_method(op, left, *args, **kwargs):
# affine_transform itself works (as well as translate), but rotate, scale
# and skew fail (they try to unpack the bounds).
# Here: consistently returning empty geom for input empty geom
data = []
out = []
for geom in left.data:
if geom is None or geom.is_empty:
res = geom
else:
res = getattr(shapely.affinity, op)(geom, *args, **kwargs)
data.append(res)
return GeometryArray(np.array(data, dtype=object))
out.append(res)
data = np.empty(len(left), dtype=object)
data[:] = out
return GeometryArray(data)
class GeometryArray(ExtensionArray):
@@ -547,8 +552,9 @@ class GeometryArray(ExtensionArray):
"Only Polygon objects have interior rings. For other "
"geometry types, None is returned."
)
return np.array(inner_rings, dtype=object)
data = np.empty(len(self), dtype=object)
data[:] = inner_rings
return data
def representative_point(self):
# method and not a property -> can't use _unary_geo
@@ -620,39 +626,44 @@ class GeometryArray(ExtensionArray):
return _binary_op_float("distance", self, other)
def buffer(self, distance, resolution=16, **kwargs):
data = data = np.empty(len(self), dtype=object)
if isinstance(distance, np.ndarray):
if len(distance) != len(self):
raise ValueError(
"Length of distance sequence does not match "
"length of the GeoSeries"
)
data = [
data[:] = [
geom.buffer(dist, resolution, **kwargs) if geom is not None else None
for geom, dist in zip(self.data, distance)
]
return GeometryArray(np.array(data, dtype=object))
return GeometryArray(data)
data = [
data[:] = [
geom.buffer(distance, resolution, **kwargs) if geom is not None else None
for geom in self.data
]
return GeometryArray(np.array(data, dtype=object))
return GeometryArray(data)
def interpolate(self, distance, normalized=False):
data = data = np.empty(len(self), dtype=object)
if isinstance(distance, np.ndarray):
if len(distance) != len(self):
raise ValueError(
"Length of distance sequence does not match "
"length of the GeoSeries"
)
data = [
data[:] = [
geom.interpolate(dist, normalized=normalized)
for geom, dist in zip(self.data, distance)
]
return GeometryArray(np.array(data, dtype=object))
return GeometryArray(data)
data = [geom.interpolate(distance, normalized=normalized) for geom in self.data]
return GeometryArray(np.array(data, dtype=object))
data[:] = [
geom.interpolate(distance, normalized=normalized) for geom in self.data
]
return GeometryArray(data)
def simplify(self, *args, **kwargs):
# method and not a property -> can't use _unary_geo
+27
View File
@@ -133,6 +133,13 @@ def test_from_wkb():
assert res[-1] is None
assert res[-2] is None
# single MultiPolygon
multi_poly = shapely.geometry.MultiPolygon(
[shapely.geometry.box(0, 0, 1, 1), shapely.geometry.box(3, 3, 4, 4)]
)
res = from_wkb([multi_poly.wkb])
assert res[0] == multi_poly
def test_to_wkb():
P = from_shapely(points_no_missing)
@@ -179,6 +186,13 @@ def test_from_wkt(string_type):
assert res[-1] is None
assert res[-2] is None
# single MultiPolygon
multi_poly = shapely.geometry.MultiPolygon(
[shapely.geometry.box(0, 0, 1, 1), shapely.geometry.box(3, 3, 4, 4)]
)
res = from_wkt([f(multi_poly.wkt)])
assert res[0] == multi_poly
def test_to_wkt():
P = from_shapely(points_no_missing)
@@ -667,3 +681,16 @@ def test_raise_on_bad_sizes():
assert "lengths" in str(info.value).lower()
assert "12" in str(info.value)
assert "21" in str(info.value)
def test_buffer_single_multipolygon():
# https://github.com/geopandas/geopandas/issues/1130
multi_poly = shapely.geometry.MultiPolygon(
[shapely.geometry.box(0, 0, 1, 1), shapely.geometry.box(3, 3, 4, 4)]
)
arr = from_shapely([multi_poly])
result = arr.buffer(1)
expected = [multi_poly.buffer(1)]
equal_geometries(result, expected)
result = arr.buffer(np.array([1]))
equal_geometries(result, expected)