Coverage for pyguymer3/geo/bufferSrc/buffer_MultiLineString.py: 3%
29 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 buffer_MultiLineString(
5 multiline,
6 dist,
7 /,
8 *,
9 debug = __debug__,
10 eps = 1.0e-12,
11 fill = 1.0,
12 fillSpace = "EuclideanSpace",
13 nAng = 9,
14 nIter = 100,
15 prefix = ".",
16 ramLimit = 1073741824,
17 simp = 0.1,
18 tol = 1.0e-10,
19):
20 """Buffer a MultiLineString
22 This function reads in a MultiLineString that exists on the surface of the
23 Earth and returns a [Multi]Polygon of the same MultiLineString buffered by a
24 constant distance (in metres).
26 Parameters
27 ----------
28 multiline : shapely.geometry.multilinestring.MultiLineString
29 the MultiLineString
30 dist : float
31 the Geodesic distance to buffer each point within the MultiLineString by
32 (in metres)
33 debug : bool, optional
34 print debug messages
35 eps : float, optional
36 the tolerance of the Vincenty formula iterations
37 fill : float, optional
38 the Euclidean or Geodesic distance to fill in between each point within
39 the shapes by (in degrees or metres)
40 fillSpace : str, optional
41 the geometric space to perform the filling in (either "EuclideanSpace"
42 or "GeodesicSpace")
43 nAng : int, optional
44 the number of angles around each point within the MultiLineString that
45 are calculated when buffering
46 nIter : int, optional
47 the maximum number of iterations (particularly the Vincenty formula)
48 prefix : str, optional
49 change the name of the output debugging CSVs
50 ramLimit : int, optional
51 the maximum RAM usage of each "large" array (in bytes)
52 simp : float, optional
53 how much intermediary [Multi]Polygons are simplified by; negative values
54 disable simplification (in degrees)
55 tol : float, optional
56 the Euclidean distance that defines two points as being the same (in
57 degrees)
59 Returns
60 -------
61 buffs : shapely.geometry.polygon.Polygon, shapely.geometry.multipolygon.MultiPolygon
62 the buffered MultiLineString
64 Notes
65 -----
66 According to the `Shapely documentation for the method object.buffer()
67 <https://shapely.readthedocs.io/en/stable/manual.html#object.buffer>`_ :
69 "Passed a distance of 0, buffer() can sometimes be used to "clean"
70 self-touching or self-crossing polygons such as the classic "bowtie".
71 Users have reported that very small distance values sometimes produce
72 cleaner results than 0. Your mileage may vary when cleaning surfaces."
74 According to the `Shapely documentation for the function
75 shapely.geometry.polygon.orient()
76 <https://shapely.readthedocs.io/en/stable/manual.html#shapely.geometry.polygon.orient>`_ :
78 "A sign of 1.0 means that the coordinates of the product's exterior ring
79 will be oriented counter-clockwise."
81 Copyright 2017 Thomas Guymer [1]_
83 References
84 ----------
85 .. [1] PyGuymer3, https://github.com/Guymer/PyGuymer3
86 """
88 # Import special modules ...
89 try:
90 import shapely
91 import shapely.geometry
92 import shapely.ops
93 except:
94 raise Exception("\"shapely\" is not installed; run \"pip install --user Shapely\"") from None
96 # Import sub-functions ...
97 from ..check import check
98 from ..fillin import fillin
99 from .buffer_LineString import buffer_LineString
101 # **************************************************************************
103 # Check argument ...
104 assert isinstance(multiline, shapely.geometry.multilinestring.MultiLineString), "\"multiline\" is not a MultiLineString"
105 if debug:
106 check(multiline, prefix = prefix)
108 # Initialize list ...
109 buffs = []
111 # Loop over LineString ...
112 for line in multiline.geoms:
113 # Append buffer of LineString to list ...
114 buffs.append(
115 buffer_LineString(
116 line,
117 dist,
118 debug = debug,
119 eps = eps,
120 fill = fill,
121 fillSpace = fillSpace,
122 nAng = nAng,
123 nIter = nIter,
124 prefix = prefix,
125 ramLimit = ramLimit,
126 simp = simp,
127 tol = tol,
128 )
129 )
131 # Convert list of [Multi]Polygons to a (unified) [Multi]Polygon ...
132 buffs = shapely.ops.unary_union(buffs).simplify(tol)
133 if debug:
134 check(buffs, prefix = prefix)
136 # Check if the user wants to fill in the [Multi]Polygon ...
137 # NOTE: This is only needed because the "shapely.ops.unary_union()" call
138 # above includes a "simplify()".
139 if simp < 0.0 < fill:
140 # Fill in [Multi]Polygon ...
141 buffs = fillin(
142 buffs,
143 fill,
144 debug = debug,
145 eps = eps,
146 fillSpace = fillSpace,
147 nIter = nIter,
148 prefix = prefix,
149 ramLimit = ramLimit,
150 tol = tol,
151 )
152 if debug:
153 check(buffs, prefix = prefix)
155 # Check if the user wants to simplify the [Multi]Polygon ...
156 # NOTE: This is only needed because the "shapely.ops.unary_union()" call
157 # above might allow more simplification.
158 if simp > 0.0:
159 # Simplify [Multi]Polygon ...
160 buffsSimp = buffs.simplify(simp)
161 if debug:
162 check(buffsSimp, prefix = prefix)
164 # Return simplified answer ...
165 return buffsSimp
167 # Return answer ...
168 return buffs