def time_tree_nearest_all_poly_python(self): # returns all input points # use an arbitrary search tolerance that seems appropriate for the density of # geometries tolerance = 200 b = shapely.buffer(self.points, tolerance, quadsegs=1) left, right = self.tree.query(b) dist = shapely.distance(self.points.take(left), self.polygons.take(right)) # sort by left, distance ix = np.lexsort((right, dist, left)) left = left[ix] right = right[ix] dist = dist[ix] run_start = np.r_[True, left[:-1] != left[1:]] run_counts = np.diff(np.r_[np.nonzero(run_start)[0], left.shape[0]]) mins = dist[run_start] # spread to rest of array so we can extract out all within each group that match all_mins = np.repeat(mins, run_counts) ix = dist == all_mins left = left[ix] right = right[ix] dist = dist[ix]
def setup(self): # create irregular polygons by merging overlapping point buffers self.left = shapely.union_all( shapely.buffer(shapely.points(np.random.random((500, 2)) * 500), 15)) # shift this up and right self.right = shapely.transform(self.left, lambda x: x + 50)
def setup(self): # create irregular polygons by merging overlapping point buffers self.polygon = shapely.union_all( shapely.buffer(shapely.points(np.random.random((1000, 2)) * 500), 10)) xmin = np.random.random(100) * 100 xmax = xmin + 100 ymin = np.random.random(100) * 100 ymax = ymin + 100 self.bounds = np.array([xmin, ymin, xmax, ymax]).T self.boxes = shapely.box(xmin, ymin, xmax, ymax)
def setup(self): # create irregular polygons my merging overlapping point buffers self.polygons = shapely.get_parts( shapely.union_all( shapely.buffer( shapely.points(np.random.random((2000, 2)) * 500), 5))) self.tree = shapely.STRtree(self.polygons) # initialize the tree by making a tiny query first self.tree.query(shapely.points(0, 0)) # create points that extend beyond the domain of the above polygons to ensure # some don't overlap self.points = shapely.points((np.random.random((2000, 2)) * 750) - 125) self.point_tree = shapely.STRtree( shapely.points(np.random.random((2000, 2)) * 750)) self.point_tree.query(shapely.points(0, 0)) # create points on a grid for testing equidistant nearest neighbors # creates 2025 points grid_coords = np.mgrid[:45, :45].T.reshape(-1, 2) self.grid_point_tree = shapely.STRtree(shapely.points(grid_coords)) self.grid_points = shapely.points(grid_coords + 0.5)
def time_tree_nearest_points_equidistant_manual_all(self): # This benchmark approximates nearest_all for equidistant results # starting from singular nearest neighbors and searching for more # within same distance. # try to find all equidistant neighbors ourselves given single nearest # result l, r = self.grid_point_tree.nearest(self.grid_points) # calculate distance to nearest neighbor dist = shapely.distance(self.grid_points.take(l), self.grid_point_tree.geometries.take(r)) # include a slight epsilon to ensure nearest are within this radius b = shapely.buffer(self.grid_points, dist + 1e-8) # query the tree for others in the same buffer distance left, right = self.grid_point_tree.query(b, predicate="intersects") dist = shapely.distance(self.grid_points.take(left), self.grid_point_tree.geometries.take(right)) # sort by left, distance ix = np.lexsort((right, dist, left)) left = left[ix] right = right[ix] dist = dist[ix] run_start = np.r_[True, left[:-1] != left[1:]] run_counts = np.diff(np.r_[np.nonzero(run_start)[0], left.shape[0]]) mins = dist[run_start] # spread to rest of array so we can extract out all within each group that match all_mins = np.repeat(mins, run_counts) ix = dist == all_mins left = left[ix] right = right[ix] dist = dist[ix]
def test_buffer_join_style_invalid(): with pytest.raises(ValueError, match="'invalid' is not a valid option"): shapely.buffer(point, 1, join_style="invalid")
def test_minimum_bounding_circle_all_types(geometry): actual = shapely.minimum_bounding_circle([geometry, geometry]) assert actual.shape == (2,) assert actual[0] is None or isinstance(actual[0], Geometry) actual = shapely.minimum_bounding_circle(None) assert actual is None @pytest.mark.skipif(shapely.geos_version < (3, 8, 0), reason="GEOS < 3.8") @pytest.mark.parametrize( "geometry, expected", [ ( shapely.Geometry("POLYGON ((0 5, 5 10, 10 5, 5 0, 0 5))"), shapely.buffer(shapely.Geometry("POINT (5 5)"), 5), ), ( shapely.Geometry("LINESTRING (1 0, 1 10)"), shapely.buffer(shapely.Geometry("POINT (1 5)"), 5), ), ( shapely.Geometry("MULTIPOINT (2 2, 4 2)"), shapely.buffer(shapely.Geometry("POINT (3 2)"), 1), ), ( shapely.Geometry("POINT (2 2)"), shapely.Geometry("POINT (2 2)"), ), ( shapely.Geometry("GEOMETRYCOLLECTION EMPTY"),
def buffer( self, distance, resolution=16, quadsegs=None, cap_style=CAP_STYLE.round, join_style=JOIN_STYLE.round, mitre_limit=5.0, single_sided=False, ): """Get a geometry that represents all points within a distance of this geometry. A positive distance produces a dilation, a negative distance an erosion. A very small or zero distance may sometimes be used to "tidy" a polygon. Parameters ---------- distance : float The distance to buffer around the object. resolution : int, optional The resolution of the buffer around each vertex of the object. quadsegs : int, optional Sets the number of line segments used to approximate an angle fillet. Note: the use of a `quadsegs` parameter is deprecated and will be gone from the next major release. cap_style : int, optional The styles of caps are: CAP_STYLE.round (1), CAP_STYLE.flat (2), and CAP_STYLE.square (3). join_style : int, optional The styles of joins between offset segments are: JOIN_STYLE.round (1), JOIN_STYLE.mitre (2), and JOIN_STYLE.bevel (3). mitre_limit : float, optional The mitre limit ratio is used for very sharp corners. The mitre ratio is the ratio of the distance from the corner to the end of the mitred offset corner. When two line segments meet at a sharp angle, a miter join will extend the original geometry. To prevent unreasonable geometry, the mitre limit allows controlling the maximum length of the join corner. Corners with a ratio which exceed the limit will be beveled. single_side : bool, optional The side used is determined by the sign of the buffer distance: a positive distance indicates the left-hand side a negative distance indicates the right-hand side The single-sided buffer of point geometries is the same as the regular buffer. The End Cap Style for single-sided buffers is always ignored, and forced to the equivalent of CAP_FLAT. Returns ------- Geometry Notes ----- The return value is a strictly two-dimensional geometry. All Z coordinates of the original geometry will be ignored. Examples -------- >>> from shapely.wkt import loads >>> g = loads('POINT (0.0 0.0)') >>> g.buffer(1.0).area # 16-gon approx of a unit radius circle 3.1365484905459... >>> g.buffer(1.0, 128).area # 128-gon approximation 3.141513801144... >>> g.buffer(1.0, 3).area # triangle approximation 3.0 >>> list(g.buffer(1.0, cap_style=CAP_STYLE.square).exterior.coords) [(1.0, 1.0), (1.0, -1.0), (-1.0, -1.0), (-1.0, 1.0), (1.0, 1.0)] >>> g.buffer(1.0, cap_style=CAP_STYLE.square).area 4.0 """ if quadsegs is not None: warn( "The `quadsegs` argument is deprecated. Use `resolution`.", DeprecationWarning, ) resolution = quadsegs if mitre_limit == 0.0: raise ValueError( "Cannot compute offset from zero-length line segment") return shapely.buffer( self, distance, quadsegs=resolution, cap_style=cap_style, join_style=join_style, mitre_limit=mitre_limit, single_sided=single_sided, )