2020from collections .abc import Collection
2121from datetime import date
2222from struct import Struct , calcsize , error , pack , unpack
23- from typing import Any , Iterable , Iterator , Optional , Union
23+ from typing import Any , Iterable , Iterator , Optional , Reversible , Union
2424from urllib .error import HTTPError
2525from urllib .parse import urlparse , urlunparse
2626from urllib .request import Request , urlopen
@@ -149,14 +149,16 @@ def __repr__(self):
149149 return str (self .tolist ())
150150
151151
152+ Point2D = tuple [float , float ]
153+ PointZ = tuple [float , float , float ]
154+ PointZM = tuple [float , float , float , float ]
155+
156+ Coord = Union [Point2D , PointZ , PointZM ]
157+ Coords = Collection [Coord ]
158+
159+
152160def signed_area (
153- coords : Collection [
154- Union [
155- tuple [float , float ],
156- tuple [float , float , float ],
157- tuple [float , float , float , float ],
158- ]
159- ],
161+ coords : Coords ,
160162 fast : bool = False ,
161163) -> float :
162164 """Return the signed area enclosed by a ring using the linear time
@@ -174,43 +176,46 @@ def signed_area(
174176 return area2 / 2.0
175177
176178
177- def is_cw (coords ) :
179+ def is_cw (coords : Coords ) -> bool :
178180 """Returns True if a polygon ring has clockwise orientation, determined
179181 by a negatively signed area.
180182 """
181183 area2 = signed_area (coords , fast = True )
182184 return area2 < 0
183185
184186
185- def rewind (coords ) :
187+ def rewind (coords : Reversible [ Coord ]) -> list [ Coord ] :
186188 """Returns the input coords in reversed order."""
187189 return list (reversed (coords ))
188190
189191
190- def ring_bbox (coords ):
192+ BBox = tuple [float , float , float , float ]
193+
194+
195+ def ring_bbox (coords : Coords ) -> BBox :
191196 """Calculates and returns the bounding box of a ring."""
192197 xs , ys = zip (* coords )
193198 bbox = min (xs ), min (ys ), max (xs ), max (ys )
194199 return bbox
195200
196201
197- def bbox_overlap (bbox1 , bbox2 ) :
198- """Tests whether two bounding boxes overlap, returning a boolean """
202+ def bbox_overlap (bbox1 : BBox , bbox2 : BBox ) -> bool :
203+ """Tests whether two bounding boxes overlap. """
199204 xmin1 , ymin1 , xmax1 , ymax1 = bbox1
200205 xmin2 , ymin2 , xmax2 , ymax2 = bbox2
201206 overlap = xmin1 <= xmax2 and xmax1 >= xmin2 and ymin1 <= ymax2 and ymax1 >= ymin2
202207 return overlap
203208
204209
205- def bbox_contains (bbox1 , bbox2 ) :
206- """Tests whether bbox1 fully contains bbox2, returning a boolean """
210+ def bbox_contains (bbox1 : BBox , bbox2 : BBox ) -> bool :
211+ """Tests whether bbox1 fully contains bbox2. """
207212 xmin1 , ymin1 , xmax1 , ymax1 = bbox1
208213 xmin2 , ymin2 , xmax2 , ymax2 = bbox2
209214 contains = xmin1 < xmin2 and xmax1 > xmax2 and ymin1 < ymin2 and ymax1 > ymax2
210215 return contains
211216
212217
213- def ring_contains_point (coords , p ) :
218+ def ring_contains_point (coords : list [ Coord ] , p : Point2D ) -> bool :
214219 """Fast point-in-polygon crossings algorithm, MacMartin optimization.
215220
216221 Adapted from code by Eric Haynes
@@ -255,7 +260,7 @@ def ring_contains_point(coords, p):
255260 return inside_flag
256261
257262
258- def ring_sample (coords , ccw = False ):
263+ def ring_sample (coords : list [ Coord ] , ccw : bool = False ) -> Coord :
259264 """Return a sample point guaranteed to be within a ring, by efficiently
260265 finding the first centroid of a coordinate triplet whose orientation
261266 matches the orientation of the ring and passes the point-in-ring test.
@@ -302,7 +307,7 @@ def itercoords():
302307 raise Exception ("Unexpected error: Unable to find a ring sample point." )
303308
304309
305- def ring_contains_ring (coords1 , coords2 ) :
310+ def ring_contains_ring (coords1 : list [ Coord ] , coords2 : list [ Point2D ]) -> bool :
306311 """Returns True if all vertexes in coords2 are fully inside coords1."""
307312 return all (ring_contains_point (coords1 , p2 ) for p2 in coords2 )
308313
0 commit comments