天天看点

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重采样。接下来是过程。

具体过程

首先是读取数据,让我们先打开老师发过来的有关于点的文本文件。

Python通过离散的点的数据由TIN构造等高线写在前面(重要)具体过程

可以看到每一行数据,第一个是点号,第二第三个分别为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的格式
           

效果如下

Python通过离散的点的数据由TIN构造等高线写在前面(重要)具体过程

检验

大家都知道由TIN生成等高线的方法,先是构建delaunay三角形,然后再在三角形的边上内插等值点,然后追踪等值点画出等高线。下面我们就由已知点构建delaunay三角形。如图所示

Python通过离散的点的数据由TIN构造等高线写在前面(重要)具体过程

(蓝色的点为已知点)可以看到TIN网构建出来了,然后再根据等高差得到内插的等值点(红色)

Python通过离散的点的数据由TIN构造等高线写在前面(重要)具体过程

然后我们可以发现,之前生成的等高线几乎可以穿过红色的点。

Python通过离散的点的数据由TIN构造等高线写在前面(重要)具体过程

由于是通过格网数据生成的等高线,数据精度会下降。才疏学浅,欢迎批评指正!

写在最后

其实这个方法生成格网的方式太过于粗暴,所以最后拟合出来的等高线并不完美。希望能有人告诉更好的方法,由TIN生成GRID的,感激不尽!