1

The code below makes a bank of cylinders (acceptable). I am trying to make two more banks of cylinders at right angles to this. The second is in a parallel plane such that looking normal through both there are empty square apertures. The third is a bank with cylinders normal to the plane which penetrate the square apertures.

I have tried a variety of rotations and can't seem to master the transforms needed.

The goal is to create a mesh which can be parameterized such that the cylinders are thin and don't get close to touching in one expression, or the cylinders are thick and overlap in another.

One way to think about this is the arrangement of subway tubes in New York City where they must pass without touching, including the elevator shafts going down to the platforms.

MWE

\documentclass[12pt]{article}

\usepackage{tikz}

\usetikzlibrary{backgrounds,shapes}

\listfiles
\begin{document}

\newcommand\Cylinder[3]{%
    \begin{scope}
        \tikzset{every node/.style={
            cylinder,
            rotate=#3,
            draw,
            cylinder uses custom fill,
            cylinder end fill=white!25!black,
            cylinder body fill=white!60!black,
            minimum height=10cm,
            minimum width=0.1cm,
            opacity=.4}}
        \node at (#1,#2) {};
    \end{scope}
}
    \begin{tikzpicture}
    [background rectangle/.style={fill=yellow!45!white},
    show background rectangle]
    \foreach \y in {0,1,2,3,4,5,6,7,8,9}{
        \Cylinder{0}{\y}{0}
    }
\end{tikzpicture}

\end{document}

Thank you S.c.!!!!!! After guidance by S.c. Here is a MWE doing almost exactly what I wanted.

\documentclass[12pt]{article}

\usepackage{tikz}
\usepackage{tikz-3dplot}

\usetikzlibrary{backgrounds,shapes}

\tikzset{pics/simple 3d cylinder/.style={code={ 
\tikzset{simple 3d cylinder/.cd,#1}
\def\pv##1{\pgfkeysvalueof{/tikz/simple 3d cylinder/##1}}%
\tdplotsetrotatedcoords{\pv{alpha}}{\pv{beta}}{0}
\begin{scope}[tdplot_rotated_coords]
    \draw[simple 3d cylinder/mantle,line width=2*\pv{r}*1cm]
        (0,0,-\pv{h}/2) -- (0,0,\pv{h}/2);
    \pgfmathtruncatemacro{\itest}{sign(
    sin(\tdplotmaintheta)*sin(\tdplotmainphi)*cos(\pv{alpha})*sin(\pv{beta})
 -1*sin(\tdplotmaintheta)*cos(\tdplotmainphi)*sin(\pv{alpha})*sin(\pv{beta})
   +cos(\tdplotmaintheta)*cos(\pv{beta})
    )}
 \unless\ifnum\itest=0
 \path[fill,simple 3d cylinder/mantle]
    plot[variable=\t,domain=0:360,smooth cycle]
        ({\pv{r}*cos(\t)},{\pv{r}*sin(\t)},{-\itest*\pv{h}/2});
 \path[fill,simple 3d cylinder/top]
    plot[variable=\t,domain=0:360,smooth cycle]
        ({\pv{r}*cos(\t)},{\pv{r}*sin(\t)},{\itest*\pv{h}/2});
 \fi
\end{scope}
}},
    simple 3d cylinder/.cd,
    r/.initial=0.1,
    h/.initial=10,
    alpha/.initial=0,
    beta/.initial=0,
    top/.style={fill=gray},
    mantle/.style={black}
}

\listfiles
\begin{document}

% TODO build chopstick mesh up from the bottom to satisfy hiddenness
\tdplotsetmaincoords{70}{126}

\noindent
\begin{tikzpicture}[tdplot_main_coords,scale=0.95]
    % actin vertical
    \path foreach \X in {0,...,10} {
        (-0.5,\X-0.5,-5)
            pic{
                simple 3d cylinder=
                {mantle/.style={blue},h=12}
            }
    };
    % actin horizontal
    \path foreach \X in {0,...,10} {
        (0,4.5,-\X)
            pic{
                simple 3d cylinder=
                {mantle/.style={red},h=12,alpha=90,beta=90}
            }
    };
    % Calcium crosslink
    \foreach \Z in {0,...,10} { \foreach \Y in {0,...,10} {
        \shade [ball color=gray] (-0.2,\Y-0.3,-\Z-0.1)
            circle [radius=0.2cm]; % 0.2 some, 0.7 complete
    }}
    % neurofibril
    \path foreach \X in {1,...,10} {
        (3.5,-0.5,-\X)
            pic{
                simple 3d cylinder=
                {h=9.2,beta=90}
            }
    };
\end{tikzpicture}

\noindent\rule{\textwidth}{1pt}

\end{document}
jlettvin
  • 317
  • It is a bit hard for me to interpret your description. However, you may want to look at https://tex.stackexchange.com/a/517748, where the projections of such cylinders are discussed. –  Jan 15 '20 at 17:49
  • Your recommendation is excellent, but still outside my grasp. Think of a whole lot of chopsticks in your hand. Lay a bunch of them down on a table in parallel with spaces about the same width. Now lay another bunch down across the first in the same way. This can be one time, or stack after stack of crossed chopsticks. Now insert a bunch more chopsticks vertically down the holes between the layers. That is actually a MUCH better description than I gave before. TNX 4 asking. – jlettvin Jan 15 '20 at 18:17

1 Answers1

5

Here is a fully rotatable version of a "simple" cylinder, where "simple" means that we cheat a bit and just draw a thick line and make sure that the ends are fine. We do no have the contour in this version (yet contours can be found here). Yet these cylinders are fully rotatable. The rotation angles are alpha and beta. (Obviously we need only two rotation angles since the cylinder has a rotational symmetry about its axis.) However, this answer does not (yet) have any 3d ordering. It is (probably) possible to order the cylinders on the basis of their center-of-mass coordinates. I do not think that TikZ is the right tool to go beyond that.

\documentclass[tikz,border=3mm]{standalone}
\usepackage{tikz-3dplot}
\tikzset{pics/simple 3d cylinder/.style={code={ 
 \tikzset{simple 3d cylinder/.cd,#1}
 \def\pv##1{\pgfkeysvalueof{/tikz/simple 3d cylinder/##1}}%
 \tdplotsetrotatedcoords{\pv{alpha}}{\pv{beta}}{0}
 \begin{scope}[tdplot_rotated_coords]
 \draw[simple 3d cylinder/mantle,line width=2*\pv{r}*1cm] (0,0,-\pv{h}/2) --
 (0,0,\pv{h}/2);
 \pgfmathtruncatemacro{\itest}{sign(
    sin(\tdplotmaintheta)*sin(\tdplotmainphi)*cos(\pv{alpha})*sin(\pv{beta})
    -1*sin(\tdplotmaintheta)*cos(\tdplotmainphi)*sin(\pv{alpha})*sin(\pv{beta})
    +cos(\tdplotmaintheta)*cos(\pv{beta})
    )}
 \unless\ifnum\itest=0
    \path[fill,simple 3d cylinder/mantle] plot[variable=\t,domain=0:360,smooth cycle]
    ({\pv{r}*cos(\t)},{\pv{r}*sin(\t)},{-\itest*\pv{h}/2}) ;
    \path[fill,simple 3d cylinder/top] plot[variable=\t,domain=0:360,smooth cycle]
    ({\pv{r}*cos(\t)},{\pv{r}*sin(\t)},{\itest*\pv{h}/2});
 \fi
 \end{scope}
}},simple 3d cylinder/.cd,r/.initial=0.2,h/.initial=2,
    alpha/.initial=0,beta/.initial=0,
    top/.style={fill=gray},mantle/.style={blue}}
\begin{document}
\tdplotsetmaincoords{70}{110}
\begin{tikzpicture}[tdplot_main_coords]
 \path foreach \X in {1,...,10}
 {(0,4,-\X) pic{simple 3d cylinder={alpha=90,beta=90,h=6,mantle/.style={red}}}
 (4,0,-\X) pic{simple 3d cylinder={alpha=0,beta=90,h=6}}
 (\X,\X,3) pic{simple 3d cylinder={alpha=0,beta=0,h=6,mantle/.style={orange}}}
 };
\end{tikzpicture}
\end{document}

enter image description here

You can do 3d ordering by hand, e.g. by drawing a grid layer by layer.

\documentclass[tikz,border=3mm]{standalone}
\usepackage{tikz-3dplot}
\tikzset{pics/simple 3d cylinder/.style={code={ 
 \tikzset{simple 3d cylinder/.cd,#1}
 \def\pv##1{\pgfkeysvalueof{/tikz/simple 3d cylinder/##1}}%
 \tdplotsetrotatedcoords{\pv{alpha}}{\pv{beta}}{0}
 \begin{scope}[tdplot_rotated_coords]
 \draw[simple 3d cylinder/mantle,line width=2*\pv{r}*1cm] (0,0,-\pv{h}/2) --
 (0,0,\pv{h}/2);
 \pgfmathtruncatemacro{\itest}{sign(
    sin(\tdplotmaintheta)*sin(\tdplotmainphi)*cos(\pv{alpha})*sin(\pv{beta})
    -1*sin(\tdplotmaintheta)*cos(\tdplotmainphi)*sin(\pv{alpha})*sin(\pv{beta})
    +cos(\tdplotmaintheta)*cos(\pv{beta})
    )}
 \unless\ifnum\itest=0
    \path[fill,simple 3d cylinder/mantle] plot[variable=\t,domain=0:360,smooth cycle]
    ({\pv{r}*cos(\t)},{\pv{r}*sin(\t)},{-\itest*\pv{h}/2}) ;
    \path[fill,simple 3d cylinder/top] plot[variable=\t,domain=0:360,smooth cycle]
    ({\pv{r}*cos(\t)},{\pv{r}*sin(\t)},{\itest*\pv{h}/2});
 \fi
 \end{scope}
}},simple 3d cylinder/.cd,r/.initial=0.15,h/.initial=12,
    alpha/.initial=0,beta/.initial=0,
    top/.style={fill=gray},mantle/.style={blue}}
\begin{document}
\tdplotsetmaincoords{70}{120}
\begin{tikzpicture}[tdplot_main_coords]
 \foreach \X in {1,...,5}
 {\path foreach \Z in {1,...,5}
 {(-1+2*\X-6,0,2*\Z-6) 
    pic{simple 3d cylinder={alpha=90,beta=90,mantle/.style={red}}}
 };
 \path foreach \Y in {1,...,5}
  { foreach \Z in {1,...,5}
   {(2*\X-5,2*\Y-7,2*\Z-5)
    pic{simple 3d cylinder={alpha=0,beta=90,h=2,mantle/.style={blue}}}
    }
  (2*\X-6,2*\Y-6,0) 
    pic{simple 3d cylinder={alpha=0,beta=0,mantle/.style={orange}}} 
 };}
\end{tikzpicture}
\end{document}

enter image description here

The following animation is meant to illustrate what "layer by layer" means.

\documentclass[tikz,border=3mm]{standalone}
\usepackage{tikz-3dplot}
\tikzset{pics/simple 3d cylinder/.style={code={ 
 \tikzset{simple 3d cylinder/.cd,#1}
 \def\pv##1{\pgfkeysvalueof{/tikz/simple 3d cylinder/##1}}%
 \tdplotsetrotatedcoords{\pv{alpha}}{\pv{beta}}{0}
 \begin{scope}[tdplot_rotated_coords]
 \draw[simple 3d cylinder/mantle,line width=2*\pv{r}*1cm] (0,0,-\pv{h}/2) --
 (0,0,\pv{h}/2);
 \pgfmathtruncatemacro{\itest}{sign(
    sin(\tdplotmaintheta)*sin(\tdplotmainphi)*cos(\pv{alpha})*sin(\pv{beta})
    -1*sin(\tdplotmaintheta)*cos(\tdplotmainphi)*sin(\pv{alpha})*sin(\pv{beta})
    +cos(\tdplotmaintheta)*cos(\pv{beta})
    )}
 \unless\ifnum\itest=0
    \path[fill,simple 3d cylinder/mantle] plot[variable=\t,domain=0:360,smooth cycle]
    ({\pv{r}*cos(\t)},{\pv{r}*sin(\t)},{-\itest*\pv{h}/2}) ;
    \path[fill,simple 3d cylinder/top] plot[variable=\t,domain=0:360,smooth cycle]
    ({\pv{r}*cos(\t)},{\pv{r}*sin(\t)},{\itest*\pv{h}/2});
 \fi
 \end{scope}
}},simple 3d cylinder/.cd,r/.initial=0.15,h/.initial=12,
    alpha/.initial=0,beta/.initial=0,
    top/.style={fill=gray},mantle/.style={blue}}
\begin{document}
\tdplotsetmaincoords{70}{120}
\foreach \Step in {1,...,15}
{\begin{tikzpicture}[tdplot_main_coords]
\path[tdplot_screen_coords,use as bounding box] (-8,-8) rectangle (8,8);
 \foreach \X in {1,...,5}
 {\path foreach \Z in {1,...,5}
 {(-1+2*\X-6,0,2*\Z-6) \ifnum\numexpr3*\X-3<\Step
    pic{simple 3d cylinder={alpha=90,beta=90,mantle/.style={red}}}
    \fi
 };
 \path foreach \Y in {1,...,5}
  { foreach \Z in {1,...,5}
   {(2*\X-5,2*\Y-7,2*\Z-5) \ifnum\numexpr3*\X-1<\Step
    pic{simple 3d cylinder={alpha=0,beta=90,h=2,mantle/.style={blue}}}
    \fi
    }
  (2*\X-6,2*\Y-6,0) \ifnum\numexpr3*\X-2<\Step
    pic{simple 3d cylinder={alpha=0,beta=0,mantle/.style={orange}}} 
    \fi
 };}
\end{tikzpicture}}
\end{document}

enter image description here

Obviously, for (very) different view angles one needs to change the layers.

  • Beautiful! You have my idea exactly. I will play with this too so I can be ready to understand what else you planned to show. TNX – jlettvin Jan 15 '20 at 18:20
  • BTW, is there any way to have things in back hidden by things in front? This is a common operation in displays of 3D objects in gaming and scientific graphics. – jlettvin Jan 15 '20 at 18:36
  • @jlettvin No, TikZ has no built-in 3d engine. You'd have to write your own algorithm. I have started to develop something that works in simple cases. asymptote has this built in (for pixel graphics), and pgfplots also has means to order objects (but to the best of my knowledge it does not have cylinder plot marks as of now). –  Jan 15 '20 at 18:52
  • Asymptote will take some work to install well on my linux. I do not know if it will help yet.

    Meanwhile, where you have alpha, I am trying to play around with beta to allow the second orthogonal rotation.

    – jlettvin Jan 15 '20 at 19:38
  • It is rather easy to generalize the above, all you need is the projection of the cylinder axis on the normal of the screen. I am just not at the machine where I have all the stuff, and am busy, but will try to complete this later. –  Jan 15 '20 at 19:42
  • Thank you. I have gotten further towards my goals as a result of your help. Still a ways to go. – jlettvin Jan 15 '20 at 20:45
  • @jlettvin I added a fully rotatable version. –  Jan 16 '20 at 01:03
  • Thank you S.c. I have what you wrote operational. It is now my turn to massage it into the form I need. I have marked your answer as accepted. Now I will play with things until I can make my chopstick meshes illustrate an idea for a scientific paper I hope to publish. – jlettvin Jan 16 '20 at 03:54
  • Beautiful. Just plain perfect! Thank you. I learned a lot reviewing your code. – jlettvin Jan 16 '20 at 13:55
  • @jlettvin You're welcome! I cleaned up a bit to make it more accessible. The code on the top got removed as the cylinder there was less versatile. –  Jan 16 '20 at 16:46
  • I notice that pdflatex really GRINDS to make those images. I was thinking of adding floating spheres to what you've done. It really is going to work out for one paper I am writing. But I think you are right to recommend this is about the limit of "economical to use". I may go back to C++ or Python with OpenGL to make the advanced diagrams. You have been very helpful. TNX – jlettvin Jan 16 '20 at 18:50