From 6856844b97e8c35049ea6b88cbf975a916f5175d Mon Sep 17 00:00:00 2001 From: Christian Ledermann Date: Sat, 27 Apr 2024 17:35:27 +0100 Subject: [PATCH] return an empty tuple for coordinates if point is empty --- pygeoif/geometry.py | 22 +++++++++++++++------- tests/test_line.py | 12 ++++++++++++ tests/test_point.py | 6 ++++++ 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/pygeoif/geometry.py b/pygeoif/geometry.py index 06222f6..688dc86 100644 --- a/pygeoif/geometry.py +++ b/pygeoif/geometry.py @@ -289,9 +289,9 @@ def z(self) -> Optional[float]: raise DimensionError(msg) @property - def coords(self) -> Tuple[PointType]: + def coords(self) -> Union[Tuple[PointType], Tuple[()]]: """Return the geometry coordinates.""" - return (self._geoms,) + return () if self.is_empty else (self._geoms,) @property def has_z(self) -> bool: @@ -372,7 +372,10 @@ def geoms(self) -> Tuple[Point, ...]: @property def coords(self) -> LineType: """Return the geometry coordinates.""" - return cast(LineType, tuple(point.coords[0] for point in self.geoms)) + return cast( + LineType, + tuple(point.coords[0] for point in self.geoms if point.coords), + ) @property def is_empty(self) -> bool: @@ -407,7 +410,9 @@ def from_coordinates(cls, coordinates: LineType) -> "LineString": @classmethod def from_points(cls, *args: Point) -> "LineString": """Create a linestring from points.""" - return cls(cast(LineType, tuple(point.coords[0] for point in args))) + return cls( + cast(LineType, tuple(point.coords[0] for point in args if point.coords)), + ) @classmethod def _from_dict(cls, geo_interface: GeoInterface) -> "LineString": @@ -730,7 +735,8 @@ def __len__(self) -> int: def __repr__(self) -> str: """Return the representation.""" return ( - f"{self.geom_type}({tuple(geom.coords[0] for geom in self._geoms if geom)})" + f"{self.geom_type}" + f"({tuple(geom.coords[0] for geom in self._geoms if geom.coords)})" ) @property @@ -746,13 +752,15 @@ def _wkt_coords(self) -> str: def __geo_interface__(self) -> GeoInterface: """Return the geo interface.""" geo_interface = super().__geo_interface__ - geo_interface["coordinates"] = tuple(geom.coords[0] for geom in self.geoms) + geo_interface["coordinates"] = tuple( + geom.coords[0] for geom in self.geoms if geom.coords + ) return geo_interface @classmethod def from_points(cls, *args: Point, unique: bool = False) -> "MultiPoint": """Create a MultiPoint from Points.""" - return cls([point.coords[0] for point in args], unique=unique) + return cls([point.coords[0] for point in args if point.coords], unique=unique) @classmethod def _from_dict(cls, geo_interface: GeoInterface) -> "MultiPoint": diff --git a/tests/test_line.py b/tests/test_line.py index fff6b6b..1c69aab 100644 --- a/tests/test_line.py +++ b/tests/test_line.py @@ -220,3 +220,15 @@ def test_empty_bounds() -> None: line = geometry.LineString([]) assert line.bounds == () + + +def test_bounds_1_pt() -> None: + line = geometry.LineString([(0, 0)]) + + assert line.bounds == (0, 0, 0, 0) + + +def test_empty_coords() -> None: + line = geometry.LineString([]) + + assert line.coords == () diff --git a/tests/test_point.py b/tests/test_point.py index 9d91682..eacb587 100644 --- a/tests/test_point.py +++ b/tests/test_point.py @@ -82,6 +82,12 @@ def test_repr_empty() -> None: assert repr(point) == "Point()" +def test_coords_empty() -> None: + point = geometry.Point(None, None) + + assert point.coords == () + + def test_repr2d() -> None: point = geometry.Point(1, 0)