6

Question

Description and sample

I would like to create a cylinder made up of various layers, then cut parts out from the front view such that the composition of the various layers is revealed.

enter image description here

Thought process

  1. Figure out how to create cylinders
  2. Change the circles/ellipses to arcs
  3. Draw the exposed surfaces as parallellograms
  4. Draw and connect two arcs per extra layer around the middle cylinder
  5. Draw more exposed surfaces

1. Figure out how to create cylinders

2. Change the circles/ellipses to arcs

I'm already stuck on this part, I found out how to draw elliptical arcs by modifying the answer to this question but I'm not sure how to connect both ends of the arc to the centre of the ellipse to create a fillable shape.

3. Draw the exposed surfaces as parallellograms

For a circle, it's easy to calculate the exact coordinates of an arc spanning some angle, but I'm not sure how I would do it for an ellipse. I was wondering if I could let TikZ do the work of finding the start and end coordinates of the elliptical arc. Once I got those points, I suppose it would be easy to use -- and cycle to trace out the exposed surfaces.

4. Draw and connect two arcs per extra layer around the middle cylinder

Similar problem to 2. but I'd have to loop over the starting points as well as the end points of both arcs.

5. Draw more exposed surfaces

Same as 3.

What I've tried so far

I've been browsing the TikZ manual but the awkward wording and unintuitive flow kind of threw me off. I've looked up some questions that seemed relevant and tried to re-use the code from their answers, but ultimately I'm just not familiar enough with the framework to get a good grasp of what I should be doing here.

Is there a newbie-friendly way to accomplish this? I think I've seen some 3D samples in the TikZ manual, but I'm not interested in a Z-axis. I'm trying to create a picture in the XY-plane with the Z-axis pointing straight out of the page, if that makes sense.

2
  • Nice question. If it's just to draw what you illustrated your post with, it's pretty straightforward. If it's meant to be automaticaly reading datas and draw multiple cylinders like this, it would be a bunch of work. – SebGlav May 3 at 17:33
  • Thanks for the quick response. No, I'm not looking to automate the drawing, I would like to have some control over the thickness of each extra layer around the central cylinder though (and the radius of the inner cylinder itself). – JansthcirlU May 3 at 17:42
4

I offer a solution which uses isometric axes and that takes advantage of the symmetry of the drawing. A couple of tikz styles and you have it.

\documentclass[border=2mm]{standalone}
\usepackage    {tikz}
\usetikzlibrary{3d}

