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

1#!/usr/bin/env python3 

2 

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 

13 

14 This function cleans a Polygon (with an exterior and any number of 

15 interiors) by removing bad points. 

16 

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) 

28 

29 Returns 

30 ------- 

31 cleans : shapely.geometry.polygon.Polygon 

32 the cleaned Polygon 

33 

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>`_ : 

39 

40 "A sign of 1.0 means that the coordinates of the product's exterior ring 

41 will be oriented counter-clockwise." 

42 

43 Copyright 2017 Thomas Guymer [1]_ 

44 

45 References 

46 ---------- 

47 .. [1] PyGuymer3, https://github.com/Guymer/PyGuymer3 

48 """ 

49 

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 

57 

58 # Import sub-functions ... 

59 from ..check import check 

60 from .clean_LinearRing import clean_LinearRing 

61 

62 # ************************************************************************** 

63 

64 # Check argument ... 

65 assert isinstance(poly, shapely.geometry.polygon.Polygon), "\"poly\" is not a Polygon" 

66 

67 # Clean exterior LinearRing ... 

68 exterior = clean_LinearRing( 

69 poly.exterior, 

70 debug = debug, 

71 prefix = prefix, 

72 tol = tol, 

73 ) 

74 

75 # Initialize list ... 

76 interiors = [] 

77 

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 

85 

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 ) 

95 

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) 

101 

102 # Return answer ... 

103 return cleans