Coverage for pyguymer3/geo/cleanSrc/clean_Polygon.py: 5%
22 statements
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-08 18:47 +0000
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-08 18:47 +0000
1#!/usr/bin/env python3
3# Define function ...
4def clean_Polygon(
5 poly,
6 /,
7 *,
8 debug = __debug__,
9 prefix = ".",
10 tol = 1.0e-10,
11):
12 """Clean a Polygon
14 This function cleans a Polygon (with an exterior and any number of
15 interiors) by removing bad points.
17 Parameters
18 ----------
19 poly : shapely.geometry.polygon.Polygon
20 the Polygon
21 debug : bool, optional
22 print debug messages
23 prefix : str, optional
24 change the name of the output debugging CSVs
25 tol : float, optional
26 the Euclidean distance that defines two points as being the same (in
27 degrees)
29 Returns
30 -------
31 cleans : shapely.geometry.polygon.Polygon
32 the cleaned Polygon
34 Notes
35 -----
36 According to the `Shapely documentation for the function
37 shapely.geometry.polygon.orient()
38 <https://shapely.readthedocs.io/en/stable/manual.html#shapely.geometry.polygon.orient>`_ :
40 "A sign of 1.0 means that the coordinates of the product's exterior ring
41 will be oriented counter-clockwise."
43 Copyright 2017 Thomas Guymer [1]_
45 References
46 ----------
47 .. [1] PyGuymer3, https://github.com/Guymer/PyGuymer3
48 """
50 # Import special modules ...
51 try:
52 import shapely
53 import shapely.geometry
54 import shapely.ops
55 except:
56 raise Exception("\"shapely\" is not installed; run \"pip install --user Shapely\"") from None
58 # Import sub-functions ...
59 from ..check import check
60 from .clean_LinearRing import clean_LinearRing
62 # **************************************************************************
64 # Check argument ...
65 assert isinstance(poly, shapely.geometry.polygon.Polygon), "\"poly\" is not a Polygon"
67 # Clean exterior LinearRing ...
68 exterior = clean_LinearRing(
69 poly.exterior,
70 debug = debug,
71 prefix = prefix,
72 tol = tol,
73 )
75 # Initialize list ...
76 interiors = []
78 # Loop over interior LinearRings ...
79 for interior in poly.interiors:
80 # Skip if it doesn't contain any length ...
81 if interior.length < tol:
82 if debug:
83 print(f"INFO: Removing a tiny-length interior ring at ({interior.centroid.x:+.6f}°,{interior.centroid.y:+.6f}°).")
84 continue
86 # Append cleaned interior LinearRing to list ...
87 interiors.append(
88 clean_LinearRing(
89 interior,
90 debug = debug,
91 prefix = prefix,
92 tol = tol,
93 )
94 )
96 # Convert exterior LinearRing and list of interior LinearRings to a
97 # correctly oriented Polygon ...
98 cleans = shapely.geometry.polygon.orient(shapely.geometry.polygon.Polygon(exterior, interiors))
99 if debug:
100 check(cleans, prefix = prefix)
102 # Return answer ...
103 return cleans