Python源码示例:shapely.ops.unary_union()
示例1
def _construct_centerline(self):
vertices, ridges = self._get_voronoi_vertices_and_ridges()
linestrings = []
for ridge in ridges:
if self._ridge_is_finite(ridge):
starting_point = self._create_point_with_restored_coordinates(
x=vertices[ridge[0]][0], y=vertices[ridge[0]][1]
)
ending_point = self._create_point_with_restored_coordinates(
x=vertices[ridge[1]][0], y=vertices[ridge[1]][1]
)
linestring = LineString((starting_point, ending_point))
if self._linestring_is_within_input_geometry(linestring):
linestrings.append(linestring)
if len(linestrings) < 2:
raise exceptions.TooFewRidgesError
return unary_union(linestrings)
示例2
def minimal_set(polys):
"""Remove overlaps from a set of polygons.
:param polys: List of polygons.
:returns: List of polygons with no overlaps.
"""
normal = polys[0].normal_vector
as_2d = [p.project_to_2D() for p in polys]
as_shapely = [Polygon(p) for p in as_2d]
lines = [p.boundary for p in as_shapely]
borders = unary_union(lines)
shapes = [Polygon2D(p.boundary.coords) for p in polygonize(borders)]
as_3d = [p.project_to_3D(polys[0]) for p in shapes]
if not almostequal(as_3d[0].normal_vector, normal):
as_3d = [p.invert_orientation() for p in as_3d]
return [p for p in as_3d if p.area > 0]
示例3
def _union_in_blocks(contours, block_size):
"""
Generator which yields a valid shape for each block_size multiple of
input contours. This merges together the contours for each block before
yielding them.
"""
n_contours = len(contours)
for i in range(0, n_contours, block_size):
j = min(i + block_size, n_contours)
inners = []
for c in contours[i:j]:
p = _contour_to_poly(c)
if p.type == 'Polygon':
inners.append(p)
elif p.type == 'MultiPolygon':
inners.extend(p.geoms)
holes = unary_union(inners)
assert holes.is_valid
yield holes
示例4
def ToShapely(geometry):
"""Returns a |shapely| geometry from a generic geometry or a GeoJSON.
The original geometry structure is maintained, for example GeometryCollections
and MultiPolygons are kept as is. To dissolve them, apply the
`shapely.ops.unary_union()` routine on the output.
Args:
geometry: A generic geometry or a GeoJSON geometry (dict or str). A generic
geometry is any object implementing the __geo_interface__ supported by all
major geometry libraries (shapely, ..)
"""
if isinstance(geometry, sgeo.base.BaseGeometry):
return geometry
try:
return _GeoJsonToShapelyGeometry(geometry.__geo_interface__)
except AttributeError:
return _GeoJsonToShapelyGeometry(geometry)
示例5
def _GetAllExclusionZones():
"""Read all exclusion zones."""
global _exclusion_zones_gbs
global _exclusion_zones_p90
if _exclusion_zones_gbs is None:
kml_file = os.path.join(CONFIG.GetNtiaDir(), EXCLUSION_ZONE_FILE)
zones = _ReadKmlZones(kml_file, data_fields=['freqRangeMhz'])
gbs_zones = []
p90_zones = []
for name, zone in zones.items():
freq_range = _SplitFreqRange(zone.freqRangeMhz)
if (3550, 3650) in freq_range:
gbs_zones.append(zone.geometry)
elif (3650, 3700) in freq_range:
p90_zones.append(zone.geometry)
else:
raise ValueError('Zone %s: unsupported freq range %r',
name, freq_range)
_exclusion_zones_gbs = ops.unary_union(gbs_zones)
_exclusion_zones_p90 = ops.unary_union(p90_zones)
示例6
def _union_in_blocks(contours, block_size):
"""
Generator which yields a valid shape for each block_size multiple of
input contours. This merges together the contours for each block before
yielding them.
"""
n_contours = len(contours)
for i in range(0, n_contours, block_size):
j = min(i + block_size, n_contours)
inners = []
for c in contours[i:j]:
p = _contour_to_poly(c)
if p.type == 'Polygon':
inners.append(p)
elif p.type == 'MultiPolygon':
inners.extend(p.geoms)
holes = unary_union(inners)
assert holes.is_valid
yield holes
示例7
def getBridgesPoly(o):
if not hasattr(o, 'bridgespolyorig'):
bridgecollectionname = o.bridges_collection_name
bridgecollection = bpy.data.collections[bridgecollectionname]
shapes = []
bpy.ops.object.select_all(action='DESELECT')
for ob in bridgecollection.objects:
if ob.type == 'CURVE':
ob.select_set(state=True)
bpy.context.view_layer.objects.active = ob
bpy.ops.object.duplicate();
bpy.ops.object.join()
ob = bpy.context.active_object
shapes.extend(curveToShapely(ob, o.use_bridge_modifiers))
ob.select_set(state=True)
bpy.ops.object.delete(use_global=False)
bridgespoly = sops.unary_union(shapes)
# buffer the poly, so the bridges are not actually milled...
o.bridgespolyorig = bridgespoly.buffer(distance=o.cutter_diameter / 2.0)
o.bridgespoly_boundary = o.bridgespolyorig.boundary
o.bridgespoly_boundary_prep = prepared.prep(o.bridgespolyorig.boundary)
o.bridgespoly = prepared.prep(o.bridgespolyorig)
示例8
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)
示例9
def geom(self, union=False):
"""
Converts the Points to a shapely geometry.
Parameters
----------
union: boolean (default=False)
Whether to compute a union between the geometries
Returns
-------
A shapely geometry
"""
points = [Point(x, y) for (x, y) in self.array([0, 1])]
npoints = len(points)
if not npoints:
geom = GeometryCollection()
elif len(points) == 1:
geom = points[0]
else:
geom = MultiPoint(points)
return unary_union(geom) if union else geom
示例10
def geom(self, union=False):
"""
Converts the Path to a shapely geometry.
Parameters
----------
union: boolean (default=False)
Whether to compute a union between the geometries
Returns
-------
A shapely geometry
"""
geoms = expand_geoms([g['geometry'] for g in path_to_geom_dicts(self)])
ngeoms = len(geoms)
if not ngeoms:
geom = GeometryCollection()
elif ngeoms == 1:
geom = geoms[0]
else:
geom = MultiLineString(geoms)
return unary_union(geom) if union else geom
示例11
def geom(self, union=False):
"""
Converts the Contours to a shapely geometry.
Parameters
----------
union: boolean (default=False)
Whether to compute a union between the geometries
Returns
-------
A shapely geometry
"""
geoms = expand_geoms([g['geometry'] for g in path_to_geom_dicts(self)])
ngeoms = len(geoms)
if not ngeoms:
geom = GeometryCollection()
elif ngeoms == 1:
geom = geoms[0]
else:
geom = MultiLineString(geoms)
return unary_union(geom) if union else geom
示例12
def geom(self, union=False):
"""
Converts the Path to a shapely geometry.
Parameters
----------
union: boolean (default=False)
Whether to compute a union between the geometries
Returns
-------
A shapely geometry
"""
geoms = expand_geoms([g['geometry'] for g in polygons_to_geom_dicts(self)])
ngeoms = len(geoms)
if not ngeoms:
geom = GeometryCollection()
elif ngeoms == 1:
geom = geoms[0]
else:
geom = MultiPolygon(geoms)
return unary_union(geom) if union else geom
示例13
def geom(self, union=False):
"""
Converts the Rectangles to a shapely geometry.
Parameters
----------
union: boolean (default=False)
Whether to compute a union between the geometries
Returns
-------
A shapely geometry
"""
boxes = [box(*g) for g in self.array([0, 1, 2, 3])]
nboxes = len(boxes)
if not nboxes:
geom = GeometryCollection()
elif nboxes == 1:
geom = boxes[0]
else:
geom = MultiPolygon(boxes)
return unary_union(geom) if union else geom
示例14
def test_snap_bounds_to_zoom():
bounds = (-180, -90, -60, -30)
for pixelbuffer in [0, 5, 10]:
for metatiling in [1, 2, 4]:
pyramid = BufferedTilePyramid(
"geodetic", pixelbuffer=pixelbuffer, metatiling=metatiling
)
for zoom in range(3, 5):
snapped_bounds = mapchete.config.snap_bounds(
bounds=bounds,
pyramid=pyramid,
zoom=zoom
)
control_bounds = unary_union([
t.bbox for t in pyramid.tiles_from_bounds(bounds, zoom)
]).bounds
assert snapped_bounds == control_bounds
示例15
def draw_v_pair(pair, strip, l):
# Drow polligons between two masks from test
if l > 0:
roi_points = [(0, 0), (img_side_len, 0),
(img_side_len*l, img_side_len), (0, img_side_len)]
roi_poly = Polygon(roi_points)
top_tile = find_points(pair[0])
bottom_tile = find_points(pair[1])
top_tile_pos, top_tile_neg = top_tile
bottom_tile_pos, bottom_tile_neg = bottom_tile
v_shift = l * img_side_len
square_points = [(0, 0), (img_side_len, 0), (img_side_len, v_shift), (0, v_shift)]
square_poly = Polygon(square_points)
lines = []
for i in range(len(top_tile_pos[bottom])):
line = LineString([(top_tile_pos[bottom][i], 0),
(bottom_tile_pos[top][i], v_shift),
(bottom_tile_neg[top][i], v_shift),
(top_tile_neg[bottom][i], 0)])
lines.append(line)
merged = linemerge([square_poly.boundary, *lines])
borders = unary_union(merged)
polygons = []
for poly in polygonize(borders):
polygons.append(poly)
masks = [mask_for_polygons([polygons[i]], (v_shift, img_side_len))
for i in range(0, len(polygons), 2)]
mask = (np.any(masks, axis=0)*255).astype(np.uint8)
return mask
return None
示例16
def copdem_zone(lon_ex, lat_ex):
"""Returns a list of Copernicus DEM tarfile and tilename tuples
"""
# path to the lookup shapefiles
gdf = gpd.read_file(get_demo_file('RGI60_COPDEM_lookup.shp'))
# intersect with lat lon extents
p = _extent_to_polygon(lon_ex, lat_ex, to_crs=gdf.crs)
gdf = gdf.loc[gdf.intersects(p)]
# COPDEM is global, if we miss any tile it is worth an error
if (len(gdf) == 0) or (not unary_union(gdf.geometry).contains(p)):
raise InvalidDEMError('Could not find all necessary Copernicus DEM '
'tiles. This should not happen in a global DEM. '
'Check the RGI-CopernicusDEM lookup shapefile '
'for this particular glacier!')
flist = []
for _, g in gdf.iterrows():
cpp = g['CPP File']
eop = g['Eop Id']
eop = eop.split(':')[-2]
assert 'Copernicus' in eop
flist.append((cpp, eop))
return flist
示例17
def compute_bb(self) -> List[float]:
"""Compute the bounding box of all of the parts in the geometry.
Returns
-------
List of [min_x, max_x, min_y, max_y].
"""
all_shapes = list(self.parts.values())
bbox_vertices = unary_union(all_shapes).envelope.exterior.coords.xy
min_x = min(bbox_vertices[0])
max_x = max(bbox_vertices[0])
min_y = min(bbox_vertices[1])
max_y = max(bbox_vertices[1])
return [min_x, max_x, min_y, max_y]
示例18
def test_grid_complex(self):
with open(os.path.join(TEST_DIR, 'test_geocollection.json'), 'r') as fd:
json_geo = json.load(fd)
shape_geo = utils.ToShapely(json_geo)
exp_pts = {(-95, 40), (-95.5, 40.5), (-95.5, 40),
(-96, 40), (-96.5, 40.5), (-96.5, 40)}
pts = utils.GridPolygon(json_geo, res_arcsec=1800)
self.assertSetEqual(set(pts), exp_pts)
pts = utils.GridPolygon(shape_geo, res_arcsec=1800)
self.assertSetEqual(set(pts), exp_pts)
pts = utils.GridPolygon(ops.unary_union(shape_geo), res_arcsec=1800)
self.assertSetEqual(set(pts), exp_pts)
示例19
def GeometryArea(geometry, merge_geometries=False):
"""Returns the approximate area of a geometry on earth (in km2).
This uses the approximate formula on spheroid derived from:
Robert. G. Chamberlain and William H. Duquette
"Some Algorithms for Polygons on a Sphere",
See: https://trs-new.jpl.nasa.gov/bitstream/handle/2014/40409/JPL%20Pub%2007-3%20%20w%20Errata.pdf
An additional small correction is performed to account partially for the earth
ellipsoid.
Args:
geometry: A geometry defined in WGS84 or NAD83 coordinates (degrees) and
encoded either as shapely, GeoJson (dict or str) or a generic geometry.
A generic geometry is any object implementing the __geo_interface__ protocol.
merge_geometries (bool): If True, then multi geometries will be unioned to
dissolve intersection prior to the area calculation.
Returns:
The approximate area within the geometry (in square kilometers).
"""
geometry = ToShapely(geometry)
if (isinstance(geometry, sgeo.Point) or
isinstance(geometry, sgeo.LineString) or
isinstance(geometry, sgeo.LinearRing)):
# Lines, rings and points have null area
return 0.
elif isinstance(geometry, sgeo.Polygon):
return (_RingArea(geometry.exterior.xy[1], geometry.exterior.xy[0])
- sum(_RingArea(interior.xy[1], interior.xy[0])
for interior in geometry.interiors))
else:
# Multi geometries
if merge_geometries:
geometry = ops.unary_union(geometry)
# Test if dissolved into a simple geometry.
try:
iter(geometry)
except TypeError:
return GeometryArea(geometry)
return sum(GeometryArea(simple_shape) for simple_shape in geometry)
示例20
def GetUsCanadaBorder():
"""Gets the US/Canada border as a |shapely.MultiLineString|."""
global _uscanada_border
if _uscanada_border is None:
kml_file = os.path.join(CONFIG.GetFccDir(), USCANADA_BORDER_FILE)
lines = _ReadKmlBorder(kml_file)
_uscanada_border = ops.unary_union(lines.values())
return _uscanada_border
示例21
def GetUsBorder():
"""Gets the US border as a |shapely.MultiPolygon|.
This is a composite US border for simulation purposes only.
"""
global _border_zone
if _border_zone is None:
kml_file = os.path.join(CONFIG.GetFccDir(), USBORDER_FILE)
zones = _ReadKmlZones(kml_file)
_border_zone = ops.unary_union(zones.values())
return _border_zone
示例22
def GetUrbanAreas(simplify_deg=1e-3):
"""Gets the US urban area as a |shapely.GeometryCollection|.
Note: Client code should cache it as expensive to load (and not cached here).
Args:
simplify_deg: if defined, simplify the zone with given tolerance (degrees).
Default is 1e-3 which corresponds roughly to 100m in continental US.
"""
kml_file = os.path.join(CONFIG.GetNtiaDir(), URBAN_AREAS_FILE)
zones = _ReadKmlZones(kml_file, root_id_zone='Document', simplify=simplify_deg)
urban_areas = sgeo.GeometryCollection(zones.values()) # ops.unary_union(zones.values())
return urban_areas
示例23
def make_clusters_geojson(self):
"""Makes a feature collection of aggregated feature geometries """
geojson = LastUpdatedOrderedDict()
geojson['type'] = 'FeatureCollection'
geojson['features'] = []
for cluster_group, feat_geoms in self.raw_features.items():
geoms = []
for feat_geometry in feat_geoms:
geom_raw = shape(feat_geometry)
geom = geom_raw.buffer(self.buffer_tolerance)
if geom.is_valid:
geoms.append(geom)
if len(geoms) < 1:
# No valid geometries for this cluster, so skip
continue
union_geom = unary_union(geoms)
poly_union = union_geom.convex_hull
poly_union_simple = poly_union.simplify(self.simplify_tolerance)
feat = LastUpdatedOrderedDict()
feat['type'] = 'Feature'
feat['properties'] = LastUpdatedOrderedDict()
feat['properties'][self.cluster_property] = cluster_group
feat['properties'][self.cluster_num_features_prop] = len(geoms)
feat['geometry'] = LastUpdatedOrderedDict()
geometry_type = poly_union_simple.geom_type
coordinates = [list(poly_union_simple.exterior.coords)]
v_geojson = ValidateGeoJson()
c_ok = v_geojson.validate_all_geometry_coordinates(geometry_type,
coordinates)
if not c_ok:
coordinates = v_geojson.fix_geometry_rings_dir(geometry_type, coordinates)
feat['geometry']['type'] = geometry_type
feat['geometry']['coordinates'] = coordinates
centroid = self.get_feature_centroid(feat['geometry'])
feat['properties']['latitude'] = centroid[1]
feat['properties']['longitude'] = centroid[0]
geojson['features'].append(feat)
return geojson
示例24
def get_bounds(feature_collection):
"""Get a bounding box for a FeatureCollection"""
shape_lst = [shape(f['geometry']) for f in feature_collection['features']]
return unary_union(shape_lst).bounds
示例25
def silhoueteOffset(context, offset):
bpy.context.scene.cursor.location = (0, 0, 0)
ob = bpy.context.active_object
if ob.type == 'CURVE' or ob.type == 'FONT':
silhs = curveToShapely(ob)
else:
silhs = getObjectSilhouete('OBJECTS', [ob])
polys = []
mp = shapely.ops.unary_union(silhs)
mp = mp.buffer(offset, resolution=64)
shapelyToCurve('offset curve', mp, ob.location.z)
return {'FINISHED'}
示例26
def getAmbient(o):
if o.update_ambient_tag:
if o.ambient_cutter_restrict: # cutter stays in ambient & limit curve
m = o.cutter_diameter / 2
else:
m = 0
if o.ambient_behaviour == 'AROUND':
r = o.ambient_radius - m
o.ambient = getObjectOutline(r, o, True) # in this method we need ambient from silhouete
else:
o.ambient = spolygon.Polygon(((o.min.x + m, o.min.y + m), (o.min.x + m, o.max.y - m),
(o.max.x - m, o.max.y - m), (o.max.x - m, o.min.y + m)))
if o.use_limit_curve:
if o.limit_curve != '':
limit_curve = bpy.data.objects[o.limit_curve]
# polys=curveToPolys(limit_curve)
polys = curveToShapely(limit_curve)
o.limit_poly = shapely.ops.unary_union(polys)
# for p in polys:
# o.limit_poly+=p
if o.ambient_cutter_restrict:
o.limit_poly = o.limit_poly.buffer(o.cutter_diameter / 2, resolution=o.circle_detail)
o.ambient = o.ambient.intersection(o.limit_poly)
o.update_ambient_tag = False
示例27
def getObjectOutline(radius, o, Offset): # FIXME: make this one operation independent
# circle detail, optimize, optimize thresold.
polygons = getOperationSilhouete(o)
i = 0
# print('offseting polygons')
if Offset:
offset = 1
else:
offset = -1
outlines = []
i = 0
# print(polygons, polygons.type)
for p1 in polygons: # sort by size before this???
print(p1.type, len(polygons))
i += 1
if radius > 0:
p1 = p1.buffer(radius * offset, resolution=o.circle_detail)
outlines.append(p1)
print(outlines)
if o.dont_merge:
outline = sgeometry.MultiPolygon(outlines)
# for ci in range(0,len(p)):
# outline.addContour(p[ci],p.isHole(ci))
else:
# print(p)
outline = shapely.ops.unary_union(outlines)
# outline = sgeometry.MultiPolygon([outline])
# shapelyToCurve('oboutline',outline,0)
return outline
示例28
def _get_unary_union(self, level_id):
union = self._unary_unions.get(level_id)
if union is None:
union = unary_union(self._geometries_by_level[level_id])
self._unary_unions[level_id] = union
return union
示例29
def save(self, last_update, new_update):
self.finalize()
for level_id, geometries in self._geometries_by_level.items():
geometries = unary_union(geometries)
if geometries.is_empty:
continue
history = MapHistory.open_level(level_id, mode='base', default_update=last_update)
history.add_geometry(geometries.buffer(1), new_update)
history.save()
self.reset()
示例30
def clip_altitudes(self, new_geometry, new_altitude=None):
# register new geometry with an altitude
# a geometry with no altitude will reset the altitude information of its area as if nothing was ever there
if self.last_altitude is not None and self.last_altitude > new_altitude:
raise ValueError('Altitudes have to be ascending.')
if new_altitude in self.altitudes:
self.altitudes[new_altitude] = unary_union([self.altitudes[new_altitude], new_geometry])
else:
self.altitudes[new_altitude] = new_geometry