venv
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -92,3 +92,34 @@ def ignore_invalid(condition=True):
|
||||
|
||||
with ignore_invalid():
|
||||
line_string_nan = shapely.LineString([(np.nan, np.nan), (np.nan, np.nan)])
|
||||
|
||||
|
||||
class ArrayLike:
|
||||
"""
|
||||
Simple numpy Array like class that implements the
|
||||
ufunc protocol.
|
||||
"""
|
||||
|
||||
def __init__(self, array):
|
||||
self._array = np.asarray(array)
|
||||
|
||||
def __len__(self):
|
||||
return len(self._array)
|
||||
|
||||
def __getitem(self, key):
|
||||
return self._array[key]
|
||||
|
||||
def __iter__(self):
|
||||
return self._array.__iter__()
|
||||
|
||||
def __array__(self):
|
||||
return np.asarray(self._array)
|
||||
|
||||
def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
|
||||
if method == "__call__":
|
||||
inputs = [
|
||||
arg._array if isinstance(arg, self.__class__) else arg for arg in inputs
|
||||
]
|
||||
return self.__class__(ufunc(*inputs, **kwargs))
|
||||
else:
|
||||
return NotImplemented
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -2,6 +2,7 @@ import numpy as np
|
||||
import pytest
|
||||
|
||||
from shapely import LineString
|
||||
from shapely.tests.common import line_string, line_string_z, point, point_z
|
||||
|
||||
|
||||
class TestCoords:
|
||||
@@ -84,3 +85,18 @@ class TestXY:
|
||||
assert list(x) == [0.0, 1.0]
|
||||
assert len(y) == 2
|
||||
assert list(y) == [0.0, 1.0]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("geom", [point, point_z, line_string, line_string_z])
|
||||
def test_coords_array_copy(geom):
|
||||
"""Test CoordinateSequence.__array__ method."""
|
||||
coord_seq = geom.coords
|
||||
assert np.array(coord_seq) is not np.array(coord_seq)
|
||||
assert np.array(coord_seq, copy=True) is not np.array(coord_seq, copy=True)
|
||||
|
||||
# Behaviour of copy=False is different between NumPy 1.x and 2.x
|
||||
if int(np.version.short_version.split(".", 1)[0]) >= 2:
|
||||
with pytest.raises(ValueError, match="A copy is always created"):
|
||||
np.array(coord_seq, copy=False)
|
||||
else:
|
||||
assert np.array(coord_seq, copy=False) is np.array(coord_seq, copy=False)
|
||||
|
||||
@@ -47,7 +47,7 @@ def test_format_point():
|
||||
("g", xy2, "POINT (-169.910918 -18.997564)", False),
|
||||
("0.2g", xy2, "POINT (-169.91 -19)", False),
|
||||
]
|
||||
# without precsions test GEOS rounding_precision=-1; different than Python
|
||||
# without precisions test GEOS rounding_precision=-1; different than Python
|
||||
test_list += [
|
||||
("f", (1, 2), f"POINT ({1:.16f} {2:.16f})", False),
|
||||
("F", xyz3, "POINT Z ({:.16f} {:.16f} {:.16f})".format(*xyz3), False),
|
||||
@@ -84,23 +84,28 @@ def test_format_polygon():
|
||||
assert format(poly, "X") == poly.wkb_hex
|
||||
|
||||
# Use f-strings with extra characters and rounding precision
|
||||
assert f"<{poly:.2f}>" == (
|
||||
"<POLYGON ((10.00 0.00, 7.07 -7.07, 0.00 -10.00, -7.07 -7.07, "
|
||||
"-10.00 -0.00, -7.07 7.07, -0.00 10.00, 7.07 7.07, 10.00 0.00))>"
|
||||
)
|
||||
if geos_version < (3, 13, 0):
|
||||
assert f"<{poly:.2f}>" == (
|
||||
"<POLYGON ((10.00 0.00, 7.07 -7.07, 0.00 -10.00, -7.07 -7.07, "
|
||||
"-10.00 -0.00, -7.07 7.07, -0.00 10.00, 7.07 7.07, 10.00 0.00))>"
|
||||
)
|
||||
else:
|
||||
assert f"<{poly:.2f}>" == (
|
||||
"<POLYGON ((10.00 0.00, 7.07 -7.07, 0.00 -10.00, -7.07 -7.07, "
|
||||
"-10.00 0.00, -7.07 7.07, 0.00 10.00, 7.07 7.07, 10.00 0.00))>"
|
||||
)
|
||||
|
||||
# 'g' format varies depending on GEOS version
|
||||
if geos_version < (3, 10, 0):
|
||||
expected_2G = (
|
||||
assert f"{poly:.2G}" == (
|
||||
"POLYGON ((10 0, 7.1 -7.1, 1.6E-14 -10, -7.1 -7.1, "
|
||||
"-10 -3.2E-14, -7.1 7.1, -4.6E-14 10, 7.1 7.1, 10 0))"
|
||||
)
|
||||
else:
|
||||
expected_2G = (
|
||||
assert f"{poly:.2G}" == (
|
||||
"POLYGON ((10 0, 7.07 -7.07, 0 -10, -7.07 -7.07, "
|
||||
"-10 0, -7.07 7.07, 0 10, 7.07 7.07, 10 0))"
|
||||
)
|
||||
assert f"{poly:.2G}" == expected_2G
|
||||
|
||||
# check empty
|
||||
empty = Polygon()
|
||||
|
||||
@@ -101,7 +101,9 @@ class TestPoint:
|
||||
# Test 2D points
|
||||
p = Point(1.0, 2.0)
|
||||
assert p.x == 1.0
|
||||
assert type(p.x) is float
|
||||
assert p.y == 2.0
|
||||
assert type(p.y) is float
|
||||
assert p.coords[:] == [(1.0, 2.0)]
|
||||
assert str(p) == p.wkt
|
||||
assert p.has_z is False
|
||||
@@ -114,6 +116,7 @@ class TestPoint:
|
||||
assert str(p) == p.wkt
|
||||
assert p.has_z is True
|
||||
assert p.z == 3.0
|
||||
assert type(p.z) is float
|
||||
|
||||
# Coordinate access
|
||||
p = Point((3.0, 4.0))
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -3,6 +3,7 @@ import unittest
|
||||
import pytest
|
||||
|
||||
import shapely
|
||||
from shapely import geos_version
|
||||
from shapely.errors import TopologicalError
|
||||
from shapely.geometry import GeometryCollection, LineString, MultiPoint, Point, Polygon
|
||||
from shapely.wkt import loads
|
||||
@@ -79,8 +80,11 @@ class OperationsTestCase(unittest.TestCase):
|
||||
"POLYGON ((40 100, 80 100, 80 60, 40 60, 40 100), (60 60, 80 60, 80 40, 60 40, 60 60))"
|
||||
)
|
||||
assert not invalid_polygon.is_valid
|
||||
with pytest.raises((TopologicalError, shapely.GEOSException)):
|
||||
invalid_polygon.relate(invalid_polygon)
|
||||
if geos_version < (3, 13, 0):
|
||||
with pytest.raises((TopologicalError, shapely.GEOSException)):
|
||||
invalid_polygon.relate(invalid_polygon)
|
||||
else: # resolved with RelateNG
|
||||
assert invalid_polygon.relate(invalid_polygon) == "2FFF1FFF2"
|
||||
|
||||
def test_hausdorff_distance(self):
|
||||
point = Point(1, 1)
|
||||
|
||||
@@ -5,6 +5,7 @@ import unittest
|
||||
import pytest
|
||||
|
||||
import shapely
|
||||
from shapely import geos_version
|
||||
from shapely.geometry import Point, Polygon
|
||||
|
||||
|
||||
@@ -67,8 +68,15 @@ class PredicatesTestCase(unittest.TestCase):
|
||||
(339, 207),
|
||||
]
|
||||
|
||||
with pytest.raises(shapely.GEOSException):
|
||||
Polygon(p1).within(Polygon(p2))
|
||||
g1 = Polygon(p1)
|
||||
g2 = Polygon(p2)
|
||||
assert not g1.is_valid
|
||||
assert not g2.is_valid
|
||||
if geos_version < (3, 13, 0):
|
||||
with pytest.raises(shapely.GEOSException):
|
||||
g1.within(g2)
|
||||
else: # resolved with RelateNG
|
||||
assert not g1.within(g2)
|
||||
|
||||
def test_relate_pattern(self):
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ from shapely import (
|
||||
from shapely.testing import assert_geometries_equal
|
||||
from shapely.tests.common import (
|
||||
all_types,
|
||||
ArrayLike,
|
||||
empty,
|
||||
empty_line_string,
|
||||
empty_point,
|
||||
@@ -981,6 +982,17 @@ def test_oriented_envelope_pre_geos_312(geometry, expected):
|
||||
assert_geometries_equal(actual, expected, normalize=True, tolerance=1e-3)
|
||||
|
||||
|
||||
def test_oriented_evelope_array_like():
|
||||
# https://github.com/shapely/shapely/issues/1929
|
||||
# because we have a custom python implementation, need to ensure this has
|
||||
# the same capabilities as numpy ufuncs to work with array-likes
|
||||
geometries = [Point(1, 1).buffer(1), Point(2, 2).buffer(1)]
|
||||
actual = shapely.oriented_envelope(ArrayLike(geometries))
|
||||
assert isinstance(actual, ArrayLike)
|
||||
expected = shapely.oriented_envelope(geometries)
|
||||
assert_geometries_equal(np.asarray(actual), expected)
|
||||
|
||||
|
||||
@pytest.mark.skipif(shapely.geos_version < (3, 11, 0), reason="GEOS < 3.11")
|
||||
def test_concave_hull_kwargs():
|
||||
p = Point(10, 10)
|
||||
|
||||
@@ -255,7 +255,7 @@ def test_set_nan():
|
||||
|
||||
def test_set_nan_same_objects():
|
||||
# You can't put identical objects in a set.
|
||||
# x = float("nan"); set([x, x]) also retuns a set with 1 element
|
||||
# x = float("nan"); set([x, x]) also returns a set with 1 element
|
||||
a = set([line_string_nan] * 10)
|
||||
assert len(a) == 1
|
||||
|
||||
|
||||
@@ -287,6 +287,15 @@ def test_to_wkt_none():
|
||||
assert shapely.to_wkt(None) is None
|
||||
|
||||
|
||||
def test_to_wkt_array_with_empty_z():
|
||||
# See GH-2004
|
||||
empty_wkt = ["POINT Z EMPTY", None, "POLYGON Z EMPTY"]
|
||||
empty_geoms = shapely.from_wkt(empty_wkt)
|
||||
if shapely.geos_version < (3, 9, 0):
|
||||
empty_wkt = ["POINT EMPTY", None, "POLYGON EMPTY"]
|
||||
assert list(shapely.to_wkt(empty_geoms)) == empty_wkt
|
||||
|
||||
|
||||
def test_to_wkt_exceptions():
|
||||
with pytest.raises(TypeError):
|
||||
shapely.to_wkt(1)
|
||||
|
||||
@@ -178,7 +178,7 @@ def test_shared_paths_non_linestring():
|
||||
|
||||
|
||||
def _prepare_input(geometry, prepare):
|
||||
"""Prepare without modifying inplace"""
|
||||
"""Prepare without modifying in-place"""
|
||||
if prepare:
|
||||
geometry = shapely.transform(geometry, lambda x: x) # makes a copy
|
||||
shapely.prepare(geometry)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import os
|
||||
import sys
|
||||
from inspect import cleandoc
|
||||
from itertools import chain
|
||||
from string import ascii_letters, digits
|
||||
from unittest import mock
|
||||
@@ -83,13 +84,22 @@ class SomeClass:
|
||||
"""
|
||||
|
||||
|
||||
expected_docstring = """Docstring that will be mocked.
|
||||
def expected_docstring(**kwds):
|
||||
doc = """Docstring that will be mocked.
|
||||
{indent}A multiline.
|
||||
|
||||
{indent}.. note:: 'func' requires at least GEOS {version}.
|
||||
|
||||
{indent}Some description.
|
||||
{indent}"""
|
||||
{indent}""".format(
|
||||
**kwds
|
||||
)
|
||||
if sys.version_info[:2] >= (3, 13):
|
||||
# There are subtle differences between inspect.cleandoc() and
|
||||
# _PyCompile_CleanDoc(). Most significantly, the latter does not remove
|
||||
# leading or trailing blank lines.
|
||||
return cleandoc(doc) + "\n"
|
||||
return doc
|
||||
|
||||
|
||||
@pytest.mark.parametrize("version", ["3.7.0", "3.7.1", "3.6.2"])
|
||||
@@ -104,7 +114,7 @@ def test_requires_geos_not_ok(version, mocked_geos_version):
|
||||
with pytest.raises(shapely.errors.UnsupportedGEOSVersionError):
|
||||
wrapped()
|
||||
|
||||
assert wrapped.__doc__ == expected_docstring.format(version=version, indent=" " * 4)
|
||||
assert wrapped.__doc__ == expected_docstring(version=version, indent=" " * 4)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("version", ["3.6.0", "3.8.0"])
|
||||
@@ -112,7 +122,7 @@ def test_requires_geos_doc_build(version, mocked_geos_version, sphinx_doc_build)
|
||||
"""The requires_geos decorator always adapts the docstring."""
|
||||
wrapped = requires_geos(version)(func)
|
||||
|
||||
assert wrapped.__doc__ == expected_docstring.format(version=version, indent=" " * 4)
|
||||
assert wrapped.__doc__ == expected_docstring(version=version, indent=" " * 4)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("version", ["3.6.0", "3.8.0"])
|
||||
@@ -120,7 +130,7 @@ def test_requires_geos_method(version, mocked_geos_version, sphinx_doc_build):
|
||||
"""The requires_geos decorator adjusts methods docstrings correctly"""
|
||||
wrapped = requires_geos(version)(SomeClass.func)
|
||||
|
||||
assert wrapped.__doc__ == expected_docstring.format(version=version, indent=" " * 8)
|
||||
assert wrapped.__doc__ == expected_docstring(version=version, indent=" " * 8)
|
||||
|
||||
|
||||
@multithreading_enabled
|
||||
|
||||
@@ -298,7 +298,7 @@ def test_is_ccw(geom, expected):
|
||||
|
||||
|
||||
def _prepare_with_copy(geometry):
|
||||
"""Prepare without modifying inplace"""
|
||||
"""Prepare without modifying in-place"""
|
||||
geometry = shapely.transform(geometry, lambda x: x) # makes a copy
|
||||
shapely.prepare(geometry)
|
||||
return geometry
|
||||
|
||||
@@ -110,18 +110,30 @@ def test_points():
|
||||
"POINT EMPTY",
|
||||
"POINT EMPTY",
|
||||
"POINT (4 4)",
|
||||
None,
|
||||
"POINT EMPTY",
|
||||
]
|
||||
)
|
||||
typ, result, offsets = shapely.to_ragged_array(arr)
|
||||
expected = np.array(
|
||||
[[0, 0], [1, 1], [np.nan, np.nan], [np.nan, np.nan], [4, 4], [np.nan, np.nan]]
|
||||
[
|
||||
[0, 0],
|
||||
[1, 1],
|
||||
[np.nan, np.nan],
|
||||
[np.nan, np.nan],
|
||||
[4, 4],
|
||||
[np.nan, np.nan],
|
||||
[np.nan, np.nan],
|
||||
]
|
||||
)
|
||||
assert typ == shapely.GeometryType.POINT
|
||||
assert len(result) == len(arr)
|
||||
assert_allclose(result, expected)
|
||||
assert len(offsets) == 0
|
||||
|
||||
geoms = shapely.from_ragged_array(typ, result)
|
||||
# in a roundtrip, missing geometries come back as empty
|
||||
arr[-2] = shapely.from_wkt("POINT EMPTY")
|
||||
assert_geometries_equal(geoms, arr)
|
||||
|
||||
|
||||
@@ -133,6 +145,7 @@ def test_linestrings():
|
||||
"LINESTRING EMPTY",
|
||||
"LINESTRING EMPTY",
|
||||
"LINESTRING (10 10, 20 20, 10 40)",
|
||||
None,
|
||||
"LINESTRING EMPTY",
|
||||
]
|
||||
)
|
||||
@@ -151,13 +164,15 @@ def test_linestrings():
|
||||
[10.0, 40.0],
|
||||
]
|
||||
)
|
||||
expected_offsets = np.array([0, 3, 7, 7, 7, 10, 10])
|
||||
expected_offsets = np.array([0, 3, 7, 7, 7, 10, 10, 10])
|
||||
assert typ == shapely.GeometryType.LINESTRING
|
||||
assert_allclose(coords, expected)
|
||||
assert len(offsets) == 1
|
||||
assert_allclose(offsets[0], expected_offsets)
|
||||
|
||||
result = shapely.from_ragged_array(typ, coords, offsets)
|
||||
# in a roundtrip, missing geometries come back as empty
|
||||
arr[-2] = shapely.from_wkt("LINESTRING EMPTY")
|
||||
assert_geometries_equal(result, arr)
|
||||
|
||||
|
||||
@@ -169,6 +184,7 @@ def test_polygons():
|
||||
"POLYGON EMPTY",
|
||||
"POLYGON EMPTY",
|
||||
"POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))",
|
||||
None,
|
||||
"POLYGON EMPTY",
|
||||
]
|
||||
)
|
||||
@@ -197,7 +213,7 @@ def test_polygons():
|
||||
]
|
||||
)
|
||||
expected_offsets1 = np.array([0, 5, 10, 14, 19])
|
||||
expected_offsets2 = np.array([0, 1, 3, 3, 3, 4, 4])
|
||||
expected_offsets2 = np.array([0, 1, 3, 3, 3, 4, 4, 4])
|
||||
|
||||
assert typ == shapely.GeometryType.POLYGON
|
||||
assert_allclose(coords, expected)
|
||||
@@ -206,6 +222,8 @@ def test_polygons():
|
||||
assert_allclose(offsets[1], expected_offsets2)
|
||||
|
||||
result = shapely.from_ragged_array(typ, coords, offsets)
|
||||
# in a roundtrip, missing geometries come back as empty
|
||||
arr[-2] = shapely.from_wkt("POLYGON EMPTY")
|
||||
assert_geometries_equal(result, arr)
|
||||
|
||||
|
||||
@@ -217,6 +235,7 @@ def test_multipoints():
|
||||
"MULTIPOINT EMPTY",
|
||||
"MULTIPOINT EMPTY",
|
||||
"MULTIPOINT (30 10, 10 30, 40 40)",
|
||||
None,
|
||||
"MULTIPOINT EMPTY",
|
||||
]
|
||||
)
|
||||
@@ -233,7 +252,7 @@ def test_multipoints():
|
||||
[40.0, 40.0],
|
||||
]
|
||||
)
|
||||
expected_offsets = np.array([0, 4, 5, 5, 5, 8, 8])
|
||||
expected_offsets = np.array([0, 4, 5, 5, 5, 8, 8, 8])
|
||||
|
||||
assert typ == shapely.GeometryType.MULTIPOINT
|
||||
assert_allclose(coords, expected)
|
||||
@@ -241,6 +260,8 @@ def test_multipoints():
|
||||
assert_allclose(offsets[0], expected_offsets)
|
||||
|
||||
result = shapely.from_ragged_array(typ, coords, offsets)
|
||||
# in a roundtrip, missing geometries come back as empty
|
||||
arr[-2] = shapely.from_wkt("MULTIPOINT EMPTY")
|
||||
assert_geometries_equal(result, arr)
|
||||
|
||||
|
||||
@@ -252,6 +273,7 @@ def test_multilinestrings():
|
||||
"MULTILINESTRING EMPTY",
|
||||
"MULTILINESTRING EMPTY",
|
||||
"MULTILINESTRING ((35 10, 45 45), (15 40, 10 20), (30 10, 10 30, 40 40))",
|
||||
None,
|
||||
"MULTILINESTRING EMPTY",
|
||||
]
|
||||
)
|
||||
@@ -278,7 +300,7 @@ def test_multilinestrings():
|
||||
]
|
||||
)
|
||||
expected_offsets1 = np.array([0, 3, 6, 10, 12, 14, 17])
|
||||
expected_offsets2 = np.array([0, 1, 3, 3, 3, 6, 6])
|
||||
expected_offsets2 = np.array([0, 1, 3, 3, 3, 6, 6, 6])
|
||||
|
||||
assert typ == shapely.GeometryType.MULTILINESTRING
|
||||
assert_allclose(coords, expected)
|
||||
@@ -287,6 +309,8 @@ def test_multilinestrings():
|
||||
assert_allclose(offsets[1], expected_offsets2)
|
||||
|
||||
result = shapely.from_ragged_array(typ, coords, offsets)
|
||||
# in a roundtrip, missing geometries come back as empty
|
||||
arr[-2] = shapely.from_wkt("MULTILINESTRING EMPTY")
|
||||
assert_geometries_equal(result, arr)
|
||||
|
||||
|
||||
@@ -298,6 +322,7 @@ def test_multipolygons():
|
||||
"MULTIPOLYGON EMPTY",
|
||||
"MULTIPOLYGON EMPTY",
|
||||
"MULTIPOLYGON (((40 40, 20 45, 45 30, 40 40)))",
|
||||
None,
|
||||
"MULTIPOLYGON EMPTY",
|
||||
]
|
||||
)
|
||||
@@ -335,7 +360,7 @@ def test_multipolygons():
|
||||
)
|
||||
expected_offsets1 = np.array([0, 5, 9, 13, 19, 23, 27])
|
||||
expected_offsets2 = np.array([0, 2, 3, 5, 6])
|
||||
expected_offsets3 = np.array([0, 1, 3, 3, 3, 4, 4])
|
||||
expected_offsets3 = np.array([0, 1, 3, 3, 3, 4, 4, 4])
|
||||
|
||||
assert typ == shapely.GeometryType.MULTIPOLYGON
|
||||
assert_allclose(coords, expected)
|
||||
@@ -345,6 +370,8 @@ def test_multipolygons():
|
||||
assert_allclose(offsets[2], expected_offsets3)
|
||||
|
||||
result = shapely.from_ragged_array(typ, coords, offsets)
|
||||
# in a roundtrip, missing geometries come back as empty
|
||||
arr[-2] = shapely.from_wkt("MULTIPOLYGON EMPTY")
|
||||
assert_geometries_equal(result, arr)
|
||||
|
||||
|
||||
|
||||
@@ -22,14 +22,14 @@ SET_OPERATIONS = (
|
||||
shapely.intersection,
|
||||
shapely.symmetric_difference,
|
||||
shapely.union,
|
||||
# shapely.coverage_union is tested seperately
|
||||
# shapely.coverage_union is tested separately
|
||||
)
|
||||
|
||||
REDUCE_SET_OPERATIONS = (
|
||||
(shapely.intersection_all, shapely.intersection),
|
||||
(shapely.symmetric_difference_all, shapely.symmetric_difference),
|
||||
(shapely.union_all, shapely.union),
|
||||
# shapely.coverage_union_all, shapely.coverage_union) is tested seperately
|
||||
# shapely.coverage_union_all, shapely.coverage_union) is tested separately
|
||||
)
|
||||
|
||||
# operations that support fixed precision
|
||||
@@ -53,6 +53,13 @@ non_polygon_types = [
|
||||
@pytest.mark.parametrize("a", all_types)
|
||||
@pytest.mark.parametrize("func", SET_OPERATIONS)
|
||||
def test_set_operation_array(a, func):
|
||||
if (
|
||||
func is shapely.difference
|
||||
and a.geom_type == "GeometryCollection"
|
||||
and shapely.get_num_geometries(a) == 2
|
||||
and shapely.geos_version == (3, 9, 5)
|
||||
):
|
||||
pytest.xfail("GEOS 3.9.5 crashes with mixed collection")
|
||||
actual = func(a, point)
|
||||
assert isinstance(actual, Geometry)
|
||||
|
||||
@@ -270,7 +277,7 @@ def test_set_operation_prec_reduce_all_none(n, func, related_func):
|
||||
@pytest.mark.parametrize("n", range(1, 4))
|
||||
def test_coverage_union_reduce_1dim(n):
|
||||
"""
|
||||
This is tested seperately from other set operations as it differs in two ways:
|
||||
This is tested separately from other set operations as it differs in two ways:
|
||||
1. It expects only non-overlapping polygons
|
||||
2. It expects GEOS 3.8.0+
|
||||
"""
|
||||
@@ -307,7 +314,7 @@ def test_coverage_union_overlapping_inputs():
|
||||
other = Polygon([(1, 0), (0.9, 1), (2, 1), (2, 0), (1, 0)])
|
||||
|
||||
if shapely.geos_version >= (3, 12, 0):
|
||||
# Return mostly unchaged output
|
||||
# Return mostly unchanged output
|
||||
result = shapely.coverage_union(polygon, other)
|
||||
expected = shapely.multipolygons([polygon, other])
|
||||
assert_geometries_equal(result, expected, normalize=True)
|
||||
|
||||
@@ -10,7 +10,7 @@ import pytest
|
||||
from numpy.testing import assert_array_equal
|
||||
|
||||
import shapely
|
||||
from shapely import box, geos_version, MultiPoint, Point, STRtree
|
||||
from shapely import box, geos_version, LineString, MultiPoint, Point, STRtree
|
||||
from shapely.errors import UnsupportedGEOSVersionError
|
||||
from shapely.testing import assert_geometries_equal
|
||||
from shapely.tests.common import (
|
||||
@@ -368,39 +368,51 @@ def test_query_with_partially_prepared_inputs(tree):
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"predicate",
|
||||
"predicate,expected",
|
||||
[
|
||||
# intersects is intentionally omitted; it does not raise an exception
|
||||
pytest.param(
|
||||
"intersects",
|
||||
[1],
|
||||
marks=pytest.mark.xfail(geos_version < (3, 13, 0), reason="GEOS < 3.13"),
|
||||
),
|
||||
pytest.param(
|
||||
"within",
|
||||
[],
|
||||
marks=pytest.mark.xfail(geos_version < (3, 8, 0), reason="GEOS < 3.8"),
|
||||
),
|
||||
pytest.param(
|
||||
"contains",
|
||||
[],
|
||||
marks=pytest.mark.xfail(geos_version < (3, 8, 0), reason="GEOS < 3.8"),
|
||||
),
|
||||
"overlaps",
|
||||
"crosses",
|
||||
"touches",
|
||||
("overlaps", []),
|
||||
("crosses", [1]),
|
||||
("touches", []),
|
||||
pytest.param(
|
||||
"covers",
|
||||
[],
|
||||
marks=pytest.mark.xfail(geos_version < (3, 8, 0), reason="GEOS < 3.8"),
|
||||
),
|
||||
pytest.param(
|
||||
"covered_by",
|
||||
[],
|
||||
marks=pytest.mark.xfail(geos_version < (3, 8, 0), reason="GEOS < 3.8"),
|
||||
),
|
||||
pytest.param(
|
||||
"contains_properly",
|
||||
[],
|
||||
marks=pytest.mark.xfail(geos_version < (3, 8, 0), reason="GEOS < 3.8"),
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_query_predicate_errors(tree, predicate):
|
||||
def test_query_predicate_errors(tree, predicate, expected):
|
||||
with ignore_invalid():
|
||||
line_nan = shapely.linestrings([1, 1], [1, float("nan")])
|
||||
with pytest.raises(shapely.GEOSException):
|
||||
tree.query(line_nan, predicate=predicate)
|
||||
if geos_version < (3, 13, 0):
|
||||
with pytest.raises(shapely.GEOSException):
|
||||
tree.query(line_nan, predicate=predicate)
|
||||
else:
|
||||
assert_array_equal(tree.query(line_nan, predicate=predicate), expected)
|
||||
|
||||
|
||||
### predicate == 'intersects'
|
||||
@@ -928,12 +940,12 @@ def test_query_crosses_polygons(poly_tree, geometry, expected):
|
||||
# box contains points but touches only those at edges
|
||||
(box(3, 3, 6, 6), [3, 6]),
|
||||
([box(3, 3, 6, 6)], [[0, 0], [3, 6]]),
|
||||
# buffer completely contains point in tree
|
||||
# polygon completely contains point in tree
|
||||
(shapely.buffer(Point(3, 3), 1), []),
|
||||
([shapely.buffer(Point(3, 3), 1)], [[], []]),
|
||||
# buffer intersects 2 points but touches only one
|
||||
(shapely.buffer(Point(0, 1), 1), [1]),
|
||||
([shapely.buffer(Point(0, 1), 1)], [[0], [1]]),
|
||||
# linestring intersects 2 points but touches only one
|
||||
(LineString([(-1, -1), (1, 1)]), [1]),
|
||||
([LineString([(-1, -1), (1, 1)])], [[0], [1]]),
|
||||
# multipoints intersect but not valid relation
|
||||
(MultiPoint([[5, 5], [7, 7]]), []),
|
||||
([MultiPoint([[5, 5], [7, 7]])], [[], []]),
|
||||
|
||||
Reference in New Issue
Block a user