how to create a volume from the revolution of a variable area trapezoid

344 views (last 30 days)
I'm looking for the work flow of how to create a volume by revolving a variable area trapezoid around the z axis. I have a formula for the area of the trapezoid and it is a function of the radial distance from the origin. Both the height and this radial distance vary with the angle of revolution.
The figure immediately below shows the elliptical path that the rotation takes. Because the trapezoid area varies with the angle of revolution, the path traced in the x-y plane is an ellipse and not a circle. The figure below shows the path in the x-y plane:
This next figure shows the x-z plane which shows the variable-area trapezoid at phi = 0 degrees and phi = 180 degrees. The rotation occurs around the vertical axis that goes through the point "S". Notice the large reduction in area of the trapezoid.
The radial line length, p, to the ellipse edge is given by,
where θ is a constant value as are w and R. At θ = 45 degrees and R = 0.0006, w = 0.0007908.
NOTE: Figure 2 is not to scale with Fig. 1.
What I am trying to do is to verify an equation that I have developed for calculating this volume. I want to make sure that my equation, in fact, produces the volume of the revolved variable-area trapezoid. The area of the trapezoid is given by
and h is given by:
where B is a constant and is a constant where p is evaluated at ϕ = 90 degrees. For the values of θ, w and R given above, B = 0.867.
The volume then is given by,
The next figure shows an incremental volume diagram which is then integrated as in the equation immediately above,
And so the final result should look something like the blue portion of each drawing below. How would I go about implementing this in Matlab?
  35 Comments
Matt J
Matt J 22 minutes ago
Edited: Matt J 14 minutes ago
It looks like William Rose commented on this issue several days ago
You haven't provided a link to his comment, but you might be refering to this comment, describing that the top surface of your volume is not planar. An implication of this is that the central spine of your volume (at ) is in fact not the highest. For every fixed x, the points at the rim of your volume are higher than at the center.
That does indeed explain what you are seeing, but I still wanted to illustrate how, even when the top surface is planar, you can still see the concave envelope, depending on your display settings. In this first figure below, I plot the cutoff cylinder that I showed you how to generate using AxelRot. The top and bottom surfaces are planes perpendicular to the x-z plane, and therefore the central spine of the object really is maximally high in this case for any fixed x.
figure;
plotVolume();
view(-30,20)
Accordingly at view(0,0), the central trapezoid is snug against the blue envelope of the object, as long as the axes' Projection property is orthographic (the default).
figure;
plotVolume();
view(0,0)
However, if we switch to perspective projection, which is how peoples' eyes more naturally see the world, the central trapezoid will never be flush with the upper an lower envelopes of view(0,0), and you get the concave envelope. This is because the edge closer to the observer will always appear higher than the central spine.
figure;
plotVolume();
view(0,0)
set(gca,'Projection','perspective');
function plotVolume()
%Volume parameters (independent)
N=100; %discretize the perimeter into N points
diam=6; %tube diameter
ho=1;
hi=4;
xS=-2; %x-coordinate of S
%Volume parameters (derived)
dh=(hi-ho)/2;
angle=atand(dh/diam);
axMajor=hypot(diam,dh);
hS=ho+2*dh/diam*(xS+diam/2);
%Compute boundary vertices
t=linspace(0,360,N+1)'; t(end)=[];
V=0.5*[axMajor*cosd(t),diam*sind(t),0*t];
XYZ1=AxelRot( (V+[0,0,+ho/2])' ,+angle,[0,-1,0], [-diam/2,0,+ho/2])';
XYZ2=AxelRot( (V+[0,0,-ho/2])' ,-angle,[0,-1,0], [-diam/2,0,-ho/2])';
XYZ=[XYZ1;XYZ2];
%Display
trisurf(convhulln(XYZ), XYZ(:,1), XYZ(:,2), XYZ(:,3), ...
'FaceColor', 'cyan', 'EdgeColor', 'none','FaceAlpha',0.3);
axis equal; xlabel x; ylabel y; zlabel z
camlight
%Movie
i=1;
A=XYZ1(i,:);
B=XYZ2(i,:);
C=[xS,0,-hS/2];
D=[xS,0,+hS/2];
args=num2cell([A;B;C;D;A],1);
[x,y,z]=deal(args{:});
line(x,y,z,Color='r',LineWidth=2);
view(0,0)
camdolly(0,+30,0,'fixtarget','data');
end

Sign in to comment.

Accepted Answer

William Rose
William Rose on 17 Oct 2025 at 18:42
Edited: William Rose on 20 Oct 2025 at 18:35
{Edit 10/20/2025: Fix error in code below by changing a 1 to a 3. It was
[hst(1),pt(i,3),pb(i,3),hsb(3),hst(3)],'-r.')
and it should be, and now is
[hst(3),pt(i,3),pb(i,3),hsb(3),hst(3)],'-r.')
}
I like the elegant solution of @Matt J.
You indicate in your comments that you are also interested in solving the problem by explicit rotation of the trapezoid.
Here is code that that generates a wire frame view of the shape, by rotating the trapezoid.
N=40; % number of angular steps in one rotation
w=7.908e-4; R=6e-4; % constants in equation for p(t) [units=length]
B=0.867; % constant in equation for h(t): h(t)=B*p(t) [dimensionless]
dt=2*pi/N; % angle step size [radians]
t=[0:dt:2*pi]'; % angle of rotation (vector, length N+1) [radians]
% Compute p(t):
p=((w/2)*cos(t)+(R^2*(sin(t).^2+0.5*cos(t).^2)-(w^2/2)*sin(t).^2).^0.5)./(sin(t).^2+0.5*cos(t).^2);
h=B*p; % [length]
hs=B*sqrt(R^2-w^2/2);
% Compute arrays of 3D points
pt=[p.*cos(t),p.*sin(t),h/2]; % x,y,z coords of points along top of shape
pb=[p.*cos(t),p.*sin(t),-h/2]; % x,y,z coords of points along bottom of shape
hst=[0,0,hs/2]; hsb=[0,0,-hs/2]; % x,y,z coords of top, bottom central points
% Plot the trapezoid in 3D at various rotation angles
figure; hold on
for i=1:N
plot3([hst(1),pt(i,1),pb(i,1),hsb(1),hst(1)],...
[hst(2),pt(i,2),pb(i,2),hsb(2),hst(2)],...
[hst(3),pt(i,3),pb(i,3),hsb(3),hst(3)],'-r.')
end
plot3(pt(:,1),pt(:,2),pt(:,3),'-g') % curve connecting top points
plot3(pb(:,1),pb(:,2),pb(:,3),'-b') % curve connecting bottom points
xlabel('x'); ylabel('y'); zlabel('z');
hold off; axis equal; grid on; view(-45,25)
If you run the code locally, you will be able to rotate the 3D plot by clicking on the 3D rotate tool at top of the plot, then click and drag inside the plot.
Wrap a surface around the points, compute the volume, plot the surface:
pAll=[pt;pb;hst;hsb]; % all the 3D points
[k,v]=convhull(pAll); % wrap the points and compute volume
fprintf('Volume=%.3e\n',v)
Volume=1.323e-09
figure
trisurf(k,pAll(:,1),pAll(:,2),pAll(:,3),'FaceColor','c','EdgeColor','none')
axis equal; camlight
I am attaching a script which has the code above, with more comments and an additional plot.
  12 Comments
