structure saas with tools
This commit is contained in:
@@ -0,0 +1 @@
|
||||
"""Algorithms implemented in Shapely."""
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,56 @@
|
||||
import math
|
||||
from itertools import islice
|
||||
|
||||
import numpy as np
|
||||
|
||||
import shapely
|
||||
from shapely.affinity import affine_transform
|
||||
|
||||
|
||||
def _oriented_envelope_min_area(geometry, **kwargs):
|
||||
"""Compute the oriented envelope (minimum rotated rectangle).
|
||||
|
||||
This is a fallback implementation for GEOS < 3.12 to have the correct
|
||||
minimum area behaviour.
|
||||
"""
|
||||
if geometry is None:
|
||||
return None
|
||||
if geometry.is_empty:
|
||||
return shapely.from_wkt("POLYGON EMPTY")
|
||||
|
||||
# first compute the convex hull
|
||||
hull = geometry.convex_hull
|
||||
try:
|
||||
coords = hull.exterior.coords
|
||||
except AttributeError: # may be a Point or a LineString
|
||||
return hull
|
||||
# generate the edge vectors between the convex hull's coords
|
||||
edges = (
|
||||
(pt2[0] - pt1[0], pt2[1] - pt1[1])
|
||||
for pt1, pt2 in zip(coords, islice(coords, 1, None))
|
||||
)
|
||||
|
||||
def _transformed_rects():
|
||||
for dx, dy in edges:
|
||||
# compute the normalized direction vector of the edge
|
||||
# vector.
|
||||
length = math.sqrt(dx**2 + dy**2)
|
||||
ux, uy = dx / length, dy / length
|
||||
# compute the normalized perpendicular vector
|
||||
vx, vy = -uy, ux
|
||||
# transform hull from the original coordinate system to
|
||||
# the coordinate system defined by the edge and compute
|
||||
# the axes-parallel bounding rectangle.
|
||||
transf_rect = affine_transform(hull, (ux, uy, vx, vy, 0, 0)).envelope
|
||||
# yield the transformed rectangle and a matrix to
|
||||
# transform it back to the original coordinate system.
|
||||
yield (transf_rect, (ux, vx, uy, vy, 0, 0))
|
||||
|
||||
# check for the minimum area rectangle and return it
|
||||
transf_rect, inv_matrix = min(_transformed_rects(), key=lambda r: r[0].area)
|
||||
return affine_transform(transf_rect, inv_matrix)
|
||||
|
||||
|
||||
_oriented_envelope_min_area_vectorized = np.frompyfunc(
|
||||
_oriented_envelope_min_area, 1, 1
|
||||
)
|
||||
50
.venv/lib/python3.10/site-packages/shapely/algorithms/cga.py
Normal file
50
.venv/lib/python3.10/site-packages/shapely/algorithms/cga.py
Normal file
@@ -0,0 +1,50 @@
|
||||
"""Shapely CGA algorithms."""
|
||||
|
||||
import numpy as np
|
||||
|
||||
import shapely
|
||||
|
||||
|
||||
def signed_area(ring):
|
||||
"""Return the signed area enclosed by a ring in linear time.
|
||||
|
||||
Algorithm used: https://web.archive.org/web/20080209143651/http://cgafaq.info:80/wiki/Polygon_Area
|
||||
"""
|
||||
coords = np.array(ring.coords)[:, :2]
|
||||
xs, ys = np.vstack([coords, coords[1]]).T
|
||||
return np.sum(xs[1:-1] * (ys[2:] - ys[:-2])) / 2.0
|
||||
|
||||
|
||||
def _reverse_conditioned(rings, condition):
|
||||
"""Return a copy of the rings potentially reversed depending on `condition`."""
|
||||
condition = np.asarray(condition)
|
||||
if np.all(condition):
|
||||
rings = shapely.reverse(rings)
|
||||
elif np.any(condition):
|
||||
rings = np.array(rings)
|
||||
rings[condition] = shapely.reverse(rings[condition])
|
||||
return rings
|
||||
|
||||
|
||||
def _orient_polygon(geometry, exterior_cw=False):
|
||||
if geometry is None:
|
||||
return None
|
||||
if geometry.geom_type in ["MultiPolygon", "GeometryCollection"]:
|
||||
return geometry.__class__(
|
||||
[_orient_polygon(geom, exterior_cw) for geom in geometry.geoms]
|
||||
)
|
||||
# elif geometry.geom_type in ["LinearRing"]:
|
||||
# return reverse_conditioned(geometry, is_ccw(geometry) != ccw)
|
||||
elif geometry.geom_type == "Polygon":
|
||||
rings = np.array([geometry.exterior, *geometry.interiors])
|
||||
reverse_condition = shapely.is_ccw(rings)
|
||||
reverse_condition[0] = not reverse_condition[0]
|
||||
if exterior_cw:
|
||||
reverse_condition = np.logical_not(reverse_condition)
|
||||
if np.any(reverse_condition):
|
||||
rings = _reverse_conditioned(rings, reverse_condition)
|
||||
return geometry.__class__(rings[0], rings[1:])
|
||||
return geometry
|
||||
|
||||
|
||||
_orient_polygons_vectorized = np.frompyfunc(_orient_polygon, nin=2, nout=1)
|
||||
@@ -0,0 +1,43 @@
|
||||
"""Provides functions for finding the pole of inaccessibility for a given polygon."""
|
||||
|
||||
from shapely._geometry import get_point
|
||||
from shapely.constructive import maximum_inscribed_circle
|
||||
|
||||
|
||||
def polylabel(polygon, tolerance=1.0):
|
||||
"""Find pole of inaccessibility for a given polygon.
|
||||
|
||||
Based on Vladimir Agafonkin's https://github.com/mapbox/polylabel
|
||||
|
||||
Parameters
|
||||
----------
|
||||
polygon : shapely.geometry.Polygon
|
||||
Polygon for which to find the pole of inaccessibility.
|
||||
tolerance : int or float, optional
|
||||
`tolerance` represents the highest resolution in units of the
|
||||
input geometry that will be considered for a solution. (default
|
||||
value is 1.0).
|
||||
|
||||
Returns
|
||||
-------
|
||||
shapely.geometry.Point
|
||||
A point representing the pole of inaccessibility for the given input
|
||||
polygon.
|
||||
|
||||
Raises
|
||||
------
|
||||
shapely.errors.TopologicalError
|
||||
If the input polygon is not a valid geometry.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> from shapely.ops import polylabel
|
||||
>>> from shapely import LineString
|
||||
>>> polygon = LineString([(0, 0), (50, 200), (100, 100), (20, 50),
|
||||
... (-100, -20), (-150, -200)]).buffer(100)
|
||||
>>> polylabel(polygon, tolerance=0.001)
|
||||
<POINT (59.733 111.33)>
|
||||
|
||||
"""
|
||||
line = maximum_inscribed_circle(polygon, tolerance)
|
||||
return get_point(line, 0)
|
||||
Reference in New Issue
Block a user