How to parameterize a curved cylinder?

2019-08-02 21:56发布

问题:

I want to generate a curved cylinder. For example, with axis being a sine curve or a circle.

I can get a straight cylinder as follows

% Parameters
r=5; l=5; nTheta=100;

theta = 2*pi*(linspace(0,1,nTheta+1));
x = r * cos(theta);
x(end) = [];    % Last element is same as first. So, just remove it
y = r * sin(theta);
y(end) = [];
z = repmat((0:l-1)', 1, nTheta);

% Plot
surf(repmat(x,l,1),repmat(y,l,1),z); 

gives a cylinder and if the 9th line is changed to

z = (0:l-1)' * sin(linspace(-pi,pi,nTheta));

which I think should give me a cylinder with sine curve as axis. But, it gives me Now, I know that the parameterization is wrong. What would be the right parameterization to get a cylinder along a sine as axis?

回答1:

First, you should specify the orientation of the axis of the cylinder. For now, I'm going to assume it's pointed in the z-direction, and that it's going to oscillate only in the x-direction (i.e. The equation of the axis is x = sin(z) and y=0 ).

If the cylinder's axis changes with z, then the x,y coordinates of the cylinder's surface should also be functions of z. You can do this by first computing the x,y points for the straight cylinder like you have already done, and then adding a "shift" that depends on the local z value.

Here's the code:

% Parameters
r=5; l=5; nTheta=100, nL = 20;

theta = linspace(0,2*pi,nTheta+1);
x = r * cos(theta);
y = r * sin(theta);

z = linspace(0,l,nL)';
xshift = repmat( sin(z), 1, nTheta+1); %this is a function of z

X = repmat(x,nL,1) + xshift;
Y = repmat(y,nL,1);
Z = repmat(z, 1, nTheta+1);

% Plot
surf(X,Y,Z)

You will also need a yshift if the axis of the cylinder oscillates (or curves) in both x- and y-directions.



回答2:

Sorry, I don't have Matlab, but this is a Mathematica analogue. I think you can translate it

Instead of having an oblique cylinder as presented in the answer of Savithru, we can do the version that follows a given curve.

Essentially what you need is a set of circles which are all orthogonal to the curve f(x) which you try to follow. First, let us define a circle:

The circle:

Suppose a circle of radius R in a plane perpendicular to unit vector w=(w1,w2,w3) which goes through the point (X0,Y0,Z0). That plane is defined by two unit vectors u=(u1,u2,u3) and v=(v1,v2,v3) which are perpendicular to w. The parametric equation of the circle is than:

x = X0 + R cos(theta) u1 + R sin(theta) v1
y = Y0 + R cos(theta) u2 + R sin(theta) v2
z = Z0 + R cos(theta) u3 + R sin(theta) v3

where theta varies over the interval 0 to 2π.

So now that we defined the circle, let's define the tube.

The tube:

To define a surface, we need two parameters, the first is theta from the circle. The second will be x if we want to follow f(x). All we need to do is define the orthogonal vectors u and v. We know that they are orthogonal to the unit-vector w and this is nothing more then the tangent line of f(x) which is obtained with the first derivative. Thus you can define:

w = Normalize[{1,f'(x),0}]
u = Normalize[Cross[w,{0,0,1}]]
v = Cross[w,u]

So your parametric equation becomes:

x = x    + R cos(theta) u1(x) + R sin(theta) v1(x)
y = f(x) + R cos(theta) u2(x) + R sin(theta) v2(x)
z = 0    + R cos(theta) u3(x) + R sin(theta) v3(x)

In Mathematica this reads:

R=1
f[x_] := Sin[x]
w[x_] := Normalize[{1, f'[x], 0}]
u[x_] := Normalize[Cross[w[x], {0, 0, 1}]]
v[x_] := Cross[w[x], u[x]]
ParametricPlot3D[{x, f[x], 0} + R Cos[t] u[x] + R Sin[t] v[x], {x, 0, 2 Pi}, {t, 0, 2 Pi}]

note: you can easily extend this using the Frenet-Serret frame build from the Tangent, Normal and BiNormal vectors for a curve in 3D space f(r)