如何用椭圆放样在MATLAB或Python中创建一个3d空心管?

时间:2017-03-16 02:11:28

标签: python matlab 3d

我有一系列的椭圆,知道它们的中心的尺寸和位置。我想绘制它们并通过它们中的每一个来创建一个3d管道。

在MATLAB中或在Python中的3D库中是否存在放样功能(如果是,哪个库)?另外,我想实时添加这些省略号,因此留在MATLAB中会更好。但是,如果有一个Python解决方案,我将如何实现它以在MATLAB和Python文件之间进行通信以维持实时链接。

我认为除了空洞之外它看起来像这样:

.

如果您能在MATLAB或Python中为此提供解决方案,那就太棒了。

2 个答案:

答案 0 :(得分:2)

对于那些对以上答案的Python实现感兴趣的人:

import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from scipy.interpolate import CubicSpline
from matplotlib import cm

#Create the profile
Radii = [1, 1.5, 1, 0.8, 1.3, 0.6, 0.5]
Zradii = [0, 1, 5, 10, 12, 14, 16]

radius = CubicSpline(Zradii, Radii, bc_type=((1, 0.5), (1, 0.0)))

# Make data
thetarange = np.linspace(0, 2 * np.pi, 100)
zrange = np.linspace(min(Zradii), max(Zradii),100)
X = [radius(z)*np.cos(thetarange) for z in zrange]
Y = [radius(z)*np.sin(thetarange) for z in zrange]
Z = np.array([[z] for z in zrange])

# Plot the surface
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.set_xlim3d(-2, 2)
ax.set_ylim3d(-2, 2)
ax.set_zlim3d(0, 20)
ax.plot_surface(X, Y, Z, cmap=cm.coolwarm)

#Plot the circles
for zz in Zradii:
    XX = radius(zz)*np.cos(thetarange)
    YY = radius(zz)*np.sin(thetarange)
    ax.plot(XX,YY,zz, lw=1, color='k')

plt.show();

Lofted circles

对于椭圆:

import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from scipy.interpolate import CubicSpline
from matplotlib import cm

#Create the profile
Zradii = [0, 1, 5, 10, 12, 14, 16]
ARadii = [1, 1.5, 1, 0.8, 1.3, 0.6, 0.5] #Major axis
BRadii = [0.5, 1, 1.2, 1, 0.5, 0.7, 0.5] # Minor Axis
XOFFSET = [1, 1, 1, 1, 2, 2, 2]    # X Offset of each ellipse
YOFFSET = [1, 1, 1, 1, 2, 2, 2]    # Y Offset of each ellipse

aradius = CubicSpline(Zradii, ARadii, bc_type=((1, 0.5), (1, 0.0)))
bradius = CubicSpline(Zradii, BRadii, bc_type=((1, 0.5), (1, 0.0)))
xoffset = CubicSpline(Zradii, XOFFSET)
yoffset = CubicSpline(Zradii, YOFFSET)

# Make data
npoints=100
thetarange = np.linspace(0, 2 * np.pi, npoints)
zrange = np.linspace(min(Zradii), max(Zradii), npoints)

X = [xoffset(z) + aradius(z)*np.cos(thetarange) for z in zrange]
Y = [yoffset(z) + bradius(z)*np.sin(thetarange) for z in zrange]
Z = np.array([[z] for z in zrange])

# Plot the surface
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.set_xlim3d(-2, 5)
ax.set_ylim3d(-2, 5)
ax.set_zlim3d(0, 20)
ax.plot_surface(X, Y, Z, cmap=cm.coolwarm)

#Plot the ellipses
for zz in Zradii:
    XX = xoffset(zz) + aradius(zz)*np.cos(thetarange)
    YY = yoffset(zz) + bradius(zz)*np.sin(thetarange)
    ax.plot(XX,YY,zz, lw=1, color='k')

plt.show();

Lofted ellipses

答案 1 :(得分:1)

您可以通过两个步骤完成此操作。

首先,通过将曲线拟合到所需的半径来创建所需的轮廓,如:

% Create the profile
Zradii = [0 1 5 10 12 14 16];
Rradii = [1 1.5 1 0.8 1.3 0.6 0.5];
pp = spline(Zradii,[0.5 Rradii 0]);

在这里,我在Zradii中给出的高度定义了环,并在Rradii中给出了相应的半径。

接下来,通过使用fsurf绘制该配置文件来创建放样曲面:

% Loft
r = @(u,v) ppval(pp,v);
funx = @(u,v) r(u,v).*cos(u);
funy = @(u,v) r(u,v).*sin(u);
funz = @(u,v) v;
fsurf(funx,funy,funz,[0 2*pi min(Zradii) max(Zradii)]) 
camlight
axis square;
view(70,10);

此示例的结果如下所示: picture of plot

<强>扩展

以前的方法可以扩展到其他任意形状。例如,我们使用等式从圆圈变为椭圆:

equation of ellipse

然后可以将之前的代码修改为如下所示:

%% Create the profile
Z = [0 1 5 10 12 14 16];
A = [1 1.5 1 0.8 1.3 0.6 0.5]; % Major Axis
B = [0.5 1 1.2 1 0.5 0.7 0.5]; % Minor Axis
X = [1 1 1 1 2 2 2];    % X Offset of each ellipse
Y = [1 1 1 1 2 2 2];    % Y Offset of each ellipse
ppA = spline(Z,[0.5 A 0]);
ppB = spline(Z,[0.5 B 0]);
ppX = spline(Z,X);
ppY = spline(Z,Y);

%% Loft
ellipse = @(t,a,b) a.*b./sqrt((a.*cos(t)).^2 + (b.*sin(t)).^2);
r = @(u,v) ellipse(u, ppval(ppA,v), ppval(ppB,v));
funx = @(u,v) r(u,v).*cos(u) + ppval(ppX,v);
funy = @(u,v) r(u,v).*sin(u) + ppval(ppY,v);
funz = @(u,v) v;
fsurf(funx,funy,funz,[0 2*pi min(Z) max(Z)],'linestyle','none') 
camlight
axis square;
view(80,5);

%% Add the ellipses in black
hold on
t=linspace(0,2*pi);
arrayfun(@(z)plot3(funx(t,z),funy(t,z),z*ones(size(t)),'k','Linewidth',2),Z)
hold off

生成下图,其中生成放样的椭圆以黑色显示:

loft with ellipses