gpt4 book ai didi

python - 从边界点创建闭合多边形

转载 作者:太空狗 更新时间:2023-10-30 02:21:25 25 4
gpt4 key购买 nike

我有一组定义区域边界的经纬度点。我想根据这些点创建一个多边形并在 map 上绘制多边形并填充它。目前,我的多边形似乎由许多连接所有点的补丁组成,但点的顺序不正确,当我尝试填充多边形时,我得到一个看起来很奇怪的区域(见附件)。 The black dots indicate the position of the boundary points

我根据多边形的中心对经度-纬度点(mypolyXY 数组)进行排序,但我猜测这是不正确的:

cent=(np.sum([p[0] for p in mypolyXY])/len(mypolyXY),np.sum([p[1] for p in mypolyXY])/len(mypolyXY))
# sort by polar angle
mypolyXY.sort(key=lambda p: math.atan2(p[1]-cent[1],p[0]-cent[0]))

我绘制点位置(黑色圆圈)和我的多边形(彩色 block )使用

scatter([p[0] for p in mypolyXY],[p[1] for p in mypolyXY],2)
p = Polygon(mypolyXY,facecolor=colors,edgecolor='none')
ax.add_artist(p)

我的问题是:如何根据我的经度-纬度点数组来关闭多边形?

更新:我对如何绘制多边形进行了更多测试。我删除了排序例程,只是按照它们在文件中出现的顺序使用数据。这似乎改善了结果,但正如@tcaswell 所提到的,多边形形状仍然削弱了自身(见新图)。我希望有一个路径/多边形例程可以解决我的问题,并在某种程度上合并多边形边界内的所有形状或路径。非常欢迎提出建议。

enter image description here

更新 2:

我现在有一个基于@Rutger Kassies 和 Roland Smith 建议的脚本的工作版本。我最终使用 org 阅读了 Shapefile,效果相对较好。它适用于标准 lmes_64.shp 文件,但当我使用更详细的 LME 文件时,其中每个 LME 可能由多个多边形组成,此脚本崩溃了。我将不得不找到一种方法来合并具有相同 LME 名称的各种多边形以使其工作。我附上了我最终得到的脚本,以防有人看到它。我非常感谢有关如何改进此脚本或使其更通用的评论。该脚本在我从 netcdf 文件读取的多边形区域内创建多边形并提取数据。输入文件的网格是-180到180和-90到90。

import numpy as np
import math
from pylab import *
import matplotlib.patches as patches
import string, os, sys
import datetime, types
from netCDF4 import Dataset
import matplotlib.nxutils as nx
from mpl_toolkits.basemap import Basemap
import ogr
import matplotlib.path as mpath
import matplotlib.patches as patches


def getLMEpolygon(coordinatefile,mymap,index,first):

ds = ogr.Open(coordinatefile)
lyr = ds.GetLayer(0)
numberOfPolygons=lyr.GetFeatureCount()

if first is False:
ft = lyr.GetFeature(index)
print "Found polygon:", ft.items()['LME_NAME']
geom = ft.GetGeometryRef()

codes = []
all_x = []
all_y = []
all_XY= []

if (geom.GetGeometryType() == ogr.wkbPolygon):
for i in range(geom.GetGeometryCount()):

r = geom.GetGeometryRef(i)
x = [r.GetX(j) for j in range(r.GetPointCount())]
y = [r.GetY(j) for j in range(r.GetPointCount())]

codes += [mpath.Path.MOVETO] + (len(x)-1)*[mpath.Path.LINETO]
all_x += x
all_y += y
all_XY +=mymap(x,y)


if len(all_XY)==0:
all_XY=None
mypoly=None
else:
mypoly=np.empty((len(all_XY[:][0]),2))
mypoly[:,0]=all_XY[:][0]
mypoly[:,1]=all_XY[:][3]
else:
print "Will extract data for %s polygons"%(numberOfPolygons)
mypoly=None
first=False
return mypoly, first, numberOfPolygons


def openCMIP5file(CMIP5name,myvar,mymap):
if os.path.exists(CMIP5name):
myfile=Dataset(CMIP5name)
print "Opened CMIP5 file: %s"%(CMIP5name)
else:
print "Could not find CMIP5 input file %s : abort"%(CMIP5name)
sys.exit()
mydata=np.squeeze(myfile.variables[myvar][-1,:,:]) - 273.15
lonCMIP5=np.squeeze(myfile.variables["lon"][:])
latCMIP5=np.squeeze(myfile.variables["lat"][:])

lons,lats=np.meshgrid(lonCMIP5,latCMIP5)

lons=lons.flatten()
lats=lats.flatten()
mygrid=np.empty((len(lats),2))
mymapgrid=np.empty((len(lats),2))

for i in xrange(len(lats)):
mygrid[i,0]=lons[i]
mygrid[i,1]=lats[i]
X,Y=mymap(lons[i],lats[i])
mymapgrid[i,0]=X
mymapgrid[i,1]=Y

return mydata, mygrid, mymapgrid

def drawMap(NUM_COLORS):

ax = plt.subplot(111)
cm = plt.get_cmap('RdBu')
ax.set_color_cycle([cm(1.*j/NUM_COLORS) for j in range(NUM_COLORS)])
mymap = Basemap(resolution='l',projection='robin',lon_0=0)

mymap.drawcountries()

mymap.drawcoastlines()
mymap.fillcontinents(color='grey',lake_color='white')
mymap.drawparallels(np.arange(-90.,120.,30.))
mymap.drawmeridians(np.arange(0.,360.,60.))
mymap.drawmapboundary(fill_color='white')

return ax, mymap, cm

"""Edit the correct names below:"""

LMEcoordinatefile='ShapefileBoundaries/lmes_64.shp'
CMIP5file='tos_Omon_CCSM4_rcp85_r1i1p1_200601-210012_regrid.nc'

mydebug=False
doPoints=False
first=True


"""initialize the map:"""
mymap=None
mypolyXY, first, numberOfPolygons = getLMEpolygon(LMEcoordinatefile, mymap, 0,first)
NUM_COLORS=numberOfPolygons
ax, mymap, cm = drawMap(NUM_COLORS)


"""Get the CMIP5 data together with the grid"""
SST,mygrid, mymapgrid = openCMIP5file(CMIP5file,"tos",mymap)

"""For each LME of interest create a polygon of coordinates defining the boundaries"""
for counter in xrange(numberOfPolygons-1):

mypolyXY,first,numberOfPolygons = getLMEpolygon(LMEcoordinatefile, mymap,counter,first)

if mypolyXY != None:
"""Find the indices inside the grid that are within the polygon"""
insideBoolean = plt.mlab.inside_poly(np.c_[mymapgrid[:,0],mymapgrid[:,1]],np.c_[mypolyXY[:,0],mypolyXY[:,1]])
SST=SST.flatten()
SST=np.ma.masked_where(SST>50,SST)

mymapgrid=np.c_[mymapgrid[:,0],mymapgrid[:,1]]
myaverageSST=np.mean(SST[insideBoolean])

mycolor=cm(myaverageSST/SST.max())
scaled_z = (myaverageSST - SST.min()) / SST.ptp()
colors = plt.cm.coolwarm(scaled_z)

scatter([p[0] for p in mypolyXY],[p[1] for p in mypolyXY],2)

p = Polygon(mypolyXY,facecolor=colors,edgecolor='none')
ax.add_artist(p)

if doPoints is True:

for point in xrange(len(insideBoolean)):
pointX=mymapgrid[insideBoolean[point],0]
pointY=mymapgrid[insideBoolean[point],1]
ax.scatter(pointX,pointY,8,color=colors)
ax.hold(True)


if doPoints is True:
colorbar()
print "Extracted average values for %s LMEs"%(numberOfPolygons)
plt.savefig('LMEs.png',dpi=300)
plt.show()

附上最终图片。感谢所有帮助。

enter image description here干杯,特隆

最佳答案

只有一个点数组是不够的。您需要知道点的顺序。通常,多边形的点按顺序给出。所以你从第一点到第二点画一条线,然后从第二点到第三点等等。

如果您的列表没有按顺序排列,您需要额外的信息才能制作一个按顺序排列的列表。

shapefile(参见 documentation)包含一个形状列表,例如空形状、点、折线、多边形,其变体还包含 Z 和 M(测量)坐标。所以仅仅倾倒点数是不行的。您必须将它们分成不同的形状并渲染您感兴趣的形状。在这种情况下可能是 PolyLine 或 Polygon。有关这些形状的数据格式,请参见上面的链接。请记住,文件的某些部分是大端,而其他部分是小端。真是一团糟。

我建议使用 struct模块来解析二进制 .shp 文件,因为再次根据文档,单个多边形的点 是有序的,它们形成一个闭合链(最后一个点与第一个相同)。

您可以尝试使用当前坐标列表的另一件事是从一个点开始,然后在列表中进一步查找相同的点。这些相同点之间的一切都应该是一个多边形。这可能不是万无一失的,但看看它能让你走多远。

关于python - 从边界点创建闭合多边形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16326068/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com