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?
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.
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)