Skip to main content
Source Link
Charles Staats
  • 19.7k
  • 6
  • 77
  • 133

Here is a picture intended to explain the disk method for computing the volume of a solid of revolution. I originally created it for my calculus class; I later redrew it to use as the central example in my still-unfinished Asymptote tutorial. Consequently, the code is fairly mature.

It is, of course, drawn using Asymptote.

The source code:

//Function to return a brace path
real innerangle = radians(60);
real outerangle = radians(70);
real midangle = radians(0);
path brace(pair a, pair b, real amplitude = .14*length(b-a)) {
  transform t = identity();
  real length = length(b-a);
  real sign = 1;
  if (amplitude < 0) {
    //    amplitude *= -1;
    sign = -1;
  }
  path brace = (0,0){expi(sign*outerangle)} :: {expi(sign*midangle)}(length/4, amplitude/2)
          :: {expi(sign*innerangle)} (length/2, amplitude) {expi(-sign*innerangle)}
  :: {expi(-sign*midangle)}(3*length/4, amplitude/2) :: {expi(-sign*outerangle)} (length,0);
  real angle = degrees(atan2((b-a).y, (b-a).x));
  t = rotate(angle)*t;
  t = shift(a) * t;
  return t * brace;
}

//Define the command drawshifted, to be used later
void drawshifted(path g, pair trueshift, picture pic = currentpicture, Label label="", pen pen=currentpen, arrowbar arrow=None, arrowbar bar=None, margin margin=NoMargin, marker marker=nomarker)
{
  picture opic;
  draw(opic, L=label, g, p=pen, arrow=arrow, bar=bar, margin=margin, marker=marker);
  
  pic.add(new void(frame f, transform t) {
      add(f,opic.fit(shift(trueshift)*t));
    });
  pic.addBox(min(opic), max(opic), trueshift, trueshift);
}

usepackage("amsmath");

real yellowPart = 0.2;
real unit = 2cm;
real truecm = cm / unit;
unitsize(unit);
pen backgroundpen = yellowPart*yellow + (1-yellowPart)*white;
frame finish() {
  currentlight.background = backgroundpen;
  frame toreturn = bbox(backgroundpen, Fill);
  currentpicture = new picture;
  unitsize(unit);
  return toreturn;
}

/*------------------------------*/

//Basic settings
settings.outformat="pdf";
defaultpen(fontsize(10pt));
import graph;

//Save some important numbers.
real xmin = -0.1;
real xmax = 2;
real ymin = -0.1;
real ymax = 2;

//Draw the graph and fill the area under it.
real f(real x) { return sqrt(x); }
path s = graph(f, 0, 2, operator..);
path fillregion = s -- (xmax,0) -- cycle;
pen fillpen = mediumgray;
fill(fillregion, fillpen);
draw(s, L=Label("$y=f(x)$", position=EndPoint));

//Fill the strip of width dx
real x = 1.4;
real dx = .05;
real t0 = times(s,x)[0];
real t1 = times(s,x+dx)[0];
path striptop = subpath(s,t0,t1);
filldraw((x,0) -- striptop -- (x+dx,0) --  cycle, black);

//Draw the bars labeling the width dx
real barheight = f(x+dx);
pair barshifty = (0, 0.2cm);
Label dxlabel = Label("$dx$", position=MidPoint, align=2N);
drawshifted((x,barheight) -- (x+dx, barheight), trueshift=barshifty, label=dxlabel, bar=Bars);

//Draw the arrows pointing inward toward the dx label
real myarrowlength = 0.3cm;
margin arrowmargin = DotMargin;
path leftarrow = shift(barshifty) * ((-myarrowlength, 0) -- (0,0));
path rightarrow = shift(barshifty) * ((myarrowlength, 0) -- (0,0));
draw((x, barheight), leftarrow, arrow=Arrow(), margin=arrowmargin);
draw((x+dx, barheight), rightarrow, arrow=Arrow(), margin=arrowmargin);

//Draw the bar labeling the height f(x)
real barx = x + dx;
pair barshiftx = (0.42cm, 0);
Label fxlabel = Label("$f(x)$", align=(0,0), position=MidPoint, filltype=Fill(fillpen));
drawshifted((barx,0) -- (barx, f(x)), trueshift=barshiftx, label=fxlabel, arrow=Arrows(), bar=Bars); 

//Draw the axes on top of everything that has gone before
arrowbar axisarrow = Arrow(TeXHead);
Label xlabel = Label("$x$", position=EndPoint);
draw((xmin,0) -- (xmax,0), arrow=axisarrow, L=xlabel);
Label ylabel = Label("$y$", position=EndPoint);
draw((0,ymin) -- (0,ymax), arrow = axisarrow, L=ylabel);

//Draw the tick mark on the x-axis
path tick = (0,0) -- (0,-0.15cm);
Label ticklabel = Label("$x$", position=EndPoint);
draw((x,0), tick, L=ticklabel);

