shapely 2.0.4__tar.gz → 2.0.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {shapely-2.0.4 → shapely-2.0.5}/CHANGES.txt +13 -0
- {shapely-2.0.4 → shapely-2.0.5}/CITATION.cff +2 -2
- {shapely-2.0.4 → shapely-2.0.5}/PKG-INFO +1 -1
- {shapely-2.0.4 → shapely-2.0.5}/docs/geometry.rst +35 -0
- {shapely-2.0.4 → shapely-2.0.5}/docs/installation.rst +2 -2
- {shapely-2.0.4 → shapely-2.0.5}/docs/migration_pygeos.rst +2 -2
- {shapely-2.0.4 → shapely-2.0.5}/pyproject.toml +1 -1
- {shapely-2.0.4 → shapely-2.0.5}/setup.py +11 -13
- {shapely-2.0.4 → shapely-2.0.5}/shapely/_geometry.py +32 -23
- {shapely-2.0.4 → shapely-2.0.5}/shapely/_geometry_helpers.pyx +1 -1
- {shapely-2.0.4 → shapely-2.0.5}/shapely/_version.py +3 -3
- {shapely-2.0.4 → shapely-2.0.5}/shapely/affinity.py +23 -7
- {shapely-2.0.4 → shapely-2.0.5}/shapely/constructive.py +13 -12
- {shapely-2.0.4 → shapely-2.0.5}/shapely/coords.py +7 -2
- {shapely-2.0.4 → shapely-2.0.5}/shapely/creation.py +1 -1
- {shapely-2.0.4 → shapely-2.0.5}/shapely/geometry/point.py +2 -2
- {shapely-2.0.4 → shapely-2.0.5}/shapely/io.py +2 -2
- {shapely-2.0.4 → shapely-2.0.5}/shapely/plotting.py +5 -5
- {shapely-2.0.4 → shapely-2.0.5}/shapely/predicates.py +2 -2
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/geometry/test_coords.py +16 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/geometry/test_format.py +1 -1
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/geometry/test_point.py +3 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/test_geometry.py +1 -1
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/test_linear.py +1 -1
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/test_predicates.py +1 -1
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/test_set_operations.py +4 -4
- {shapely-2.0.4 → shapely-2.0.5}/shapely.egg-info/PKG-INFO +1 -1
- {shapely-2.0.4 → shapely-2.0.5}/src/coords.c +2 -2
- {shapely-2.0.4 → shapely-2.0.5}/src/geos.c +1 -1
- {shapely-2.0.4 → shapely-2.0.5}/src/strtree.c +2 -2
- {shapely-2.0.4 → shapely-2.0.5}/src/ufuncs.c +3 -3
- {shapely-2.0.4 → shapely-2.0.5}/CREDITS.txt +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/LICENSE.txt +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/README.rst +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/docs/constructive.rst +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/docs/coordinates.rst +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/docs/creation.rst +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/docs/design.rst +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/docs/index.rst +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/docs/io.rst +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/docs/linear.rst +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/docs/manual.rst +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/docs/measurement.rst +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/docs/migration.rst +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/docs/predicates.rst +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/docs/properties.rst +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/docs/release.rst +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/docs/set_operations.rst +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/docs/strtree.rst +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/docs/testing.rst +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/setup.cfg +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/__init__.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/_enum.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/_geos.pxd +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/_geos.pyx +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/_pygeos_api.pxd +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/_ragged_array.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/algorithms/__init__.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/algorithms/_oriented_envelope.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/algorithms/cga.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/algorithms/polylabel.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/coordinates.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/decorators.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/errors.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/geometry/__init__.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/geometry/base.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/geometry/collection.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/geometry/conftest.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/geometry/geo.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/geometry/linestring.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/geometry/multilinestring.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/geometry/multipoint.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/geometry/multipolygon.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/geometry/polygon.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/geos.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/linear.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/measurement.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/ops.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/prepared.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/set_operations.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/speedups.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/strtree.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/testing.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/__init__.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/common.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/geometry/__init__.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/geometry/test_collection.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/geometry/test_decimal.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/geometry/test_emptiness.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/geometry/test_equality.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/geometry/test_geometry_base.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/geometry/test_hash.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/geometry/test_linestring.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/geometry/test_multi.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/geometry/test_multilinestring.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/geometry/test_multipoint.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/geometry/test_multipolygon.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/geometry/test_polygon.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/__init__.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/conftest.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_affinity.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_box.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_buffer.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_cga.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_clip_by_rect.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_create_inconsistent_dimensionality.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_delaunay.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_empty_polygons.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_equality.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_geointerface.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_invalid_geometries.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_linear_referencing.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_linemerge.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_locale.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_make_valid.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_mapping.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_minimum_clearance.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_ndarrays.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_nearest.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_operations.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_operators.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_orient.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_parallel_offset.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_persist.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_pickle.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_polygonize.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_polylabel.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_predicates.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_prepared.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_products_z.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_shape.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_shared_paths.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_singularity.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_snap.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_split.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_substring.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_svg.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_transform.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_union.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_validation.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_vectorized.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_voronoi_diagram.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_wkb.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/test_wkt.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/legacy/threading_test.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/test_constructive.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/test_coordinates.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/test_creation.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/test_creation_indices.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/test_io.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/test_measurement.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/test_misc.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/test_plotting.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/test_ragged_array.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/test_strtree.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/tests/test_testing.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/validation.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/vectorized/__init__.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/wkb.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely/wkt.py +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely.egg-info/SOURCES.txt +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely.egg-info/dependency_links.txt +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely.egg-info/requires.txt +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/shapely.egg-info/top_level.txt +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/src/c_api.c +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/src/c_api.h +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/src/coords.h +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/src/fast_loop_macros.h +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/src/geos.h +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/src/kvec.h +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/src/lib.c +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/src/pygeom.c +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/src/pygeom.h +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/src/strtree.h +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/src/ufuncs.h +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/src/vector.c +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/src/vector.h +0 -0
- {shapely-2.0.4 → shapely-2.0.5}/versioneer.py +0 -0
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
Changes
|
|
2
2
|
=======
|
|
3
3
|
|
|
4
|
+
2.0.5 (2024-07-13)
|
|
5
|
+
------------------
|
|
6
|
+
|
|
7
|
+
Binary wheels on PyPI include GEOS 3.11.4 from 2024-06-05. Furthermore,
|
|
8
|
+
universal2 wheels are removed for macOS since both x86_64 and arm64 wheels are
|
|
9
|
+
provided.
|
|
10
|
+
|
|
11
|
+
Bug fixes:
|
|
12
|
+
|
|
13
|
+
- Fix Point x/y/z attributes to return Python floats (#2074).
|
|
14
|
+
- Fix affinity for Apple silicon with NumPy 2.0 by reverting matmul, and
|
|
15
|
+
use direct matrix multiplication instead (#2085).
|
|
16
|
+
|
|
4
17
|
2.0.4 (2024-04-16)
|
|
5
18
|
------------------
|
|
6
19
|
|
|
@@ -2,8 +2,8 @@ cff-version: 1.2.0
|
|
|
2
2
|
message: "Please cite this software using these metadata."
|
|
3
3
|
type: software
|
|
4
4
|
title: Shapely
|
|
5
|
-
version: "2.0.
|
|
6
|
-
date-released: "2024-
|
|
5
|
+
version: "2.0.5"
|
|
6
|
+
date-released: "2024-07-13"
|
|
7
7
|
doi: 10.5281/zenodo.5597138
|
|
8
8
|
abstract: "Manipulation and analysis of geometric objects in the Cartesian plane."
|
|
9
9
|
repository-artifact: https://pypi.org/project/Shapely
|
|
@@ -173,3 +173,38 @@ specified, rounding precision will be disabled showing full precision.
|
|
|
173
173
|
Format types ``'x'`` and ``'X'`` show a hex-encoded string representation of
|
|
174
174
|
WKB or Well-Known Binary, with the case of the output matched the
|
|
175
175
|
case of the format type character.
|
|
176
|
+
|
|
177
|
+
.. _canonical-form:
|
|
178
|
+
|
|
179
|
+
Canonical form
|
|
180
|
+
--------------
|
|
181
|
+
When operations are applied on geometries the result is returned according to
|
|
182
|
+
some conventions.
|
|
183
|
+
|
|
184
|
+
In most cases, geometries will be returned in "mild" canonical form. There is no
|
|
185
|
+
goal to keep this form stable, so it is expected to change in future versions of
|
|
186
|
+
GEOS:
|
|
187
|
+
|
|
188
|
+
- the coordinates of exterior rings follow a clockwise orientation and interior
|
|
189
|
+
rings have a counter-clockwise orientation. This is the opposite of the OGC
|
|
190
|
+
specifications because the choice was made before this was included in the
|
|
191
|
+
standard.
|
|
192
|
+
- the starting point of rings can be changed in the output, but the exact order
|
|
193
|
+
is undefined and should not be relied upon
|
|
194
|
+
- the order of geometry types in a collection can be changed, but the order is
|
|
195
|
+
undefined
|
|
196
|
+
|
|
197
|
+
When :func:`~shapely.normalize` is used, the "strict" canonical form is applied.
|
|
198
|
+
This type of normalization is meant to be stable, so changes to it will be
|
|
199
|
+
avoided if possible:
|
|
200
|
+
|
|
201
|
+
- the coordinates of exterior rings follow a clockwise orientation and interior
|
|
202
|
+
rings have a counter-clockwise orientation
|
|
203
|
+
- the starting point of rings is lower left
|
|
204
|
+
- elements in collections are ordered by geometry type: by descending dimension
|
|
205
|
+
and multi-types first (MultiPolygon, Polygon, MultiLineString, LineString,
|
|
206
|
+
MultiPoint, Point). Multiple elements from the same type are ordered from
|
|
207
|
+
right to left and from top to bottom.
|
|
208
|
+
|
|
209
|
+
It is important to note that input geometries do not have to follow these
|
|
210
|
+
conventions.
|
|
@@ -26,8 +26,8 @@ Shapely is available on the conda-forge channel. Install as follows::
|
|
|
26
26
|
$ conda install shapely --channel conda-forge
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
Installation from source with custom GEOS
|
|
30
|
-
|
|
29
|
+
Installation from source with custom GEOS library
|
|
30
|
+
-------------------------------------------------
|
|
31
31
|
|
|
32
32
|
You may want to use a specific GEOS version or a GEOS distribution that is
|
|
33
33
|
already present on your system (for compatibility with other modules that
|
|
@@ -14,7 +14,7 @@ Therefore, everybody using PyGEOS is highly recommended to migrate to Shapely
|
|
|
14
14
|
|
|
15
15
|
Generally speaking, this should be a smooth experience because all
|
|
16
16
|
functionality of PyGEOS was added to Shapely. All vectorized functions
|
|
17
|
-
|
|
17
|
+
available in ``pygeos`` have been added to the top-level ``shapely`` module,
|
|
18
18
|
with only minor differences (see below). Migrating from PyGEOS to Shapely 2.0
|
|
19
19
|
can thus be done by replacing the ``pygeos`` import and module calls::
|
|
20
20
|
|
|
@@ -87,4 +87,4 @@ Other differences
|
|
|
87
87
|
- The behaviour of ``union_all()`` / ``intersection_all()`` / ``symmetric_difference_all``
|
|
88
88
|
was changed to return an empty GeometryCollection for an empty or all-None
|
|
89
89
|
sequence as input (instead of returning None).
|
|
90
|
-
- The ``radius`` keyword of the ``buffer()``
|
|
90
|
+
- The ``radius`` keyword of the ``buffer()`` function was renamed to ``distance``.
|
|
@@ -3,7 +3,7 @@ requires = [
|
|
|
3
3
|
"Cython",
|
|
4
4
|
# Starting with NumPy 1.25, NumPy is (by default) as far back compatible
|
|
5
5
|
# as oldest-support-numpy was (customizable with a NPY_TARGET_VERSION
|
|
6
|
-
# define). For older Python versions (where NumPy 1.25 is not yet
|
|
6
|
+
# define). For older Python versions (where NumPy 1.25 is not yet available)
|
|
7
7
|
# continue using oldest-support-numpy.
|
|
8
8
|
"oldest-supported-numpy; python_version<'3.9'",
|
|
9
9
|
"numpy>=1.25; python_version>='3.9'",
|
|
@@ -5,8 +5,7 @@ import subprocess
|
|
|
5
5
|
import sys
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
|
|
8
|
-
from
|
|
9
|
-
from setuptools import Extension, find_packages, setup
|
|
8
|
+
from setuptools import Extension, setup
|
|
10
9
|
from setuptools.command.build_ext import build_ext as _build_ext
|
|
11
10
|
|
|
12
11
|
# ensure the current directory is on sys.path so versioneer can be imported
|
|
@@ -42,15 +41,13 @@ def get_geos_config(option):
|
|
|
42
41
|
"""
|
|
43
42
|
cmd = os.environ.get("GEOS_CONFIG", "geos-config")
|
|
44
43
|
try:
|
|
45
|
-
|
|
46
|
-
[cmd, option], stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
|
47
|
-
).communicate()
|
|
44
|
+
proc = subprocess.run([cmd, option], capture_output=True, text=True)
|
|
48
45
|
except OSError:
|
|
49
46
|
return
|
|
50
|
-
if stderr and not stdout:
|
|
51
|
-
log.warning("geos-config %s returned '%s'", option, stderr.
|
|
47
|
+
if proc.stderr and not proc.stdout:
|
|
48
|
+
log.warning("geos-config %s returned '%s'", option, proc.stderr.strip())
|
|
52
49
|
return
|
|
53
|
-
result = stdout.
|
|
50
|
+
result = proc.stdout.strip()
|
|
54
51
|
log.debug("geos-config %s returned '%s'", option, result)
|
|
55
52
|
return result
|
|
56
53
|
|
|
@@ -86,11 +83,12 @@ def get_geos_paths():
|
|
|
86
83
|
)
|
|
87
84
|
return {}
|
|
88
85
|
|
|
89
|
-
|
|
86
|
+
def version_tuple(ver):
|
|
87
|
+
return tuple(int(itm) if itm.isnumeric() else itm for itm in ver.split("."))
|
|
88
|
+
|
|
89
|
+
if version_tuple(geos_version) < version_tuple(MIN_GEOS_VERSION):
|
|
90
90
|
raise ImportError(
|
|
91
|
-
"GEOS version should be >={}, found {}"
|
|
92
|
-
MIN_GEOS_VERSION, geos_version
|
|
93
|
-
)
|
|
91
|
+
f"GEOS version should be >={MIN_GEOS_VERSION}, found {geos_version}"
|
|
94
92
|
)
|
|
95
93
|
|
|
96
94
|
libraries = []
|
|
@@ -133,7 +131,7 @@ class build_ext(_build_ext):
|
|
|
133
131
|
|
|
134
132
|
import numpy
|
|
135
133
|
|
|
136
|
-
self.include_dirs.
|
|
134
|
+
self.include_dirs.insert(0, numpy.get_include())
|
|
137
135
|
|
|
138
136
|
|
|
139
137
|
ext_modules = []
|
|
@@ -728,20 +728,26 @@ def set_precision(geometry, grid_size, mode="valid_output", **kwargs):
|
|
|
728
728
|
|
|
729
729
|
By default, geometries use double precision coordinates (grid_size = 0).
|
|
730
730
|
|
|
731
|
-
Coordinates will be rounded if
|
|
732
|
-
input geometry. Duplicated vertices will be dropped from lines and
|
|
731
|
+
Coordinates will be rounded if the precision grid specified is less precise
|
|
732
|
+
than the input geometry. Duplicated vertices will be dropped from lines and
|
|
733
733
|
polygons for grid sizes greater than 0. Line and polygon geometries may
|
|
734
734
|
collapse to empty geometries if all vertices are closer together than
|
|
735
|
-
grid_size
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
735
|
+
``grid_size`` or if a polygon becomes significantly narrower than
|
|
736
|
+
``grid_size``. Spikes or sections in polygons narrower than ``grid_size``
|
|
737
|
+
after rounding the vertices will be removed, which can lead to multipolygons
|
|
738
|
+
or empty geometries. Z values, if present, will not be modified.
|
|
739
|
+
|
|
740
|
+
Notes:
|
|
741
|
+
|
|
742
|
+
* subsequent operations will always be performed in the precision of the
|
|
743
|
+
geometry with higher precision (smaller "grid_size"). That same precision
|
|
744
|
+
will be attached to the operation outputs.
|
|
745
|
+
* input geometries should be geometrically valid; unexpected results may
|
|
746
|
+
occur if input geometries are not.
|
|
747
|
+
* the geometry returned will be in
|
|
748
|
+
:ref:`mild canonical form <canonical-form>`, and the order of vertices can
|
|
749
|
+
change and should not be relied upon.
|
|
750
|
+
* returns None if geometry is None.
|
|
745
751
|
|
|
746
752
|
Parameters
|
|
747
753
|
----------
|
|
@@ -752,21 +758,24 @@ def set_precision(geometry, grid_size, mode="valid_output", **kwargs):
|
|
|
752
758
|
value is more precise than input geometry, the input geometry will
|
|
753
759
|
not be modified.
|
|
754
760
|
mode : {'valid_output', 'pointwise', 'keep_collapsed'}, default 'valid_output'
|
|
755
|
-
This parameter determines
|
|
761
|
+
This parameter determines the way a precision reduction is applied on
|
|
762
|
+
the geometry. There are three modes:
|
|
756
763
|
|
|
757
|
-
1. `'valid_output'` (default): The output is always valid. Collapsed
|
|
758
|
-
(including both polygons and lines) are removed.
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
764
|
+
1. `'valid_output'` (default): The output is always valid. Collapsed
|
|
765
|
+
geometry elements (including both polygons and lines) are removed.
|
|
766
|
+
Duplicate vertices are removed.
|
|
767
|
+
2. `'pointwise'`: Precision reduction is performed pointwise. Output
|
|
768
|
+
geometry may be invalid due to collapse or self-intersection.
|
|
769
|
+
Duplicate vertices are not removed. In GEOS this option is called
|
|
770
|
+
NO_TOPO.
|
|
762
771
|
|
|
763
772
|
.. note::
|
|
764
773
|
|
|
765
|
-
'pointwise' mode requires at least GEOS 3.10. It is accepted in
|
|
766
|
-
but the results may be unexpected.
|
|
767
|
-
3. `'keep_collapsed'`: Like the default mode, except that collapsed
|
|
768
|
-
elements are preserved. Collapsed polygonal input
|
|
769
|
-
vertices are removed.
|
|
774
|
+
'pointwise' mode requires at least GEOS 3.10. It is accepted in
|
|
775
|
+
earlier versions, but the results may be unexpected.
|
|
776
|
+
3. `'keep_collapsed'`: Like the default mode, except that collapsed
|
|
777
|
+
linear geometry elements are preserved. Collapsed polygonal input
|
|
778
|
+
elements are removed. Duplicate vertices are removed.
|
|
770
779
|
**kwargs
|
|
771
780
|
See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
|
|
772
781
|
|
|
@@ -302,7 +302,7 @@ def collections_1d(object geometries, object indices, int geometry_type = 7, obj
|
|
|
302
302
|
cdef int[:] collection_size = np.bincount(indices).astype(np.int32)
|
|
303
303
|
|
|
304
304
|
# A temporary array for the geometries that will be given to CreateCollection.
|
|
305
|
-
# Its size equals max(collection_size) to
|
|
305
|
+
# Its size equals max(collection_size) to accommodate the largest collection.
|
|
306
306
|
temp_geoms = np.empty(shape=(np.max(collection_size), ), dtype=np.intp)
|
|
307
307
|
cdef np.intp_t[:] temp_geoms_view = temp_geoms
|
|
308
308
|
|
|
@@ -8,11 +8,11 @@ import json
|
|
|
8
8
|
|
|
9
9
|
version_json = '''
|
|
10
10
|
{
|
|
11
|
-
"date": "2024-
|
|
11
|
+
"date": "2024-07-13T16:49:25+1200",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "2.0.
|
|
14
|
+
"full-revisionid": "a4fe42f45db97f264d7ba71671fc9718063a3aa2",
|
|
15
|
+
"version": "2.0.5"
|
|
16
16
|
}
|
|
17
17
|
''' # END VERSION_JSON
|
|
18
18
|
|
|
@@ -61,15 +61,31 @@ def affine_transform(geom, matrix):
|
|
|
61
61
|
ndim = 2
|
|
62
62
|
else:
|
|
63
63
|
raise ValueError("'matrix' expects either 6 or 12 coefficients")
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
64
|
+
|
|
65
|
+
# if ndim == 2:
|
|
66
|
+
# A = np.array([[a, b], [d, e]], dtype=float)
|
|
67
|
+
# off = np.array([xoff, yoff], dtype=float)
|
|
68
|
+
# else:
|
|
69
|
+
# A = np.array([[a, b, c], [d, e, f], [g, h, i]], dtype=float)
|
|
70
|
+
# off = np.array([xoff, yoff, zoff], dtype=float)
|
|
70
71
|
|
|
71
72
|
def _affine_coords(coords):
|
|
72
|
-
|
|
73
|
+
# These are equivalent, but unfortunately not robust
|
|
74
|
+
# result = np.matmul(coords, A.T) + off
|
|
75
|
+
# result = np.matmul(A, coords.T).T + off
|
|
76
|
+
# Therefore, manual matrix multiplication is needed
|
|
77
|
+
if ndim == 2:
|
|
78
|
+
x, y = coords.T
|
|
79
|
+
xp = a * x + b * y + xoff
|
|
80
|
+
yp = d * x + e * y + yoff
|
|
81
|
+
result = np.stack([xp, yp]).T
|
|
82
|
+
elif ndim == 3:
|
|
83
|
+
x, y, z = coords.T
|
|
84
|
+
xp = a * x + b * y + c * z + xoff
|
|
85
|
+
yp = d * x + e * y + f * z + yoff
|
|
86
|
+
zp = g * x + h * y + i * z + zoff
|
|
87
|
+
result = np.stack([xp, yp, zp]).T
|
|
88
|
+
return result
|
|
73
89
|
|
|
74
90
|
return shapely.transform(geom, _affine_coords, include_z=ndim == 3)
|
|
75
91
|
|
|
@@ -412,17 +412,18 @@ def delaunay_triangles(geometry, tolerance=0.0, only_edges=False, **kwargs):
|
|
|
412
412
|
--------
|
|
413
413
|
>>> from shapely import GeometryCollection, LineString, MultiPoint, Polygon
|
|
414
414
|
>>> points = MultiPoint([(50, 30), (60, 30), (100, 100)])
|
|
415
|
-
>>> delaunay_triangles(points)
|
|
416
|
-
<GEOMETRYCOLLECTION (POLYGON ((50 30,
|
|
415
|
+
>>> delaunay_triangles(points).normalize()
|
|
416
|
+
<GEOMETRYCOLLECTION (POLYGON ((50 30, 100 100, 60 30, 50 30)))>
|
|
417
417
|
>>> delaunay_triangles(points, only_edges=True)
|
|
418
418
|
<MULTILINESTRING ((50 30, 100 100), (50 30, 60 30), ...>
|
|
419
419
|
>>> delaunay_triangles(MultiPoint([(50, 30), (51, 30), (60, 30), (100, 100)]), \
|
|
420
|
-
tolerance=2)
|
|
421
|
-
<GEOMETRYCOLLECTION (POLYGON ((50 30,
|
|
422
|
-
>>> delaunay_triangles(Polygon([(50, 30), (60, 30), (100, 100), (50, 30)]))
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
420
|
+
tolerance=2).normalize()
|
|
421
|
+
<GEOMETRYCOLLECTION (POLYGON ((50 30, 100 100, 60 30, 50 30)))>
|
|
422
|
+
>>> delaunay_triangles(Polygon([(50, 30), (60, 30), (100, 100), (50, 30)]))\
|
|
423
|
+
.normalize()
|
|
424
|
+
<GEOMETRYCOLLECTION (POLYGON ((50 30, 100 100, 60 30, 50 30)))>
|
|
425
|
+
>>> delaunay_triangles(LineString([(50, 30), (60, 30), (100, 100)])).normalize()
|
|
426
|
+
<GEOMETRYCOLLECTION (POLYGON ((50 30, 100 100, 60 30, 50 30)))>
|
|
426
427
|
>>> delaunay_triangles(GeometryCollection([]))
|
|
427
428
|
<GEOMETRYCOLLECTION EMPTY>
|
|
428
429
|
"""
|
|
@@ -533,11 +534,11 @@ def make_valid(geometry, **kwargs):
|
|
|
533
534
|
|
|
534
535
|
@multithreading_enabled
|
|
535
536
|
def normalize(geometry, **kwargs):
|
|
536
|
-
"""Converts Geometry to normal form (or canonical form).
|
|
537
|
+
"""Converts Geometry to strict normal form (or canonical form).
|
|
537
538
|
|
|
538
|
-
|
|
539
|
-
multi geometries consistently. Typically useful for testing
|
|
540
|
-
(for example in combination with ``equals_exact``).
|
|
539
|
+
In :ref:`strict canonical form <canonical-form>`, the coordinates, rings of a polygon and
|
|
540
|
+
parts of multi geometries are ordered consistently. Typically useful for testing
|
|
541
|
+
purposes (for example in combination with ``equals_exact``).
|
|
541
542
|
|
|
542
543
|
Parameters
|
|
543
544
|
----------
|
|
@@ -46,8 +46,13 @@ class CoordinateSequence:
|
|
|
46
46
|
else:
|
|
47
47
|
raise TypeError("key must be an index or slice")
|
|
48
48
|
|
|
49
|
-
def __array__(self, dtype=None):
|
|
50
|
-
|
|
49
|
+
def __array__(self, dtype=None, copy=None):
|
|
50
|
+
if copy is False:
|
|
51
|
+
raise ValueError("`copy=False` isn't supported. A copy is always created.")
|
|
52
|
+
elif copy is True:
|
|
53
|
+
return self._coords.copy()
|
|
54
|
+
else:
|
|
55
|
+
return self._coords
|
|
51
56
|
|
|
52
57
|
@property
|
|
53
58
|
def xy(self):
|
|
@@ -511,7 +511,7 @@ def destroy_prepared(geometry, **kwargs):
|
|
|
511
511
|
Parameters
|
|
512
512
|
----------
|
|
513
513
|
geometry : Geometry or array_like
|
|
514
|
-
Geometries are changed
|
|
514
|
+
Geometries are changed in-place
|
|
515
515
|
**kwargs
|
|
516
516
|
See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
|
|
517
517
|
|
|
@@ -85,12 +85,12 @@ class Point(BaseGeometry):
|
|
|
85
85
|
@property
|
|
86
86
|
def x(self):
|
|
87
87
|
"""Return x coordinate."""
|
|
88
|
-
return shapely.get_x(self)
|
|
88
|
+
return float(shapely.get_x(self))
|
|
89
89
|
|
|
90
90
|
@property
|
|
91
91
|
def y(self):
|
|
92
92
|
"""Return y coordinate."""
|
|
93
|
-
return shapely.get_y(self)
|
|
93
|
+
return float(shapely.get_y(self))
|
|
94
94
|
|
|
95
95
|
@property
|
|
96
96
|
def z(self):
|
|
@@ -139,12 +139,12 @@ def to_wkb(
|
|
|
139
139
|
----------
|
|
140
140
|
geometry : Geometry or array_like
|
|
141
141
|
hex : bool, default False
|
|
142
|
-
If true, export the WKB as a
|
|
142
|
+
If true, export the WKB as a hexadecimal string. The default is to
|
|
143
143
|
return a binary bytes object.
|
|
144
144
|
output_dimension : int, default 3
|
|
145
145
|
The output dimension for the WKB. Supported values are 2 and 3.
|
|
146
146
|
Specifying 3 means that up to 3 dimensions will be written but 2D
|
|
147
|
-
geometries will still be represented as 2D in the WKB
|
|
147
|
+
geometries will still be represented as 2D in the WKB representation.
|
|
148
148
|
byte_order : int, default -1
|
|
149
149
|
Defaults to native machine byte order (-1). Use 0 to force big endian
|
|
150
150
|
and 1 for little endian.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Plot single geometries using Matplotlib.
|
|
3
3
|
|
|
4
|
-
Note: this module is experimental, and mainly
|
|
4
|
+
Note: this module is experimental, and mainly targeting (interactive)
|
|
5
5
|
exploration, debugging and illustration purposes.
|
|
6
6
|
|
|
7
7
|
"""
|
|
@@ -38,7 +38,7 @@ def patch_from_polygon(polygon, **kwargs):
|
|
|
38
38
|
"""
|
|
39
39
|
Gets a Matplotlib patch from a (Multi)Polygon.
|
|
40
40
|
|
|
41
|
-
Note: this function is experimental, and mainly
|
|
41
|
+
Note: this function is experimental, and mainly targeting (interactive)
|
|
42
42
|
exploration, debugging and illustration purposes.
|
|
43
43
|
|
|
44
44
|
Parameters
|
|
@@ -69,7 +69,7 @@ def plot_polygon(
|
|
|
69
69
|
"""
|
|
70
70
|
Plot a (Multi)Polygon.
|
|
71
71
|
|
|
72
|
-
Note: this function is experimental, and mainly
|
|
72
|
+
Note: this function is experimental, and mainly targeting (interactive)
|
|
73
73
|
exploration, debugging and illustration purposes.
|
|
74
74
|
|
|
75
75
|
Parameters
|
|
@@ -132,7 +132,7 @@ def plot_line(line, ax=None, add_points=True, color=None, linewidth=2, **kwargs)
|
|
|
132
132
|
"""
|
|
133
133
|
Plot a (Multi)LineString/LinearRing.
|
|
134
134
|
|
|
135
|
-
Note: this function is experimental, and mainly
|
|
135
|
+
Note: this function is experimental, and mainly targeting (interactive)
|
|
136
136
|
exploration, debugging and illustration purposes.
|
|
137
137
|
|
|
138
138
|
Parameters
|
|
@@ -144,7 +144,7 @@ def plot_line(line, ax=None, add_points=True, color=None, linewidth=2, **kwargs)
|
|
|
144
144
|
add_points : bool, default True
|
|
145
145
|
If True, also plot the coordinates (vertices) as points.
|
|
146
146
|
color : matplotlib color specification
|
|
147
|
-
Color for the line (edgecolor under the hood) and
|
|
147
|
+
Color for the line (edgecolor under the hood) and points.
|
|
148
148
|
linewidth : float, default 2
|
|
149
149
|
The line width for the polygon boundary.
|
|
150
150
|
**kwargs
|
|
@@ -81,7 +81,7 @@ def is_ccw(geometry, **kwargs):
|
|
|
81
81
|
Parameters
|
|
82
82
|
----------
|
|
83
83
|
geometry : Geometry or array_like
|
|
84
|
-
This function will return False for non-linear
|
|
84
|
+
This function will return False for non-linear geometries and for
|
|
85
85
|
lines with fewer than 4 points (including the closing point).
|
|
86
86
|
**kwargs
|
|
87
87
|
See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
|
|
@@ -748,7 +748,7 @@ def equals(a, b, **kwargs):
|
|
|
748
748
|
def intersects(a, b, **kwargs):
|
|
749
749
|
"""Returns True if A and B share any portion of space.
|
|
750
750
|
|
|
751
|
-
Intersects implies that overlaps, touches
|
|
751
|
+
Intersects implies that overlaps, touches, covers, or within are True.
|
|
752
752
|
|
|
753
753
|
Parameters
|
|
754
754
|
----------
|
|
@@ -2,6 +2,7 @@ import numpy as np
|
|
|
2
2
|
import pytest
|
|
3
3
|
|
|
4
4
|
from shapely import LineString
|
|
5
|
+
from shapely.tests.common import line_string, line_string_z, point, point_z
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
class TestCoords:
|
|
@@ -84,3 +85,18 @@ class TestXY:
|
|
|
84
85
|
assert list(x) == [0.0, 1.0]
|
|
85
86
|
assert len(y) == 2
|
|
86
87
|
assert list(y) == [0.0, 1.0]
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@pytest.mark.parametrize("geom", [point, point_z, line_string, line_string_z])
|
|
91
|
+
def test_coords_array_copy(geom):
|
|
92
|
+
"""Test CoordinateSequence.__array__ method."""
|
|
93
|
+
coord_seq = geom.coords
|
|
94
|
+
assert np.array(coord_seq) is not np.array(coord_seq)
|
|
95
|
+
assert np.array(coord_seq, copy=True) is not np.array(coord_seq, copy=True)
|
|
96
|
+
|
|
97
|
+
# Behaviour of copy=False is different between NumPy 1.x and 2.x
|
|
98
|
+
if int(np.version.short_version.split(".", 1)[0]) >= 2:
|
|
99
|
+
with pytest.raises(ValueError, match="A copy is always created"):
|
|
100
|
+
np.array(coord_seq, copy=False)
|
|
101
|
+
else:
|
|
102
|
+
assert np.array(coord_seq, copy=False) is np.array(coord_seq, copy=False)
|
|
@@ -47,7 +47,7 @@ def test_format_point():
|
|
|
47
47
|
("g", xy2, "POINT (-169.910918 -18.997564)", False),
|
|
48
48
|
("0.2g", xy2, "POINT (-169.91 -19)", False),
|
|
49
49
|
]
|
|
50
|
-
# without
|
|
50
|
+
# without precisions test GEOS rounding_precision=-1; different than Python
|
|
51
51
|
test_list += [
|
|
52
52
|
("f", (1, 2), f"POINT ({1:.16f} {2:.16f})", False),
|
|
53
53
|
("F", xyz3, "POINT Z ({:.16f} {:.16f} {:.16f})".format(*xyz3), False),
|
|
@@ -101,7 +101,9 @@ class TestPoint:
|
|
|
101
101
|
# Test 2D points
|
|
102
102
|
p = Point(1.0, 2.0)
|
|
103
103
|
assert p.x == 1.0
|
|
104
|
+
assert type(p.x) is float
|
|
104
105
|
assert p.y == 2.0
|
|
106
|
+
assert type(p.y) is float
|
|
105
107
|
assert p.coords[:] == [(1.0, 2.0)]
|
|
106
108
|
assert str(p) == p.wkt
|
|
107
109
|
assert p.has_z is False
|
|
@@ -114,6 +116,7 @@ class TestPoint:
|
|
|
114
116
|
assert str(p) == p.wkt
|
|
115
117
|
assert p.has_z is True
|
|
116
118
|
assert p.z == 3.0
|
|
119
|
+
assert type(p.z) is float
|
|
117
120
|
|
|
118
121
|
# Coordinate access
|
|
119
122
|
p = Point((3.0, 4.0))
|
|
@@ -255,7 +255,7 @@ def test_set_nan():
|
|
|
255
255
|
|
|
256
256
|
def test_set_nan_same_objects():
|
|
257
257
|
# You can't put identical objects in a set.
|
|
258
|
-
# x = float("nan"); set([x, x]) also
|
|
258
|
+
# x = float("nan"); set([x, x]) also returns a set with 1 element
|
|
259
259
|
a = set([line_string_nan] * 10)
|
|
260
260
|
assert len(a) == 1
|
|
261
261
|
|
|
@@ -178,7 +178,7 @@ def test_shared_paths_non_linestring():
|
|
|
178
178
|
|
|
179
179
|
|
|
180
180
|
def _prepare_input(geometry, prepare):
|
|
181
|
-
"""Prepare without modifying
|
|
181
|
+
"""Prepare without modifying in-place"""
|
|
182
182
|
if prepare:
|
|
183
183
|
geometry = shapely.transform(geometry, lambda x: x) # makes a copy
|
|
184
184
|
shapely.prepare(geometry)
|
|
@@ -298,7 +298,7 @@ def test_is_ccw(geom, expected):
|
|
|
298
298
|
|
|
299
299
|
|
|
300
300
|
def _prepare_with_copy(geometry):
|
|
301
|
-
"""Prepare without modifying
|
|
301
|
+
"""Prepare without modifying in-place"""
|
|
302
302
|
geometry = shapely.transform(geometry, lambda x: x) # makes a copy
|
|
303
303
|
shapely.prepare(geometry)
|
|
304
304
|
return geometry
|
|
@@ -22,14 +22,14 @@ SET_OPERATIONS = (
|
|
|
22
22
|
shapely.intersection,
|
|
23
23
|
shapely.symmetric_difference,
|
|
24
24
|
shapely.union,
|
|
25
|
-
# shapely.coverage_union is tested
|
|
25
|
+
# shapely.coverage_union is tested separately
|
|
26
26
|
)
|
|
27
27
|
|
|
28
28
|
REDUCE_SET_OPERATIONS = (
|
|
29
29
|
(shapely.intersection_all, shapely.intersection),
|
|
30
30
|
(shapely.symmetric_difference_all, shapely.symmetric_difference),
|
|
31
31
|
(shapely.union_all, shapely.union),
|
|
32
|
-
# shapely.coverage_union_all, shapely.coverage_union) is tested
|
|
32
|
+
# shapely.coverage_union_all, shapely.coverage_union) is tested separately
|
|
33
33
|
)
|
|
34
34
|
|
|
35
35
|
# operations that support fixed precision
|
|
@@ -277,7 +277,7 @@ def test_set_operation_prec_reduce_all_none(n, func, related_func):
|
|
|
277
277
|
@pytest.mark.parametrize("n", range(1, 4))
|
|
278
278
|
def test_coverage_union_reduce_1dim(n):
|
|
279
279
|
"""
|
|
280
|
-
This is tested
|
|
280
|
+
This is tested separately from other set operations as it differs in two ways:
|
|
281
281
|
1. It expects only non-overlapping polygons
|
|
282
282
|
2. It expects GEOS 3.8.0+
|
|
283
283
|
"""
|
|
@@ -314,7 +314,7 @@ def test_coverage_union_overlapping_inputs():
|
|
|
314
314
|
other = Polygon([(1, 0), (0.9, 1), (2, 1), (2, 0), (1, 0)])
|
|
315
315
|
|
|
316
316
|
if shapely.geos_version >= (3, 12, 0):
|
|
317
|
-
# Return mostly
|
|
317
|
+
# Return mostly unchanged output
|
|
318
318
|
result = shapely.coverage_union(polygon, other)
|
|
319
319
|
expected = shapely.multipolygons([polygon, other])
|
|
320
320
|
assert_geometries_equal(result, expected, normalize=True)
|
|
@@ -371,7 +371,7 @@ npy_intp CountCoords(PyArrayObject* arr) {
|
|
|
371
371
|
result = -1;
|
|
372
372
|
goto finish;
|
|
373
373
|
}
|
|
374
|
-
/* skip
|
|
374
|
+
/* skip in case obj was None */
|
|
375
375
|
if (geom == NULL) {
|
|
376
376
|
continue;
|
|
377
377
|
}
|
|
@@ -519,7 +519,7 @@ PyObject* SetCoords(PyArrayObject* geoms, PyArrayObject* coords) {
|
|
|
519
519
|
PyObject* new_obj;
|
|
520
520
|
GEOSGeometry *geom, *new_geom;
|
|
521
521
|
|
|
522
|
-
/* SetCoords acts
|
|
522
|
+
/* SetCoords acts in-place: if the array is zero-sized, just return the
|
|
523
523
|
same object */
|
|
524
524
|
if (PyArray_SIZE(geoms) == 0) {
|
|
525
525
|
Py_INCREF((PyObject*)geoms);
|
|
@@ -306,7 +306,7 @@ char check_to_wkt_compatible(GEOSContextHandle_t ctx, GEOSGeometry* geom) {
|
|
|
306
306
|
|
|
307
307
|
/* Checks whether the geometry is a 3D empty geometry and, if so, create the WKT string
|
|
308
308
|
*
|
|
309
|
-
* GEOS 3.9.* is able to
|
|
309
|
+
* GEOS 3.9.* is able to distinguish 2D and 3D simple geometries (non-collections). But the
|
|
310
310
|
* but the WKT serialization never writes a 3D empty geometry. This function fixes that.
|
|
311
311
|
* It only makes sense to use this for GEOS versions >= 3.9.
|
|
312
312
|
*
|