Sam Chak
Sam Chak on 21 Oct 2025 at 13:07
+1 👍 to you and @Matt J. Loved all three solutions as they are practical and well-explained. Initially, I was confused because I thought the OP wanted to estimate the air volume of a section of the circular ventilation duct with a 45° bend, rather than the elliptical duct.
William Rose
William Rose on 21 Oct 2025 at 13:44
@Sam Chak, nice photo! THank you! Your comme nt means a lot, considering how many nice solutions and explanations you have posted.

Sign in to comment.

More Answers (2)

Matt J
Matt J on 17 Oct 2025 at 8:39
Edited: Matt J on 17 Oct 2025 at 13:58
Along the lines of what @Mathieu NOE commented, I think it does make more sense to start with an elliptic cylinder and clip off the top and bottom with cutting planes. That will be much easier than approaching it as a solid of revolution:
%Volume parameters
N=1000;
ellipse=scale(nsidedpoly(N),[1.5,1]);
planeSlope=0.1;
planeHeight=0.2;
cylLength=0.5;
%Get the outside vertices
X=ellipse.Vertices(:,1);
Y=ellipse.Vertices(:,2);
Z=linspace(-cylLength,+cylLength,N);
[X,Z]=ndgrid(X,Z);
Y=repmat(Y,1,N);
keep=Z<=planeSlope*X+planeHeight & Z>=-planeSlope*X-planeHeight;
X=X(keep); Y=Y(keep); Z=Z(keep);
%Triangulate and compute volume
[K,volume]=convhulln([X,Y,Z]);
volume,
volume = 1.8849
%Display
trisurf(K, X, Y, Z, ...
'FaceColor', 'cyan', 'EdgeColor', 'none');
axis equal
camlight
view(-15,15)
  5 Comments
Matt J
Matt J on 17 Oct 2025 at 16:47
There are many videos explaing how a volume can be determined by revolving an area around an axis;
But when the area is changing with angle? That seems non-standard.
Matt J
Matt J on 17 Oct 2025 at 17:02
Edited: Matt J on 17 Oct 2025 at 17:03
To make the movie, you could use this File Exchange tool,
which computes the intersection of two triangulated surfaces. To triangulate your solid you would give inputs from my code,
TR = triangulation(K,X,Y,Z);
while the second triangulated surface would just be the cut plane you want for a particular frame of your movie. You would represent the plane as a sufficiently big rectangle (two triangles) passing through S.