frame pic2dFrame = finish();

/* ----------------------------------------------------- */

settings.prc = false;
settings.render=8;
import three;

currentprojection = orthographic(5,0,10, up=Y);
//currentprojection=oblique;
//currentprojection=perspective(6,0,10,up=Y);

pen color = white;
material surfacepen = material(diffusepen=color+opacity(1.0), emissivepen=0.2*color);
material planepen = material(diffusepen=opacity(0.6), emissivepen=0.8*color);
pen diskpen = black+opacity(1.0);

path3 p3 = path3(s);
draw(p3);

surface FilledRegion = surface(fillregion);
draw(FilledRegion, surfacepen = gray(0.6) + opacity(0.8));

surface solidsurface = surface(p3, c=O, axis=X);
draw(solidsurface, surfacepen=surfacepen);

/*
int n = length(p3);
for (real i = 0; i <= n; i += n/10) {
  if (i >= n) i -= .01;
  draw(solidsurface.vequals(i), gray(0.3));
}
*/
draw(solidsurface.vequals(length(p3) - .001), gray(0.3));

real extra = 0.4 truecm;
path planeboundary = (xmin,ymin) -- (xmax+extra,ymin) -- (xmax+extra,ymax+extra) -- (xmin,ymax+extra) -- cycle;
path planeoutside = planeboundary -- fillregion -- cycle;
draw(surface(planeoutside), surfacepen=planepen);

transform pushoutside = shift(0,.001);
striptop = pushoutside*striptop;
path3 dVtop = path3(striptop);
path3 openStrip = (x,0,0) -- dVtop -- (x+dx,0,0);
surface disk = surface(openStrip, c=O, axis=X);
draw(disk, diskpen);

triple cameraDirection(triple pt, projection P = currentprojection) {
  if (P.infinity) {
    return unit(P.camera);
  } else {
    return unit(P.camera - pt);
  }
}

triple towardCamera(triple pt, real dist = 1 truecm, projection P = currentprojection) {
  return pt + dist*cameraDirection(pt, P);
}

draw(xmin*X -- xmax*X, arrow=Arrow3(TeXHead2(normal=Z)));
draw(ymin*Y -- ymax*Y, arrow=Arrow3(TeXHead2(normal=Z)));
label("$x$", position=towardCamera(xmax*X), align = E);
label("$y$", position=towardCamera(ymax*Y), align=N);

frame pic3dFrame = finish();

/* ----------------------------------------------------------------- */

currentprojection=orthographic((3,0,10), up=Y);

diskpen = mediumgray;
draw(disk, diskpen);

transform3 T = rotate(10, X);
path3 brace = T*path3(brace((x+dx,barheight), (x+dx,0)));
draw(brace--cycle);
label("$r=f(x)$", position=midpoint(brace), align=E);

//Draw the bars labeling the width dx
path3 dxlabelpath = T * ((x, barheight, 0) -- (x+dx, barheight, 0));
draw(dxlabelpath, L=dxlabel, Bars3);

arrow(relpoint(dxlabelpath,0), dir=W, length=myarrowlength, margin=DotMargin3, arrow=Arrow3(emissive(black)));
arrow(relpoint(dxlabelpath,1), dir=E, length=myarrowlength, margin=DotMargin3, arrow=Arrow3(emissive(black)));

draw(xmin*X -- xmax*X, arrow=Arrow3(TeXHead2(normal=Z)));
draw(ymin*Y -- ymax*Y, arrow=Arrow3(TeXHead2(normal=Z)));
label("$x$", position=towardCamera(xmax*X), align = E);
label("$y$", position=towardCamera(ymax*Y), align=N);

frame oneSlice = finish();
/* ----------------------------------------------------------------- */

label(minipage("\raggedright Dimensions of infinitesimally thin sheet: 
\begin{description}
\item[Area:] $\pi r^2 = \pi [f(x)]^2$
\item[Thickness:] $dx$
\item[Volume:] $dV = \text{Area}\cdot\text{thickness} = \pi [f(x)]^2\;dx$
\end{description}"
,6cm));

frame labelFrame = finish();

/* ----------------------------------------------------------------- */

unit = 1;
unitsize(unit);
add(pic3dFrame);
add(labelFrame, position=(max(pic3dFrame).x, min(pic3dFrame).y - 1cm), align=SW);
pic3dFrame = finish();

/* ----------------------------------------------------------------- */

//unitsize(1);    // Set the usual (postscript) coordinates.
add(pic2dFrame);
add(pic3dFrame, position=max(pic2dFrame), align=SE);
add(oneSlice, position=min(pic2dFrame)+(0,-1cm), align=SE);

// Scale up by 4 in order to increase resolution.
shipout(scale(4)*finish());
Post Made Community Wiki by Charles Staats