Coverage for pyguymer3/geo/bufferSrc/buffer_MultiPoint.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_MultiPoint(
5 multipoint,
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 MultiPoint
22 This function reads in a MultiPoint that exists on the surface of the Earth
23 and returns a [Multi]Polygon of the same MultiPoint buffered by a constant
24 distance (in metres).
26 Parameters
27 ----------
28 multipoint : shapely.geometry.multipoint.MultiPoint
29 the MultiPoint
30 dist : float
31 the Geodesic distance to buffer each point within the MultiPoint 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 nAng : int, optional
44 the number of angles around each point within the MultiPoint that are
45 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 MultiPoint
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_Point import buffer_Point
101 # **************************************************************************
103 # Check argument ...
104 assert isinstance(multipoint, shapely.geometry.multipoint.MultiPoint), "\"multipoint\" is not a MultiPoint"
105 if debug:
106 check(multipoint, prefix = prefix)
108 # Initialize list ...
109 buffs = []
111 # Loop over Point ...
112 for point in multipoint.geoms:
113 # Append buffer of Point to list ...
114 buffs.append(
115 buffer_Point(
116 point,
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