1 回答
TA贡献1871条经验 获得超13个赞
一位matplotlib开发人员指出,重新采样是错误的。修复后,这是更正后的情节。
对于边上看到数据的坐标平面,例如本例中的 yz 平面,等高线看起来可能有点不稳定。这是意料之中的,因为数据可以接近多值。xz平面轮廓看起来也很粗糙。我怀疑这两个问题都可以通过单独三角化和轮廓化每个平面来改善,而不是像这里所做的那样偏爱 xy 平面。
下面是固定的测试脚本。唯一重要的更改是 和 。plot()resample()
import math
import sys
import matplotlib as mpl
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d
import numpy as np
import scipy.spatial
#np.random.seed(4)
numPts = 1000 # number of points in cloud
numGrid = 120 # number of points in meshgrid used in resample for contours
scatter = False # adds scatter plot to show point cloud
def main():
(pts, f) = mkData() # create the point cloud
tris = mkTris(pts) # triangulate it
plot(pts, tris, f) # plot it
def plot(pts, tris, f):
fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")
cmap = plt.get_cmap("coolwarm")
collec = ax.plot_trisurf(tris, pts[:, 2], cmap=cmap)
colors = np.mean(f[tris.triangles], axis=1)
collec.set_array(colors)
collec.autoscale()
(xr, yr, zr, fr, xMin, xMax, yMin, yMax, zMin, zMax) = resample(ax, tris,
pts, f)
ax.set_xlim(xMin, xMax) # default always includes zero for some reason
ax.set_ylim(yMin, yMax)
ax.set_zlim(zMin, zMax)
ax.contour(xr, yr, fr, 10, zdir="z", cmap=cmap, offset=zMin)
ax.contour(fr, yr, zr, 10, zdir="x", cmap=cmap, offset=xMin)
ax.contour(xr, fr, zr, 10, zdir="y", cmap=cmap, offset=yMax)
if scatter:
ax.scatter(pts[:, 0], pts[:, 1], pts[:, 2], alpha=0.1)
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_zlabel("z")
fig.colorbar(collec, shrink=0.5, aspect=5)
plt.show()
def mkData():
"""
Create a random point cloud near a random plane, and define a function on
the plane for colors and contours.
"""
offset = 1 # generate points near a unit square, xy-plane
pts = 2 * np.random.rand(numPts, 3) - 1
pts[:, 2] = offset * (2 * np.random.rand(numPts) - 1)
x = 2 * np.ravel(pts[:, 0])
y = 2 * np.ravel(pts[:, 1])
f = x * np.exp(-x**2 - y**2) # just some function for colors, contours
width = 100 # scale unit square to a larger rectangle
height = 20
pts[:, 0] *= width
pts[:, 1] *= height
(e1, e2, e3) =[2 * np.pi * np.random.rand() for _ in range(3)]
(c1, s1) = (math.cos(e1), math.sin(e1)) # rotate scaled rectangle
(c2, s2) = (math.cos(e2), math.sin(e2))
(c3, s3) = (math.cos(e3), math.sin(e3))
Ta2b = np.array(( # do not have scipy.spatial.transform
[ c1 *c2, s2, -s1 * c2],
[s1 * s3 - c1 * s2 * c3, c2 * c3, c1 *s3 + s1 * s2 * c3],
[s1 * c3 + c1 * s2 * s3, -c2 * s3, c1 *c3 - s1 * s2 * s3]))
pts = (Ta2b @ pts.T).T
dist = 500 # translate away from the origin
Ra2bNb = dist * (2 * np.random.rand(3, 1) - 1)
pts += Ra2bNb.T
return (pts, f)
def mkTris(pts):
"Triangulate the point cloud."
u = np.ravel(pts[:, 0])
v = np.ravel(pts[:, 1])
try:
return mpl.tri.Triangulation(u, v)
except (ValueError, RuntimeError) as ex:
sys.exit(f"Unable to compute triangulation: {ex}.")
def resample(ax, tris, pts, f):
"Resample the triangulation onto a regular grid for contours."
(xMin, xMax) = ax.get_xlim()
(yMin, yMax) = ax.get_ylim()
(zMin, zMax) = ax.get_zlim()
x = np.linspace(xMin, xMax, numGrid)
y = np.linspace(yMin, yMax, numGrid)
(xm, ym)=np.meshgrid(x, y)
fInterp = mpl.tri.CubicTriInterpolator(tris, f)
fm = fInterp(xm, ym)
zInterp = mpl.tri.CubicTriInterpolator(tris, pts[:,2])
zm = zInterp(xm, ym)
return (xm, ym, zm, fm, xMin, xMax, yMin, yMax, zMin, zMax)
if __name__ == "__main__":
main()
添加回答
举报