-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
introduced force_2d for a subset of geometries #180 #183
Changes from all commits
0fdc579
f28889f
a654b38
8466fd9
a213905
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -19,8 +19,10 @@ | |||||||||
import math | ||||||||||
from itertools import groupby | ||||||||||
from itertools import zip_longest | ||||||||||
from typing import Any | ||||||||||
from typing import Iterable | ||||||||||
from typing import List | ||||||||||
from typing import Sequence | ||||||||||
from typing import Tuple | ||||||||||
from typing import Union | ||||||||||
from typing import cast | ||||||||||
|
@@ -188,11 +190,73 @@ def compare_geo_interface( | |||||||||
return False | ||||||||||
|
||||||||||
|
||||||||||
def move_coordinate( | ||||||||||
coordinate: Sequence[float], | ||||||||||
move_by: Sequence[float], | ||||||||||
Comment on lines
+194
to
+195
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
and add |
||||||||||
z: float = 0, | ||||||||||
) -> Tuple[float, ...]: | ||||||||||
""" | ||||||||||
Move the coordinate by the given vector. | ||||||||||
|
||||||||||
This forcefully changes the dimensions of the coordinate to match the latter. | ||||||||||
>>> move_coordinate((0, 0), (-1, 1)) | ||||||||||
(-1, 1) | ||||||||||
>>> move_coordinate((0, 0, 0), (-1, 1)) | ||||||||||
(-1, 1) | ||||||||||
>>> move_coordinate((0, 0), (-1, 1, 0)) | ||||||||||
(-1, 1, 0) | ||||||||||
""" | ||||||||||
if len(coordinate) > len(move_by): | ||||||||||
return tuple(c + m for c, m in zip(coordinate, move_by)) | ||||||||||
return tuple(c + m for c, m in zip_longest(coordinate, move_by, fillvalue=z)) | ||||||||||
|
||||||||||
|
||||||||||
def move_coordinates( | ||||||||||
coordinates: Sequence[Any], | ||||||||||
move_by: Sequence[float], | ||||||||||
Comment on lines
+215
to
+216
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
z: float = 0, | ||||||||||
) -> Sequence[Any]: | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
""" | ||||||||||
Move the coordinates recursively by the given vector. | ||||||||||
|
||||||||||
This forcefully changes the dimension of each of the coordinate to match | ||||||||||
the dimensionality of the vector. | ||||||||||
>>> move_coordinates(((0, 0), (-1, 1)), (-1, 1)) | ||||||||||
((-1, 1), (-2, 2)) | ||||||||||
>>> move_coordinates(((0, 0, 0), (-1, 1, 0)), (-1, 1)) | ||||||||||
((-1, 1), (-2, 2)) | ||||||||||
>>> move_coordinates(((0, 0), (-1, 1)), (-1, 1, 0)) | ||||||||||
((-1, 1, 0), (-2, 2, 0)) | ||||||||||
""" | ||||||||||
if is_coordinate(coordinates): | ||||||||||
# a single coordinate | ||||||||||
return move_coordinate(coordinates, move_by, z) | ||||||||||
# a list of coordinates | ||||||||||
return tuple(move_coordinates(c, move_by, z) for c in coordinates) | ||||||||||
|
||||||||||
|
||||||||||
def is_coordinate(val: Any) -> bool: # noqa: ANN401 | ||||||||||
""" | ||||||||||
Check if given value is a coordinate i.e. vector of generic dimensionality. | ||||||||||
|
||||||||||
>>> is_coordinate((1, 0)) | ||||||||||
True | ||||||||||
>>> is_coordinate(1) | ||||||||||
False | ||||||||||
>>> is_coordinate([(1, 2), (3, 4)]) | ||||||||||
False | ||||||||||
""" | ||||||||||
return isinstance(val, tuple) and all(isinstance(x, (int, float)) for x in val) | ||||||||||
|
||||||||||
|
||||||||||
__all__ = [ | ||||||||||
"centroid", | ||||||||||
"compare_coordinates", | ||||||||||
"compare_geo_interface", | ||||||||||
"convex_hull", | ||||||||||
"dedupe", | ||||||||||
"move_coordinate", | ||||||||||
"move_coordinates", | ||||||||||
"is_coordinate", | ||||||||||
"signed_area", | ||||||||||
] |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -21,6 +21,167 @@ def test_num_float() -> None: | |||||
assert isinstance(factories.num("1.1"), float) | ||||||
|
||||||
|
||||||
def test_force_2d_point() -> None: | ||||||
# 2d point to 2d point (no actual change) | ||||||
p = geometry.Point(-1, 1) | ||||||
p2d = factories.force_2d(p) | ||||||
assert p2d.x == -1 | ||||||
assert p2d.y == 1 | ||||||
assert not p2d.has_z | ||||||
|
||||||
# 3d point to 2d point | ||||||
p = geometry.Point(-1, 1, 2) | ||||||
p2d = factories.force_2d(p) | ||||||
assert p2d.x == -1 | ||||||
assert p2d.y == 1 | ||||||
assert not p2d.has_z | ||||||
|
||||||
|
||||||
def test_force_2d_multipoint() -> None: | ||||||
# 2d to 2d (no actual change) | ||||||
p = geometry.MultiPoint([(-1, 1), (2, 3)]) | ||||||
p2d = factories.force_2d(p) | ||||||
assert list(p2d.geoms) == [geometry.Point(-1, 1), geometry.Point(2, 3)] | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
|
||||||
def test_force_2d_linestring() -> None: | ||||||
# 2d line string to 2d line string (no actual change) | ||||||
ls = geometry.LineString([(1, 2), (3, 4)]) | ||||||
l2d = factories.force_2d(ls) | ||||||
assert l2d.coords == ((1, 2), (3, 4)) | ||||||
|
||||||
# 3d line string to 2d line string | ||||||
ls = geometry.LineString([(1, 2, 3), (4, 5, 6)]) | ||||||
l2d = factories.force_2d(ls) | ||||||
assert l2d.coords == ((1, 2), (4, 5)) | ||||||
|
||||||
|
||||||
def test_force_2d_linearring() -> None: | ||||||
# 2d linear ring to 2d linear ring (no actual change) | ||||||
r = geometry.LinearRing([(1, 2), (3, 4)]) | ||||||
r2d = factories.force_2d(r) | ||||||
assert r2d.coords == ((1, 2), (3, 4), (1, 2)) | ||||||
|
||||||
# 3d linear ring to 2d linear ring | ||||||
r = geometry.LinearRing([(1, 2, 3), (4, 5, 6)]) | ||||||
r2d = factories.force_2d(r) | ||||||
assert r2d.coords == ((1, 2), (4, 5), (1, 2)) | ||||||
|
||||||
|
||||||
def test_force_2d_multilinestring() -> None: | ||||||
# 2d multi line string to 2d multi line string (no actual change) | ||||||
mls = geometry.MultiLineString([[(1, 2), (3, 4)], [(5, 6), (7, 8)]]) | ||||||
mls2d = factories.force_2d(mls) | ||||||
assert list(mls2d.geoms) == list(mls.geoms) | ||||||
|
||||||
# 3d multi line string to 2d multi line string | ||||||
mls = geometry.MultiLineString([[(1, 2, 3), (4, 5, 6)], [(7, 8, 9), (10, 11, 12)]]) | ||||||
mls2d = factories.force_2d(mls) | ||||||
assert list(mls2d.geoms) == [ | ||||||
geometry.LineString([(1, 2), (4, 5)]), | ||||||
geometry.LineString([(7, 8), (10, 11)]), | ||||||
] | ||||||
|
||||||
|
||||||
def test_force_2d_polygon() -> None: | ||||||
# 2d to 2d (no actual change) | ||||||
external = [(0, 0), (0, 2), (2, 2), (2, 0), (0, 0)] | ||||||
internal = [(0.5, 0.5), (0.5, 1.5), (1.5, 1.5), (1.5, 0.5), (0.5, 0.5)] | ||||||
p = geometry.Polygon(external, [internal]) | ||||||
p2d = factories.force_2d(p) | ||||||
assert p2d.coords[0] == (((0, 0), (0, 2), (2, 2), (2, 0), (0, 0))) | ||||||
assert p2d.coords[1] == ( | ||||||
((0.5, 0.5), (0.5, 1.5), (1.5, 1.5), (1.5, 0.5), (0.5, 0.5)), | ||||||
) | ||||||
assert not p2d.has_z | ||||||
assert p.maybe_valid == p2d.maybe_valid | ||||||
|
||||||
# 3d to 2d | ||||||
external = [(0, 0, 1), (0, 2, 1), (2, 2, 1), (2, 0, 1), (0, 0, 1)] | ||||||
internal = [ | ||||||
(0.5, 0.5, 1), | ||||||
(0.5, 1.5, 1), | ||||||
(1.5, 1.5, 1), | ||||||
(1.5, 0.5, 1), | ||||||
(0.5, 0.5, 1), | ||||||
] | ||||||
|
||||||
p = geometry.Polygon(external, [internal]) | ||||||
p2d = factories.force_2d(p) | ||||||
assert p2d.coords[0] == (((0, 0), (0, 2), (2, 2), (2, 0), (0, 0))) | ||||||
assert p2d.coords[1] == ( | ||||||
((0.5, 0.5), (0.5, 1.5), (1.5, 1.5), (1.5, 0.5), (0.5, 0.5)), | ||||||
) | ||||||
assert not p2d.has_z | ||||||
|
||||||
|
||||||
def test_force_2d_multipolygon() -> None: | ||||||
# 2d to 2d (no actual change) | ||||||
external = [(0, 0), (0, 2), (2, 2), (2, 0), (0, 0)] | ||||||
internal = [(0.5, 0.5), (0.5, 1.5), (1.5, 1.5), (1.5, 0.5), (0.5, 0.5)] | ||||||
mp = geometry.MultiPolygon([(external, [internal]), (external, [internal])]) | ||||||
mp2d = factories.force_2d(mp) | ||||||
|
||||||
assert list(mp2d.geoms) == list(mp.geoms) | ||||||
|
||||||
|
||||||
def test_force2d_collection() -> None: | ||||||
# 2d to 2d (no actual change) | ||||||
gc = geometry.GeometryCollection([geometry.Point(-1, 1), geometry.Point(-2, 2)]) | ||||||
gc2d = factories.force_2d(gc) | ||||||
assert list(gc2d.geoms) == list(gc.geoms) | ||||||
|
||||||
# 3d to 2d | ||||||
gc = geometry.GeometryCollection( | ||||||
[geometry.Point(-1, 1, 0), geometry.Point(-2, 2, 0)], | ||||||
) | ||||||
gc2d = factories.force_2d(gc) | ||||||
assert list(gc2d.geoms) == [geometry.Point(-1, 1), geometry.Point(-2, 2)] | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
|
||||||
def test_force_2d_nongeo() -> None: | ||||||
pytest.raises(AttributeError, factories.force_2d, (1, 2, 3)) | ||||||
|
||||||
|
||||||
def test_force_3d_point() -> None: | ||||||
p = geometry.Point(0, 0) | ||||||
p3d = factories.force_3d(p) | ||||||
assert p3d.x == 0 | ||||||
assert p3d.y == 0 | ||||||
assert p3d.z == 0 | ||||||
assert p3d.has_z | ||||||
|
||||||
|
||||||
def test_force_3d_collection() -> None: | ||||||
gc = geometry.GeometryCollection( | ||||||
[geometry.Point(-1, 1), geometry.Point(-2, 2)], | ||||||
) | ||||||
gc3d = factories.force_3d(gc) | ||||||
assert list(gc3d.geoms) == [geometry.Point(-1, 1, 0), geometry.Point(-2, 2, 0)] | ||||||
|
||||||
|
||||||
def test_force_3d_point_with_z() -> None: | ||||||
p = geometry.Point(0, 0, 1) | ||||||
p3d = factories.force_3d(p) | ||||||
assert p3d.x == 0 | ||||||
assert p3d.y == 0 | ||||||
assert p3d.z == 1 | ||||||
assert p3d.has_z | ||||||
|
||||||
|
||||||
def test_force_3d_point_noop() -> None: | ||||||
p = geometry.Point(1, 2, 3) | ||||||
p3d = factories.force_3d(p) | ||||||
assert p3d.x == 1 | ||||||
assert p3d.y == 2 | ||||||
assert p3d.z == 3 | ||||||
assert p3d.has_z | ||||||
|
||||||
|
||||||
def test_force_3d_nongeo() -> None: | ||||||
pytest.raises(AttributeError, factories.force_3d, (1, 2)) | ||||||
|
||||||
|
||||||
def test_orient_true() -> None: | ||||||
ext = [(0, 0), (0, 2), (2, 2), (2, 0), (0, 0)] | ||||||
int_1 = [(0.5, 0.25), (1.5, 0.25), (1.5, 1.25), (0.5, 1.25), (0.5, 0.25)] | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if I call