initial commit
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.
@@ -0,0 +1,82 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from shapely import GeometryCollection, LineString, Point, wkt
|
||||
from shapely.geometry import shape
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def geometrycollection_geojson():
|
||||
return {
|
||||
"type": "GeometryCollection",
|
||||
"geometries": [
|
||||
{"type": "Point", "coordinates": (0, 3, 0)},
|
||||
{"type": "LineString", "coordinates": ((2, 0), (1, 0))},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"geom",
|
||||
[
|
||||
GeometryCollection(),
|
||||
shape({"type": "GeometryCollection", "geometries": []}),
|
||||
wkt.loads("GEOMETRYCOLLECTION EMPTY"),
|
||||
],
|
||||
)
|
||||
def test_empty(geom):
|
||||
assert geom.geom_type == "GeometryCollection"
|
||||
assert geom.is_empty
|
||||
assert len(geom.geoms) == 0
|
||||
assert list(geom.geoms) == []
|
||||
|
||||
|
||||
def test_empty_subgeoms():
|
||||
geom = GeometryCollection([Point(), LineString()])
|
||||
assert geom.geom_type == "GeometryCollection"
|
||||
assert geom.is_empty
|
||||
assert len(geom.geoms) == 2
|
||||
assert list(geom.geoms) == [Point(), LineString()]
|
||||
|
||||
|
||||
def test_child_with_deleted_parent():
|
||||
# test that we can remove a collection while keeping
|
||||
# children around
|
||||
a = LineString([(0, 0), (1, 1), (1, 2), (2, 2)])
|
||||
b = LineString([(0, 0), (1, 1), (2, 1), (2, 2)])
|
||||
collection = a.intersection(b)
|
||||
|
||||
child = collection.geoms[0]
|
||||
# delete parent of child
|
||||
del collection
|
||||
|
||||
# access geometry, this should not seg fault as 1.2.15 did
|
||||
assert child.wkt is not None
|
||||
|
||||
|
||||
def test_from_geojson(geometrycollection_geojson):
|
||||
geom = shape(geometrycollection_geojson)
|
||||
assert geom.geom_type == "GeometryCollection"
|
||||
assert len(geom.geoms) == 2
|
||||
|
||||
geom_types = [g.geom_type for g in geom.geoms]
|
||||
assert "Point" in geom_types
|
||||
assert "LineString" in geom_types
|
||||
|
||||
|
||||
def test_geointerface(geometrycollection_geojson):
|
||||
geom = shape(geometrycollection_geojson)
|
||||
assert geom.__geo_interface__ == geometrycollection_geojson
|
||||
|
||||
|
||||
def test_len_raises(geometrycollection_geojson):
|
||||
geom = shape(geometrycollection_geojson)
|
||||
with pytest.raises(TypeError):
|
||||
len(geom)
|
||||
|
||||
|
||||
def test_numpy_object_array():
|
||||
geom = GeometryCollection([LineString([(0, 0), (1, 1)])])
|
||||
ar = np.empty(1, object)
|
||||
ar[:] = [geom]
|
||||
assert ar[0] == geom
|
||||
86
billinglayer/python/shapely/tests/geometry/test_coords.py
Normal file
86
billinglayer/python/shapely/tests/geometry/test_coords.py
Normal file
@@ -0,0 +1,86 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from shapely import LineString
|
||||
|
||||
|
||||
class TestCoords:
|
||||
"""
|
||||
Shapely assumes contiguous C-order float64 data for internal ops.
|
||||
Data should be converted to contiguous float64 if numpy exists.
|
||||
c9a0707 broke this a little bit.
|
||||
"""
|
||||
|
||||
def test_data_promotion(self):
|
||||
coords = np.array([[12, 34], [56, 78]], dtype=np.float32)
|
||||
processed_coords = np.array(LineString(coords).coords)
|
||||
|
||||
assert coords.tolist() == processed_coords.tolist()
|
||||
|
||||
def test_data_destriding(self):
|
||||
coords = np.array([[12, 34], [56, 78]], dtype=np.float32)
|
||||
|
||||
# Easy way to introduce striding: reverse list order
|
||||
processed_coords = np.array(LineString(coords[::-1]).coords)
|
||||
|
||||
assert coords[::-1].tolist() == processed_coords.tolist()
|
||||
|
||||
|
||||
class TestCoordsGetItem:
|
||||
def test_index_2d_coords(self):
|
||||
c = [(float(x), float(-x)) for x in range(4)]
|
||||
g = LineString(c)
|
||||
for i in range(-4, 4):
|
||||
assert g.coords[i] == c[i]
|
||||
with pytest.raises(IndexError):
|
||||
g.coords[4]
|
||||
with pytest.raises(IndexError):
|
||||
g.coords[-5]
|
||||
|
||||
def test_index_3d_coords(self):
|
||||
c = [(float(x), float(-x), float(x * 2)) for x in range(4)]
|
||||
g = LineString(c)
|
||||
for i in range(-4, 4):
|
||||
assert g.coords[i] == c[i]
|
||||
with pytest.raises(IndexError):
|
||||
g.coords[4]
|
||||
with pytest.raises(IndexError):
|
||||
g.coords[-5]
|
||||
|
||||
def test_index_coords_misc(self):
|
||||
g = LineString() # empty
|
||||
with pytest.raises(IndexError):
|
||||
g.coords[0]
|
||||
with pytest.raises(TypeError):
|
||||
g.coords[0.0]
|
||||
|
||||
def test_slice_2d_coords(self):
|
||||
c = [(float(x), float(-x)) for x in range(4)]
|
||||
g = LineString(c)
|
||||
assert g.coords[1:] == c[1:]
|
||||
assert g.coords[:-1] == c[:-1]
|
||||
assert g.coords[::-1] == c[::-1]
|
||||
assert g.coords[::2] == c[::2]
|
||||
assert g.coords[:4] == c[:4]
|
||||
assert g.coords[4:] == c[4:] == []
|
||||
|
||||
def test_slice_3d_coords(self):
|
||||
c = [(float(x), float(-x), float(x * 2)) for x in range(4)]
|
||||
g = LineString(c)
|
||||
assert g.coords[1:] == c[1:]
|
||||
assert g.coords[:-1] == c[:-1]
|
||||
assert g.coords[::-1] == c[::-1]
|
||||
assert g.coords[::2] == c[::2]
|
||||
assert g.coords[:4] == c[:4]
|
||||
assert g.coords[4:] == c[4:] == []
|
||||
|
||||
|
||||
class TestXY:
|
||||
"""New geometry/coordseq method 'xy' makes numpy interop easier"""
|
||||
|
||||
def test_arrays(self):
|
||||
x, y = LineString([(0, 0), (1, 1)]).xy
|
||||
assert len(x) == 2
|
||||
assert list(x) == [0.0, 1.0]
|
||||
assert len(y) == 2
|
||||
assert list(y) == [0.0, 1.0]
|
||||
117
billinglayer/python/shapely/tests/geometry/test_decimal.py
Normal file
117
billinglayer/python/shapely/tests/geometry/test_decimal.py
Normal file
@@ -0,0 +1,117 @@
|
||||
from decimal import Decimal
|
||||
|
||||
import pytest
|
||||
|
||||
from shapely import (
|
||||
GeometryCollection,
|
||||
LinearRing,
|
||||
LineString,
|
||||
MultiLineString,
|
||||
MultiPoint,
|
||||
MultiPolygon,
|
||||
Point,
|
||||
Polygon,
|
||||
)
|
||||
|
||||
items2d = [
|
||||
[(0.0, 0.0), (70.0, 120.0), (140.0, 0.0), (0.0, 0.0)],
|
||||
[(60.0, 80.0), (80.0, 80.0), (70.0, 60.0), (60.0, 80.0)],
|
||||
]
|
||||
|
||||
items2d_mixed = [
|
||||
[
|
||||
(Decimal(0.0), Decimal(0.0)),
|
||||
(Decimal(70.0), 120.0),
|
||||
(140.0, Decimal(0.0)),
|
||||
(0.0, 0.0),
|
||||
],
|
||||
[
|
||||
(Decimal(60.0), Decimal(80.0)),
|
||||
(Decimal(80.0), 80.0),
|
||||
(70.0, Decimal(60.0)),
|
||||
(60.0, 80.0),
|
||||
],
|
||||
]
|
||||
|
||||
items2d_decimal = [
|
||||
[
|
||||
(Decimal(0.0), Decimal(0.0)),
|
||||
(Decimal(70.0), Decimal(120.0)),
|
||||
(Decimal(140.0), Decimal(0.0)),
|
||||
(Decimal(0.0), Decimal(0.0)),
|
||||
],
|
||||
[
|
||||
(Decimal(60.0), Decimal(80.0)),
|
||||
(Decimal(80.0), Decimal(80.0)),
|
||||
(Decimal(70.0), Decimal(60.0)),
|
||||
(Decimal(60.0), Decimal(80.0)),
|
||||
],
|
||||
]
|
||||
|
||||
items3d = [
|
||||
[(0.0, 0.0, 1), (70.0, 120.0, 2), (140.0, 0.0, 3), (0.0, 0.0, 1)],
|
||||
[(60.0, 80.0, 1), (80.0, 80.0, 2), (70.0, 60.0, 3), (60.0, 80.0, 1)],
|
||||
]
|
||||
|
||||
items3d_mixed = [
|
||||
[
|
||||
(Decimal(0.0), Decimal(0.0), Decimal(1)),
|
||||
(Decimal(70.0), 120.0, Decimal(2)),
|
||||
(140.0, Decimal(0.0), 3),
|
||||
(0.0, 0.0, 1),
|
||||
],
|
||||
[
|
||||
(Decimal(60.0), Decimal(80.0), Decimal(1)),
|
||||
(Decimal(80.0), 80.0, 2),
|
||||
(70.0, Decimal(60.0), Decimal(3)),
|
||||
(60.0, 80.0, 1),
|
||||
],
|
||||
]
|
||||
|
||||
items3d_decimal = [
|
||||
[
|
||||
(Decimal(0.0), Decimal(0.0), Decimal(1)),
|
||||
(Decimal(70.0), Decimal(120.0), Decimal(2)),
|
||||
(Decimal(140.0), Decimal(0.0), Decimal(3)),
|
||||
(Decimal(0.0), Decimal(0.0), Decimal(1)),
|
||||
],
|
||||
[
|
||||
(Decimal(60.0), Decimal(80.0), Decimal(1)),
|
||||
(Decimal(80.0), Decimal(80.0), Decimal(2)),
|
||||
(Decimal(70.0), Decimal(60.0), Decimal(3)),
|
||||
(Decimal(60.0), Decimal(80.0), Decimal(1)),
|
||||
],
|
||||
]
|
||||
|
||||
all_geoms = [
|
||||
[
|
||||
Point(items[0][0]),
|
||||
Point(*items[0][0]),
|
||||
MultiPoint(items[0]),
|
||||
LinearRing(items[0]),
|
||||
LineString(items[0]),
|
||||
MultiLineString(items),
|
||||
Polygon(items[0]),
|
||||
MultiPolygon(
|
||||
[
|
||||
Polygon(items[1]),
|
||||
Polygon(items[0], holes=items[1:]),
|
||||
]
|
||||
),
|
||||
GeometryCollection([Point(items[0][0]), Polygon(items[0])]),
|
||||
]
|
||||
for items in [
|
||||
items2d,
|
||||
items2d_mixed,
|
||||
items2d_decimal,
|
||||
items3d,
|
||||
items3d_mixed,
|
||||
items3d_decimal,
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("geoms", list(zip(*all_geoms)))
|
||||
def test_decimal(geoms):
|
||||
assert geoms[0] == geoms[1] == geoms[2]
|
||||
assert geoms[3] == geoms[4] == geoms[5]
|
||||
98
billinglayer/python/shapely/tests/geometry/test_emptiness.py
Normal file
98
billinglayer/python/shapely/tests/geometry/test_emptiness.py
Normal file
@@ -0,0 +1,98 @@
|
||||
import math
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from shapely import (
|
||||
GeometryCollection,
|
||||
LinearRing,
|
||||
LineString,
|
||||
MultiLineString,
|
||||
MultiPoint,
|
||||
MultiPolygon,
|
||||
Point,
|
||||
Polygon,
|
||||
)
|
||||
from shapely.geometry import mapping, shape
|
||||
from shapely.geometry.base import BaseGeometry, EmptyGeometry
|
||||
|
||||
|
||||
def empty_generator():
|
||||
return iter([])
|
||||
|
||||
|
||||
class TestEmptiness:
|
||||
def test_empty_class(self):
|
||||
with pytest.warns(FutureWarning):
|
||||
g = EmptyGeometry()
|
||||
assert g.is_empty
|
||||
|
||||
def test_empty_base(self):
|
||||
with pytest.warns(FutureWarning):
|
||||
g = BaseGeometry()
|
||||
assert g.is_empty
|
||||
|
||||
def test_empty_point(self):
|
||||
assert Point().is_empty
|
||||
|
||||
def test_empty_multipoint(self):
|
||||
assert MultiPoint().is_empty
|
||||
|
||||
def test_empty_geometry_collection(self):
|
||||
assert GeometryCollection().is_empty
|
||||
|
||||
def test_empty_linestring(self):
|
||||
assert LineString().is_empty
|
||||
assert LineString(None).is_empty
|
||||
assert LineString([]).is_empty
|
||||
assert LineString(empty_generator()).is_empty
|
||||
|
||||
def test_empty_multilinestring(self):
|
||||
assert MultiLineString([]).is_empty
|
||||
|
||||
def test_empty_polygon(self):
|
||||
assert Polygon().is_empty
|
||||
assert Polygon(None).is_empty
|
||||
assert Polygon([]).is_empty
|
||||
assert Polygon(empty_generator()).is_empty
|
||||
|
||||
def test_empty_multipolygon(self):
|
||||
assert MultiPolygon([]).is_empty
|
||||
|
||||
def test_empty_linear_ring(self):
|
||||
assert LinearRing().is_empty
|
||||
assert LinearRing(None).is_empty
|
||||
assert LinearRing([]).is_empty
|
||||
assert LinearRing(empty_generator()).is_empty
|
||||
|
||||
|
||||
def test_numpy_object_array():
|
||||
geoms = [Point(), GeometryCollection()]
|
||||
arr = np.empty(2, object)
|
||||
arr[:] = geoms
|
||||
|
||||
|
||||
def test_shape_empty():
|
||||
empty_mp = MultiPolygon()
|
||||
empty_json = mapping(empty_mp)
|
||||
empty_shape = shape(empty_json)
|
||||
assert empty_shape.is_empty
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"geom",
|
||||
[
|
||||
Point(),
|
||||
LineString(),
|
||||
Polygon(),
|
||||
MultiPoint(),
|
||||
MultiLineString(),
|
||||
MultiPolygon(),
|
||||
GeometryCollection(),
|
||||
LinearRing(),
|
||||
],
|
||||
)
|
||||
def test_empty_geometry_bounds(geom):
|
||||
"""The bounds of an empty geometry is a tuple of NaNs"""
|
||||
assert len(geom.bounds) == 4
|
||||
assert all(math.isnan(v) for v in geom.bounds)
|
||||
111
billinglayer/python/shapely/tests/geometry/test_format.py
Normal file
111
billinglayer/python/shapely/tests/geometry/test_format.py
Normal file
@@ -0,0 +1,111 @@
|
||||
import pytest
|
||||
|
||||
from shapely import Point, Polygon
|
||||
from shapely.geos import geos_version
|
||||
|
||||
|
||||
def test_format_invalid():
|
||||
# check invalid spec formats
|
||||
pt = Point(1, 2)
|
||||
test_list = [
|
||||
("5G", ValueError, "invalid format specifier"),
|
||||
(".f", ValueError, "invalid format specifier"),
|
||||
("0.2e", ValueError, "invalid format specifier"),
|
||||
(".1x", ValueError, "hex representation does not specify precision"),
|
||||
]
|
||||
for format_spec, err, match in test_list:
|
||||
with pytest.raises(err, match=match):
|
||||
format(pt, format_spec)
|
||||
|
||||
|
||||
def test_format_point():
|
||||
# example coordinate data
|
||||
xy1 = (0.12345678901234567, 1.2345678901234567e10)
|
||||
xy2 = (-169.910918, -18.997564)
|
||||
xyz3 = (630084, 4833438, 76)
|
||||
|
||||
# list of tuples to test; see structure at top of the for-loop
|
||||
test_list = [
|
||||
(".0f", xy1, "POINT (0 12345678901)", True),
|
||||
(".1f", xy1, "POINT (0.1 12345678901.2)", True),
|
||||
("0.2f", xy2, "POINT (-169.91 -19.00)", True),
|
||||
(".3F", (float("inf"), -float("inf")), "POINT (INF -INF)", True),
|
||||
]
|
||||
if geos_version < (3, 10, 0):
|
||||
# 'g' format varies depending on GEOS version
|
||||
test_list += [
|
||||
(".1g", xy1, "POINT (0.1 1e+10)", True),
|
||||
(".6G", xy1, "POINT (0.123457 1.23457E+10)", True),
|
||||
("0.12g", xy1, "POINT (0.123456789012 12345678901.2)", True),
|
||||
("0.4g", xy2, "POINT (-169.9 -19)", True),
|
||||
]
|
||||
else:
|
||||
test_list += [
|
||||
(".1g", xy1, "POINT (0.1 12345678901.2)", False),
|
||||
(".6G", xy1, "POINT (0.123457 12345678901.234568)", False),
|
||||
("0.12g", xy1, "POINT (0.123456789012 12345678901.234568)", False),
|
||||
("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
|
||||
test_list += [
|
||||
("f", (1, 2), f"POINT ({1:.16f} {2:.16f})", False),
|
||||
("F", xyz3, "POINT Z ({:.16f} {:.16f} {:.16f})".format(*xyz3), False),
|
||||
("g", xyz3, "POINT Z (630084 4833438 76)", False),
|
||||
]
|
||||
for format_spec, coords, expt_wkt, same_python_float in test_list:
|
||||
pt = Point(*coords)
|
||||
# basic checks
|
||||
assert f"{pt}" == pt.wkt
|
||||
assert format(pt, "") == pt.wkt
|
||||
assert format(pt, "x") == pt.wkb_hex.lower()
|
||||
assert format(pt, "X") == pt.wkb_hex
|
||||
# check formatted WKT to expected
|
||||
assert format(pt, format_spec) == expt_wkt, format_spec
|
||||
# check Python's format consistency
|
||||
text_coords = expt_wkt[expt_wkt.index("(") + 1 : expt_wkt.index(")")]
|
||||
is_same = []
|
||||
for coord, expt_coord in zip(coords, text_coords.split()):
|
||||
py_fmt_float = format(float(coord), format_spec)
|
||||
if same_python_float:
|
||||
assert py_fmt_float == expt_coord, format_spec
|
||||
else:
|
||||
is_same.append(py_fmt_float == expt_coord)
|
||||
if not same_python_float:
|
||||
assert not all(is_same), f"{format_spec!r} with {expt_wkt}"
|
||||
|
||||
|
||||
def test_format_polygon():
|
||||
# check basic cases
|
||||
poly = Point(0, 0).buffer(10, 2)
|
||||
assert f"{poly}" == poly.wkt
|
||||
assert format(poly, "") == poly.wkt
|
||||
assert format(poly, "x") == poly.wkb_hex.lower()
|
||||
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))>"
|
||||
)
|
||||
|
||||
# 'g' format varies depending on GEOS version
|
||||
if geos_version < (3, 10, 0):
|
||||
expected_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 = (
|
||||
"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()
|
||||
assert f"{empty}" == "POLYGON EMPTY"
|
||||
assert format(empty, "") == empty.wkt
|
||||
assert format(empty, ".2G") == empty.wkt
|
||||
assert format(empty, "x") == empty.wkb_hex.lower()
|
||||
assert format(empty, "X") == empty.wkb_hex
|
||||
274
billinglayer/python/shapely/tests/geometry/test_geometry_base.py
Normal file
274
billinglayer/python/shapely/tests/geometry/test_geometry_base.py
Normal file
@@ -0,0 +1,274 @@
|
||||
import platform
|
||||
import weakref
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
import shapely
|
||||
from shapely import (
|
||||
GeometryCollection,
|
||||
LinearRing,
|
||||
LineString,
|
||||
MultiLineString,
|
||||
MultiPoint,
|
||||
MultiPolygon,
|
||||
Point,
|
||||
Polygon,
|
||||
)
|
||||
from shapely.errors import ShapelyDeprecationWarning
|
||||
from shapely.testing import assert_geometries_equal
|
||||
|
||||
|
||||
def test_polygon():
|
||||
assert bool(Polygon()) is False
|
||||
|
||||
|
||||
def test_linestring():
|
||||
assert bool(LineString()) is False
|
||||
|
||||
|
||||
def test_point():
|
||||
assert bool(Point()) is False
|
||||
|
||||
|
||||
def test_geometry_collection():
|
||||
assert bool(GeometryCollection()) is False
|
||||
|
||||
|
||||
geometries_all_types = [
|
||||
Point(1, 1),
|
||||
LinearRing([(0, 0), (1, 1), (0, 1), (0, 0)]),
|
||||
LineString([(0, 0), (1, 1), (0, 1), (0, 0)]),
|
||||
Polygon([(0, 0), (1, 1), (0, 1), (0, 0)]),
|
||||
MultiPoint([(1, 1)]),
|
||||
MultiLineString([[(0, 0), (1, 1), (0, 1), (0, 0)]]),
|
||||
MultiPolygon([Polygon([(0, 0), (1, 1), (0, 1), (0, 0)])]),
|
||||
GeometryCollection([Point(1, 1)]),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
platform.python_implementation() == "PyPy",
|
||||
reason="Setting custom attributes doesn't fail on PyPy",
|
||||
)
|
||||
@pytest.mark.parametrize("geom", geometries_all_types)
|
||||
def test_setattr_disallowed(geom):
|
||||
with pytest.raises(AttributeError):
|
||||
geom.name = "test"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("geom", geometries_all_types)
|
||||
def test_weakrefable(geom):
|
||||
_ = weakref.ref(geom)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("geom", geometries_all_types)
|
||||
def test_comparison_notimplemented(geom):
|
||||
# comparing to a non-geometry class should return NotImplemented in __eq__
|
||||
# to ensure proper delegation to other (eg to ensure comparison of scalar
|
||||
# with array works)
|
||||
# https://github.com/shapely/shapely/issues/1056
|
||||
assert geom.__eq__(1) is NotImplemented
|
||||
|
||||
# with array
|
||||
arr = np.array([geom, geom], dtype=object)
|
||||
|
||||
result = arr == geom
|
||||
assert isinstance(result, np.ndarray)
|
||||
assert result.all()
|
||||
|
||||
result = geom == arr
|
||||
assert isinstance(result, np.ndarray)
|
||||
assert result.all()
|
||||
|
||||
result = arr != geom
|
||||
assert isinstance(result, np.ndarray)
|
||||
assert not result.any()
|
||||
|
||||
result = geom != arr
|
||||
assert isinstance(result, np.ndarray)
|
||||
assert not result.any()
|
||||
|
||||
|
||||
def test_base_class_not_callable():
|
||||
with pytest.raises(TypeError):
|
||||
shapely.Geometry("POINT (1 1)")
|
||||
|
||||
|
||||
def test_GeometryType_deprecated():
|
||||
geom = Point(1, 1)
|
||||
|
||||
with pytest.warns(ShapelyDeprecationWarning):
|
||||
geom_type = geom.geometryType()
|
||||
|
||||
assert geom_type == geom.geom_type
|
||||
|
||||
|
||||
def test_type_deprecated():
|
||||
geom = Point(1, 1)
|
||||
|
||||
with pytest.warns(ShapelyDeprecationWarning):
|
||||
geom_type = geom.type
|
||||
|
||||
assert geom_type == geom.geom_type
|
||||
|
||||
|
||||
@pytest.mark.skipif(shapely.geos_version < (3, 10, 0), reason="GEOS < 3.10")
|
||||
def test_segmentize():
|
||||
line = LineString([(0, 0), (0, 10)])
|
||||
result = line.segmentize(max_segment_length=5)
|
||||
assert result.equals(LineString([(0, 0), (0, 5), (0, 10)]))
|
||||
|
||||
|
||||
@pytest.mark.skipif(shapely.geos_version < (3, 7, 0), reason="GEOS < 3.7")
|
||||
def test_reverse():
|
||||
coords = [(0, 0), (1, 2)]
|
||||
line = LineString(coords)
|
||||
result = line.reverse()
|
||||
assert result.coords[:] == coords[::-1]
|
||||
|
||||
|
||||
@pytest.mark.skipif(shapely.geos_version < (3, 9, 0), reason="GEOS < 3.9")
|
||||
@pytest.mark.parametrize(
|
||||
"op", ["union", "intersection", "difference", "symmetric_difference"]
|
||||
)
|
||||
@pytest.mark.parametrize("grid_size", [0, 1, 2])
|
||||
def test_binary_op_grid_size(op, grid_size):
|
||||
geom1 = shapely.box(0, 0, 2.5, 2.5)
|
||||
geom2 = shapely.box(2, 2, 3, 3)
|
||||
|
||||
result = getattr(geom1, op)(geom2, grid_size=grid_size)
|
||||
expected = getattr(shapely, op)(geom1, geom2, grid_size=grid_size)
|
||||
assert result == expected
|
||||
|
||||
|
||||
@pytest.mark.skipif(shapely.geos_version < (3, 10, 0), reason="GEOS < 3.10")
|
||||
def test_dwithin():
|
||||
point = Point(1, 1)
|
||||
line = LineString([(0, 0), (0, 10)])
|
||||
assert point.dwithin(line, 0.5) is False
|
||||
assert point.dwithin(line, 1.5) is True
|
||||
|
||||
|
||||
def test_contains_properly():
|
||||
polygon = Polygon([(0, 0), (10, 10), (10, -10)])
|
||||
line = LineString([(0, 0), (10, 0)])
|
||||
assert polygon.contains_properly(line) is False
|
||||
assert polygon.contains(line) is True
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"op", ["convex_hull", "envelope", "oriented_envelope", "minimum_rotated_rectangle"]
|
||||
)
|
||||
def test_constructive_properties(op):
|
||||
geom = LineString([(0, 0), (0, 10), (10, 10)])
|
||||
result = getattr(geom, op)
|
||||
expected = getattr(shapely, op)(geom)
|
||||
assert result == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"op",
|
||||
[
|
||||
"crosses",
|
||||
"contains",
|
||||
"contains_properly",
|
||||
"covered_by",
|
||||
"covers",
|
||||
"disjoint",
|
||||
"equals",
|
||||
"intersects",
|
||||
"overlaps",
|
||||
"touches",
|
||||
"within",
|
||||
],
|
||||
)
|
||||
def test_array_argument_binary_predicates(op):
|
||||
polygon = Polygon([(0, 0), (0, 1), (1, 1), (1, 0), (0, 0)])
|
||||
points = shapely.points([(0, 0), (0.5, 0.5), (1, 1)])
|
||||
|
||||
result = getattr(polygon, op)(points)
|
||||
assert isinstance(result, np.ndarray)
|
||||
expected = np.array([getattr(polygon, op)(p) for p in points], dtype=bool)
|
||||
np.testing.assert_array_equal(result, expected)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"op, kwargs",
|
||||
[
|
||||
pytest.param(
|
||||
"dwithin",
|
||||
dict(distance=0.5),
|
||||
marks=pytest.mark.skipif(
|
||||
shapely.geos_version < (3, 10, 0), reason="GEOS < 3.10"
|
||||
),
|
||||
),
|
||||
("equals_exact", dict(tolerance=0.01)),
|
||||
("relate_pattern", dict(pattern="T*F**F***")),
|
||||
],
|
||||
)
|
||||
def test_array_argument_binary_predicates2(op, kwargs):
|
||||
polygon = Polygon([(0, 0), (0, 1), (1, 1), (1, 0), (0, 0)])
|
||||
points = shapely.points([(0, 0), (0.5, 0.5), (1, 1)])
|
||||
|
||||
result = getattr(polygon, op)(points, **kwargs)
|
||||
assert isinstance(result, np.ndarray)
|
||||
expected = np.array([getattr(polygon, op)(p, **kwargs) for p in points], dtype=bool)
|
||||
np.testing.assert_array_equal(result, expected)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"op",
|
||||
[
|
||||
"difference",
|
||||
"intersection",
|
||||
"symmetric_difference",
|
||||
"union",
|
||||
],
|
||||
)
|
||||
def test_array_argument_binary_geo(op):
|
||||
box = Polygon([(0, 0), (0, 1), (1, 1), (1, 0), (0, 0)])
|
||||
polygons = shapely.buffer(shapely.points([(0, 0), (0.5, 0.5), (1, 1)]), 0.5)
|
||||
|
||||
result = getattr(box, op)(polygons)
|
||||
assert isinstance(result, np.ndarray)
|
||||
expected = np.array([getattr(box, op)(g) for g in polygons], dtype=object)
|
||||
assert_geometries_equal(result, expected)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("op", ["distance", "hausdorff_distance"])
|
||||
def test_array_argument_float(op):
|
||||
polygon = Polygon([(0, 0), (0, 1), (1, 1), (1, 0), (0, 0)])
|
||||
points = shapely.points([(0, 0), (0.5, 0.5), (1, 1)])
|
||||
|
||||
result = getattr(polygon, op)(points)
|
||||
assert isinstance(result, np.ndarray)
|
||||
expected = np.array([getattr(polygon, op)(p) for p in points], dtype="float64")
|
||||
np.testing.assert_array_equal(result, expected)
|
||||
|
||||
|
||||
def test_array_argument_linear():
|
||||
line = LineString([(0, 0), (0, 1), (1, 1)])
|
||||
distances = np.array([0, 0.5, 1])
|
||||
result = line.line_interpolate_point(distances)
|
||||
assert isinstance(result, np.ndarray)
|
||||
expected = np.array(
|
||||
[line.line_interpolate_point(d) for d in distances], dtype=object
|
||||
)
|
||||
assert_geometries_equal(result, expected)
|
||||
|
||||
points = shapely.points([(0, 0), (0.5, 0.5), (1, 1)])
|
||||
result = line.line_locate_point(points)
|
||||
assert isinstance(result, np.ndarray)
|
||||
expected = np.array([line.line_locate_point(p) for p in points], dtype="float64")
|
||||
np.testing.assert_array_equal(result, expected)
|
||||
|
||||
|
||||
def test_array_argument_buffer():
|
||||
point = Point(1, 1)
|
||||
distances = np.array([0, 0.5, 1])
|
||||
|
||||
result = point.buffer(distances)
|
||||
assert isinstance(result, np.ndarray)
|
||||
expected = np.array([point.buffer(d) for d in distances], dtype=object)
|
||||
assert_geometries_equal(result, expected)
|
||||
28
billinglayer/python/shapely/tests/geometry/test_hash.py
Normal file
28
billinglayer/python/shapely/tests/geometry/test_hash.py
Normal file
@@ -0,0 +1,28 @@
|
||||
import pytest
|
||||
|
||||
import shapely
|
||||
from shapely.affinity import translate
|
||||
from shapely.geometry import GeometryCollection, LineString, MultiPoint, Point
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"geom",
|
||||
[
|
||||
Point(1, 2),
|
||||
MultiPoint([(1, 2), (3, 4)]),
|
||||
LineString([(1, 2), (3, 4)]),
|
||||
Point(0, 0).buffer(1.0),
|
||||
GeometryCollection([Point(1, 2), LineString([(1, 2), (3, 4)])]),
|
||||
],
|
||||
ids=[
|
||||
"Point",
|
||||
"MultiPoint",
|
||||
"LineString",
|
||||
"Polygon",
|
||||
"GeometryCollection",
|
||||
],
|
||||
)
|
||||
def test_hash(geom):
|
||||
h1 = hash(geom)
|
||||
assert h1 == hash(shapely.from_wkb(geom.wkb))
|
||||
assert h1 != hash(translate(geom, 1.0, 2.0))
|
||||
213
billinglayer/python/shapely/tests/geometry/test_linestring.py
Normal file
213
billinglayer/python/shapely/tests/geometry/test_linestring.py
Normal file
@@ -0,0 +1,213 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
import shapely
|
||||
from shapely import LinearRing, LineString, Point
|
||||
from shapely.coords import CoordinateSequence
|
||||
|
||||
|
||||
def test_from_coordinate_sequence():
|
||||
# From coordinate tuples
|
||||
line = LineString([(1.0, 2.0), (3.0, 4.0)])
|
||||
assert len(line.coords) == 2
|
||||
assert line.coords[:] == [(1.0, 2.0), (3.0, 4.0)]
|
||||
|
||||
line = LineString([(1.0, 2.0), (3.0, 4.0)])
|
||||
assert line.coords[:] == [(1.0, 2.0), (3.0, 4.0)]
|
||||
|
||||
|
||||
def test_from_coordinate_sequence_3D():
|
||||
line = LineString([(1.0, 2.0, 3.0), (3.0, 4.0, 5.0)])
|
||||
assert line.has_z
|
||||
assert line.coords[:] == [(1.0, 2.0, 3.0), (3.0, 4.0, 5.0)]
|
||||
|
||||
|
||||
def test_from_points():
|
||||
# From Points
|
||||
line = LineString([Point(1.0, 2.0), Point(3.0, 4.0)])
|
||||
assert line.coords[:] == [(1.0, 2.0), (3.0, 4.0)]
|
||||
|
||||
line = LineString([Point(1.0, 2.0), Point(3.0, 4.0)])
|
||||
assert line.coords[:] == [(1.0, 2.0), (3.0, 4.0)]
|
||||
|
||||
|
||||
def test_from_mix():
|
||||
# From mix of tuples and Points
|
||||
line = LineString([Point(1.0, 2.0), (2.0, 3.0), Point(3.0, 4.0)])
|
||||
assert line.coords[:] == [(1.0, 2.0), (2.0, 3.0), (3.0, 4.0)]
|
||||
|
||||
|
||||
def test_from_linestring():
|
||||
# From another linestring
|
||||
line = LineString([(1.0, 2.0), (3.0, 4.0)])
|
||||
copy = LineString(line)
|
||||
assert copy.coords[:] == [(1.0, 2.0), (3.0, 4.0)]
|
||||
assert copy.geom_type == "LineString"
|
||||
|
||||
|
||||
def test_from_linearring():
|
||||
coords = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0)]
|
||||
ring = LinearRing(coords)
|
||||
copy = LineString(ring)
|
||||
assert copy.coords[:] == coords
|
||||
assert copy.geom_type == "LineString"
|
||||
|
||||
|
||||
def test_from_linestring_z():
|
||||
coords = [(1.0, 2.0, 3.0), (4.0, 5.0, 6.0)]
|
||||
line = LineString(coords)
|
||||
copy = LineString(line)
|
||||
assert copy.coords[:] == coords
|
||||
assert copy.geom_type == "LineString"
|
||||
|
||||
|
||||
def test_from_generator():
|
||||
gen = (coord for coord in [(1.0, 2.0), (3.0, 4.0)])
|
||||
line = LineString(gen)
|
||||
assert line.coords[:] == [(1.0, 2.0), (3.0, 4.0)]
|
||||
|
||||
|
||||
def test_from_empty():
|
||||
line = LineString()
|
||||
assert line.is_empty
|
||||
assert isinstance(line.coords, CoordinateSequence)
|
||||
assert line.coords[:] == []
|
||||
|
||||
line = LineString([])
|
||||
assert line.is_empty
|
||||
assert isinstance(line.coords, CoordinateSequence)
|
||||
assert line.coords[:] == []
|
||||
|
||||
|
||||
def test_from_numpy():
|
||||
# Construct from a numpy array
|
||||
line = LineString(np.array([[1.0, 2.0], [3.0, 4.0]]))
|
||||
assert line.coords[:] == [(1.0, 2.0), (3.0, 4.0)]
|
||||
|
||||
|
||||
def test_numpy_empty_linestring_coords():
|
||||
# Check empty
|
||||
line = LineString([])
|
||||
la = np.asarray(line.coords)
|
||||
|
||||
assert la.shape == (0, 2)
|
||||
|
||||
|
||||
def test_numpy_object_array():
|
||||
geom = LineString([(0.0, 0.0), (0.0, 1.0)])
|
||||
ar = np.empty(1, object)
|
||||
ar[:] = [geom]
|
||||
assert ar[0] == geom
|
||||
|
||||
|
||||
@pytest.mark.filterwarnings("ignore:Creating an ndarray from ragged nested sequences:")
|
||||
def test_from_invalid_dim():
|
||||
# TODO(shapely-2.0) better error message?
|
||||
# pytest.raises(ValueError, match="at least 2 coordinate tuples|at least 2 coordinates"):
|
||||
with pytest.raises(shapely.GEOSException):
|
||||
LineString([(1, 2)])
|
||||
|
||||
# exact error depends on numpy version
|
||||
with pytest.raises((ValueError, TypeError)):
|
||||
LineString([(1, 2, 3), (4, 5)])
|
||||
|
||||
with pytest.raises((ValueError, TypeError)):
|
||||
LineString([(1, 2), (3, 4, 5)])
|
||||
|
||||
msg = r"The ordinate \(last\) dimension should be 2 or 3, got {}"
|
||||
with pytest.raises(ValueError, match=msg.format(4)):
|
||||
LineString([(1, 2, 3, 4), (4, 5, 6, 7)])
|
||||
|
||||
with pytest.raises(ValueError, match=msg.format(1)):
|
||||
LineString([(1,), (4,)])
|
||||
|
||||
|
||||
def test_from_single_coordinate():
|
||||
"""Test for issue #486"""
|
||||
coords = [[-122.185933073564, 37.3629353839073]]
|
||||
with pytest.raises(shapely.GEOSException):
|
||||
ls = LineString(coords)
|
||||
ls.geom_type # caused segfault before fix
|
||||
|
||||
|
||||
class TestLineString:
|
||||
def test_linestring(self):
|
||||
|
||||
# From coordinate tuples
|
||||
line = LineString([(1.0, 2.0), (3.0, 4.0)])
|
||||
assert len(line.coords) == 2
|
||||
assert line.coords[:] == [(1.0, 2.0), (3.0, 4.0)]
|
||||
|
||||
# Bounds
|
||||
assert line.bounds == (1.0, 2.0, 3.0, 4.0)
|
||||
|
||||
# Coordinate access
|
||||
assert tuple(line.coords) == ((1.0, 2.0), (3.0, 4.0))
|
||||
assert line.coords[0] == (1.0, 2.0)
|
||||
assert line.coords[1] == (3.0, 4.0)
|
||||
with pytest.raises(IndexError):
|
||||
line.coords[2] # index out of range
|
||||
|
||||
# Geo interface
|
||||
assert line.__geo_interface__ == {
|
||||
"type": "LineString",
|
||||
"coordinates": ((1.0, 2.0), (3.0, 4.0)),
|
||||
}
|
||||
|
||||
def test_linestring_empty(self):
|
||||
# Test Non-operability of Null geometry
|
||||
l_null = LineString()
|
||||
assert l_null.wkt == "LINESTRING EMPTY"
|
||||
assert l_null.length == 0.0
|
||||
|
||||
def test_equals_argument_order(self):
|
||||
"""
|
||||
Test equals predicate functions correctly regardless of the order
|
||||
of the inputs. See issue #317.
|
||||
"""
|
||||
coords = ((0, 0), (1, 0), (1, 1), (0, 0))
|
||||
ls = LineString(coords)
|
||||
lr = LinearRing(coords)
|
||||
|
||||
assert ls.__eq__(lr) is False # previously incorrectly returned True
|
||||
assert lr.__eq__(ls) is False
|
||||
assert (ls == lr) is False
|
||||
assert (lr == ls) is False
|
||||
|
||||
ls_clone = LineString(coords)
|
||||
lr_clone = LinearRing(coords)
|
||||
|
||||
assert ls.__eq__(ls_clone) is True
|
||||
assert lr.__eq__(lr_clone) is True
|
||||
assert (ls == ls_clone) is True
|
||||
assert (lr == lr_clone) is True
|
||||
|
||||
def test_numpy_linestring_coords(self):
|
||||
from numpy.testing import assert_array_equal
|
||||
|
||||
line = LineString([(1.0, 2.0), (3.0, 4.0)])
|
||||
expected = np.array([[1.0, 2.0], [3.0, 4.0]])
|
||||
|
||||
# Coordinate sequences can be adapted as well
|
||||
la = np.asarray(line.coords)
|
||||
assert_array_equal(la, expected)
|
||||
|
||||
|
||||
def test_linestring_immutable():
|
||||
line = LineString([(1.0, 2.0), (3.0, 4.0)])
|
||||
|
||||
with pytest.raises(AttributeError):
|
||||
line.coords = [(-1.0, -1.0), (1.0, 1.0)]
|
||||
|
||||
with pytest.raises(TypeError):
|
||||
line.coords[0] = (-1.0, -1.0)
|
||||
|
||||
|
||||
def test_linestring_array_coercion():
|
||||
# don't convert to array of coordinates, keep objects
|
||||
line = LineString([(1.0, 2.0), (3.0, 4.0)])
|
||||
arr = np.array(line)
|
||||
assert arr.ndim == 0
|
||||
assert arr.size == 1
|
||||
assert arr.dtype == np.dtype("object")
|
||||
assert arr.item() == line
|
||||
11
billinglayer/python/shapely/tests/geometry/test_multi.py
Normal file
11
billinglayer/python/shapely/tests/geometry/test_multi.py
Normal file
@@ -0,0 +1,11 @@
|
||||
import numpy as np
|
||||
|
||||
test_int_types = [int, np.int16, np.int32, np.int64]
|
||||
|
||||
|
||||
class MultiGeometryTestCase:
|
||||
def subgeom_access_test(self, cls, geoms):
|
||||
geom = cls(geoms)
|
||||
for t in test_int_types:
|
||||
for i, g in enumerate(geoms):
|
||||
assert geom.geoms[t(i)] == geoms[i]
|
||||
@@ -0,0 +1,79 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from shapely import LineString, MultiLineString
|
||||
from shapely.errors import EmptyPartError
|
||||
from shapely.geometry.base import dump_coords
|
||||
|
||||
from .test_multi import MultiGeometryTestCase
|
||||
|
||||
|
||||
class TestMultiLineString(MultiGeometryTestCase):
|
||||
def test_multilinestring(self):
|
||||
|
||||
# From coordinate tuples
|
||||
geom = MultiLineString([[(1.0, 2.0), (3.0, 4.0)]])
|
||||
assert isinstance(geom, MultiLineString)
|
||||
assert len(geom.geoms) == 1
|
||||
assert dump_coords(geom) == [[(1.0, 2.0), (3.0, 4.0)]]
|
||||
|
||||
# From lines
|
||||
a = LineString([(1.0, 2.0), (3.0, 4.0)])
|
||||
ml = MultiLineString([a])
|
||||
assert len(ml.geoms) == 1
|
||||
assert dump_coords(ml) == [[(1.0, 2.0), (3.0, 4.0)]]
|
||||
|
||||
# From another multi-line
|
||||
ml2 = MultiLineString(ml)
|
||||
assert len(ml2.geoms) == 1
|
||||
assert dump_coords(ml2) == [[(1.0, 2.0), (3.0, 4.0)]]
|
||||
|
||||
# Sub-geometry Access
|
||||
geom = MultiLineString([(((0.0, 0.0), (1.0, 2.0)))])
|
||||
assert isinstance(geom.geoms[0], LineString)
|
||||
assert dump_coords(geom.geoms[0]) == [(0.0, 0.0), (1.0, 2.0)]
|
||||
with pytest.raises(IndexError): # index out of range
|
||||
geom.geoms[1]
|
||||
|
||||
# Geo interface
|
||||
assert geom.__geo_interface__ == {
|
||||
"type": "MultiLineString",
|
||||
"coordinates": (((0.0, 0.0), (1.0, 2.0)),),
|
||||
}
|
||||
|
||||
def test_from_multilinestring_z(self):
|
||||
coords1 = [(0.0, 1.0, 2.0), (3.0, 4.0, 5.0)]
|
||||
coords2 = [(6.0, 7.0, 8.0), (9.0, 10.0, 11.0)]
|
||||
|
||||
# From coordinate tuples
|
||||
ml = MultiLineString([coords1, coords2])
|
||||
copy = MultiLineString(ml)
|
||||
assert isinstance(copy, MultiLineString)
|
||||
assert copy.geom_type == "MultiLineString"
|
||||
assert len(copy.geoms) == 2
|
||||
assert dump_coords(copy.geoms[0]) == coords1
|
||||
assert dump_coords(copy.geoms[1]) == coords2
|
||||
|
||||
def test_numpy(self):
|
||||
# Construct from a numpy array
|
||||
geom = MultiLineString([np.array(((0.0, 0.0), (1.0, 2.0)))])
|
||||
assert isinstance(geom, MultiLineString)
|
||||
assert len(geom.geoms) == 1
|
||||
assert dump_coords(geom) == [[(0.0, 0.0), (1.0, 2.0)]]
|
||||
|
||||
def test_subgeom_access(self):
|
||||
line0 = LineString([(0.0, 1.0), (2.0, 3.0)])
|
||||
line1 = LineString([(4.0, 5.0), (6.0, 7.0)])
|
||||
self.subgeom_access_test(MultiLineString, [line0, line1])
|
||||
|
||||
def test_create_multi_with_empty_component(self):
|
||||
msg = "Can't create MultiLineString with empty component"
|
||||
with pytest.raises(EmptyPartError, match=msg):
|
||||
MultiLineString([LineString([(0, 0), (1, 1), (2, 2)]), LineString()]).wkt
|
||||
|
||||
|
||||
def test_numpy_object_array():
|
||||
geom = MultiLineString([[[5.0, 6.0], [7.0, 8.0]]])
|
||||
ar = np.empty(1, object)
|
||||
ar[:] = [geom]
|
||||
assert ar[0] == geom
|
||||
@@ -0,0 +1,79 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from shapely import MultiPoint, Point
|
||||
from shapely.errors import EmptyPartError
|
||||
from shapely.geometry.base import dump_coords
|
||||
|
||||
from .test_multi import MultiGeometryTestCase
|
||||
|
||||
|
||||
class TestMultiPoint(MultiGeometryTestCase):
|
||||
def test_multipoint(self):
|
||||
|
||||
# From coordinate tuples
|
||||
geom = MultiPoint([(1.0, 2.0), (3.0, 4.0)])
|
||||
assert len(geom.geoms) == 2
|
||||
assert dump_coords(geom) == [[(1.0, 2.0)], [(3.0, 4.0)]]
|
||||
|
||||
# From points
|
||||
geom = MultiPoint([Point(1.0, 2.0), Point(3.0, 4.0)])
|
||||
assert len(geom.geoms) == 2
|
||||
assert dump_coords(geom) == [[(1.0, 2.0)], [(3.0, 4.0)]]
|
||||
|
||||
# From another multi-point
|
||||
geom2 = MultiPoint(geom)
|
||||
assert len(geom2.geoms) == 2
|
||||
assert dump_coords(geom2) == [[(1.0, 2.0)], [(3.0, 4.0)]]
|
||||
|
||||
# Sub-geometry Access
|
||||
assert isinstance(geom.geoms[0], Point)
|
||||
assert geom.geoms[0].x == 1.0
|
||||
assert geom.geoms[0].y == 2.0
|
||||
with pytest.raises(IndexError): # index out of range
|
||||
geom.geoms[2]
|
||||
|
||||
# Geo interface
|
||||
assert geom.__geo_interface__ == {
|
||||
"type": "MultiPoint",
|
||||
"coordinates": ((1.0, 2.0), (3.0, 4.0)),
|
||||
}
|
||||
|
||||
def test_multipoint_from_numpy(self):
|
||||
# Construct from a numpy array
|
||||
geom = MultiPoint(np.array([[0.0, 0.0], [1.0, 2.0]]))
|
||||
assert isinstance(geom, MultiPoint)
|
||||
assert len(geom.geoms) == 2
|
||||
assert dump_coords(geom) == [[(0.0, 0.0)], [(1.0, 2.0)]]
|
||||
|
||||
def test_subgeom_access(self):
|
||||
p0 = Point(1.0, 2.0)
|
||||
p1 = Point(3.0, 4.0)
|
||||
self.subgeom_access_test(MultiPoint, [p0, p1])
|
||||
|
||||
def test_create_multi_with_empty_component(self):
|
||||
msg = "Can't create MultiPoint with empty component"
|
||||
with pytest.raises(EmptyPartError, match=msg):
|
||||
MultiPoint([Point(0, 0), Point()]).wkt
|
||||
|
||||
|
||||
def test_multipoint_array_coercion():
|
||||
geom = MultiPoint([(1.0, 2.0), (3.0, 4.0)])
|
||||
arr = np.array(geom)
|
||||
assert arr.ndim == 0
|
||||
assert arr.size == 1
|
||||
assert arr.dtype == np.dtype("object")
|
||||
assert arr.item() == geom
|
||||
|
||||
|
||||
def test_numpy_object_array():
|
||||
geom = MultiPoint([(1.0, 2.0), (3.0, 4.0)])
|
||||
ar = np.empty(1, object)
|
||||
ar[:] = [geom]
|
||||
assert ar[0] == geom
|
||||
|
||||
|
||||
def test_len_raises():
|
||||
geom = MultiPoint([[5.0, 6.0], [7.0, 8.0]])
|
||||
with pytest.raises(TypeError):
|
||||
len(geom)
|
||||
121
billinglayer/python/shapely/tests/geometry/test_multipolygon.py
Normal file
121
billinglayer/python/shapely/tests/geometry/test_multipolygon.py
Normal file
@@ -0,0 +1,121 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from shapely import MultiPolygon, Polygon
|
||||
from shapely.geometry.base import dump_coords
|
||||
|
||||
from .test_multi import MultiGeometryTestCase
|
||||
|
||||
|
||||
class TestMultiPolygon(MultiGeometryTestCase):
|
||||
def test_multipolygon(self):
|
||||
|
||||
# From coordinate tuples
|
||||
coords = [
|
||||
(
|
||||
((0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0)),
|
||||
[((0.25, 0.25), (0.25, 0.5), (0.5, 0.5), (0.5, 0.25))],
|
||||
)
|
||||
]
|
||||
geom = MultiPolygon(coords)
|
||||
assert isinstance(geom, MultiPolygon)
|
||||
assert len(geom.geoms) == 1
|
||||
assert dump_coords(geom) == [
|
||||
[
|
||||
(0.0, 0.0),
|
||||
(0.0, 1.0),
|
||||
(1.0, 1.0),
|
||||
(1.0, 0.0),
|
||||
(0.0, 0.0),
|
||||
[(0.25, 0.25), (0.25, 0.5), (0.5, 0.5), (0.5, 0.25), (0.25, 0.25)],
|
||||
]
|
||||
]
|
||||
|
||||
# Or from polygons
|
||||
p = Polygon(
|
||||
((0, 0), (0, 1), (1, 1), (1, 0)),
|
||||
[((0.25, 0.25), (0.25, 0.5), (0.5, 0.5), (0.5, 0.25))],
|
||||
)
|
||||
geom = MultiPolygon([p])
|
||||
assert len(geom.geoms) == 1
|
||||
assert dump_coords(geom) == [
|
||||
[
|
||||
(0.0, 0.0),
|
||||
(0.0, 1.0),
|
||||
(1.0, 1.0),
|
||||
(1.0, 0.0),
|
||||
(0.0, 0.0),
|
||||
[(0.25, 0.25), (0.25, 0.5), (0.5, 0.5), (0.5, 0.25), (0.25, 0.25)],
|
||||
]
|
||||
]
|
||||
|
||||
# Or from another multi-polygon
|
||||
geom2 = MultiPolygon(geom)
|
||||
assert len(geom2.geoms) == 1
|
||||
assert dump_coords(geom2) == [
|
||||
[
|
||||
(0.0, 0.0),
|
||||
(0.0, 1.0),
|
||||
(1.0, 1.0),
|
||||
(1.0, 0.0),
|
||||
(0.0, 0.0),
|
||||
[(0.25, 0.25), (0.25, 0.5), (0.5, 0.5), (0.5, 0.25), (0.25, 0.25)],
|
||||
]
|
||||
]
|
||||
|
||||
# Sub-geometry Access
|
||||
assert isinstance(geom.geoms[0], Polygon)
|
||||
assert dump_coords(geom.geoms[0]) == [
|
||||
(0.0, 0.0),
|
||||
(0.0, 1.0),
|
||||
(1.0, 1.0),
|
||||
(1.0, 0.0),
|
||||
(0.0, 0.0),
|
||||
[(0.25, 0.25), (0.25, 0.5), (0.5, 0.5), (0.5, 0.25), (0.25, 0.25)],
|
||||
]
|
||||
with pytest.raises(IndexError): # index out of range
|
||||
geom.geoms[1]
|
||||
|
||||
# Geo interface
|
||||
assert geom.__geo_interface__ == {
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [
|
||||
(
|
||||
((0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0), (0.0, 0.0)),
|
||||
((0.25, 0.25), (0.25, 0.5), (0.5, 0.5), (0.5, 0.25), (0.25, 0.25)),
|
||||
)
|
||||
],
|
||||
}
|
||||
|
||||
def test_subgeom_access(self):
|
||||
poly0 = Polygon([(0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0)])
|
||||
poly1 = Polygon([(0.25, 0.25), (0.25, 0.5), (0.5, 0.5), (0.5, 0.25)])
|
||||
self.subgeom_access_test(MultiPolygon, [poly0, poly1])
|
||||
|
||||
|
||||
def test_fail_list_of_multipolygons():
|
||||
"""A list of multipolygons is not a valid multipolygon ctor argument"""
|
||||
multi = MultiPolygon(
|
||||
[
|
||||
(
|
||||
((0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0)),
|
||||
[((0.25, 0.25), (0.25, 0.5), (0.5, 0.5), (0.5, 0.25))],
|
||||
)
|
||||
]
|
||||
)
|
||||
with pytest.raises(ValueError):
|
||||
MultiPolygon([multi])
|
||||
|
||||
|
||||
def test_numpy_object_array():
|
||||
geom = MultiPolygon(
|
||||
[
|
||||
(
|
||||
((0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0)),
|
||||
[((0.25, 0.25), (0.25, 0.5), (0.5, 0.5), (0.5, 0.25))],
|
||||
)
|
||||
]
|
||||
)
|
||||
ar = np.empty(1, object)
|
||||
ar[:] = [geom]
|
||||
assert ar[0] == geom
|
||||
185
billinglayer/python/shapely/tests/geometry/test_point.py
Normal file
185
billinglayer/python/shapely/tests/geometry/test_point.py
Normal file
@@ -0,0 +1,185 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from shapely import Point
|
||||
from shapely.coords import CoordinateSequence
|
||||
from shapely.errors import DimensionError
|
||||
|
||||
|
||||
def test_from_coordinates():
|
||||
# 2D points
|
||||
p = Point(1.0, 2.0)
|
||||
assert p.coords[:] == [(1.0, 2.0)]
|
||||
assert p.has_z is False
|
||||
|
||||
# 3D Point
|
||||
p = Point(1.0, 2.0, 3.0)
|
||||
assert p.coords[:] == [(1.0, 2.0, 3.0)]
|
||||
assert p.has_z
|
||||
|
||||
# empty
|
||||
p = Point()
|
||||
assert p.is_empty
|
||||
assert isinstance(p.coords, CoordinateSequence)
|
||||
assert p.coords[:] == []
|
||||
|
||||
|
||||
def test_from_sequence():
|
||||
# From single coordinate pair
|
||||
p = Point((3.0, 4.0))
|
||||
assert p.coords[:] == [(3.0, 4.0)]
|
||||
p = Point([3.0, 4.0])
|
||||
assert p.coords[:] == [(3.0, 4.0)]
|
||||
|
||||
# From coordinate sequence
|
||||
p = Point([(3.0, 4.0)])
|
||||
assert p.coords[:] == [(3.0, 4.0)]
|
||||
p = Point([[3.0, 4.0]])
|
||||
assert p.coords[:] == [(3.0, 4.0)]
|
||||
|
||||
# 3D
|
||||
p = Point((3.0, 4.0, 5.0))
|
||||
assert p.coords[:] == [(3.0, 4.0, 5.0)]
|
||||
p = Point([3.0, 4.0, 5.0])
|
||||
assert p.coords[:] == [(3.0, 4.0, 5.0)]
|
||||
p = Point([(3.0, 4.0, 5.0)])
|
||||
assert p.coords[:] == [(3.0, 4.0, 5.0)]
|
||||
|
||||
|
||||
def test_from_numpy():
|
||||
# Construct from a numpy array
|
||||
p = Point(np.array([1.0, 2.0]))
|
||||
assert p.coords[:] == [(1.0, 2.0)]
|
||||
|
||||
p = Point(np.array([1.0, 2.0, 3.0]))
|
||||
assert p.coords[:] == [(1.0, 2.0, 3.0)]
|
||||
|
||||
|
||||
def test_from_numpy_xy():
|
||||
# Construct from separate x, y numpy arrays - if those are length 1,
|
||||
# this is allowed for compat with shapely 1.8
|
||||
# (https://github.com/shapely/shapely/issues/1587)
|
||||
p = Point(np.array([1.0]), np.array([2.0]))
|
||||
assert p.coords[:] == [(1.0, 2.0)]
|
||||
|
||||
p = Point(np.array([1.0]), np.array([2.0]), np.array([3.0]))
|
||||
assert p.coords[:] == [(1.0, 2.0, 3.0)]
|
||||
|
||||
|
||||
def test_from_point():
|
||||
# From another point
|
||||
p = Point(3.0, 4.0)
|
||||
q = Point(p)
|
||||
assert q.coords[:] == [(3.0, 4.0)]
|
||||
|
||||
p = Point(3.0, 4.0, 5.0)
|
||||
q = Point(p)
|
||||
assert q.coords[:] == [(3.0, 4.0, 5.0)]
|
||||
|
||||
|
||||
def test_from_generator():
|
||||
gen = (coord for coord in [(1.0, 2.0)])
|
||||
p = Point(gen)
|
||||
assert p.coords[:] == [(1.0, 2.0)]
|
||||
|
||||
|
||||
def test_from_invalid():
|
||||
|
||||
with pytest.raises(TypeError, match="takes at most 3 arguments"):
|
||||
Point(1, 2, 3, 4)
|
||||
|
||||
# this worked in shapely 1.x, just ignoring the other coords
|
||||
with pytest.raises(
|
||||
ValueError, match="takes only scalar or 1-size vector arguments"
|
||||
):
|
||||
Point([(2, 3), (11, 4)])
|
||||
|
||||
|
||||
class TestPoint:
|
||||
def test_point(self):
|
||||
|
||||
# Test 2D points
|
||||
p = Point(1.0, 2.0)
|
||||
assert p.x == 1.0
|
||||
assert p.y == 2.0
|
||||
assert p.coords[:] == [(1.0, 2.0)]
|
||||
assert str(p) == p.wkt
|
||||
assert p.has_z is False
|
||||
with pytest.raises(DimensionError):
|
||||
p.z
|
||||
|
||||
# Check 3D
|
||||
p = Point(1.0, 2.0, 3.0)
|
||||
assert p.coords[:] == [(1.0, 2.0, 3.0)]
|
||||
assert str(p) == p.wkt
|
||||
assert p.has_z is True
|
||||
assert p.z == 3.0
|
||||
|
||||
# Coordinate access
|
||||
p = Point((3.0, 4.0))
|
||||
assert p.x == 3.0
|
||||
assert p.y == 4.0
|
||||
assert tuple(p.coords) == ((3.0, 4.0),)
|
||||
assert p.coords[0] == (3.0, 4.0)
|
||||
with pytest.raises(IndexError): # index out of range
|
||||
p.coords[1]
|
||||
|
||||
# Bounds
|
||||
assert p.bounds == (3.0, 4.0, 3.0, 4.0)
|
||||
|
||||
# Geo interface
|
||||
assert p.__geo_interface__ == {"type": "Point", "coordinates": (3.0, 4.0)}
|
||||
|
||||
def test_point_empty(self):
|
||||
# Test Non-operability of Null geometry
|
||||
p_null = Point()
|
||||
assert p_null.wkt == "POINT EMPTY"
|
||||
assert p_null.coords[:] == []
|
||||
assert p_null.area == 0.0
|
||||
|
||||
def test_coords(self):
|
||||
# From Array.txt
|
||||
p = Point(0.0, 0.0, 1.0)
|
||||
coords = p.coords[0]
|
||||
assert coords == (0.0, 0.0, 1.0)
|
||||
|
||||
# Convert to Numpy array, passing through Python sequence
|
||||
a = np.asarray(coords)
|
||||
assert a.ndim == 1
|
||||
assert a.size == 3
|
||||
assert a.shape == (3,)
|
||||
|
||||
|
||||
def test_point_immutable():
|
||||
p = Point(3.0, 4.0)
|
||||
|
||||
with pytest.raises(AttributeError):
|
||||
p.coords = (2.0, 1.0)
|
||||
|
||||
with pytest.raises(TypeError):
|
||||
p.coords[0] = (2.0, 1.0)
|
||||
|
||||
|
||||
def test_point_array_coercion():
|
||||
# don't convert to array of coordinates, keep objects
|
||||
p = Point(3.0, 4.0)
|
||||
arr = np.array(p)
|
||||
assert arr.ndim == 0
|
||||
assert arr.size == 1
|
||||
assert arr.dtype == np.dtype("object")
|
||||
assert arr.item() == p
|
||||
|
||||
|
||||
def test_numpy_empty_point_coords():
|
||||
pe = Point()
|
||||
|
||||
# Access the coords
|
||||
a = np.asarray(pe.coords)
|
||||
assert a.shape == (0, 2)
|
||||
|
||||
|
||||
def test_numpy_object_array():
|
||||
geom = Point(3.0, 4.0)
|
||||
ar = np.empty(1, object)
|
||||
ar[:] = [geom]
|
||||
assert ar[0] == geom
|
||||
463
billinglayer/python/shapely/tests/geometry/test_polygon.py
Normal file
463
billinglayer/python/shapely/tests/geometry/test_polygon.py
Normal file
@@ -0,0 +1,463 @@
|
||||
"""Polygons and Linear Rings
|
||||
"""
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from shapely import LinearRing, LineString, Point, Polygon
|
||||
from shapely.coords import CoordinateSequence
|
||||
from shapely.errors import TopologicalError
|
||||
from shapely.wkb import loads as load_wkb
|
||||
|
||||
|
||||
def test_empty_linearring_coords():
|
||||
assert LinearRing().coords[:] == []
|
||||
|
||||
|
||||
def test_linearring_from_coordinate_sequence():
|
||||
expected_coords = [(0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (0.0, 0.0)]
|
||||
|
||||
ring = LinearRing([(0.0, 0.0), (0.0, 1.0), (1.0, 1.0)])
|
||||
assert ring.coords[:] == expected_coords
|
||||
|
||||
ring = LinearRing([(0.0, 0.0), (0.0, 1.0), (1.0, 1.0)])
|
||||
assert ring.coords[:] == expected_coords
|
||||
|
||||
|
||||
def test_linearring_from_points():
|
||||
# From Points
|
||||
expected_coords = [(0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (0.0, 0.0)]
|
||||
|
||||
ring = LinearRing([Point(0.0, 0.0), Point(0.0, 1.0), Point(1.0, 1.0)])
|
||||
assert ring.coords[:] == expected_coords
|
||||
|
||||
|
||||
def test_linearring_from_closed_linestring():
|
||||
coords = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0)]
|
||||
line = LineString(coords)
|
||||
ring = LinearRing(line)
|
||||
assert len(ring.coords) == 4
|
||||
assert ring.coords[:] == coords
|
||||
assert ring.geom_type == "LinearRing"
|
||||
|
||||
|
||||
def test_linearring_from_unclosed_linestring():
|
||||
coords = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0)]
|
||||
line = LineString(coords[:-1]) # Pass in unclosed line
|
||||
ring = LinearRing(line)
|
||||
assert len(ring.coords) == 4
|
||||
assert ring.coords[:] == coords
|
||||
assert ring.geom_type == "LinearRing"
|
||||
|
||||
|
||||
def test_linearring_from_invalid():
|
||||
coords = [(0.0, 0.0), (0.0, 0.0), (0.0, 0.0)]
|
||||
line = LineString(coords)
|
||||
assert not line.is_valid
|
||||
with pytest.raises(TopologicalError):
|
||||
LinearRing(line)
|
||||
|
||||
|
||||
def test_linearring_from_too_short_linestring():
|
||||
# Creation of LinearRing request at least 3 coordinates (unclosed) or
|
||||
# 4 coordinates (closed)
|
||||
coords = [(0.0, 0.0), (1.0, 1.0)]
|
||||
line = LineString(coords)
|
||||
with pytest.raises(ValueError, match="requires at least 4 coordinates"):
|
||||
LinearRing(line)
|
||||
|
||||
|
||||
def test_linearring_from_linearring():
|
||||
coords = [(0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (0.0, 0.0)]
|
||||
ring = LinearRing(coords)
|
||||
assert ring.coords[:] == coords
|
||||
|
||||
|
||||
def test_linearring_from_generator():
|
||||
coords = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0)]
|
||||
gen = (coord for coord in coords)
|
||||
ring = LinearRing(gen)
|
||||
assert ring.coords[:] == coords
|
||||
|
||||
|
||||
def test_linearring_from_empty():
|
||||
ring = LinearRing()
|
||||
assert ring.is_empty
|
||||
assert isinstance(ring.coords, CoordinateSequence)
|
||||
assert ring.coords[:] == []
|
||||
|
||||
ring = LinearRing([])
|
||||
assert ring.is_empty
|
||||
assert isinstance(ring.coords, CoordinateSequence)
|
||||
assert ring.coords[:] == []
|
||||
|
||||
|
||||
def test_linearring_from_numpy():
|
||||
# Construct from a numpy array
|
||||
coords = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0)]
|
||||
|
||||
ring = LinearRing(np.array(coords))
|
||||
assert ring.coords[:] == [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0)]
|
||||
|
||||
|
||||
def test_numpy_linearring_coords():
|
||||
from numpy.testing import assert_array_equal
|
||||
|
||||
ring = LinearRing([(0.0, 0.0), (0.0, 1.0), (1.0, 1.0)])
|
||||
ra = np.asarray(ring.coords)
|
||||
expected = np.asarray([(0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (0.0, 0.0)])
|
||||
assert_array_equal(ra, expected)
|
||||
|
||||
|
||||
def test_numpy_empty_linearring_coords():
|
||||
ring = LinearRing()
|
||||
assert np.asarray(ring.coords).shape == (0, 2)
|
||||
|
||||
|
||||
def test_numpy_object_array():
|
||||
geom = Polygon([(0.0, 0.0), (0.0, 1.0), (1.0, 1.0)])
|
||||
ar = np.empty(1, object)
|
||||
ar[:] = [geom]
|
||||
assert ar[0] == geom
|
||||
|
||||
|
||||
def test_polygon_from_coordinate_sequence():
|
||||
coords = [(0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (0.0, 0.0)]
|
||||
|
||||
# Construct a polygon, exterior ring only
|
||||
polygon = Polygon([(0.0, 0.0), (0.0, 1.0), (1.0, 1.0)])
|
||||
assert polygon.exterior.coords[:] == coords
|
||||
assert len(polygon.interiors) == 0
|
||||
|
||||
polygon = Polygon([(0.0, 0.0), (0.0, 1.0), (1.0, 1.0)])
|
||||
assert polygon.exterior.coords[:] == coords
|
||||
assert len(polygon.interiors) == 0
|
||||
|
||||
|
||||
def test_polygon_from_coordinate_sequence_with_holes():
|
||||
coords = [(0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (0.0, 0.0)]
|
||||
|
||||
# Interior rings (holes)
|
||||
polygon = Polygon(coords, [[(0.25, 0.25), (0.25, 0.5), (0.5, 0.5), (0.5, 0.25)]])
|
||||
assert polygon.exterior.coords[:] == coords
|
||||
assert len(polygon.interiors) == 1
|
||||
assert len(polygon.interiors[0].coords) == 5
|
||||
|
||||
# Multiple interior rings with different length
|
||||
coords = [(0, 0), (0, 10), (10, 10), (10, 0), (0, 0)]
|
||||
holes = [
|
||||
[(1, 1), (2, 1), (2, 2), (1, 2), (1, 1)],
|
||||
[(3, 3), (3, 4), (4, 5), (5, 4), (5, 3), (3, 3)],
|
||||
]
|
||||
polygon = Polygon(coords, holes)
|
||||
assert polygon.exterior.coords[:] == coords
|
||||
assert len(polygon.interiors) == 2
|
||||
assert len(polygon.interiors[0].coords) == 5
|
||||
assert len(polygon.interiors[1].coords) == 6
|
||||
|
||||
|
||||
def test_polygon_from_linearring():
|
||||
coords = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0)]
|
||||
ring = LinearRing(coords)
|
||||
|
||||
polygon = Polygon(ring)
|
||||
assert polygon.exterior.coords[:] == coords
|
||||
assert len(polygon.interiors) == 0
|
||||
|
||||
# from shell and holes linearrings
|
||||
shell = LinearRing([(0.0, 0.0), (70.0, 120.0), (140.0, 0.0), (0.0, 0.0)])
|
||||
holes = [
|
||||
LinearRing([(60.0, 80.0), (80.0, 80.0), (70.0, 60.0), (60.0, 80.0)]),
|
||||
LinearRing([(30.0, 10.0), (50.0, 10.0), (40.0, 30.0), (30.0, 10.0)]),
|
||||
LinearRing([(90.0, 10), (110.0, 10.0), (100.0, 30.0), (90.0, 10.0)]),
|
||||
]
|
||||
polygon = Polygon(shell, holes)
|
||||
assert polygon.exterior.coords[:] == shell.coords[:]
|
||||
assert len(polygon.interiors) == 3
|
||||
for i in range(3):
|
||||
assert polygon.interiors[i].coords[:] == holes[i].coords[:]
|
||||
|
||||
|
||||
def test_polygon_from_linestring():
|
||||
coords = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0)]
|
||||
line = LineString(coords)
|
||||
polygon = Polygon(line)
|
||||
assert polygon.exterior.coords[:] == coords
|
||||
|
||||
# from unclosed linestring
|
||||
line = LineString(coords[:-1])
|
||||
polygon = Polygon(line)
|
||||
assert polygon.exterior.coords[:] == coords
|
||||
|
||||
|
||||
def test_polygon_from_points():
|
||||
polygon = Polygon([Point(0.0, 0.0), Point(0.0, 1.0), Point(1.0, 1.0)])
|
||||
expected_coords = [(0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (0.0, 0.0)]
|
||||
assert polygon.exterior.coords[:] == expected_coords
|
||||
|
||||
|
||||
def test_polygon_from_polygon():
|
||||
coords = [(0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0)]
|
||||
polygon = Polygon(coords, [[(0.25, 0.25), (0.25, 0.5), (0.5, 0.5), (0.5, 0.25)]])
|
||||
|
||||
# Test from another Polygon
|
||||
copy = Polygon(polygon)
|
||||
assert len(copy.exterior.coords) == 5
|
||||
assert len(copy.interiors) == 1
|
||||
assert len(copy.interiors[0].coords) == 5
|
||||
|
||||
|
||||
def test_polygon_from_invalid():
|
||||
# Error handling
|
||||
with pytest.raises(ValueError):
|
||||
# A LinearRing must have at least 3 coordinate tuples
|
||||
Polygon([[1, 2], [2, 3]])
|
||||
|
||||
|
||||
def test_polygon_from_empty():
|
||||
polygon = Polygon()
|
||||
assert polygon.is_empty
|
||||
assert polygon.exterior.coords[:] == []
|
||||
|
||||
polygon = Polygon([])
|
||||
assert polygon.is_empty
|
||||
assert polygon.exterior.coords[:] == []
|
||||
|
||||
|
||||
def test_polygon_from_numpy():
|
||||
a = np.array(((0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0), (0.0, 0.0)))
|
||||
polygon = Polygon(a)
|
||||
assert len(polygon.exterior.coords) == 5
|
||||
assert polygon.exterior.coords[:] == [
|
||||
(0.0, 0.0),
|
||||
(0.0, 1.0),
|
||||
(1.0, 1.0),
|
||||
(1.0, 0.0),
|
||||
(0.0, 0.0),
|
||||
]
|
||||
assert len(polygon.interiors) == 0
|
||||
|
||||
|
||||
def test_polygon_from_generator():
|
||||
coords = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0)]
|
||||
gen = (coord for coord in coords)
|
||||
polygon = Polygon(gen)
|
||||
assert polygon.exterior.coords[:] == coords
|
||||
|
||||
|
||||
class TestPolygon:
|
||||
def test_linearring(self):
|
||||
|
||||
# Initialization
|
||||
# Linear rings won't usually be created by users, but by polygons
|
||||
coords = ((0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0))
|
||||
ring = LinearRing(coords)
|
||||
assert len(ring.coords) == 5
|
||||
assert ring.coords[0] == ring.coords[4]
|
||||
assert ring.coords[0] == ring.coords[-1]
|
||||
assert ring.is_ring is True
|
||||
|
||||
def test_polygon(self):
|
||||
coords = ((0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0))
|
||||
|
||||
# Construct a polygon, exterior ring only
|
||||
polygon = Polygon(coords)
|
||||
assert len(polygon.exterior.coords) == 5
|
||||
|
||||
# Ring Access
|
||||
assert isinstance(polygon.exterior, LinearRing)
|
||||
ring = polygon.exterior
|
||||
assert len(ring.coords) == 5
|
||||
assert ring.coords[0] == ring.coords[4]
|
||||
assert ring.coords[0] == (0.0, 0.0)
|
||||
assert ring.is_ring is True
|
||||
assert len(polygon.interiors) == 0
|
||||
|
||||
# Create a new polygon from WKB
|
||||
data = polygon.wkb
|
||||
polygon = None
|
||||
ring = None
|
||||
polygon = load_wkb(data)
|
||||
ring = polygon.exterior
|
||||
assert len(ring.coords) == 5
|
||||
assert ring.coords[0] == ring.coords[4]
|
||||
assert ring.coords[0] == (0.0, 0.0)
|
||||
assert ring.is_ring is True
|
||||
polygon = None
|
||||
|
||||
# Interior rings (holes)
|
||||
polygon = Polygon(
|
||||
coords, [((0.25, 0.25), (0.25, 0.5), (0.5, 0.5), (0.5, 0.25))]
|
||||
)
|
||||
assert len(polygon.exterior.coords) == 5
|
||||
assert len(polygon.interiors[0].coords) == 5
|
||||
with pytest.raises(IndexError): # index out of range
|
||||
polygon.interiors[1]
|
||||
|
||||
# Coordinate getter raises exceptions
|
||||
with pytest.raises(NotImplementedError):
|
||||
polygon.coords
|
||||
|
||||
# Geo interface
|
||||
assert polygon.__geo_interface__ == {
|
||||
"type": "Polygon",
|
||||
"coordinates": (
|
||||
((0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0), (0.0, 0.0)),
|
||||
((0.25, 0.25), (0.25, 0.5), (0.5, 0.5), (0.5, 0.25), (0.25, 0.25)),
|
||||
),
|
||||
}
|
||||
|
||||
def test_linearring_empty(self):
|
||||
# Test Non-operability of Null rings
|
||||
r_null = LinearRing()
|
||||
assert r_null.wkt == "LINEARRING EMPTY"
|
||||
assert r_null.length == 0.0
|
||||
|
||||
def test_dimensions(self):
|
||||
|
||||
# Background: see http://trac.gispython.org/lab/ticket/168
|
||||
# http://lists.gispython.org/pipermail/community/2008-August/001859.html
|
||||
|
||||
coords = ((0.0, 0.0, 0.0), (0.0, 1.0, 0.0), (1.0, 1.0, 0.0), (1.0, 0.0, 0.0))
|
||||
polygon = Polygon(coords)
|
||||
assert polygon._ndim == 3
|
||||
gi = polygon.__geo_interface__
|
||||
assert gi["coordinates"] == (
|
||||
(
|
||||
(0.0, 0.0, 0.0),
|
||||
(0.0, 1.0, 0.0),
|
||||
(1.0, 1.0, 0.0),
|
||||
(1.0, 0.0, 0.0),
|
||||
(0.0, 0.0, 0.0),
|
||||
),
|
||||
)
|
||||
|
||||
e = polygon.exterior
|
||||
assert e._ndim == 3
|
||||
gi = e.__geo_interface__
|
||||
assert gi["coordinates"] == (
|
||||
(0.0, 0.0, 0.0),
|
||||
(0.0, 1.0, 0.0),
|
||||
(1.0, 1.0, 0.0),
|
||||
(1.0, 0.0, 0.0),
|
||||
(0.0, 0.0, 0.0),
|
||||
)
|
||||
|
||||
def test_attribute_chains(self):
|
||||
|
||||
# Attribute Chaining
|
||||
# See also ticket #151.
|
||||
p = Polygon([(0.0, 0.0), (0.0, 1.0), (-1.0, 1.0), (-1.0, 0.0)])
|
||||
assert list(p.boundary.coords) == [
|
||||
(0.0, 0.0),
|
||||
(0.0, 1.0),
|
||||
(-1.0, 1.0),
|
||||
(-1.0, 0.0),
|
||||
(0.0, 0.0),
|
||||
]
|
||||
|
||||
ec = list(Point(0.0, 0.0).buffer(1.0, 1).exterior.coords)
|
||||
assert isinstance(ec, list) # TODO: this is a poor test
|
||||
|
||||
# Test chained access to interiors
|
||||
p = Polygon(
|
||||
[(0.0, 0.0), (0.0, 1.0), (-1.0, 1.0), (-1.0, 0.0)],
|
||||
[[(-0.25, 0.25), (-0.25, 0.75), (-0.75, 0.75), (-0.75, 0.25)]],
|
||||
)
|
||||
assert p.area == 0.75
|
||||
|
||||
"""Not so much testing the exact values here, which are the
|
||||
responsibility of the geometry engine (GEOS), but that we can get
|
||||
chain functions and properties using anonymous references.
|
||||
"""
|
||||
assert list(p.interiors[0].coords) == [
|
||||
(-0.25, 0.25),
|
||||
(-0.25, 0.75),
|
||||
(-0.75, 0.75),
|
||||
(-0.75, 0.25),
|
||||
(-0.25, 0.25),
|
||||
]
|
||||
xy = list(p.interiors[0].buffer(1).exterior.coords)[0]
|
||||
assert len(xy) == 2
|
||||
|
||||
# Test multiple operators, boundary of a buffer
|
||||
ec = list(p.buffer(1).boundary.coords)
|
||||
assert isinstance(ec, list) # TODO: this is a poor test
|
||||
|
||||
def test_empty_equality(self):
|
||||
# Test equals operator, including empty geometries
|
||||
# see issue #338
|
||||
|
||||
point1 = Point(0, 0)
|
||||
polygon1 = Polygon([(0.0, 0.0), (0.0, 1.0), (-1.0, 1.0), (-1.0, 0.0)])
|
||||
polygon2 = Polygon([(0.0, 0.0), (0.0, 1.0), (-1.0, 1.0), (-1.0, 0.0)])
|
||||
polygon_empty1 = Polygon()
|
||||
polygon_empty2 = Polygon()
|
||||
|
||||
assert point1 != polygon1
|
||||
assert polygon_empty1 == polygon_empty2
|
||||
assert polygon1 != polygon_empty1
|
||||
assert polygon1 == polygon2
|
||||
assert polygon_empty1 is not None
|
||||
|
||||
def test_from_bounds(self):
|
||||
xmin, ymin, xmax, ymax = -180, -90, 180, 90
|
||||
coords = [(xmin, ymin), (xmin, ymax), (xmax, ymax), (xmax, ymin)]
|
||||
assert Polygon(coords) == Polygon.from_bounds(xmin, ymin, xmax, ymax)
|
||||
|
||||
def test_empty_polygon_exterior(self):
|
||||
p = Polygon()
|
||||
assert p.exterior == LinearRing()
|
||||
|
||||
|
||||
def test_linearring_immutable():
|
||||
ring = LinearRing([(0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0)])
|
||||
|
||||
with pytest.raises(AttributeError):
|
||||
ring.coords = [(1.0, 1.0), (2.0, 2.0), (1.0, 2.0)]
|
||||
|
||||
with pytest.raises(TypeError):
|
||||
ring.coords[0] = (1.0, 1.0)
|
||||
|
||||
|
||||
class TestLinearRingGetItem:
|
||||
def test_index_linearring(self):
|
||||
shell = LinearRing([(0.0, 0.0), (70.0, 120.0), (140.0, 0.0), (0.0, 0.0)])
|
||||
holes = [
|
||||
LinearRing([(60.0, 80.0), (80.0, 80.0), (70.0, 60.0), (60.0, 80.0)]),
|
||||
LinearRing([(30.0, 10.0), (50.0, 10.0), (40.0, 30.0), (30.0, 10.0)]),
|
||||
LinearRing([(90.0, 10), (110.0, 10.0), (100.0, 30.0), (90.0, 10.0)]),
|
||||
]
|
||||
g = Polygon(shell, holes)
|
||||
for i in range(-3, 3):
|
||||
assert g.interiors[i].equals(holes[i])
|
||||
with pytest.raises(IndexError):
|
||||
g.interiors[3]
|
||||
with pytest.raises(IndexError):
|
||||
g.interiors[-4]
|
||||
|
||||
def test_index_linearring_misc(self):
|
||||
g = Polygon() # empty
|
||||
with pytest.raises(IndexError):
|
||||
g.interiors[0]
|
||||
with pytest.raises(TypeError):
|
||||
g.interiors[0.0]
|
||||
|
||||
def test_slice_linearring(self):
|
||||
shell = LinearRing([(0.0, 0.0), (70.0, 120.0), (140.0, 0.0), (0.0, 0.0)])
|
||||
holes = [
|
||||
LinearRing([(60.0, 80.0), (80.0, 80.0), (70.0, 60.0), (60.0, 80.0)]),
|
||||
LinearRing([(30.0, 10.0), (50.0, 10.0), (40.0, 30.0), (30.0, 10.0)]),
|
||||
LinearRing([(90.0, 10), (110.0, 10.0), (100.0, 30.0), (90.0, 10.0)]),
|
||||
]
|
||||
g = Polygon(shell, holes)
|
||||
t = [a.equals(b) for (a, b) in zip(g.interiors[1:], holes[1:])]
|
||||
assert all(t)
|
||||
t = [a.equals(b) for (a, b) in zip(g.interiors[:-1], holes[:-1])]
|
||||
assert all(t)
|
||||
t = [a.equals(b) for (a, b) in zip(g.interiors[::-1], holes[::-1])]
|
||||
assert all(t)
|
||||
t = [a.equals(b) for (a, b) in zip(g.interiors[::2], holes[::2])]
|
||||
assert all(t)
|
||||
t = [a.equals(b) for (a, b) in zip(g.interiors[:3], holes[:3])]
|
||||
assert all(t)
|
||||
assert g.interiors[3:] == holes[3:] == []
|
||||
Reference in New Issue
Block a user