Sign in to comment.


Matt J
Matt J on 17 Oct 2025 at 23:54
Edited: Matt J on 19 Oct 2025 at 16:04
Here's a little bit more of a polished version of my original answer, which also generates a movie of the trapezoidal cross-sections. You can adjust the VideoWriter properties to your liking.
This code requires the download of AxelRot,
%Volume parameters (independent)
N=100; %discretize the perimeter into N points
diam=8; %tube diameter
ho=1;
hi=4;
xS=-3; %x-coordinate of S
%Volume parameters (derived)
dh=(hi-ho)/2;
angle=atand(dh/diam);
axMajor=hypot(diam,dh);
hS=ho+2*dh/diam*(xS+diam/2);
%Compute boundary vertices
t=linspace(0,360,N+1)'; t(end)=[];
V=0.5*[axMajor*cosd(t),diam*sind(t),0*t];
XYZ1=AxelRot( (V+[0,0,+ho/2])' ,+angle,[0,-1,0], [-diam/2,0,+ho/2])';
XYZ2=AxelRot( (V+[0,0,-ho/2])' ,-angle,[0,-1,0], [-diam/2,0,-ho/2])';
XYZ=[XYZ1;XYZ2];
%Triangulate and compute volume
[K,volume]=convhulln(XYZ);
volume,
volume = 122.1617
%Display
trisurf(K, XYZ(:,1), XYZ(:,2), XYZ(:,3), ...
'FaceColor', 'cyan', 'EdgeColor', 'none','FaceAlpha',0.5);
axis equal; xlabel x; ylabel y; zlabel z
camlight
view(-30,20)
%Movie
shg
v=VideoWriter('trapezoidMovie.mp4','MPEG-4');
v.Quality=95;
v.FrameRate=30;
v.open;
for i=1:N
A=XYZ1(i,:);
B=XYZ2(i,:);
C=[xS,0,-hS/2];
D=[xS,0,+hS/2];
args=num2cell([A;B;C;D;A],1);
[x,y,z]=deal(args{:});
h=line(x,y,z,Color='r',LineWidth=2);
drawnow;
v.writeVideo(getframe(gcf));
if i<N, delete(h); end
end
v.close
  24 Comments
William Rose
William Rose on 20 Oct 2025 at 0:25
Edited: William Rose on 20 Oct 2025 at 0:27
[Edit: add .mpeg file made by the script]
This script makes a series of figures similar to the nice ones by @John D'Errico, but the surrounding volume is the convex hull around all the trapezoids, instead of being a cylinder with an elliptical cross section, sliced by two planes. I realize that this convex hull is not perfect, as discussed in an earlier comment. But this convex hull is exactly correct along the non-planar top and bottom edges, which you can see by rotating it to az=0, el=0. Screenshots from the .mpeg file during playback are shown, at the 8th and final frames.
William Rose
William Rose on 20 Oct 2025 at 1:51
Edited: William Rose on 20 Oct 2025 at 1:52
@Robert Demyanovich, you wrote:
"Are you now of the mind that your original equation for dV is correct? Or are you just using it as a point of reference."
I think my equation for dV is correct,
,
to the extent that each dV has the same length, p, on each long sides. This is a pretty good approximation, when the wedges are skinny. In my code, I use the length of the trailing edge of each wedge to calculate dV, all the way around. This means I overestimate the volume of each dV, for phi=0 to 180, because the leading edge is shorter than the trailing edge. But from phi=180 to 360, I underestimate the volume of each wedge, because the leading edge is longer than the trailing edge. The errors in my dVs from phi=0 to 180 pretty much cancel out the errors from 180 to 360, and that is why vol=sum(dV) does not change (at 4 significant digits), when I vary N from 40 wedges (9 deg each) to 720 (0.5 deg each).
If you need each dV to be more accurate, use p=mean(leading & trailing edge lengths) in the formula for each dV, instead of using p=trailing edge length.
For one wedge, comprised of 6 vertices, I expect the volume from convhull() will be very close to the volume from the formula, if we use the mean value of p. Check this with the following commands, after running rotateTrapezoid, with N=80:
wedge1verts=[hst;hsb;pt([1,2],:);pb([1,2],:)]; % array with 6 vertices of wedge 1
[~,wedge1vol]=convhull(wedge1verts); % wedge volume from convhull
p1=mean(p(1:2)); % mean p for wedge 1
dV1=(B*p1^3/3+hs*p1^2/6)*dt; % wedge volume from formula
fprintf('convhull volume=%.3e, formula volume=%.3e.\n',wedge1vol,dV1)
convhull volume=1.052e-10, formula volume=1.053e-10.
The two volume estimates are very close, as expected.

Sign in to comment.

Tags

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!