I want to draw an image like this with asymptote, but I don't know how to draw the cylinder part like in this image.

enter image description here

I try with this code

triple v=O;
real cyl_r=2;
real cyl_h=3;
triple axis=Z;
axis = X;
revolution r = cylinder(v, cyl_r, cyl_h, axis);
r = shift(-0.5*cyl_h,-ho,lf)*r;
// draw(surface(r),green,render(merge=true));

But the result is not as I expected, the cylinder is not solid

enter image description here

I want the cylinder image same as the first image


1 Answer 1


Your code is not complete.

To have solid cylinders and silhouette you have to mix the 3D OpenGL (unitcylinder, unitsphere, etc...) and the solids package (to have silhouette of your cylinder). For the construction I have created one function which draws a cylinder (solid and silhouette) and another function (a simple loop) to avoid a very long list of triple and axis. The code is not perfect, there is one warning because I use the silhouette function.

import three;
import solids;

triple v=O;
real cyl_r=.4;
real cyl_h=.7;
triple axis=Z;

void cyl_oriented_shifted(triple pO=v, real r=cyl_r, real h=cyl_h, triple maxis=Z)
  // v should be the center
  // if maxis=O there is no cylinder, not very elegant
  if (maxis!=O)
      surface cylinder=shift(pO)*align(unit(maxis))*shift((0,0,-cyl_h/2))*scale(cyl_r,cyl_r,cyl_h)*unitcylinder;
      surface disq_cyl=shift(pO)*align(unit(maxis))*shift((0,0,-cyl_h/2))*scale(cyl_r,cyl_r,cyl_h)*unitdisk;
      surface disq_cyl1=shift(pO)*align(unit(maxis))*shift((0,0,cyl_h/2))*scale(cyl_r,cyl_r,0)*unitdisk;
      revolution rcyl = cylinder(pO-h/2*unit(maxis), r, h, maxis);
      material whitem =  material(diffusepen=white,emissivepen=white);

void sequence_of_node_and_segment (triple [] T, triple [] AT, pen p1=currentpen)
  // T is the array of node
  // AT the array of associated axis for the cylinders or not if AT[i]==O
  for (int i=0;i<T.length;++i)
      if (i<T.length-1)
        { // the segment

pen pentige=black+2bp;
// lower part
triple[] RL={(0,0,0),(0,0,1), (2,0,4),(0,0,8),(0,3,8),(2,3,4),(0,3,1),(0,3,0)};
triple[] ARL={O,Y,Y,Y,Y,Y,Y,O};

// arms
triple[] HRL={(0,-1.5,11), (0,-1.5,13.3),(0,-1.5,14),(0,0,14),(0,3,14),(0,4.5,14),(0,4.5,13.3),(0,4.5,11)};
triple[] AHRL={Y,X,O,Y,Y,O,X,Y};

// to the upper part
triple[] HC={(0,1.5,8), (0,1.5,10),(0,1.5,14),(0,1.5,15.6)};//,(0,0,13),(0,3,13),(0,4.5,13),(0,4.5,12),(0,4.5,10)};
triple[] AHC={O,Z,Z,Y};

revolution sph=sphere((0,1.5,8),.2);

and the result. Please notice that the picture is not vectorized since the true 3D OpenGL renderer is used.

enter image description here

  • Hi, @O.G. I have just test your code. I just paste your code to the webpage: asymptote.ualberta.ca, it looks like the generated image is not the same as the one in the answer. Half of the cylinder is not shown. I change the line to draw(cylinder,whitem); //,render(merge=true));, then it works OK. Here are two questions: 1, what dose the render argument in your code used for? 2, why there is a check of maxis!=O , what does the parameter maxis used for? Thanks.
    – ollydbg23
    Apr 21, 2022 at 6:55
  • I guess that the maxis is the direction of the axis of the cylinder. So, this vector should not be zero, am I correct?
    – ollydbg23
    Apr 21, 2022 at 7:02
  • @ollydbg23 : I proposed this code two years ago (and I have no answer). I have no idea about your question, only that the option merge is related to Bezier patches. Sorry. For maxis, you're right !
    – O.G.
    Apr 27, 2022 at 19:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .