Python通过离散的点的数据由TIN构造等高线
作者:互联网
写在前面(重要)
这学期有一门课有关于lisp对CAD二次开发的,老师上课时候放话谁编出了等高线自动绘制程序期末成绩可以提档,当时我下课就去问老师“什么语言编都行吗?”老师很肯定的说:随便!。我一听乐了,这python调个matplotlib库中的函数画个等高线图这不是十分到手了吗?当老师把测试用的离散的点文件发过来的时候我就迫不及待去试了。
后来发现,还真不是简单用个库就完事了。
contour函数所需要的参数X,Y,Z,Z是关于(X,Y)的函数。网上的文章的实例操作都挺千篇一律的。就是先用numpy的linspace生成一个列表x,和一个列表y,然后把x,y网格化成X,Y,接下来很关键,网上的文章就会说为了方便,这里的Z就用f(X,Y)代替,把Z作为以(X,Y)为变量的函数值。这一听很有道理!但是……假设你是要五个点的(x,y)坐标,你网格化之后就会有25个点,你采用Z=f(X,Y)的方式,你网格化之后有多少个点,他都能根据函数弄一个点的Z出来。但是老师给的文本文件有两百多个点,点号,点的横纵坐标以及高程都给你安排得明明白白,所以当我按照网上的方法尝试的时候疯狂报错,最后放弃,开始老老实实想怎么用Lisp编出来。
但是,这学期上的地理信息系统这门课让我又有点想法了。老师在说到几何校正这个内容的时候说起重采样,重采样是可以根据已知的点得到未知点的信息,那我也可以对网格化后的x,y重采样。接下来是过程。
具体过程
首先是读取数据,让我们先打开老师发过来的有关于点的文本文件。
可以看到每一行数据,第一个是点号,第二第三个分别为X,Y坐标,第四个数据为高程。
f=open(r'C:\Users\58381\Desktop\等高线绘制数据.txt','r')
x=[]#创建三个列表用于存放点的数据
y=[]
h=[]
for line in f:
p=line[:-1]#去掉每行最后的换行符
a=p.split(',')#因为每行每个数据之间用","隔开,去掉逗号。
x.append(float(a[1]))
y.append(float(a[2]))
h.append(float(a[3]))
f.close()
然后就把根据x,y来做点表
import numpy as np
points=[]
for i in range(len(x)):
point=[]
point.append(x[i])
point.append(y[i])
points.append(point)
points=np.array(points)
再把这些点网格化
xi=np.linspace(min(x),max(x),300)
yi=np.linspace(min(y),max(y),300)
xi,yi=np.meshgrid(xi,yi)#网格化
接下来就是用这些点来重采样了,也就是函数内插。python的scipy.interpolate库里就有很多关于内插的函数,我们可以采用griddata这个函数。有关griddata,官方的文档是这样说的:
scipy.interpolate.griddata(points, values, xi, method=‘linear’, fill_value=nan, rescale=False)
可以看到参数第一个是points,可以理解为已知的数据点的坐标,第二个参数为值,这里是已知的点的高程,第三个为你要内插的点的坐标,也就是有着未知高程的点的坐标,第四个参数为方法。对于重采样,方法有最近邻元法,双线性内插法,和三次卷积的方法,对应的名称分别为"nearest",“linear”,“cubic”,对于不同的要求选择不同的方法,三次卷积运行速度最慢,但是对于平滑的曲线内插的效果最好。
from scipy.interpolate import griddata
zi=griddata(points,h,(xi,yi),method='cubic')
得到重采样后的值之后再画等高线即可。
import matplotlib.pyplot as plt
plt.contour(xi,yi,zi)
plt.savefig(r'C:\Users\58381\Desktop\1.pdf') #把得到的图保存为pdf的格式
效果如下
检验
大家都知道由TIN生成等高线的方法,先是构建delaunay三角形,然后再在三角形的边上内插等值点,然后追踪等值点画出等高线。下面我们就由已知点构建delaunay三角形。如图所示
(蓝色的点为已知点)可以看到TIN网构建出来了,然后再根据等高差得到内插的等值点(红色)
然后我们可以发现,之前生成的等高线几乎可以穿过红色的点。
由于是通过格网数据生成的等高线,数据精度会下降。才疏学浅,欢迎批评指正!
写在最后
其实这个方法生成格网的方式太过于粗暴,所以最后拟合出来的等高线并不完美。希望能有人告诉更好的方法,由TIN生成GRID的,感激不尽!
标签:采样,xi,Python,TIN,points,等高线,网格化,append 来源: https://blog.csdn.net/qq_44171096/article/details/94721002