生成渔网
以中心为基点
import geopandas as gpd
from shapely.geometry import Polygon
from shapely.ops import unary_union
from typing import Optional
def create_grid_centers(bounds_or_shp_path: str | BoundsType, output_path=None, cell_size=25, output_type="point"):
"""
@Description 以网格中心为基点生成点集或者面集,
- param bounds_or_shp_path :{str} 支持提供shp文件或者具体tuple
- param output_path=None :{param} 输出目录
- param cell_size=25 :{int} 网格的具体尺寸,间距
- param output_type=point :{string} 支持输出点或者面:polygon|point
"""
if isinstance(bounds_or_shp_path, tuple) and len(bounds_or_shp_path) == 4:
# 边界以元组形式提供
minx, miny, maxx, maxy = bounds_or_shp_path
crs = None # 如果没有提供Shapefile,则CRS默认为None
elif isinstance(bounds_or_shp_path, str) and os.path.exists(bounds_or_shp_path):
# 边界从Shapefile文件中读取
shp_gdf = gpd.read_file(bounds_or_shp_path)
total_bounds = shp_gdf.total_bounds
minx, miny, maxx, maxy = total_bounds
crs = shp_gdf.crs # 使用Shapefile的CRS
else:
raise ValueError("bounds_or_shp_path must be a tuple (minx, miny, maxx, maxy) or a valid Shapefile path.")
# 调整边界以确保中心点完全位于网格内部
adjusted_minx = minx + cell_size / 2
adjusted_miny = miny + cell_size / 2
adjusted_maxx = maxx - cell_size / 2
adjusted_maxy = maxy - cell_size / 2
# 计算网格的行数和列数
nrows = int((adjusted_maxy - adjusted_miny) / cell_size)
ncols = int((adjusted_maxx - adjusted_minx) / cell_size)
if output_type == "point":
# 生成网格中心点的x和y坐标
x_coords = np.linspace(adjusted_minx, adjusted_maxx, ncols)
y_coords = np.linspace(adjusted_miny, adjusted_maxy, nrows)
x_grid, y_grid = np.meshgrid(x_coords, y_coords, indexing="ij")
points = [(x, y) for x, y in zip(x_grid.ravel(), y_grid.ravel())]
# 创建GeoDataFrame
grid_gdf = gpd.GeoDataFrame(geometry=[Point(x, y) for x, y in points], crs=crs)
elif output_type == "polygon":
# 生成网格的面
polygons = []
for i in range(nrows):
for j in range(ncols):
# 直接使用调整后的坐标来确保网格对齐
x1, y1 = adjusted_minx + j * cell_size, adjusted_miny + i * cell_size
x2, y2 = x1 + cell_size, y1 + cell_size
# 创建一个矩形多边形并添加到列表中
polygon = Polygon([(x1, y1), (x2, y1), (x2, y2), (x1, y2), (x1, y1)])
polygons.append(polygon)
grid_gdf = gpd.GeoDataFrame(geometry=polygons, crs=crs)
else:
raise ValueError("output_type must be 'point' or 'polygon'.")
# 如果提供了output_path,则输出Shapefile
if output_path is not None:
# 确保output_path是字符串
if not isinstance(output_path, str):
raise ValueError("output_path must be a string")
# 如果output_path没有以.shp结尾,则添加.shp后缀
if not output_path.endswith(".shp"):
output_path += ".shp"
# 输出GeoDataFrame到Shapefile
grid_gdf.to_file(output_path, driver="ESRI Shapefile")
return grid_gdf
# 使用
create_grid_centers(input_shp, "create_grid_centers_polygons.shp", output_type="polygon")
使用shapely
CSDN版本1
from shapely.geometry import Polygon
import geopandas as gpd
def Fishnet(boundary,cell_height,cell_width) -> None:
# 渔网多边形
# boundary = gpd.read_file("boundary.shp")
xmin, ymin, xmax, ymax = boundary.total_bounds
rows = int((ymax - ymin) / cell_height)
cols = int((xmax - xmin) / cell_width)
polygons = []
for x in range(cols):
for y in range(rows):
polygons.append(Polygon([(xmin + x * cell_width, ymin + y * cell_height),
(xmin + (x + 1) * cell_width, ymin + y * cell_height),
(xmin + (x + 1) * cell_width, ymin + (y + 1) * cell_height),
(xmin + x * cell_width, ymin + (y + 1) * cell_height)]))
fishnet = gpd.GeoDataFrame(geometry=polygons, crs=boundary.crs)
# 计算渔网中心点
fishnet["center"] = fishnet.centroid
fishnet = fishnet.set_geometry("center")
# 设置新的crs为4326
fishnet = fishnet.to_crs(epsg=4326)
fishnet = fishnet.drop('geometry',axis =1)
return fishnet
文心一言AI版本1
import geopandas as gpd
from shapely.geometry import Polygon, Point
from shapely.ops import unary_union
import os
from decimal import Decimal
def create_fishnet(start_x, start_y, end_x, end_y, cell_size_x, cell_size_y):
# 创建一个简单的渔网
x_range = range(int(start_x), int(end_x) + 1, int(cell_size_x))
y_range = range(int(startY), int(end_y) + 1, int(cell_size_y))
polygons = []
for x in x_range:
for y in y_range:
polygons.append(Polygon([(x, y), (x + cell_size_x, y),
(x + cell_size_x, y + cell_size_y),
(x, y + cell_size_y), (x, y)]))
return gpd.GeoDataFrame(geometry=polygons)
def clip_data(fishnet_gdf, clip_gdf):
# 裁剪数据
# 假设clip_gdf是一个多边形,用于裁剪fishnet_gdf中的点或面
result = gpd.overlay(fishnet_gdf, clip_gdf, how='intersection')
return result
# 示例参数
range_shp_path = 'path/to/your/range_shp.shp' # 假设这是一个多边形文件
tmp_dir = 'path/to/tmp_dir'
output_path = os.path.join(tmp_dir, 'clipped_fishnet.shp')
# 读取范围Shapefile
range_shp = gpd.read_file(range_shp_path)
# 假设我们已知起始和结束坐标以及网格大小
startX, startY, endX, endY = range_shp.total_bounds
# startX, startY, endX, endY = 0, 0, 100, 100 # 假设的起始和结束坐标
net_pixel_x = 10 # X方向上的网格大小
net_pixel_y = 20 # Y方向上的网格大小可能不同
# 创建渔网
fishnet_gdf = create_fishnet(startX, startY, endX, endY, net_pixel_x)
# 裁剪渔网
clipped_fishnet = clip_data(fishnet_gdf, range_shp)
# 如果需要保存结果
clipped_fishnet.to_file(output_path)
# 返回输出路径(虽然在这个例子中,它已经被保存了)
return output_path
使用ORG库
代码思路
1、导入相关包 2、输入渔网范围,格网宽度和高度 3、计算行列数 4、初始化左上角格网四角范围,创建输出文件 5、遍历每一列: 初始化第一行格网上下边界(放在行循环外,以便每次进入下一列定位到第一行) 遍历每一行: 计算单个格网范围 创建ring,写入格网四点,创建polygon,写入ring,构成一个格网 多边形写入图层 本行单个格网写入完成,行数加一并向下计算下一格网上下边界 本列格网全部写入,列数加一向右计算下一列格网左右边
##创建渔网
import ogr,os,osr,sys
from math import ceil
#os.chdir(r'F:\Python+gdal\CookBook\results')
def Fishgrid(outfile,xmin,xmax,ymin,ymax,gridwidth,gridheight):
#参数转换到浮点型
xmin = float(xmin)
xmax = float(xmax)
ymin = float(ymin)
ymax = float(ymax)
gridwidth = float(gridwidth)
gridheight = float(gridheight)
#计算行数和列数
rows = ceil((ymax-ymin)/gridheight)
cols = ceil((xmax-xmin)/gridwidth)
#初始化起始格网四角范围
ringXleftOrigin = xmin
ringXrightOrigin = xmin+gridwidth
ringYtopOrigin = ymax
ringYbottomOrigin = ymax-gridheight
#创建输出文件
outdriver = ogr.GetDriverByName('ESRI Shapefile')
if os.path.exists(outfile):
outdriver.DeleteDataSource(outfile)
outds = outdriver.CreateDataSource(outfile)
outlayer = outds.CreateLayer(outfile,geom_type = ogr.wkbPolygon)
#不添加属性信息,获取图层属性
outfielddefn = outlayer.GetLayerDefn()
#遍历列,每一列写入格网
col = 0
while col<cols:
#初始化,每一列写入完成都把上下范围初始化
ringYtop = ringYtopOrigin
ringYbottom = ringYbottomOrigin
#遍历行,对这一列每一行格子创建和写入
row = 0
while row<rows:
#创建左上角第一个格子
ring = ogr.Geometry(ogr.wkbLinearRing)
ring.AddPoint(ringXleftOrigin,ringYtop)
ring.AddPoint(ringXrightOrigin,ringYtop)
ring.AddPoint(ringXrightOrigin,ringYbottom)
ring.AddPoint(ringXleftOrigin,ringYbottom)
ring.CloseRings()
#写入几何多边形
poly = ogr.Geometry(ogr.wkbPolygon)
poly.AddGeometry(ring)
#创建要素,写入多边形
outfeat = ogr.Feature(outfielddefn)
outfeat.SetGeometry(poly)
#写入图层
outlayer.CreateFeature(outfeat)
outfeat = None
#下一多边形,更新上下范围
row+=1
ringYtop = ringYtop - gridheight
ringYbottom = ringYbottom-gridheight
#一列写入完成后,下一列,更新左右范围
col+=1
ringXleftOrigin = ringXleftOrigin+gridwidth
ringXrightOrigin = ringXrightOrigin+gridwidth
#写入后清除缓存
outds = None
if __name__ == '__main__':
os.chdir(r'F:\Python+gdal\CookBook\results')
shp = 'fishgrid.shp'
Fishgrid(shp,0,1000,0,500,10,10)