def polygon_hash(polygon):
'''
An approximate hash of a a shapely Polygon object.
Arguments
---------
polygon: shapely.geometry.Polygon object
Returns
---------
hash: (5) length list of hash representing input polygon
'''
result = [len(polygon.interiors),
polygon.convex_hull.area,
polygon.convex_hull.length,
polygon.area,
polygon.length]
return result
python类Polygon()的实例源码
def random_polygon(segments=8, radius=1.0):
'''
Generate a random polygon with a maximum number of sides and approximate radius.
Arguments
---------
segments: int, the maximum number of sides the random polygon will have
radius: float, the approximate radius of the polygon desired
Returns
---------
polygon: shapely.geometry.Polygon object with random exterior, and no interiors.
'''
angles = np.sort(np.cumsum(np.random.random(segments)*np.pi*2) % (np.pi*2))
radii = np.random.random(segments)*radius
points = np.column_stack((np.cos(angles), np.sin(angles)))*radii.reshape((-1,1))
points = np.vstack((points, points[0]))
polygon = Polygon(points).buffer(0.0)
if is_sequence(polygon):
return polygon[0]
return polygon
def clean_cut_polygon(polygon: Polygon) -> Polygon:
interiors = []
interiors.extend(cut_ring(polygon.exterior))
exteriors = [(i, ring) for (i, ring) in enumerate(interiors) if ring.is_ccw]
with suppress(AttributeError):
delattr(polygon, 'c3nav_cache')
if len(exteriors) != 1:
raise ValueError('Invalid cut polygon!')
exterior = interiors[exteriors[0][0]]
interiors.pop(exteriors[0][0])
for ring in polygon.interiors:
interiors.extend(cut_ring(ring))
return Polygon(exterior, interiors)
def _create_border(self, geometry: HybridGeometry, width, append=None):
altitude = (np.vstack(chain(*(mesh.tolist() for mesh in geometry.faces)))[:, :, 2].max()+1)/1000
geometry = self.buffered_bbox.intersection(geometry.geom)
lines = tuple(chain(*(
((geom.exterior, *geom.interiors) if isinstance(geom, Polygon) else (geom,))
for geom in getattr(geometry, 'geoms', (geometry,))
)))
if not lines:
return np.empty((0, 3, 3+len(append)))
lines = unary_union(lines).buffer(width, cap_style=CAP_STYLE.flat, join_style=JOIN_STYLE.mitre)
vertices, faces = triangulate_polygon(lines)
triangles = np.dstack((vertices[faces], np.full((faces.size, 1), fill_value=altitude).reshape((-1, 3, 1))))
return self._append_to_vertices(triangles.astype(np.float32), append)
def _geometry_to_svg(self, geom):
# scale and move geometry and create svg code for it
if isinstance(geom, Polygon):
return ('<path d="' +
' '.join((('M %.1f %.1f L'+(' %.1f %.1f'*(len(ring.coords)-1))+' z') %
tuple((np.array(ring)*self.np_scale+self.np_offset).flatten()))
for ring in chain((geom.exterior,), geom.interiors))
+ '"/>').replace('.0 ', ' ')
if isinstance(geom, LineString):
return (('<path d="M %.1f %.1f L'+(' %.1f %.1f'*(len(geom.coords)-1))+'"/>') %
tuple((np.array(geom)*self.np_scale+self.np_offset).flatten())).replace('.0 ', ' ')
try:
geoms = geom.geoms
except AttributeError:
return ''
return ''.join(self._geometry_to_svg(g) for g in geoms)
def testLocator(self):
image = mk_img(400, 600)
# draw a rectangle
A = (5, 5)
B = (5, 300)
C = (250, 5)
D = (250, 300)
ABCD = Polygon([A, B, D, C, A])
image = draw_poly(image, ABCD)
# locate it
locator = BinaryLocator()
located = locator.locate(image)
polygons, labels = zip(*located)
self.assertEqual(1, len(located), "One polygon found")
self.assertTrue(ABCD.equals(polygons[0]), "Found polygon has the same shape")
# test locate with an offset
locator2 = BinaryLocator()
located2 = locator2.locate(image, offset=(50, 40))
polygons2, labels2 = zip(*located2)
self.assertEqual(1, len(located2), "One polygon found")
self.assertTrue(translate(ABCD, 50, 40).equals(polygons2[0]), "Found translated polygon")
def testLocator(self):
image = mk_img(400, 600)
# draw a rectangle
A = (5, 80)
B = (5, 300)
C = (250, 80)
D = (250, 300)
ABCD = Polygon([A, B, D, C, A])
image = draw_poly(image, ABCD)
image, circle = draw_circle(image, 85, (500, 300), return_circle=True)
# test locator
locator = BinaryLocator()
located = locator.locate(image)
polygons, labels = zip(*located)
self.assertEqual(2, len(polygons), "Two polygons found")
self.assertTrue(ABCD.equals(polygons[1]), "Rectangle polygon is found")
self.assertLessEqual(relative_error(polygons[0].area, np.pi * 85 * 85), 0.005)
def testLocate(self):
image = mk_img(200, 300)
# draw a rectangle
A = (3, 40)
B = (3, 150)
C = (125, 40)
D = (125, 150)
ABCD = Polygon([A, B, D, C, A])
image = draw_poly(image, ABCD, color=1)
image = draw_circle(image, 40, (250, 150), color=2)
# test locator
locator = SemanticLocator(background=0)
located = locator.locate(image)
polygons, labels = zip(*located)
self.assertEqual(2, len(polygons), "Two polygons found")
self.assertTrue(ABCD.equals(polygons[0]), "Rectangle polygon is found")
self.assertLessEqual(relative_error(polygons[1].area, np.pi * 40 * 40), 0.005)
def _get_intersecting_projects(search_polygon: Polygon, author_id: int):
""" executes a database query to get the intersecting projects created by the author if provided """
query = db.session.query(Project.id,
Project.status,
Project.default_locale,
Project.geometry.ST_AsGeoJSON().label('geometry')) \
.filter(ST_Intersects(Project.geometry,
ST_MakeEnvelope(search_polygon.bounds[0],
search_polygon.bounds[1],
search_polygon.bounds[2],
search_polygon.bounds[3], 4326)))
if author_id:
query = query.filter(Project.author_id == author_id)
return query.all()
def _geom_to_array(geom: BaseGeometry):
if isinstance(geom, geometry.Point):
yield np.array([(np.nan, GeomTypes.POINT)])
yield np.asarray(geom.coords)
elif isinstance(geom, geometry.LineString):
yield np.array([(np.nan, GeomTypes.LINESTRING)])
yield np.asarray(geom.coords)
elif isinstance(geom, geometry.Polygon):
for interior in geom.interiors:
yield np.array([(np.nan, GeomTypes.POLYGON_HOLE)])
yield np.asarray(interior)
yield np.array([(np.nan, GeomTypes.POLYGON_SHELL)])
yield np.asarray(geom.exterior)
elif isinstance(geom, BaseMultipartGeometry):
return chain.from_iterable(map(geom_to_array, geom))
else:
raise TypeError
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
height = self.height
width = self.width
domain = Polygon([(0, 0), (0, height), (width, height), (width, 0)])
target = LineString([(0, height / 2), (0, height)])
spawn = Polygon([(0, 0),
(0, height / 2),
(width / 2, height / 2),
(width / 2, 0)])
obstacles = LineString([(0, height / 2),
(width * self.ratio, height / 2)]) | \
domain.exterior - target
self.obstacles = obstacles
self.targets = [target]
self.spawns = [spawn]
self.domain = domain
def test_attributes():
outl = ((0, 0), (0, 1), (1, 1.), (1, 0))
r = Region_cls(1, 'Unit Square', 'USq', outl)
assert r.number == 1
assert r.name == 'Unit Square'
assert r.abbrev == 'USq'
assert np.allclose(r.coords, outl)
assert isinstance(r.coords, np.ndarray)
assert r.polygon.equals(Polygon(outl))
assert isinstance(r.polygon, Polygon)
assert np.allclose(r.centroid, (0.5, 0.5))
def ellipses_intersect(ellipse1, ellipse2):
a, b = ellipse_polyline((ellipse1, ellipse2))
ea = LinearRing(a)
eb = LinearRing(b)
mp = ea.intersection(eb)
#encloses = ea.contains(eb)
#encloses = ea.contains(Point(ellipse2[0], ellipse2[1]))
pa = Polygon(a)
pb = Polygon(b)
encloses = pa.contains(pb)
x = [p.x for p in mp]
y = [p.y for p in mp]
if len(x) > 0:
intersects = True
else:
intersects = False
return intersects, encloses
def get_way_centroid(self, way):
"""Calculate the centroid of a way
way (object): overpy.Way object
Returns dict of lat/lon
"""
# Polygon has to have at least 3 points
if len(way.nodes) >= 3:
geom = []
for node in way.nodes:
geom.append((node.lon, node.lat))
poly = Polygon(geom)
cent = poly.centroid
return {'lat': cent.y, 'lon': cent.x}
elif len(way.nodes) == 2:
# if way has 2 nodes, use average position
lat = (way.nodes[0].lat + way.nodes[1].lat) / 2
lon = (way.nodes[0].lon + way.nodes[1].lon) / 2
return {'lat': lat, 'lon': lon}
elif len(way.nodes) == 1:
# if way has 1 node, use that position
# (unusual and certainly a bug but possible)
return {'lat': way.nodes[0].lat, 'lon': way.nodes[0].lon}
else:
raise RuntimeError
def lines_within_box(self, bounding_box):
"""
Get all lines selected by a bounding box. Note that the whole line
is selected when it partially falls into the box.
:param bounding_box: the bounding coordinates in
(minx, miny, maxx, maxy) or a Polygon instance
:return: list, of LineInfo
"""
subgraph = self.subgraph_within_box(bounding_box)
lines = set()
for edge in subgraph.edges():
info = self.edge_info(edge)
if info.line_index:
lines.add(info.line_index)
return [self.line_info(i) for i in lines]
def test_polygonal_min(self):
polygon = Polygon([(0.0, 0.0), (0.0, 33.0), (33.0, 33.0), (33.0, 0.0), (0.0, 0.0)])
result = self.tiled_rdd.polygonal_min(polygon, float)
self.assertEqual(result, [0.0, 0.0])
def test_polygonal_max(self):
polygon = Polygon([(1.0, 1.0), (1.0, 10.0), (10.0, 10.0), (10.0, 1.0)])
result = self.tiled_rdd.polygonal_max(polygon, float)
self.assertEqual(result, [1.0, 1.0])
def test_polygonal_sum(self):
polygon = Polygon([(0.0, 0.0), (0.0, 33.0), (33.0, 33.0), (33.0, 0.0), (0.0, 0.0)])
result = self.tiled_rdd.polygonal_sum(polygon, float)
self.assertEqual(result, [96.0, 96.0])
def test_polygonal_mean(self):
polygon = Polygon([(1.0, 1.0), (1.0, 10.0), (10.0, 10.0), (10.0, 1.0)])
result = self.tiled_rdd.polygonal_mean(polygon)
self.assertEqual(result, [1.0, 1.0])
def polygonal_mean(self, geometry):
"""Finds the mean of all of the values for each band that are contained within the given geometry.
Args:
geometry (shapely.geometry.Polygon or shapely.geometry.MultiPolygon or bytes): A
Shapely ``Polygon`` or ``MultiPolygon`` that represents the area where the summary
should be computed; or a WKB representation of the geometry.
Returns:
[float]
"""
return self._process_polygonal_summary(geometry, self.srdd.polygonalMean)