Skip to content

Commit

Permalink
added force_3d factory
Browse files Browse the repository at this point in the history
  • Loading branch information
whisk committed Nov 5, 2023
1 parent a654b38 commit 8466fd9
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 0 deletions.
35 changes: 35 additions & 0 deletions pygeoif/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,40 @@ def force_2d(
return shape(geometry)


def force_3d(
context: Union[GeoType, GeoCollectionType],
z: float = 0,
) -> Union[Geometry, GeometryCollection]:
"""
Force the dimensionality of a geometry to 3D.
>>> force_3d(Point(0, 0))
Point(0, 0, 0)
>>> force_3d(Point(0, 0), 1)
Point(0, 0, 1)
>>> force_3d(Point(0, 0, 0))
Point(0, 0, 0)
>>> force_3d(LineString([(0, 0), (0, 1), (1, 1)]))
LineString(((0, 0, 0), (0, 1, 0), (1, 1, 0)))
"""
geometry = context if isinstance(context, dict) else mapping(context)
if not geometry:
msg = "Object does not implement __geo_interface__"
raise TypeError(msg)
if geometry["type"] == "GeometryCollection":
return GeometryCollection(
force_3d(g, z) # type: ignore [arg-type]
for g in geometry["geometries"] # type: ignore [typeddict-item]
)

geometry["coordinates"] = move_coordinates( # type: ignore [typeddict-unknown-key]
geometry["coordinates"], # type: ignore [typeddict-item]
(0, 0, 0),
z,
)
return shape(geometry)


def get_oriented_ring(ring: LineType, ccw: bool) -> LineType: # noqa: FBT001
s = 1.0 if ccw else -1.0
return ring if signed_area(ring) / s >= 0 else ring[::-1]
Expand Down Expand Up @@ -364,6 +398,7 @@ def mapping(

__all__ = [
"force_2d",
"force_3d",
"box",
"from_wkt",
"mapping",
Expand Down
39 changes: 39 additions & 0 deletions tests/test_factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,45 @@ 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)]
Expand Down

0 comments on commit 8466fd9

Please sign in to comment.