\pgfmathsetmacro\ip{0.5*sqrt(3)} % isometric perspective factor
\tikzset%
{% styles
  base/.style ={draw=#1, fill=#1!20,thick},
  inner/.style={draw=#1, fill=#1!10,thick},
  outer/.style={draw=#1, left color=#1!50,right color=#1!20,thick},
}
\begin{document}
\begin{tikzpicture}[line cap=round,line join=round,%
                    x={({-\ip cm,-0.5 cm})},y={(\ip cm,-0.5 cm)},z={(0 cm,1 cm)}]
% dimensions
\def\r{2}   % inner cylinder radius
\def\h{3}   % inner cylinder height
\def\a{20}  % inner cylinder (semi)angle
\def\R{3}   % outer cylinder radius
\def\H{2.5} % outer cylinder height
\def\A{30}  % outer cylinder (semi)angle
% outer cylinder, top base
\draw[base=red,canvas is xy plane at z=\H] (0,0) circle (\R);
% inner cylinder
\draw[base=blue,canvas is xy plane at z=\h] (0,0) circle (\r);
\foreach\i in {-1,1}
{%
  \begin{scope}[x={(-\i*\ip cm, -0.5 cm)},y={(\i*\ip cm, -0.5 cm)}]
    \draw[inner=blue,rotate around z=45+\a,canvas is xz plane at y=0] (0,0) rectangle (\r,\h);
    \draw[outer=blue] (45+\a:\r)  arc (45+\a:45+\A:\r) --++ (0,0,\H) arc (45+\A:135:\r) --++
                      (0,0,\h-\H) arc (135:45+\a:\r) -- cycle;
  \end{scope}
}
% outer cylinder
\foreach\i in {-1,1}
{%
  \begin{scope}[x={(-\i*\ip cm, -0.5 cm)},y={(\i*\ip cm, -0.5 cm)}]
    \draw[inner=red,rotate around z=45+\A,canvas is xz plane at y=0] (\r,0) rectangle (\R,\H);
    \draw[outer=red] (45+\A:\R) arc (45+\A:135:\R) --++ (0,0,\H) arc (135:45+\A:\R) -- cycle;
    \draw[red,thick,line cap=butt,canvas is xy plane at z=\H] (45+\A:\r) arc (45+\A:135:\r);
  \end{scope}
}
\end{tikzpicture}
\end{document}

enter image description here Update: I added a cylinder an base \newcommands to make the code more customizable.

\documentclass[border=2mm]{standalone}
\usepackage    {tikz}
\usetikzlibrary{3d}

\pgfmathsetmacro\ip{0.5*sqrt(3)} % isometric perspective factor
\newcommand{\cylinder}[5] % inner radius, outer radius, height, (semi)angle, color
{%
  \foreach\i in {-1,1}
  {%
    \begin{scope}[x={(-\i*\ip cm, -0.5 cm)},y={(\i*\ip cm, -0.5 cm)}]
      \draw[thick,#5,fill=#5!20,rotate around z=45+#4,canvas is xz plane at y=0] (#1,0) rectangle (#2,#3);
      \draw[thick,#5,left color=#5!40,right color=#5!10] (45+#4:#2) arc (45+#4:135:#2) --++ (0,0,#3) arc (135:45+#4:#2) -- cycle;
      \draw[thick,#5,fill=#5!10,canvas is xy plane at z=#3] (135:#2) arc (135:45+#4:#2) -- (45+#4:#1) arc (45+#4:135:#1);
    \end{scope}
  }
}
\newcommand{\base}[4] % outer radius, height, (semi)angle, color
{%
  \draw[thick,#4,fill=#4!10,canvas is xy plane at z=#2] (0,0) -- (45+#3:#1) arc (45+#3:405-#3:#1);
}
\begin{document}
\begin{tikzpicture}[line cap=round,line join=round,%
                    x={({-\ip cm,-0.5 cm})},y={(\ip cm,-0.5 cm)},z={(0 cm,1 cm)}]
% bases higher to lower
\base{4}{1}{35}{gray}
\base{3}{2}{30}{blue}
\base{2}{3}{25}{red}
\base{1}{4}{20}{green}
% cylindric surfaces, inner to outer
\cylinder{0}{1}{4}{20}{green}
\cylinder{1}{2}{3}{25}{red}
\cylinder{2}{3}{2}{30}{blue}
\cylinder{3}{4}{1}{35}{gray}
\end{tikzpicture}
\end{document}

enter image description here

3
  • Thank you for your solution, this is really compact! But I'll ask the same question I asked user241266; how would I modify this code if I wanted to add more layers? – JansthcirlU May 4 at 7:10
  • 1
    @JansthcirlU, I just made an edit, I suppose this is what you need. – Juan Castaño May 4 at 7:42
  • 1
    This is exactly what I needed, thanks again! – JansthcirlU May 4 at 7:45
7

The outer radius is called R, the inner radius r, the outer opening angle alpha, the inner beta, the height of the outer shell h and the height of the inner cylinder H. You can then install some view, draw some arcs and lines, and use some clips.

\documentclass[tikz,border=3mm]{standalone}
\usepackage{tikz-3dplot}
\tdplotsetmaincoords{70}{0}
\begin{document}
\begin{tikzpicture}[tdplot_main_coords,line join=round,line cap=round,
    declare function={alpha=50;beta=30;R=4;r=3;h=3;H=4;}]
 \path (0,0,0) coordinate (O) (0,0,h) coordinate (h) (0,0,H) coordinate (H);
 \begin{scope}[canvas is xy plane at z=0]   
    \draw[fill=red!30,draw=red,shift={(h)}] 
     (-90+alpha/2:R) 
        arc[start angle=-90+alpha/2,end angle=270-alpha/2,radius=R] 
     -- (-90-alpha/2:r)
        arc[start angle=270-alpha/2,end angle=-90+alpha/2,radius=r] 
     -- cycle;
    \draw[fill=red!30,draw=red] 
     (-90+alpha/2:R) -- (-90+alpha/2:r) -- ++ (h) -- ++ (-90+alpha/2:R-r)
     -- cycle
     (-90-alpha/2:R) -- (-90-alpha/2:r) -- ++ (h) -- ++ (-90-alpha/2:R-r)
     -- cycle;
    \draw[fill,red,radius=R] (-90+alpha/2:R) arc[start angle=-90+alpha/2,end angle=0] 
     -- ++ (h) arc[start angle=0,end angle=-90+alpha/2] -- cycle
     (-90-alpha/2:R) arc[start angle=-90-alpha/2,end angle=-180] 
     -- ++ (h) arc[start angle=-180,end angle=-90-alpha/2] -- cycle;
    \clip[radius=r] (-90+alpha/2:r) -- ++ (h) 
        arc[start angle=-90+alpha/2,end angle=0] -- 
        ([yshift=\pgflinewidth]H-|r,0) 
        arc[start angle=0,end angle=180]-- 
        (h-|-r,0) 
        arc[start angle=180,end angle=270-alpha/2]
        -- (-90-alpha/2:r) arc[start angle=-90-alpha/2,end angle=-90+alpha/2];
    \draw[fill,blue,radius=r] (-90+beta/2:r) arc[start angle=-90+beta/2,end angle=0] 
     -- ++ (H) arc[start angle=0,end angle=-90+beta/2] -- cycle
     (-90-beta/2:r) arc[start angle=-90-beta/2,end angle=-180] 
     -- ++ (H) arc[start angle=-180,end angle=-90-beta/2] -- cycle;
    \draw[fill=blue!30,draw=blue] 
     (-90+beta/2:r) -- (0,0) -- ++ (H) -- ++ (-90+beta/2:r)
     -- cycle
     (-90-beta/2:r) -- (0,0) -- ++ (H) -- ++ (-90-beta/2:r)
     -- cycle;
    \draw[fill=blue!60,draw=blue,shift={(H)}] 
     (-90+beta/2:r) 
        arc[start angle=-90+beta/2,end angle=270-beta/2,radius=r] 
     -- (0,0) -- cycle;
 \end{scope}
\end{tikzpicture}
\end{document}

enter image description here

5
  • That's a lot to process, I'll wait with accepting answers in case other people have different strategies, but I'm gonna look into this for sure! – JansthcirlU May 3 at 18:47
  • 4
    +1 Pretty clean answer and drawing, even if not that straightforward. – SebGlav May 3 at 19:55
  • How would I modify this code if I wanted to add more layers? – JansthcirlU May 4 at 7:09
  • @JansthcirlU It is very easy but why would I put more efforts into this? – user241266 May 4 at 13:36
  • 2
    Why are you asking me? Edit as you see fit, I asked about the scalability because it was part of my question and that aspect isn't present in your solution. If you feel that you shouldn't edit your solution, then don't. – JansthcirlU May 4 at 14:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.