**凹**非网格数据的 matplotlib 轮廓/轮廓

thi*_*ngs 3 python plot matplotlib

我想要做一个matplotlibcontourcontourf非网格的三维数据(X,Y,Z),这是在x和y(见示意图)在某种程度上C形的曲线图-因此封闭船体的部分周围的数据是凹在 x 和 y 中。

通常我会通过首先插入它来绘制非网格 3D 数据

from matplotlib.mlab import griddata
griddata...
Run Code Online (Sandbox Code Playgroud)

但这会在数据的凹部产生伪影,使得凹部被插值填充。

是否可以进行插值或轮廓 / 轮廓图,以便尊重数据的凹入部分?

在此处输入图片说明

Imp*_*est 5

按条件屏蔽

下面是一个示例,说明如何使用tricontourf遮罩来获得没有数据外插值部分的凹面形状。它依赖于根据条件屏蔽数据的能力。

import matplotlib.pyplot as plt
import matplotlib.tri as tri
import numpy as np

# create some data
rawx = np.random.rand(500)
rawy = np.random.rand(len(rawx))
cond01 = (rawx-1)**2 + rawy**2 <=1
cond02 = (rawx-0.7)**2 + rawy**2 >0.3
x = rawx[cond01 & cond02]
y = rawy[cond01 & cond02]
f = lambda x,y: np.sin(x*4)+np.cos(y)
z = f(x,y)
# now, x,y are points within a partially concave shape

triang0 = tri.Triangulation(x, y)
triang = tri.Triangulation(x, y)
x2 = x[triang.triangles].mean(axis=1) 
y2 = y[triang.triangles].mean(axis=1)
#note the very obscure mean command, which, if not present causes an error.
#now we need some masking condition.
# this is easy in this case where we generated the data according to the same condition
cond1 = (x2-1)**2 + y2**2 <=1
cond2 = (x2-0.7)**2 + (y2)**2 >0.3
mask = np.where(cond1 & cond2,0,1)
# apply masking
triang.set_mask(mask)


fig, (ax, ax2) = plt.subplots(ncols=2, figsize=(6,3))
ax.set_aspect("equal")
ax2.set_aspect("equal")

ax.tricontourf(triang0, z,  cmap="Oranges")
ax.scatter(x,y, s=3, color="k")

ax2.tricontourf(triang, z,  cmap="Oranges")
ax2.scatter(x,y, s=3, color="k")

ax.set_title("tricontourf without mask")
ax2.set_title("tricontourf with mask")
ax.set_xlim(0,1)
ax.set_ylim(0,1)
ax2.set_xlim(0,1)
ax2.set_ylim(0,1)

plt.show()
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

最大边长遮蔽

如果您无法访问确切条件,但点之间有最大边长(距离),则以下将是一个解决方案。它会掩盖所有至少一侧比某个最大距离长的三角形。如果点密度相当高,这可以很好地应用。

import matplotlib.pyplot as plt
import matplotlib.tri as tri
import numpy as np

# create some data
rawx = np.random.rand(500)
rawy = np.random.rand(len(rawx))
cond01 = (rawx-1)**2 + rawy**2 <=1
cond02 = (rawx-0.7)**2 + rawy**2 >0.3
x = rawx[cond01 & cond02]
y = rawy[cond01 & cond02]
f = lambda x,y: np.sin(x*4)+np.cos(y)
z = f(x,y)
# now, x,y are points within a partially concave shape

triang1 = tri.Triangulation(x, y)
triang2 = tri.Triangulation(x, y)
triang3 = tri.Triangulation(x, y)

def apply_mask(triang, alpha=0.4):
    # Mask triangles with sidelength bigger some alpha
    triangles = triang.triangles
    # Mask off unwanted triangles.
    xtri = x[triangles] - np.roll(x[triangles], 1, axis=1)
    ytri = y[triangles] - np.roll(y[triangles], 1, axis=1)
    maxi = np.max(np.sqrt(xtri**2 + ytri**2), axis=1)
    # apply masking
    triang.set_mask(maxi > alpha)

apply_mask(triang2, alpha=0.1)
apply_mask(triang3, alpha=0.3)

fig, (ax1, ax2, ax3) = plt.subplots(ncols=3, figsize=(9,3))

ax1.tricontourf(triang1, z,  cmap="Oranges")
ax1.scatter(x,y, s=3, color="k")

ax2.tricontourf(triang2, z,  cmap="Oranges")
ax2.scatter(x,y, s=3, color="k")

ax3.tricontourf(triang3, z,  cmap="Oranges")
ax3.scatter(x,y, s=3, color="k")

ax1.set_title("tricontourf without mask")
ax2.set_title("with mask (alpha=0.1)")
ax3.set_title("with mask (alpha=0.3)")

for ax in (ax1, ax2, ax3):
    ax.set(xlim=(0,1), ylim=(0,1), aspect="equal")

plt.show()
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

可以看出,在alpha这里找到正确的参数 ( ) 可能需要一些调整。