Coverage for pyguymer3/geo/buffer.py: 67%
33 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(
5 shape,
6 dist,
7 /,
8 *,
9 debug = __debug__,
10 eps = 1.0e-12,
11 fill = 1.0,
12 fillSpace = "EuclideanSpace",
13 keepInteriors = True,
14 nAng = 9,
15 nIter = 100,
16 prefix = ".",
17 ramLimit = 1073741824,
18 simp = 0.1,
19 tol = 1.0e-10,
20):
21 """Buffer a shape
23 This function reads in a shape that exists on the surface of the Earth and
24 returns the same shape buffered by a constant distance (in metres).
26 Parameters
27 ----------
28 shape : shapely.coords.CoordinateSequence, shapely.geometry.point.Point, shapely.geometry.multipoint.MultiPoint, shapely.geometry.polygon.LinearRing, shapely.geometry.linestring.LineString, shapely.geometry.multilinestring.MultiLineString, shapely.geometry.polygon.Polygon, shapely.geometry.multipolygon.MultiPolygon
29 the shape
30 dist : float
31 the Geodesic distance to buffer each point within the shape by (in
32 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 keepInteriors : bool, optional
44 keep the interiors of the Polygon
45 nAng : int, optional
46 the number of angles around each point within the shape that are
47 calculated when buffering
48 nIter : int, optional
49 the maximum number of iterations (particularly the Vincenty formula)
50 prefix : str, optional
51 change the name of the output debugging CSVs
52 ramLimit : int, optional
53 the maximum RAM usage of each "large" array (in bytes)
54 simp : float, optional
55 how much intermediary [Multi]Polygons are simplified by; negative values
56 disable simplification (in degrees)
57 tol : float, optional
58 the Euclidean distance that defines two points as being the same (in
59 degrees)
61 Returns
62 -------
63 buff : shapely.geometry.polygon.Polygon, shapely.geometry.multipolygon.MultiPolygon
64 the buffered shape
66 Notes
67 -----
68 According to the `Shapely documentation for the method object.buffer()
69 <https://shapely.readthedocs.io/en/stable/manual.html#object.buffer>`_ :
71 "Passed a distance of 0, buffer() can sometimes be used to "clean"
72 self-touching or self-crossing polygons such as the classic "bowtie".
73 Users have reported that very small distance values sometimes produce
74 cleaner results than 0. Your mileage may vary when cleaning surfaces."
76 According to the `Shapely documentation for the function
77 shapely.geometry.polygon.orient()
78 <https://shapely.readthedocs.io/en/stable/manual.html#shapely.geometry.polygon.orient>`_ :
80 "A sign of 1.0 means that the coordinates of the product's exterior ring
81 will be oriented counter-clockwise."
83 Copyright 2017 Thomas Guymer [1]_
85 References
86 ----------
87 .. [1] PyGuymer3, https://github.com/Guymer/PyGuymer3
88 """
90 # Import special modules ...
91 try:
92 import shapely
93 import shapely.geometry
94 except:
95 raise Exception("\"shapely\" is not installed; run \"pip install --user Shapely\"") from None
97 # Import sub-functions ...
98 from .bufferSrc import buffer_CoordinateSequence
99 from .bufferSrc import buffer_LinearRing
100 from .bufferSrc import buffer_LineString
101 from .bufferSrc import buffer_MultiLineString
102 from .bufferSrc import buffer_MultiPoint
103 from .bufferSrc import buffer_MultiPolygon
104 from .bufferSrc import buffer_Point
105 from .bufferSrc import buffer_Polygon
107 # **************************************************************************
109 # Check what type it is ...
110 match shape:
111 case shapely.coords.CoordinateSequence():
112 # Return it buffered ...
113 return buffer_CoordinateSequence(
114 shape,
115 dist,
116 debug = debug,
117 eps = eps,
118 fill = fill,
119 fillSpace = fillSpace,
120 nAng = nAng,
121 nIter = nIter,
122 prefix = prefix,
123 ramLimit = ramLimit,
124 simp = simp,
125 tol = tol,
126 )
127 case shapely.geometry.point.Point():
128 # Return it buffered ...
129 return buffer_Point(
130 shape,
131 dist,
132 debug = debug,
133 eps = eps,
134 fill = fill,
135 fillSpace = fillSpace,
136 nAng = nAng,
137 nIter = nIter,
138 prefix = prefix,
139 ramLimit = ramLimit,
140 simp = simp,
141 tol = tol,
142 )
143 case shapely.geometry.multipoint.MultiPoint():
144 # Return it buffered ...
145 return buffer_MultiPoint(
146 shape,
147 dist,
148 debug = debug,
149 eps = eps,
150 fill = fill,
151 fillSpace = fillSpace,
152 nAng = nAng,
153 nIter = nIter,
154 prefix = prefix,
155 ramLimit = ramLimit,
156 simp = simp,
157 tol = tol,
158 )
159 case shapely.geometry.polygon.LinearRing():
160 # Return it buffered ...
161 return buffer_LinearRing(
162 shape,
163 dist,
164 debug = debug,
165 eps = eps,
166 fill = fill,
167 fillSpace = fillSpace,
168 nAng = nAng,
169 nIter = nIter,
170 prefix = prefix,
171 ramLimit = ramLimit,
172 simp = simp,
173 tol = tol,
174 )
175 case shapely.geometry.linestring.LineString():
176 # Return it buffered ...
177 return buffer_LineString(
178 shape,
179 dist,
180 debug = debug,
181 eps = eps,
182 fill = fill,
183 fillSpace = fillSpace,
184 nAng = nAng,
185 nIter = nIter,
186 prefix = prefix,
187 ramLimit = ramLimit,
188 simp = simp,
189 tol = tol,
190 )
191 case shapely.geometry.multilinestring.MultiLineString():
192 # Return it buffered ...
193 return buffer_MultiLineString(
194 shape,
195 dist,
196 debug = debug,
197 eps = eps,
198 fill = fill,
199 fillSpace = fillSpace,
200 nAng = nAng,
201 nIter = nIter,
202 prefix = prefix,
203 ramLimit = ramLimit,
204 simp = simp,
205 tol = tol,
206 )
207 case shapely.geometry.polygon.Polygon():
208 # Return it buffered ...
209 return buffer_Polygon(
210 shape,
211 dist,
212 debug = debug,
213 eps = eps,
214 fill = fill,
215 fillSpace = fillSpace,
216 keepInteriors = keepInteriors,
217 nAng = nAng,
218 nIter = nIter,
219 prefix = prefix,
220 ramLimit = ramLimit,
221 simp = simp,
222 tol = tol,
223 )
224 case shapely.geometry.multipolygon.MultiPolygon():
225 # Return it buffered ...
226 return buffer_MultiPolygon(
227 shape,
228 dist,
229 debug = debug,
230 eps = eps,
231 fill = fill,
232 fillSpace = fillSpace,
233 keepInteriors = keepInteriors,
234 nAng = nAng,
235 nIter = nIter,
236 prefix = prefix,
237 ramLimit = ramLimit,
238 simp = simp,
239 tol = tol,
240 )
241 case _:
242 # Cry ...
243 raise TypeError(f"\"shape\" is an unexpected type ({repr(type(shape))})") from None