使用最小插值绘制3D图形

5
我正在绘制一个三维散点图,从文件中读取数值。该文件的每一行都有三个坐标和一个标准偏差。暂时不考虑误差。
import os
import numpy as np
import matplotlib.pyplot as plt

input_file = os.path.normpath('C:/Users/sturaroa/Documents/my_file.tsv')

# read data from file
my_data = np.genfromtxt(input_file, delimiter='\t', skiprows=0)
X = my_data[:, 0]  # 1st column
Y = my_data[:, 1]  # 2nd column
Z = my_data[:, 2]  # 3rd column
errors = my_data[:, 3]  # 4th column (errors)

# draw 3D scatter graph
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.scatter(X, Y, Z)

我得到了这个 3d_scatter_plot 画廊中有一个很好的例子,可以绘制表面和等高线的投影(如下图所示)。 我需要尽可能少地处理我的数据,以避免失真,并获得类似的表示形式。

contourf3d_demo2

我知道这个问题,它解释了如何从不规则的3D数据中获得3D表面。然而,它“平滑”了曲线,并插值到一组常规点。我已经阅读了griddata文档,它返回一个二维浮点数组-在(xi, yi)点插值的值数组。这不是我想要的。有些人告诉我,我绝对需要插值才能找到表面。这可能是真的。也有人告诉我插值是不好的,因为它会强制形状。这也可能是真的(对于大量的“插值”)。如何使用最小的插值获得体面3D图形?是否有像链接最近的3D点之类的东西?顺便说一下,我的数据相当规则,就像它们被组织成一组2D平面或“切片”,但我想知道如果没有做出这种假设是否可能。
这是一个示例文件,与散点图使用的相同。它简单而规则,如果可能的话,建议在更一般的文件上进行测试。
2    1    2.0    0.0
2    2    82.666664    35.30187
2    3    100.0    0.0
2    4    98.0    4.472136
2    7    100.0    0.0
2    12    100.0    0.0
2    15    100.0    0.0
2    17    100.0    0.0
2    21    100.0    0.0
2    24    100.0    0.0
3    1    2.0    0.0
3    2    4.0    0.0
3    3    6.0    0.0
3    4    8.181818    0.60302263
3    7    15.090909    1.8683975
3    12    53.454544    33.6344
3    15    97.09091    3.9358494
3    17    97.09091    3.9358494
3    21    97.09091    3.3898242
3    24    97.09091    3.5058389
4    1    2.0    0.0
4    2    4.0    0.0
4    3    6.0    0.0
4    4    8.0    0.0
4    7    14.0    0.0
4    12    24.0    0.0
4    15    30.333334    0.74535596
4    17    37.666668    2.1343749
4    21    48.0    5.1639776
4    24    92.0    11.075499

更长的示例输入。前两列应该是int类型,后两列是float类型。

这里是一个改进的加载方式,以防万一。

# tell numpy the first 2 columns are int and the last 2 are floats
my_data = np.genfromtxt(infile, dtype=[('a', '<i8'), ('b', '<i8'), ('x', '<f8'), ('d', '<f8')])

# access columns by name
print(my_data["b"]) # column 1

我认为你想做的是在相邻的三个点之间将表面作为三角形放置。这有意义吗?我相信你一定能找到一个能做到这件事的函数。 - Konstantin Schubert
三角形也可以,四边形也可以。我对matplotlib不是很熟练,需要一些代码帮助。 - Agostino
通常情况下,你不能在三维空间中通过四个点画出一个平面。这意味着四边形必须弯曲才能存在。(我的下面的答案图中没有四边形,因为它们沿着一条对角线弯曲了。) - Konstantin Schubert
如果三角形更适合,那也没关系。有趣的部分是如何找到那些具有最小偏差的三角形。 - Agostino
2个回答

1
您想要绘制一个表面,该表面正好通过所有数据点,并且可以“直接”完成而不会平滑处理。
我最近使用matplotlib创建了这个图: enter image description here 我不想声称它具有最小的“平滑度”,但至少它确切地通过所有数据点。
我使用了matplotlib中的plot_surface函数。您也可以使用plot_wireframe
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(xGrid, yGrid, zGrid, rstride=1, cstride=1,cmap="autumn")

我认为诀窍的一部分是设置 rstride=1cstride=1。您可能需要验证这一点。有更深入见解的人可能能够更好地解释这一点,在文档中只是说步幅是采样长度。

在我的情况下,它绘制了一个空的图。我没有网格,我有一组三维点。如果需要,我可以发布一个示例文件。 - Agostino
有什么新消息吗?您提供的代码使用了网格。请解释一下您是如何创建这些网格的,以及它们是否真正具有最小插值。 - Agostino
x网格是一个二维数组,包含了x-y平面上所有点的x值。y网格则包含了x-y平面上所有点的y值。z网格则包含了x-y平面上所有点的z值。如何将您的数据转换为这种格式是一个简单的问题,也许需要一些搜索和试错。我可以为您完成,或者您可以自己完成,抱歉。或者提出另一个问题。至于插值是否“最小”,我无法回答,部分原因是问题没有明确定义,部分原因是我不知道。 - Konstantin Schubert
我会很感激如果您能展示如何将我的示例输入转换成那些格子。这对我来说非常重要。我也添加了一个更长的示例输入,如果可以帮助到您的话。 - Agostino

0

这是一篇旧帖子,但我认为可以使用matplotlib三角剖分支持来完成。请参见问题中的mkTris()函数,尽管它是关于不同主题的。最终的曲面图将三角形顶点放置在原始的、不规则间隔的样本上。其余的绘制曲面位于三角形面上。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接