微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

具有2D投影的3D线框图:空间组织和投影频率

如何解决具有2D投影的3D线框图:空间组织和投影频率

我正在处理由线框显示的3D图,其中2D图分别投影在x,y和z表面上。您可以在下面找到一个最小的示例。

我有2个问题:

  1. 使用contourf,每个x = 10,x = 20,...或y = 10,y = 20,...的二维图都显示在图墙上。是否有可能定义分别显示哪些x或y等高线图?例如,如果我只想将y = 0.5的xz轮廓图镜像到墙上?

添加:为了显示“ 2D图”的含义,我将代码中的“ contourf”更改为“ contour”,并将生成的图添加到此问题中。在这里,您现在可以看到不同y值的xz线,都偏移到y = 90。如果我不想拥有所有的行,但是只定义了其中的两个,该怎么办?

3D_plot_with_2D_contours

  1. 如在最小示例中所见,2D等高线图光学地覆盖了线框3D图。通过在alpha = 0.5的情况下增加透明度,我可以增加2D轮廓的透明度以至少看到线框,但这在光学上还是错误的。是否可以对对象正确排序?
import matplotlib.pyplot as plt,numpy as np
import pylab as pl

from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt,numpy as np

plt.clf()

fig = plt.figure(1,figsize=(35,17),dpi=600,facecolor='w',edgecolor='k')
fig.set_size_inches(10.5,8)
ax  = fig.gca(projection='3d')
X,Y,Z = axes3d.get_test_data(0.05)

Xnew = X + 50
Ynew = Y + 50

cset = ax.contourf(Xnew,Ynew,Z,zdir='z',offset=-100,cmap=plt.cm.coolwarm,alpha=0.5)
cset = ax.contourf(Xnew,zdir='x',offset=10,alpha=0.5) 
cset = ax.contourf(Xnew,zdir='y',offset=90,alpha = 0.5) 

ax.plot_wireframe(Xnew,rstride=5,cstride=5,color='black')

Z=Z-Z.min()
Z=Z/Z.max()

from scipy.ndimage.interpolation import zoom

Xall=zoom(Xnew,5)
Yall=zoom(Ynew,5)
Z=zoom(Z,5)

ax.set_xlim(10,90)
ax.set_ylim(10,90)
ax.set_zlim(-100,100)

ax.tick_params(axis='z',which='major',pad=10)

ax.set_xlabel('X',labelpad=10)
ax.set_ylabel('Y',labelpad=10)
ax.set_zlabel('Z',labelpad=17)


ax.view_init(elev=35.,azim=-70)

fig.tight_layout()

plt.show()

添加2:这是我正在使用的实际代码。但是,原始数据隐藏在csv文件中,这些文件太大而无法包含在最小示例中。这就是为什么最初将其替换为测试数据的原因。但是,也许实际的代码还是有帮助的。

from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt,numpy as np
import pylab as pl
from matplotlib.markers import MarkerStyle

import csv
with open("X.csv",'r') as f:
  X = list(csv.reader(f,delimiter=";"))
import numpy as np
X = np.array(X[1:],dtype=np.float)

import csv
with open("Z.csv",'r') as f:
  Z = list(csv.reader(f,delimiter=";"))
import numpy as np
Z = np.array(Z[1:],dtype=np.float)

Y = [[7,7.1,7.2,7.3,7.4,7.5,7.6,7.7,7.8,7.9,8,8.1,8.2,8.3,8.4,8.5,8.6,8.7,8.8,8.9,9]]

Xall = np.repeat(X[:],21,axis=1)
Yall = np.repeat(Y[:],30,axis=0)

from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt,numpy as np


plt.clf()

fig = plt.figure(1,8) 
ax  = fig.gca(projection='3d')

cset = ax.contourf(Xall,Yall,2,offset=0,shade = False,edgecolor='none',alpha=0.5)
cset = ax.contourf(Xall,offset=9,alpha=0.5)

ax.plot_wireframe(Xall,rstride=1,cstride=1,color='black')

Z=Z-Z.min()
Z=Z/Z.max()

from scipy.ndimage.interpolation import zoom

Xall=zoom(Xall,5)
Yall=zoom(Yall,5)

cset = ax.plot_surface(Xall,np.zeros_like(Z)-0,facecolors=plt.cm.coolwarm(Z),shade=False,alpha=0.5,linewidth=False)

ax.set_xlim(-0.5,31)
ax.set_ylim(6.9,9.1)
ax.set_zlim(0,500)

labelsx = [item.get_text() for item in ax.get_xticklabels()]
empty_string_labelsx = ['']*len(labelsx)
ax.set_xticklabels(empty_string_labelsx)

labelsy = [item.get_text() for item in ax.get_yticklabels()]
empty_string_labelsy = ['']*len(labelsy)
ax.set_yticklabels(empty_string_labelsy)

labelsz = [item.get_text() for item in ax.get_zticklabels()]
empty_string_labelsz = ['']*len(labelsz)
ax.set_zticklabels(empty_string_labelsz)

