| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390 |
- import numpy as np
- import pytest
- import shapely
- from shapely import (
- Geometry,
- GeometryCollection,
- GEOSException,
- LinearRing,
- LineString,
- MultiLineString,
- MultiPoint,
- MultiPolygon,
- Point,
- Polygon,
- geos_version,
- )
- from shapely.errors import UnsupportedGEOSVersionError
- from shapely.testing import assert_geometries_equal
- from shapely.tests.common import (
- ArrayLike,
- all_types,
- empty,
- empty_line_string,
- empty_point,
- empty_polygon,
- ignore_invalid,
- line_string,
- multi_point,
- point,
- point_z,
- )
- geos39 = geos_version[0:2] == (3, 9)
- geos310 = geos_version[0:2] == (3, 10)
- geos311 = geos_version[0:2] == (3, 11)
- CONSTRUCTIVE_NO_ARGS = (
- shapely.boundary,
- shapely.centroid,
- shapely.convex_hull,
- pytest.param(
- shapely.concave_hull,
- marks=pytest.mark.skipif(
- shapely.geos_version < (3, 11, 0), reason="GEOS < 3.11"
- ),
- ),
- shapely.envelope,
- shapely.extract_unique_points,
- shapely.minimum_clearance_line,
- shapely.node,
- shapely.normalize,
- shapely.point_on_surface,
- pytest.param(
- shapely.constrained_delaunay_triangles,
- marks=pytest.mark.skipif(
- shapely.geos_version < (3, 10, 0), reason="GEOS < 3.10"
- ),
- ),
- )
- CONSTRUCTIVE_FLOAT_ARG = (
- shapely.buffer,
- shapely.offset_curve,
- shapely.delaunay_triangles,
- shapely.simplify,
- shapely.voronoi_polygons,
- )
- @pytest.mark.parametrize("geometry", all_types)
- @pytest.mark.parametrize("func", CONSTRUCTIVE_NO_ARGS)
- def test_no_args_array(geometry, func):
- if (
- geometry.is_empty
- and shapely.get_num_geometries(geometry) > 0
- and func is shapely.node
- and (
- (geos39 and geos_version < (3, 9, 3))
- or (geos310 and geos_version < (3, 10, 3))
- )
- ): # GEOS GH-601
- pytest.xfail("GEOS < 3.9.3 or GEOS < 3.10.3 crashes with empty geometries")
- actual = func([geometry, geometry])
- assert actual.shape == (2,)
- assert actual[0] is None or isinstance(actual[0], Geometry)
- @pytest.mark.parametrize("geometry", all_types)
- @pytest.mark.parametrize("func", CONSTRUCTIVE_FLOAT_ARG)
- def test_float_arg_array(geometry, func):
- if (
- func is shapely.offset_curve
- and shapely.get_type_id(geometry) not in [1, 2]
- and shapely.geos_version < (3, 11, 0)
- ):
- with pytest.raises(GEOSException, match="only accept linestrings"):
- func([geometry, geometry], 0.0)
- return
- # voronoi_polygons emits an "invalid" warning when supplied with an empty
- # point (see https://github.com/libgeos/geos/issues/515)
- with ignore_invalid(
- func is shapely.voronoi_polygons
- and shapely.get_type_id(geometry) == 0
- and shapely.geos_version < (3, 12, 0)
- ):
- actual = func([geometry, geometry], 0.0)
- assert actual.shape == (2,)
- assert isinstance(actual[0], Geometry)
- @pytest.mark.parametrize("geometry", all_types)
- @pytest.mark.parametrize("reference", all_types)
- def test_snap_array(geometry, reference):
- actual = shapely.snap([geometry, geometry], [reference, reference], tolerance=1.0)
- assert actual.shape == (2,)
- assert isinstance(actual[0], Geometry)
- @pytest.mark.parametrize("func", CONSTRUCTIVE_NO_ARGS)
- def test_no_args_missing(func):
- actual = func(None)
- assert actual is None
- @pytest.mark.parametrize("func", CONSTRUCTIVE_FLOAT_ARG)
- def test_float_arg_missing(func):
- actual = func(None, 1.0)
- assert actual is None
- @pytest.mark.parametrize("geometry", all_types)
- @pytest.mark.parametrize("func", CONSTRUCTIVE_FLOAT_ARG)
- def test_float_arg_nan(geometry, func):
- actual = func(geometry, float("nan"))
- assert actual is None
- def test_buffer_cap_style_invalid():
- with pytest.raises(ValueError, match="'invalid' is not a valid option"):
- shapely.buffer(point, 1, cap_style="invalid")
- def test_buffer_join_style_invalid():
- with pytest.raises(ValueError, match="'invalid' is not a valid option"):
- shapely.buffer(point, 1, join_style="invalid")
- def test_snap_none():
- actual = shapely.snap(None, point, tolerance=1.0)
- assert actual is None
- @pytest.mark.parametrize("geometry", all_types)
- def test_snap_nan_float(geometry):
- actual = shapely.snap(geometry, point, tolerance=np.nan)
- assert actual is None
- def test_build_area_none():
- actual = shapely.build_area(None)
- assert actual is None
- @pytest.mark.parametrize(
- "geom,expected",
- [
- (point, empty), # a point has no area
- (line_string, empty), # a line string has no area
- # geometry collection of two polygons are combined into one
- (
- GeometryCollection(
- [
- Polygon([(0, 0), (0, 3), (3, 3), (3, 0), (0, 0)]),
- Polygon([(1, 1), (2, 2), (1, 2), (1, 1)]),
- ]
- ),
- Polygon(
- [(0, 0), (0, 3), (3, 3), (3, 0), (0, 0)],
- holes=[[(1, 1), (2, 2), (1, 2), (1, 1)]],
- ),
- ),
- (empty, empty),
- ([empty], [empty]),
- ],
- )
- def test_build_area(geom, expected):
- actual = shapely.build_area(geom)
- assert actual is not expected
- assert actual == expected
- def test_make_valid_none():
- actual = shapely.make_valid(None)
- assert actual is None
- @pytest.mark.parametrize(
- "geom,expected",
- [
- (point, point), # a valid geometry stays the same (but is copied)
- # an L shaped polygon without area is converted to a multilinestring
- (
- Polygon([(0, 0), (1, 1), (1, 2), (1, 1), (0, 0)]),
- MultiLineString([((1, 1), (1, 2)), ((0, 0), (1, 1))]),
- ),
- # a polygon with self-intersection (bowtie) is converted into polygons
- (
- Polygon([(0, 0), (2, 2), (2, 0), (0, 2), (0, 0)]),
- MultiPolygon(
- [
- Polygon([(1, 1), (2, 2), (2, 0), (1, 1)]),
- Polygon([(0, 0), (0, 2), (1, 1), (0, 0)]),
- ]
- ),
- ),
- (empty, empty),
- ([empty], [empty]),
- ],
- )
- def test_make_valid(geom, expected):
- actual = shapely.make_valid(geom)
- assert actual is not expected
- # normalize needed to handle variation in output across GEOS versions
- assert shapely.normalize(actual) == expected
- @pytest.mark.parametrize(
- "geom,expected",
- [
- (all_types, all_types),
- # first polygon is valid, second polygon has self-intersection
- (
- [
- Polygon([(0, 0), (2, 2), (0, 2), (0, 0)]),
- Polygon([(0, 0), (2, 2), (2, 0), (0, 2), (0, 0)]),
- ],
- [
- Polygon([(0, 0), (2, 2), (0, 2), (0, 0)]),
- MultiPolygon(
- [
- Polygon([(1, 1), (0, 0), (0, 2), (1, 1)]),
- Polygon([(1, 1), (2, 2), (2, 0), (1, 1)]),
- ]
- ),
- ],
- ),
- ([point, None, empty], [point, None, empty]),
- ],
- )
- def test_make_valid_1d(geom, expected):
- actual = shapely.make_valid(geom)
- # normalize needed to handle variation in output across GEOS versions
- assert np.all(shapely.normalize(actual) == shapely.normalize(expected))
- @pytest.mark.skipif(shapely.geos_version < (3, 10, 0), reason="GEOS < 3.10")
- @pytest.mark.parametrize(
- "geom,expected",
- [
- (point, point), # a valid geometry stays the same (but is copied)
- # an L shaped polygon without area is converted to a linestring
- (
- Polygon([(0, 0), (1, 1), (1, 2), (1, 1), (0, 0)]),
- LineString([(0, 0), (1, 1), (1, 2), (1, 1), (0, 0)]),
- ),
- # a polygon with self-intersection (bowtie) is converted into polygons
- (
- Polygon([(0, 0), (2, 2), (2, 0), (0, 2), (0, 0)]),
- MultiPolygon(
- [
- Polygon([(1, 1), (2, 2), (2, 0), (1, 1)]),
- Polygon([(0, 0), (0, 2), (1, 1), (0, 0)]),
- ]
- ),
- ),
- (empty, empty),
- ([empty], [empty]),
- ],
- )
- def test_make_valid_structure(geom, expected):
- actual = shapely.make_valid(geom, method="structure")
- assert actual is not expected
- # normalize needed to handle variation in output across GEOS versions
- assert shapely.normalize(actual) == expected
- @pytest.mark.skipif(shapely.geos_version < (3, 10, 0), reason="GEOS < 3.10")
- @pytest.mark.parametrize(
- "geom,expected",
- [
- (point, point), # a valid geometry stays the same (but is copied)
- # an L shaped polygon without area is converted to Empty Polygon
- (
- Polygon([(0, 0), (1, 1), (1, 2), (1, 1), (0, 0)]),
- Polygon(),
- ),
- # a polygon with self-intersection (bowtie) is converted into polygons
- (
- Polygon([(0, 0), (2, 2), (2, 0), (0, 2), (0, 0)]),
- MultiPolygon(
- [
- Polygon([(1, 1), (2, 2), (2, 0), (1, 1)]),
- Polygon([(0, 0), (0, 2), (1, 1), (0, 0)]),
- ]
- ),
- ),
- (empty, empty),
- ([empty], [empty]),
- ],
- )
- def test_make_valid_structure_keep_collapsed_false(geom, expected):
- actual = shapely.make_valid(geom, method="structure", keep_collapsed=False)
- assert actual is not expected
- # normalize needed to handle variation in output across GEOS versions
- assert shapely.normalize(actual) == expected
- @pytest.mark.skipif(shapely.geos_version >= (3, 10, 0), reason="GEOS >= 3.10")
- def test_make_valid_structure_unsupported_geos():
- with pytest.raises(
- ValueError, match="The 'structure' method is only available in GEOS >= 3.10.0"
- ):
- _ = shapely.make_valid(Point(), method="structure")
- @pytest.mark.skipif(shapely.geos_version < (3, 10, 0), reason="GEOS < 3.10")
- @pytest.mark.parametrize(
- "method, keep_collapsed, error_type, error",
- [
- (
- np.array(["linework", "structure"]),
- True,
- TypeError,
- "method only accepts scalar values",
- ),
- (
- "linework",
- [True, False],
- TypeError,
- "keep_collapsed only accepts scalar values",
- ),
- ("unknown", True, ValueError, "Unknown method: unknown"),
- (
- "linework",
- False,
- ValueError,
- "The 'linework' method does not support 'keep_collapsed=False'",
- ),
- ],
- )
- def test_make_valid_invalid_params(method, keep_collapsed, error_type, error):
- with pytest.raises(error_type, match=error):
- _ = shapely.make_valid(Point(), method=method, keep_collapsed=keep_collapsed)
- @pytest.mark.parametrize(
- "geom,expected",
- [
- (point, point), # a point is always in normalized form
- # order coordinates of linestrings and parts of multi-linestring
- (
- MultiLineString([((1, 1), (0, 0)), ((1, 1), (1, 2))]),
- MultiLineString([((1, 1), (1, 2)), ((0, 0), (1, 1))]),
- ),
- ],
- )
- def test_normalize(geom, expected):
- actual = shapely.normalize(geom)
- assert actual == expected
- def test_offset_curve_empty():
- with ignore_invalid(shapely.geos_version < (3, 12, 0)):
- # Empty geometries emit an "invalid" warning
- # (see https://github.com/libgeos/geos/issues/515)
- actual = shapely.offset_curve(empty_line_string, 2.0)
- assert shapely.is_empty(actual)
- def test_offset_curve_distance_array():
- # check that kwargs are passed through
- result = shapely.offset_curve([line_string, line_string], [-2.0, -3.0])
- assert result[0] == shapely.offset_curve(line_string, -2.0)
- assert result[1] == shapely.offset_curve(line_string, -3.0)
- def test_offset_curve_kwargs():
- # check that kwargs are passed through
- result1 = shapely.offset_curve(
- line_string, -2.0, quad_segs=2, join_style="mitre", mitre_limit=2.0
- )
- result2 = shapely.offset_curve(line_string, -2.0)
- assert result1 != result2
- def test_offset_curve_non_scalar_kwargs():
- msg = "only accepts scalar values"
- with pytest.raises(TypeError, match=msg):
- shapely.offset_curve([line_string, line_string], 1, quad_segs=np.array([8, 9]))
- with pytest.raises(TypeError, match=msg):
- shapely.offset_curve(
- [line_string, line_string], 1, join_style=["round", "bevel"]
- )
- with pytest.raises(TypeError, match=msg):
- shapely.offset_curve([line_string, line_string], 1, mitre_limit=[5.0, 6.0])
- def test_offset_curve_join_style_invalid():
- with pytest.raises(ValueError, match="'invalid' is not a valid option"):
- shapely.offset_curve(line_string, 1.0, join_style="invalid")
- @pytest.mark.skipif(shapely.geos_version < (3, 11, 0), reason="GEOS < 3.11")
- @pytest.mark.parametrize(
- "geom,expected",
- [
- (LineString([(0, 0), (0, 0), (1, 0)]), LineString([(0, 0), (1, 0)])),
- (
- LinearRing([(0, 0), (1, 2), (1, 2), (1, 3), (0, 0)]),
- LinearRing([(0, 0), (1, 2), (1, 3), (0, 0)]),
- ),
- (
- Polygon([(0, 0), (0, 0), (1, 0), (1, 1), (1, 0), (0, 0)]),
- Polygon([(0, 0), (1, 0), (1, 1), (1, 0), (0, 0)]),
- ),
- (
- Polygon(
- [(0, 0), (10, 0), (10, 10), (0, 10), (0, 0)],
- holes=[[(2, 2), (2, 2), (2, 4), (4, 4), (4, 2), (2, 2)]],
- ),
- Polygon(
- [(0, 0), (10, 0), (10, 10), (0, 10), (0, 0)],
- holes=[[(2, 2), (2, 4), (4, 4), (4, 2), (2, 2)]],
- ),
- ),
- (
- MultiPolygon(
- [
- Polygon([(0, 0), (0, 0), (1, 0), (1, 1), (0, 1), (0, 0)]),
- Polygon([(2, 2), (2, 2), (2, 3), (3, 3), (3, 2), (2, 2)]),
- ]
- ),
- MultiPolygon(
- [
- Polygon([(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)]),
- Polygon([(2, 2), (2, 3), (3, 3), (3, 2), (2, 2)]),
- ]
- ),
- ),
- # points are unchanged
- (point, point),
- (point_z, point_z),
- (multi_point, multi_point),
- # empty geometries are unchanged
- (empty_point, empty_point),
- (empty_line_string, empty_line_string),
- (empty, empty),
- (empty_polygon, empty_polygon),
- ],
- )
- def test_remove_repeated_points(geom, expected):
- assert_geometries_equal(shapely.remove_repeated_points(geom, 0), expected)
- @pytest.mark.skipif(shapely.geos_version < (3, 12, 0), reason="GEOS < 3.12")
- @pytest.mark.parametrize(
- "geom, tolerance", [[Polygon([(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)]), 2]]
- )
- def test_remove_repeated_points_invalid_result(geom, tolerance):
- # Requiring GEOS 3.12 instead of 3.11
- # (GEOS 3.11 had a bug causing this to intermittently not fail)
- with pytest.raises(shapely.GEOSException, match="Invalid number of points"):
- shapely.remove_repeated_points(geom, tolerance)
- @pytest.mark.skipif(shapely.geos_version < (3, 11, 0), reason="GEOS < 3.11")
- def test_remove_repeated_points_none():
- assert shapely.remove_repeated_points(None, 1) is None
- assert shapely.remove_repeated_points([None], 1).tolist() == [None]
- geometry = LineString([(0, 0), (0, 0), (1, 1)])
- expected = LineString([(0, 0), (1, 1)])
- result = shapely.remove_repeated_points([None, geometry], 1)
- assert result[0] is None
- assert_geometries_equal(result[1], expected)
- @pytest.mark.skipif(shapely.geos_version < (3, 11, 0), reason="GEOS < 3.11")
- @pytest.mark.parametrize("geom, tolerance", [("Not a geometry", 1), (1, 1)])
- def test_remove_repeated_points_invalid_type(geom, tolerance):
- with pytest.raises(TypeError, match="One of the arguments is of incorrect type"):
- shapely.remove_repeated_points(geom, tolerance)
- @pytest.mark.parametrize(
- "geom,expected",
- [
- (LineString([(0, 0), (1, 2)]), LineString([(1, 2), (0, 0)])),
- (
- LinearRing([(0, 0), (1, 2), (1, 3), (0, 0)]),
- LinearRing([(0, 0), (1, 3), (1, 2), (0, 0)]),
- ),
- (
- Polygon([(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)]),
- Polygon([(0, 0), (0, 1), (1, 1), (1, 0), (0, 0)]),
- ),
- (
- Polygon(
- [(0, 0), (10, 0), (10, 10), (0, 10), (0, 0)],
- holes=[[(2, 2), (2, 4), (4, 4), (4, 2), (2, 2)]],
- ),
- Polygon(
- [(0, 0), (0, 10), (10, 10), (10, 0), (0, 0)],
- holes=[[(2, 2), (4, 2), (4, 4), (2, 4), (2, 2)]],
- ),
- ),
- (
- MultiLineString([[(0, 0), (1, 2)], [(3, 3), (4, 4)]]),
- MultiLineString([[(1, 2), (0, 0)], [(4, 4), (3, 3)]]),
- ),
- (
- MultiPolygon(
- [
- Polygon([(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)]),
- Polygon([(2, 2), (2, 3), (3, 3), (3, 2), (2, 2)]),
- ]
- ),
- MultiPolygon(
- [
- Polygon([(0, 0), (0, 1), (1, 1), (1, 0), (0, 0)]),
- Polygon([(2, 2), (3, 2), (3, 3), (2, 3), (2, 2)]),
- ]
- ),
- ),
- # points are unchanged
- (point, point),
- (point_z, point_z),
- (multi_point, multi_point),
- # empty geometries are unchanged
- (empty_point, empty_point),
- (empty_line_string, empty_line_string),
- (empty, empty),
- (empty_polygon, empty_polygon),
- ],
- )
- def test_reverse(geom, expected):
- assert_geometries_equal(shapely.reverse(geom), expected)
- def test_reverse_none():
- assert shapely.reverse(None) is None
- assert shapely.reverse([None]).tolist() == [None]
- geometry = Polygon([(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)])
- expected = Polygon([(0, 0), (0, 1), (1, 1), (1, 0), (0, 0)])
- result = shapely.reverse([None, geometry])
- assert result[0] is None
- assert_geometries_equal(result[1], expected)
- @pytest.mark.parametrize("geom", ["Not a geometry", 1])
- def test_reverse_invalid_type(geom):
- with pytest.raises(TypeError, match="One of the arguments is of incorrect type"):
- shapely.reverse(geom)
- @pytest.mark.parametrize(
- "geom,expected",
- [
- # Point outside
- (Point(0, 0), GeometryCollection()),
- # Point inside
- (Point(15, 15), Point(15, 15)),
- # Point on boundary
- (Point(15, 10), GeometryCollection()),
- # Line outside
- (LineString([(0, 0), (-5, 5)]), GeometryCollection()),
- # Line inside
- (LineString([(15, 15), (16, 15)]), LineString([(15, 15), (16, 15)])),
- # Line on boundary
- (LineString([(10, 15), (10, 10), (15, 10)]), GeometryCollection()),
- # Line splitting rectangle
- (LineString([(10, 5), (25, 20)]), LineString([(15, 10), (20, 15)])),
- ],
- )
- def test_clip_by_rect(geom, expected):
- actual = shapely.clip_by_rect(geom, 10, 10, 20, 20)
- assert_geometries_equal(actual, expected)
- @pytest.mark.parametrize(
- "geom, rect, expected",
- [
- # Polygon hole (CCW) fully on rectangle boundary"""
- (
- Polygon(
- ((0, 0), (0, 30), (30, 30), (30, 0), (0, 0)),
- holes=[((10, 10), (20, 10), (20, 20), (10, 20), (10, 10))],
- ),
- (10, 10, 20, 20),
- GeometryCollection(),
- ),
- # Polygon hole (CW) fully on rectangle boundary"""
- (
- Polygon(
- ((0, 0), (0, 30), (30, 30), (30, 0), (0, 0)),
- holes=[((10, 10), (10, 20), (20, 20), (20, 10), (10, 10))],
- ),
- (10, 10, 20, 20),
- GeometryCollection(),
- ),
- # Polygon fully within rectangle"""
- (
- Polygon(
- ((1, 1), (1, 30), (30, 30), (30, 1), (1, 1)),
- holes=[((10, 10), (20, 10), (20, 20), (10, 20), (10, 10))],
- ),
- (0, 0, 40, 40),
- Polygon(
- ((1, 1), (1, 30), (30, 30), (30, 1), (1, 1)),
- holes=[((10, 10), (20, 10), (20, 20), (10, 20), (10, 10))],
- ),
- ),
- # Polygon overlapping rectanglez
- (
- Polygon(
- [(0, 0), (0, 30), (30, 30), (30, 0), (0, 0)],
- holes=[[(10, 10), (20, 10), (20, 20), (10, 20), (10, 10)]],
- ),
- (5, 5, 15, 15),
- Polygon([(5, 5), (5, 15), (10, 15), (10, 10), (15, 10), (15, 5), (5, 5)]),
- ),
- ],
- )
- def test_clip_by_rect_polygon(geom, rect, expected):
- actual = shapely.clip_by_rect(geom, *rect)
- assert_geometries_equal(actual, expected)
- @pytest.mark.parametrize("geometry", all_types)
- def test_clip_by_rect_array(geometry):
- if (
- geometry.is_empty
- and shapely.get_type_id(geometry) == shapely.GeometryType.POINT
- and (
- (geos39 and geos_version < (3, 9, 5))
- or (geos310 and geos_version < (3, 10, 6))
- or (geos311 and geos_version < (3, 11, 3))
- )
- ):
- # GEOS GH-913
- with pytest.raises(GEOSException):
- shapely.clip_by_rect([geometry, geometry], 0.0, 0.0, 1.0, 1.0)
- return
- actual = shapely.clip_by_rect([geometry, geometry], 0.0, 0.0, 1.0, 1.0)
- assert actual.shape == (2,)
- assert actual[0] is None or isinstance(actual[0], Geometry)
- def test_clip_by_rect_missing():
- actual = shapely.clip_by_rect(None, 0, 0, 1, 1)
- assert actual is None
- @pytest.mark.parametrize("geom", [empty, empty_line_string, empty_polygon])
- def test_clip_by_rect_empty(geom):
- # TODO empty point
- actual = shapely.clip_by_rect(geom, 0, 0, 1, 1)
- assert actual == GeometryCollection()
- def test_clip_by_rect_non_scalar_kwargs():
- msg = "only accepts scalar values"
- with pytest.raises(TypeError, match=msg):
- shapely.clip_by_rect([line_string, line_string], 0, 0, 1, np.array([0, 1]))
- def test_polygonize():
- lines = [
- LineString([(0, 0), (1, 1)]),
- LineString([(0, 0), (0, 1)]),
- LineString([(0, 1), (1, 1)]),
- LineString([(1, 1), (1, 0)]),
- LineString([(1, 0), (0, 0)]),
- LineString([(5, 5), (6, 6)]),
- Point(0, 0),
- None,
- ]
- result = shapely.polygonize(lines)
- assert shapely.get_type_id(result) == 7 # GeometryCollection
- expected = GeometryCollection(
- [
- Polygon([(0, 0), (1, 1), (1, 0), (0, 0)]),
- Polygon([(1, 1), (0, 0), (0, 1), (1, 1)]),
- ]
- )
- assert result == expected
- def test_polygonize_array():
- lines = [
- LineString([(0, 0), (1, 1)]),
- LineString([(0, 0), (0, 1)]),
- LineString([(0, 1), (1, 1)]),
- ]
- expected = GeometryCollection([Polygon([(1, 1), (0, 0), (0, 1), (1, 1)])])
- result = shapely.polygonize(np.array(lines))
- assert isinstance(result, shapely.Geometry)
- assert result == expected
- result = shapely.polygonize(np.array([lines]))
- assert isinstance(result, np.ndarray)
- assert result.shape == (1,)
- assert result[0] == expected
- arr = np.array([lines, lines])
- assert arr.shape == (2, 3)
- result = shapely.polygonize(arr)
- assert isinstance(result, np.ndarray)
- assert result.shape == (2,)
- assert result[0] == expected
- assert result[1] == expected
- arr = np.array([[lines, lines], [lines, lines], [lines, lines]])
- assert arr.shape == (3, 2, 3)
- result = shapely.polygonize(arr)
- assert isinstance(result, np.ndarray)
- assert result.shape == (3, 2)
- for res in result.flatten():
- assert res == expected
- def test_polygonize_array_axis():
- lines = [
- LineString([(0, 0), (1, 1)]),
- LineString([(0, 0), (0, 1)]),
- LineString([(0, 1), (1, 1)]),
- ]
- arr = np.array([lines, lines]) # shape (2, 3)
- result = shapely.polygonize(arr, axis=1)
- assert result.shape == (2,)
- result = shapely.polygonize(arr, axis=0)
- assert result.shape == (3,)
- def test_polygonize_missing():
- # set of geometries that is all missing
- result = shapely.polygonize([None, None])
- assert result == GeometryCollection()
- def test_polygonize_full():
- lines = [
- None,
- LineString([(0, 0), (1, 1)]),
- LineString([(0, 0), (0, 1)]),
- LineString([(0, 1), (1, 1)]),
- LineString([(1, 1), (1, 0)]),
- None,
- LineString([(1, 0), (0, 0)]),
- LineString([(5, 5), (6, 6)]),
- LineString([(1, 1), (100, 100)]),
- Point(0, 0),
- None,
- ]
- result = shapely.polygonize_full(lines)
- assert len(result) == 4
- assert all(shapely.get_type_id(geom) == 7 for geom in result) # GeometryCollection
- polygons, cuts, dangles, invalid = result
- expected_polygons = GeometryCollection(
- [
- Polygon([(0, 0), (1, 1), (1, 0), (0, 0)]),
- Polygon([(1, 1), (0, 0), (0, 1), (1, 1)]),
- ]
- )
- assert polygons == expected_polygons
- assert cuts == GeometryCollection()
- expected_dangles = GeometryCollection(
- [LineString([(1, 1), (100, 100)]), LineString([(5, 5), (6, 6)])]
- )
- assert dangles == expected_dangles
- assert invalid == GeometryCollection()
- def test_polygonize_full_array():
- lines = [
- LineString([(0, 0), (1, 1)]),
- LineString([(0, 0), (0, 1)]),
- LineString([(0, 1), (1, 1)]),
- ]
- expected = GeometryCollection([Polygon([(1, 1), (0, 0), (0, 1), (1, 1)])])
- result = shapely.polygonize_full(np.array(lines))
- assert len(result) == 4
- assert all(isinstance(geom, shapely.Geometry) for geom in result)
- assert result[0] == expected
- assert all(geom == GeometryCollection() for geom in result[1:])
- result = shapely.polygonize_full(np.array([lines]))
- assert len(result) == 4
- assert all(isinstance(geom, np.ndarray) for geom in result)
- assert all(geom.shape == (1,) for geom in result)
- assert result[0][0] == expected
- assert all(geom[0] == GeometryCollection() for geom in result[1:])
- arr = np.array([lines, lines])
- assert arr.shape == (2, 3)
- result = shapely.polygonize_full(arr)
- assert len(result) == 4
- assert all(isinstance(arr, np.ndarray) for arr in result)
- assert all(arr.shape == (2,) for arr in result)
- assert result[0][0] == expected
- assert result[0][1] == expected
- assert all(g == GeometryCollection() for geom in result[1:] for g in geom)
- arr = np.array([[lines, lines], [lines, lines], [lines, lines]])
- assert arr.shape == (3, 2, 3)
- result = shapely.polygonize_full(arr)
- assert len(result) == 4
- assert all(isinstance(arr, np.ndarray) for arr in result)
- assert all(arr.shape == (3, 2) for arr in result)
- for res in result[0].flatten():
- assert res == expected
- for arr in result[1:]:
- for res in arr.flatten():
- assert res == GeometryCollection()
- def test_polygonize_full_array_axis():
- lines = [
- LineString([(0, 0), (1, 1)]),
- LineString([(0, 0), (0, 1)]),
- LineString([(0, 1), (1, 1)]),
- ]
- arr = np.array([lines, lines]) # shape (2, 3)
- result = shapely.polygonize_full(arr, axis=1)
- assert len(result) == 4
- assert all(arr.shape == (2,) for arr in result)
- result = shapely.polygonize_full(arr, axis=0)
- assert len(result) == 4
- assert all(arr.shape == (3,) for arr in result)
- def test_polygonize_full_missing():
- # set of geometries that is all missing
- result = shapely.polygonize_full([None, None])
- assert len(result) == 4
- assert all(geom == GeometryCollection() for geom in result)
- @pytest.mark.skipif(shapely.geos_version < (3, 10, 0), reason="GEOS < 3.10")
- @pytest.mark.parametrize("geometry", all_types)
- @pytest.mark.parametrize("max_segment_length", [-1, 0])
- def test_segmentize_invalid_max_segment_length(geometry, max_segment_length):
- with pytest.raises(GEOSException, match="IllegalArgumentException"):
- shapely.segmentize(geometry, max_segment_length=max_segment_length)
- @pytest.mark.skipif(shapely.geos_version < (3, 10, 0), reason="GEOS < 3.10")
- @pytest.mark.parametrize("geometry", all_types)
- def test_segmentize_max_segment_length_nan(geometry):
- actual = shapely.segmentize(geometry, max_segment_length=np.nan)
- assert actual is None
- @pytest.mark.skipif(shapely.geos_version < (3, 10, 0), reason="GEOS < 3.10")
- @pytest.mark.parametrize(
- "geometry", [empty, empty_point, empty_line_string, empty_polygon]
- )
- def test_segmentize_empty(geometry):
- actual = shapely.segmentize(geometry, max_segment_length=5)
- assert_geometries_equal(actual, geometry)
- @pytest.mark.skipif(shapely.geos_version < (3, 10, 0), reason="GEOS < 3.10")
- @pytest.mark.parametrize("geometry", [point, point_z, multi_point])
- def test_segmentize_no_change(geometry):
- actual = shapely.segmentize(geometry, max_segment_length=5)
- assert_geometries_equal(actual, geometry)
- @pytest.mark.skipif(shapely.geos_version < (3, 10, 0), reason="GEOS < 3.10")
- def test_segmentize_none():
- assert shapely.segmentize(None, max_segment_length=5) is None
- @pytest.mark.skipif(shapely.geos_version < (3, 10, 0), reason="GEOS < 3.10")
- @pytest.mark.parametrize(
- "geometry,tolerance, expected",
- [
- # tolerance greater than max edge length, no change
- (
- LineString([(0, 0), (0, 10)]),
- 20,
- LineString([(0, 0), (0, 10)]),
- ),
- (
- Polygon([(0, 0), (10, 0), (10, 10), (0, 10), (0, 0)]),
- 20,
- Polygon([(0, 0), (10, 0), (10, 10), (0, 10), (0, 0)]),
- ),
- # tolerance causes one vertex per segment
- (
- LineString([(0, 0), (0, 10)]),
- 5,
- LineString([(0, 0), (0, 5), (0, 10)]),
- ),
- (
- Polygon([(0, 0), (10, 0), (10, 10), (0, 10), (0, 0)]),
- 5,
- Polygon(
- [
- (0, 0),
- (5, 0),
- (10, 0),
- (10, 5),
- (10, 10),
- (5, 10),
- (0, 10),
- (0, 5),
- (0, 0),
- ]
- ),
- ),
- # ensure input arrays are broadcast correctly
- (
- [
- LineString([(0, 0), (0, 10)]),
- LineString([(0, 0), (0, 2)]),
- ],
- 5,
- [
- LineString([(0, 0), (0, 5), (0, 10)]),
- LineString([(0, 0), (0, 2)]),
- ],
- ),
- (
- [
- LineString([(0, 0), (0, 10)]),
- LineString([(0, 0), (0, 2)]),
- ],
- [5],
- [
- LineString([(0, 0), (0, 5), (0, 10)]),
- LineString([(0, 0), (0, 2)]),
- ],
- ),
- (
- [
- LineString([(0, 0), (0, 10)]),
- LineString([(0, 0), (0, 2)]),
- ],
- [5, 1.5],
- [
- LineString([(0, 0), (0, 5), (0, 10)]),
- LineString([(0, 0), (0, 1), (0, 2)]),
- ],
- ),
- ],
- )
- def test_segmentize(geometry, tolerance, expected):
- actual = shapely.segmentize(geometry, tolerance)
- assert_geometries_equal(actual, expected)
- @pytest.mark.parametrize("geometry", all_types)
- def test_minimum_bounding_circle_all_types(geometry):
- actual = shapely.minimum_bounding_circle([geometry, geometry])
- assert actual.shape == (2,)
- assert actual[0] is None or isinstance(actual[0], Geometry)
- actual = shapely.minimum_bounding_circle(None)
- assert actual is None
- @pytest.mark.parametrize(
- "geometry, expected",
- [
- (
- Polygon([(0, 5), (5, 10), (10, 5), (5, 0), (0, 5)]),
- shapely.buffer(Point(5, 5), 5),
- ),
- (
- LineString([(1, 0), (1, 10)]),
- shapely.buffer(Point(1, 5), 5),
- ),
- (
- MultiPoint([(2, 2), (4, 2)]),
- shapely.buffer(Point(3, 2), 1),
- ),
- (
- Point(2, 2),
- Point(2, 2),
- ),
- (
- GeometryCollection(),
- Polygon(),
- ),
- ],
- )
- def test_minimum_bounding_circle(geometry, expected):
- actual = shapely.minimum_bounding_circle(geometry)
- assert_geometries_equal(actual, expected)
- @pytest.mark.parametrize("geometry", all_types)
- def test_oriented_envelope_all_types(geometry):
- actual = shapely.oriented_envelope([geometry, geometry])
- assert actual.shape == (2,)
- assert actual[0] is None or isinstance(actual[0], Geometry)
- actual = shapely.oriented_envelope(None)
- assert actual is None
- @pytest.mark.parametrize(
- "func", [shapely.oriented_envelope, shapely.minimum_rotated_rectangle]
- )
- @pytest.mark.parametrize(
- "geometry, expected",
- [
- (
- MultiPoint([(1.0, 1.0), (1.0, 5.0), (3.0, 6.0), (4.0, 2.0), (5.0, 5.0)]),
- Polygon([(1.0, 1.0), (1.0, 6.0), (5.0, 6.0), (5.0, 1.0), (1.0, 1.0)]),
- ),
- (
- LineString([(1, 1), (5, 1), (10, 10)]),
- Polygon([(1, 1), (3, -1), (12, 8), (10, 10), (1, 1)]),
- ),
- (
- Polygon([(1, 1), (15, 1), (5, 9), (1, 1)]),
- Polygon([(1.0, 1.0), (5.0, 9.0), (16.2, 3.4), (12.2, -4.6), (1.0, 1.0)]),
- ),
- (
- LineString([(1, 1), (10, 1)]),
- LineString([(1, 1), (10, 1)]),
- ),
- (
- Point(2, 2),
- Point(2, 2),
- ),
- (
- GeometryCollection(),
- Polygon(),
- ),
- ],
- )
- def test_oriented_envelope(geometry, expected, func):
- actual = func(geometry)
- assert_geometries_equal(actual, expected, normalize=True, tolerance=1e-3)
- @pytest.mark.skipif(shapely.geos_version >= (3, 12, 0), reason="GEOS >= 3.12")
- @pytest.mark.parametrize(
- "geometry, expected",
- [
- (
- MultiPoint([(1.0, 1.0), (1.0, 5.0), (3.0, 6.0), (4.0, 2.0), (5.0, 5.0)]),
- Polygon([(-0.2, 1.4), (1.5, 6.5), (5.1, 5.3), (3.4, 0.2), (-0.2, 1.4)]),
- ),
- (
- LineString([(1, 1), (5, 1), (10, 10)]),
- Polygon([(1, 1), (3, -1), (12, 8), (10, 10), (1, 1)]),
- ),
- (
- Polygon([(1, 1), (15, 1), (5, 9), (1, 1)]),
- Polygon([(1.0, 1.0), (1.0, 9.0), (15.0, 9.0), (15.0, 1.0), (1.0, 1.0)]),
- ),
- (
- LineString([(1, 1), (10, 1)]),
- LineString([(1, 1), (10, 1)]),
- ),
- (
- Point(2, 2),
- Point(2, 2),
- ),
- (
- GeometryCollection(),
- Polygon(),
- ),
- ],
- )
- def test_oriented_envelope_pre_geos_312(geometry, expected):
- # use private method (similar as direct shapely.lib.oriented_envelope)
- # to cover the C code for older GEOS versions
- actual = shapely.constructive._oriented_envelope_geos(geometry)
- 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)
- mp = MultiPoint(p.buffer(5).exterior.coords[:] + p.buffer(4).exterior.coords[:])
- result1 = shapely.concave_hull(mp, ratio=0.5)
- assert len(result1.interiors) == 0
- result2 = shapely.concave_hull(mp, ratio=0.5, allow_holes=True)
- assert len(result2.interiors) == 1
- result3 = shapely.concave_hull(mp, ratio=0)
- result4 = shapely.concave_hull(mp, ratio=1)
- assert shapely.get_num_coordinates(result4) < shapely.get_num_coordinates(result3)
- @pytest.mark.skipif(shapely.geos_version < (3, 10, 0), reason="GEOS < 3.10")
- class TestConstrainedDelaunayTriangulation:
- """
- Only testing the number of triangles and their type here.
- This doesn't actually test the points in the resulting geometries.
- """
- def test_poly(self):
- polys = shapely.constrained_delaunay_triangles(
- Polygon([(10, 10), (20, 40), (90, 90), (90, 10), (10, 10)])
- )
- assert len(polys.geoms) == 2
- for p in polys.geoms:
- assert isinstance(p, Polygon)
- def test_multi_polygon(self):
- multipoly = MultiPolygon(
- [
- Polygon(((50, 30), (60, 30), (100, 100), (50, 30))),
- Polygon(((10, 10), (20, 40), (90, 90), (90, 10), (10, 10))),
- ]
- )
- polys = shapely.constrained_delaunay_triangles(multipoly)
- assert len(polys.geoms) == 3
- for p in polys.geoms:
- assert isinstance(p, Polygon)
- def test_point(self):
- p = Point(1, 1)
- polys = shapely.constrained_delaunay_triangles(p)
- assert len(polys.geoms) == 0
- def test_empty_poly(self):
- polys = shapely.constrained_delaunay_triangles(Polygon())
- assert len(polys.geoms) == 0
- @pytest.mark.skipif(shapely.geos_version < (3, 12, 0), reason="GEOS < 3.12")
- def test_voronoi_polygons_ordered():
- mp = MultiPoint([(3.0, 1.0), (3.0, 2.0), (1.0, 2.0), (1.0, 1.0)])
- result = shapely.voronoi_polygons(mp, ordered=False)
- assert result.geoms[0].equals(
- Polygon([(-1, -1), (-1, 1.5), (2, 1.5), (2, -1), (-1, -1)])
- )
- result_ordered = shapely.voronoi_polygons(mp, ordered=True)
- assert result_ordered.geoms[0].equals(
- Polygon([(5, -1), (2, -1), (2, 1.5), (5, 1.5), (5, -1)])
- )
- @pytest.mark.skipif(shapely.geos_version >= (3, 12, 0), reason="GEOS >= 3.12")
- def test_voronoi_polygons_ordered_raise():
- mp = MultiPoint([(3.0, 1.0), (3.0, 2.0), (1.0, 2.0), (1.0, 1.0)])
- with pytest.raises(
- UnsupportedGEOSVersionError, match="Ordered Voronoi polygons require GEOS"
- ):
- shapely.voronoi_polygons(mp, ordered=True)
- @pytest.mark.parametrize("geometry", all_types)
- def test_maximum_inscribed_circle_all_types(geometry):
- if shapely.get_type_id(geometry) not in [3, 6]:
- # Maximum Inscribed Circle is only supported for (Multi)Polygon input
- with pytest.raises(
- GEOSException,
- match=(
- "Argument must be Polygonal or LinearRing|" # GEOS < 3.10.4
- "must be a Polygon or MultiPolygon|"
- "Operation not supported by GeometryCollection"
- ),
- ):
- shapely.maximum_inscribed_circle(geometry)
- return
- if geometry.is_empty:
- with pytest.raises(
- GEOSException, match="Empty input(?: geometry)? is not supported"
- ):
- shapely.maximum_inscribed_circle(geometry)
- return
- actual = shapely.maximum_inscribed_circle([geometry, geometry])
- assert actual.shape == (2,)
- assert actual[0] is None or isinstance(actual[0], Geometry)
- actual = shapely.maximum_inscribed_circle(None)
- assert actual is None
- @pytest.mark.parametrize(
- "geometry, expected",
- [
- (
- "POLYGON ((0 5, 5 10, 10 5, 5 0, 0 5))",
- "LINESTRING (5 5, 2.5 7.5)",
- ),
- ],
- )
- def test_maximum_inscribed_circle(geometry, expected):
- geometry, expected = shapely.from_wkt(geometry), shapely.from_wkt(expected)
- actual = shapely.maximum_inscribed_circle(geometry)
- assert_geometries_equal(actual, expected)
- def test_maximum_inscribed_circle_empty():
- geometry = shapely.from_wkt("POINT EMPTY")
- with pytest.raises(
- GEOSException,
- match=(
- "Argument must be Polygonal or LinearRing|" # GEOS < 3.10.4
- "must be a Polygon or MultiPolygon"
- ),
- ):
- shapely.maximum_inscribed_circle(geometry)
- geometry = shapely.from_wkt("POLYGON EMPTY")
- with pytest.raises(
- GEOSException, match="Empty input(?: geometry)? is not supported"
- ):
- shapely.maximum_inscribed_circle(geometry)
- def test_maximum_inscribed_circle_invalid_tolerance():
- geometry = shapely.from_wkt("POLYGON ((0 5, 5 10, 10 5, 5 0, 0 5))")
- with pytest.raises(ValueError, match="'tolerance' should be positive"):
- shapely.maximum_inscribed_circle(geometry, tolerance=-1)
- @pytest.mark.parametrize("geometry", all_types)
- def test_orient_polygons_all_types(geometry):
- actual = shapely.orient_polygons([geometry, geometry])
- assert actual.shape == (2,)
- assert isinstance(actual[0], Geometry)
- actual = shapely.orient_polygons(None)
- assert actual is None
- def test_orient_polygons():
- # polygon with both shell and hole having clockwise orientation
- polygon = Polygon(
- [(0, 0), (0, 10), (10, 10), (10, 0), (0, 0)],
- holes=[[(2, 2), (2, 4), (4, 4), (4, 2), (2, 2)]],
- )
- result = shapely.orient_polygons(polygon)
- assert result.exterior.is_ccw
- assert not result.interiors[0].is_ccw
- result = shapely.orient_polygons(polygon, exterior_cw=True)
- assert not result.exterior.is_ccw
- assert result.interiors[0].is_ccw
- # in a MultiPolygon
- mp = MultiPolygon([polygon, polygon])
- result = shapely.orient_polygons(mp)
- assert len(result.geoms) == 2
- for geom in result.geoms:
- assert geom.exterior.is_ccw
- assert not geom.interiors[0].is_ccw
- result = shapely.orient_polygons([mp], exterior_cw=True)[0]
- assert len(result.geoms) == 2
- for geom in result.geoms:
- assert not geom.exterior.is_ccw
- assert geom.interiors[0].is_ccw
- # in a GeometryCollection
- gc = GeometryCollection([Point(1, 1), polygon, mp])
- result = shapely.orient_polygons(gc)
- assert len(result.geoms) == 3
- assert result.geoms[0] == Point(1, 1)
- assert result.geoms[1] == shapely.orient_polygons(polygon)
- assert result.geoms[2] == shapely.orient_polygons(mp)
- def test_orient_polygons_non_polygonal_input():
- arr = np.array([Point(0, 0), LineString([(0, 0), (1, 1)]), None])
- result = shapely.orient_polygons(arr)
- assert_geometries_equal(result, arr)
- def test_orient_polygons_array():
- # because we have a custom python implementation for older GEOS, need to
- # ensure this has the same capabilities as numpy ufuncs to work with array-likes
- polygon = Polygon(
- [(0, 0), (0, 10), (10, 10), (10, 0), (0, 0)],
- holes=[[(2, 2), (2, 4), (4, 4), (4, 2), (2, 2)]],
- )
- geometries = np.array([[polygon] * 3] * 2)
- actual = shapely.orient_polygons(geometries)
- assert isinstance(actual, np.ndarray)
- assert actual.shape == (2, 3)
- expected = shapely.orient_polygons(polygon)
- assert (actual == expected).all()
- def test_orient_polygons_array_like():
- # because we have a custom python implementation for older GEOS, need to
- # ensure this has the same capabilities as numpy ufuncs to work with array-likes
- polygon = Polygon(
- [(0, 0), (0, 10), (10, 10), (10, 0), (0, 0)],
- holes=[[(2, 2), (2, 4), (4, 4), (4, 2), (2, 2)]],
- )
- geometries = [polygon, Point(2, 2).buffer(1)]
- actual = shapely.orient_polygons(ArrayLike(geometries))
- assert isinstance(actual, ArrayLike)
- expected = shapely.orient_polygons(geometries)
- assert_geometries_equal(np.asarray(actual), expected)
- def test_buffer_deprecate_positional():
- with pytest.deprecated_call(
- match="positional argument `quad_segs` for `buffer` is deprecated"
- ):
- shapely.buffer(point, 1.0, 8)
- with pytest.deprecated_call(
- match="positional arguments `quad_segs` and `cap_style` "
- "for `buffer` are deprecated"
- ):
- shapely.buffer(point, 1.0, 8, "round")
- with pytest.deprecated_call(
- match="positional arguments `quad_segs`, `cap_style`, and `join_style` "
- "for `buffer` are deprecated"
- ):
- shapely.buffer(point, 1.0, 8, "round", "round")
- with pytest.deprecated_call():
- shapely.buffer(point, 1.0, 8, "round", "round", 5.0)
- with pytest.deprecated_call():
- shapely.buffer(point, 1.0, 8, "round", "round", 5.0, False)
- def test_offset_curve_deprecate_positional():
- with pytest.deprecated_call(
- match="positional argument `quad_segs` for `offset_curve` is deprecated"
- ):
- shapely.offset_curve(line_string, 1.0, 8)
- with pytest.deprecated_call(
- match="positional arguments `quad_segs` and `join_style` "
- "for `offset_curve` are deprecated"
- ):
- shapely.offset_curve(line_string, 1.0, 8, "round")
- with pytest.deprecated_call(
- match="positional arguments `quad_segs`, `join_style`, and `mitre_limit` "
- "for `offset_curve` are deprecated"
- ):
- shapely.offset_curve(line_string, 1.0, 8, "round", 5.0)
- def test_simplify_deprecate_positional():
- with pytest.deprecated_call(
- match="positional argument `preserve_topology` for `simplify` is deprecated"
- ):
- shapely.simplify(line_string, 1.0, True)
- def test_voronoi_polygons_deprecate_positional():
- with pytest.deprecated_call(
- match="positional argument `extend_to` for `voronoi_polygons` is deprecated"
- ):
- shapely.voronoi_polygons(multi_point, 0.0, None)
- with pytest.deprecated_call(
- match="positional arguments `extend_to` and `only_edges` "
- "for `voronoi_polygons` are deprecated"
- ):
- shapely.voronoi_polygons(multi_point, 0.0, None, False)
- with pytest.deprecated_call(
- match="positional arguments `extend_to`, `only_edges`, and `ordered` "
- "for `voronoi_polygons` are deprecated"
- ):
- shapely.voronoi_polygons(multi_point, 0.0, None, False, False)
|