import matplotlib.ticker as ticker
ax.xaxis.set_major_locator(ticker.MultipleLocator(5))
ax.xaxis.set_minor_locator(ticker.MultipleLocator(1))
ax.yaxis.set_major_locator(ticker.MultipleLocator(0.5))
ax.yaxis.set_minor_locator(ticker.MultipleLocator(0.25))
ax.zaxis.set_major_locator(ticker.MultipleLocator(100))
ax.zaxis.set_minor_locator(ticker.MultipleLocator(50))

ax.tick_params(axis='z',labelpad=5,fontsize=15)
ax.set_ylabel('Y',fontsize=15)
ax.set_zlabel('Z',fontsize=15)


ax.view_init(elev=35.,azim=-70)

fig.tight_layout()

plt.show()

解决方法

(问题1的答案)要绘制表面与指定平面(y = -20,y = 20)之间的交点,需要找出Y [?] =-20和20。我发现Y [100] = 20,Y [20] =-20。

用于绘制相交线的相关代码:

# By inspection,Y[100]=20,Y[20]=-20
ax.plot3D(X[100],Y[100],Z[100],color='red',lw=6)  # line-1 at y=20
ax.plot3D(X[20],Y[20],Z[20],color='green',lw=6)   # line-2 at y=-20

# Project them on Z=-100 plane
ax.plot3D(X[100],-100,lw=3)  # projection of Line-1
ax.plot3D(X[20],lw=3)  # projection of Line-2

输出图:

y20-20

(问题2的答案)为了使线框在表面图中突出,可以得到更好的图。表面图必须是部分透明的,这可以通过设置选项alpha=0.6来实现。相关代码如下。

Z1 = Z-Z.min()
Z1 = Z1/Z.max()
Xall = zoom(X,3)
Yall = zoom(Y,3)
Zz = zoom(Z1,3)

surf = ax.plot_surface(Xall,Yall,Zz,rstride=10,cstride=10,facecolors = cm.jet(Zz/np.amax(Zz)),linewidth=0,antialiased=True,alpha= 0.6)

# Wireframe
ax.plot_wireframe(X,Y,Z,rstride=5,cstride=5,color='black',alpha=1,lw=0.8)

情节是:

combined

,

替代答案。

此代码演示

  1. 表面及其对应线框的图
  2. 在指定的x和y值下创建数据及其3d线图(在表面上悬于1处)
  3. 3d线(在2中)在框架墙上的投影
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
from scipy import interpolate
import numpy as np

# use the test data for plotting
fig = plt.figure(1,figsize=(6,6),facecolor='w',edgecolor='gray')
ax  = fig.gca(projection='3d')
X,Z = axes3d.get_test_data(0.1)  #get 3d data at appropriate density

# create an interpolating function
# can take a long time if data is too large
f1 = interpolate.interp2d(X,kind='linear')

# in general,one can use a set of other X,Z that cover a surface
# preferably,(X,Y) are in grid arrangement

# make up a new set of 3d data to plot
# ranges of x1,and y1 will be inside (X,Y) of the data obtained above
# related grid,x1g,y1g,z1g will be obtained from meshgrid and the interpolated function
x1 = np.linspace(-15,15,10)
y1 = np.linspace(-15,10)
x1g,y1g = np.meshgrid(x1,y1)
z1g = f1(x1,y1)  #dont use (x1g,y1g)

# prep data for 3d line on the surface (X,Z) at x=7.5
n = 12
x_pf = 7.5
x5 = x_pf*np.ones(n)
y5 = np.linspace(-15,n)
z5 = f1(x_pf,y5)
# x5,y5,z5 can be used to plot 3d line on the surface (X,Z)

# prep data for 3d line on the surface (X,Z) at y=6
y_pf = 6
x6 = np.linspace(-15,n)
y6 = x_pf*np.ones(n)
z6 = f1(x6,y_pf)
# x6,y6,z6 can be used to plot 3d line on the surface (X,Z)

ax  = fig.gca(projection='3d')

ax.plot_surface(x1g,z1g,alpha=0.25)
ax.plot_wireframe(x1g,rstride=2,cstride=2,zorder=10,lw=0.8)

# 3D lines that follow the surface
ax.plot(x5,z5.flatten(),lw=4)
ax.plot(x6,z6.flatten(),lw=4)

# projections of 3d curves
# project red and green lines to the walls
ax.plot(-15*np.ones(len(y5)),lw=4,linestyle=':',alpha=0.6)
ax.plot(x6,15*np.ones(len(x6)),alpha=0.6)

# projections on other sides (become vertical lines)
# change to if True,to plot these
if False:
    ax.plot(x5,15*np.ones(len(x5)),alpha=0.3)
    ax.plot(-15*np.ones(len(x6)),alpha=0.3)

ax.set_title("Projections of 3D lines")

# set limits
ax.set_xlim(-15,15.5)
ax.set_ylim(-15.5,15)

plt.show();

enter image description here

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。