4

I'd like to create a tikz graphics such as this one with an exploded view and I was wondering if anyone knew of a tool that would help create it. I wasn't able to find any similar example online using LaTeX. The thing is I will be using several of these with variations in the components and I'd like to be able to save shapes and reuse them. That would also be useful to me to represent the molecules in the top drawing.

I assume basic tikz commands and appropriate layering would do the trick but I guess someone must have made a tool for 3D projection that would help with the appropriate dimensioning and placement of these shapes taking in arguments like angle and scale.

Example of the wanted result

2

2 Answers 2

5

The main task is to come up with a set of reasonable coordinates to define the various exploded elements.

There are several ways to do it. I'll mention 2.

1st approach

Use your drawing, read suitable coordinates from it, draw the various elements.

sketch

2nd approach

Let's pretend some perspective and construct some points from intersections with lines. For a given object, e.g. the membran:

  • start from a fixpoint
  • P1: intersect with upper back (line)
  • P2: intersect with upper forgr
  • P3: vertical down from P2, intersct with lower forgr
  • P4: vertical down from P1, intersct with lower back
  • work from there, e.g. draw a cyclic line between these 4 points

As you can see by the dashed line, this approach cheats somewhat with the concept of fixed point perspectice. But the result may be good enough.

    % ~~~ membran ~~~~~~~~~~~
    \draw[hlp,name path=ln1] (fx) -- +(230:7);          % start direction
    \path[name intersections={of=ln1 and ub, by=P1}];
    \path[name intersections={of=ln1 and uf, by=P2}];
    \draw[hlp,name path=ln1a](P2) -- +(0,-5);           % vert. down
    \path[name intersections={of=ln1a and lf, by=P3}];
    \draw[hlp,dashed]        (P3) -- (fx);              % to show cheating  
    \draw[hlp,name path=ln1b](P1) -- +(0,-5);           % vert. down
    \path[name intersections={of=ln1b and lb, by=P4}];

    \draw[mb,fill=black] (P1) -- (P2) -- (P3) node[an]{membrane} -- (P4) -- cycle;

result

Finally make the teal help lines invisible by setting opacity=0 when you're done.

The fixed point (fx) may be somewhere inside the crossection of your upper sketch (2D), i.e. it must be finished before the upper back line.

\documentclass[10pt,border=3mm,tikz]{standalone}
\usetikzlibrary{intersections}

\begin{document}
 \begin{tikzpicture}[
    hlp/.style={teal,opacity=.5}, % reduce opacity to make less visible
    ae/.style={anchor = east},
    an/.style={anchor = north},
    mb/.style={line width=2pt},
 ]
 
    % ~~~ construction lines ~~~~~~~ 
    \draw[hlp,name path=hor] (-8, 0  )  node[ae]{horizon}    -- (8,0);
    \draw[hlp,name path=ub]  (-8,-2  )  node[ae]{upper back} -- (8,-2);
    \draw[hlp,name path=uf]  (-8,-4  )  node[ae]{upper forgr}-- (8,-4);
    \draw[hlp,name path=lb]  (-8,-6.5)  node[ae]{lower back} -- (8,-6.5);
    \draw[hlp,name path=lf]  (-8,-8.5)  node[ae]{lower forgr}-- (8,-8.5);
    
    % ~~~ fixpoint ~~~~~~~
    \coordinate (fx) at (3,0);
        
    % ~~~ membran ~~~~~~~~~~~
    \draw[hlp,name path=ln1] (fx) -- +(230:7);          % start direction
    \path[name intersections={of=ln1 and ub, by=P1}];
    \path[name intersections={of=ln1 and uf, by=P2}];
    \draw[hlp,name path=ln1a](P2) -- +(0,-5);           % vert. down
    \path[name intersections={of=ln1a and lf, by=P3}];
    \draw[hlp,dashed]        (P3) -- (fx);              % to show cheating  
    \draw[hlp,name path=ln1b](P1) -- +(0,-5);           % vert. down
    \path[name intersections={of=ln1b and lb, by=P4}];

    \draw[mb,fill=black] (P1) -- (P2) -- (P3) node[an]{membrane} -- (P4) -- cycle;


    % ~~~ frame ~~~~~~~~~~~
    \draw[hlp,name path=ln1] (fx) -- +(300:7);          % start direction
    \path[name intersections={of=ln1 and ub, by=F1}];
    \path[name intersections={of=ln1 and uf, by=F2}];
    \draw[hlp,name path=ln1a](F2) -- +(0,-5);           % vert. down
    \path[name intersections={of=ln1a and lf, by=F3}];
    \draw[hlp,dashed]        (F3) -- (fx);              % to show cheating  
    \draw[hlp,name path=ln1b](F1) -- +(0,-5);           % vert. down
    \path[name intersections={of=ln1b and lb, by=F4}];

    \draw[mb] (F1) -- (F2) -- (F3) node[an]{frame} -- (F4) -- cycle;


    % ~~~ biplane ~~~~~~~~~~~
    \draw[hlp,name path=ln1] (fx) -- +(215:10);         % start direction
    \path[name intersections={of=ln1 and ub, by=B1}];
    \path[name intersections={of=ln1 and uf, by=B2}];
    \draw[hlp,name path=ln1a](B2) -- +(0,-5);           % vert. down
    \path[name intersections={of=ln1a and lf, by=B3}];
    \draw[hlp,dashed]        (B3) -- (fx);              % to show cheating  
    \draw[hlp,name path=ln1b](B1) -- +(0,-5);           % vert. down
    \path[name intersections={of=ln1b and lb, by=B4}];

    \draw[mb] (B1) -- (B2) -- (B3) node[an]{biplane} -- (B4) -- cycle;
 \end{tikzpicture}
\end{document}

2nd approach, non-cheating version

The "cheating" in the 2nd approach comes from predefining ALL 4 lines upper back ... lower foreground. When using the fixed point (fx) correctly, one of them needs to be calculated from the rest.

In belows code line lower back is calculated for the first object drawn, here membran. Once lower back is known as path lb it's simply used for the others, like in the 2nd approach above.

This way there is NO more cheating wrt (fx).

noncheating

\documentclass[10pt,border=3mm,tikz]{standalone}
\usetikzlibrary{intersections}

\begin{document}
 \begin{tikzpicture}[
    hlp/.style={teal,opacity=.5}, % reduce opacity to make less visible
    ae/.style={anchor = east},
    an/.style={anchor = north},
    mb/.style={line width=2pt},
 ]
 
    % ~~~ construction lines ~~~~~~~ 
    \draw[hlp,name path=hor] (-8, 0  )  node[ae]{horizon}    -- (8,0);
    \draw[hlp,name path=ub]  (-8,-2  )  node[ae]{upper back} -- (8,-2);
    \draw[hlp,name path=uf]  (-8,-3.5)  node[ae]{upper forgr}-- (8,-3.5);
    % ~~~ don't predefine lower back line ~~~~~~~~~~~~~~
%   \draw[hlp,name path=lb]  (-8,-6.5)  node[ae]{lower back} -- (8,-6.5);
    \draw[hlp,name path=lf]  (-8,-8.5)  node[ae]{lower forgr}-- (8,-8.5);
    
    % ~~~ fixpoint ~~~~~~~
    \coordinate (fx) at (3,0);
        
    % ~~~ membran ~~~~~~~~~~~
    \draw[hlp,name path=ln1] (fx) -- +(230:7);          % start direction
    \path[name intersections={of=ln1 and ub, by=P1}];
    \path[name intersections={of=ln1 and uf, by=P2}];
    \draw[hlp,name path=ln1a](P2) -- +(0,-5);           % vert. down
    \path[name intersections={of=ln1a and lf, by=P3}];
    \draw[hlp,dashed,name path=ln1c](P3) -- (fx);       % to show NO cheating   
    \draw[hlp,name path=ln1b](P1) -- +(0,-5);           % vert. down
    % ~~~ calculate, where lower back line should be ~~~~~~~~
    \path[name intersections={of=ln1b and ln1c, by=P4}];    % <= !
    \draw[opacity=0] (P4) -- +(-10,0) coordinate (P5);
    \draw[hlp,name path=lb,]  (P5)  node[ae]{lower back} --+(17,0);

    \draw[mb,fill=none] (P1) -- (P2) -- (P3) node[an]{membrane} -- (P4) -- cycle;


    % ~~~ frame ~~~~~~~~~~~
    \draw[hlp,name path=ln1] (fx) -- +(300:7);          % start direction
    \path[name intersections={of=ln1 and ub, by=F1}];
    \path[name intersections={of=ln1 and uf, by=F2}];
    \draw[hlp,name path=ln1a](F2) -- +(0,-5);           % vert. down
    \path[name intersections={of=ln1a and lf, by=F3}];
    \draw[hlp,dashed]        (F3) -- (fx);              % to show NO cheating   
    \draw[hlp,name path=ln1b](F1) -- +(0,-5);           % vert. down
    \path[name intersections={of=ln1b and lb, by=F4}];

    \draw[mb] (F1) -- (F2) -- (F3) node[an]{frame} -- (F4) -- cycle;


    % ~~~ biplane ~~~~~~~~~~~
    \draw[hlp,name path=ln1] (fx) -- +(215:10);         % start direction
    \path[name intersections={of=ln1 and ub, by=B1}];
    \path[name intersections={of=ln1 and uf, by=B2}];
    \draw[hlp,name path=ln1a](B2) -- +(0,-5);           % vert. down
    \path[name intersections={of=ln1a and lf, by=B3}];
    \draw[hlp,dashed]        (B3) -- (fx);              % to show NO cheating   
    \draw[hlp,name path=ln1b](B1) -- +(0,-5);           % vert. down
    \path[name intersections={of=ln1b and lb, by=B4}];

    \draw[mb] (B1) -- (B2) -- (B3) node[an]{biplane} -- (B4) -- cycle;
 \end{tikzpicture}
\end{document}
1

For fun and learning, an option that understands a bit about Tikz's 3D capabilities, you can first draw anything, either in a pic or through a definition that nests drawing code with some variables to access. future such as size, color and some coordinates in the case of using arrows; For the example I created 3 types.

The standalone class with the tikz parameter allows you to create a new page for each tikzpicture environment, this is useful for making animations, in this case I used it to reuse the drawing definitions, on the first sheet everything in 2d is drawn the 3 objects using their position, scale, color and ID variables.

RESULT:

enter image description here

In the second sheet I use the 3D library within the scope environment so that what is inside will be in different coordinates in this case 3D where the drawing definitions will be made in the ZY plane and will be positioned along the X Axis, The first 3 use standard 3D coordinates, but to create a horizon and vanishing point effect, the central one and the rest are rotated using the Z axis modifier, thus managing to flip the following figures, perhaps it will serve for a better result, but otherwise It is just a matter of copying the first 3 and modifying their displacement along the X axis.

RESULT:

enter image description here

MWE:

\documentclass[tikz,border=3.14pt]{standalone}
\usetikzlibrary{3d,arrows.meta}
\begin{document}
    
\def\BipolarPlate#1#2#3#4{
    \begin{scope}[shift={(#1)},scale=#2,transform shape]
        \node[fill=#3,draw, minimum height=2cm,minimum width=2cm] at (0,0)(#4){};
        \path[fill=#3](-1cm,1cm)coordinate(#4-EX-NW)
        -- ++ (2cm,0) coordinate(#4-EX-NE)
        -- ++ (0,-2cm) coordinate(#4-EX-SE)
        -- ++ (-2cm,0) coordinate(#4-EX-SW)
        -- cycle;
        \draw[double]
        (-0.8cm,1cm)
        \foreach \j in {1,...,4}{
            |- ++(1.6cm,-0.2cm)
            |- ++(-1.6cm,-0.2cm)
        }
        |- ++(1.6cm,-0.2cm) -- (0.8cm,-1cm);
    \end{scope} 
}
\def\Plate#1#2#3#4{
    \begin{scope}[shift={(#1)},scale=#2,transform shape]
        \node[fill=#3,draw, minimum height=2cm,minimum width=2cm] at (0,0)(#4){};
        \path[fill=#3](-1cm,1cm)coordinate(#4-EX-NW)
        -- ++ (2cm,0) coordinate(#4-EX-NE)
        -- ++ (0,-2cm) coordinate(#4-EX-SE)
        -- ++ (-2cm,0) coordinate(#4-EX-SW)
        -- cycle;
        \clip (-1,-1) rectangle ++(2,2);
        \foreach \i in {1,...,500} {\fill[white](-1,-1)++ (rnd*2cm, rnd*2cm) circle (0.45pt);}
    \end{scope} 
}

\def\OPlate#1#2#3#4{
    \begin{scope}[shift={(#1)},scale=#2,transform shape]
        \draw[fill=#3,even odd rule](-1cm,1cm)coordinate(#4-EX-NW)
            -- ++ (2cm,0) coordinate(#4-EX-NE)
            -- ++ (0,-2cm) coordinate(#4-EX-SE)
            -- ++ (-2cm,0) coordinate(#4-EX-SW)
            -- cycle
            (-0.5cm,0.5cm)coordinate(#4-IN-NW)
            -- ++ (1cm,0) coordinate(#4-IN-NE)
            -- ++ (0,-1cm) coordinate(#4-IN-SE)
            -- ++ (-1cm,0) coordinate(#4-IN-SW)
            -- cycle;
    \end{scope} 
}
    

\begin{tikzpicture}[scale=0.5]
    \BipolarPlate{0,0}{1}{orange!50!black}{BP1}
    \Plate{2.5,0}{0.5}{gray!50!black}{B1}
    \OPlate{5,0}{1}{green!50!black}{OP1}
\end{tikzpicture}


\begin{tikzpicture}[
    >=Stealth,
    rounded corners=0.25pt,
    P/.style={fill=white,pos=0.5,scale=0.75,font=\tiny\sf,inner sep=1pt}]
    
    \def\volume#1#2#3{
        \draw[fill=#3!50!white](#1-EX-NW) -- (#2-EX-NW) --(#2-EX-NE) -- (#1-EX-NE) -- (#1-EX-NW);
        \draw[fill=#3!50!black](#1-EX-SE) -- (#2-EX-SE) --(#2-EX-NE) -- (#1-EX-NE) -- (#1-EX-SE);
    }
    %First Bipolar plate
    \begin{scope}[canvas is zy plane at x=0]
        \BipolarPlate{0,0}{1}{orange!50!black}{P1b}
    \end{scope}
    \begin{scope}[canvas is zy plane at x=0.1]
        \BipolarPlate{0,0}{1}{orange!50!black}{P1f}
    \end{scope}
    \volume{P1b}{P1f}{orange!50!black}
    
    %Cathode
    \begin{scope}[canvas is zy plane at x=0.9]
        \Plate{0,0}{0.5}{gray!50!black}{P2b}
    \end{scope}
    \begin{scope}[canvas is zy plane at x=1]
        \Plate{0,0}{0.5}{gray!50!black}{P2f}
    \end{scope}
    \volume{P2b}{P2f}{gray!50!black}
    
    %Frame
    \begin{scope}[z={(240:0.45)},canvas is zy plane at x=1.95]
        \OPlate{0,0}{1}{green!50!black}{P3b}
    \end{scope}
    \begin{scope}[z={(240:0.45)},canvas is zy plane at x=2]
        \OPlate{0,0}{1}{green!50!black}{P3f}
    \end{scope}
    \volume{P3b}{P3f}{green!50!black}
    \draw(P3b-IN-SW)--(P3f-IN-SW);
    
    %Membrane
    \begin{scope}[z={(-95:0.4)},canvas is zy plane at x=2.9]
        \OPlate{0,0}{1}{green!20!black}{P4b}
    \end{scope}
    \begin{scope}[z={(-85:0.4)},canvas is zy plane at x=3]
        \OPlate{0,0}{1}{green!20!black}{P4f}
    \end{scope}
    \volume{P4b}{P4f}{green!20!black}
    
    %Frame 2
    \begin{scope}[z={(-60:0.45)},canvas is zy plane at x=4]
        \OPlate{0,0}{1}{green!50!black}{P5b}
    \end{scope}
    \begin{scope}[z={(-60:0.45)},canvas is zy plane at x=3.95]
        \OPlate{0,0}{1}{green!50!black}{P5f}
    \end{scope}
    \volume{P5b}{P5f}{green!50!black}
    \draw(P5b-IN-SW)--(P5f-IN-SW);
    
    %Anode
    \begin{scope}[z={(-45:0.45)},canvas is zy plane at x=5]
        \Plate{0,0}{0.5}{gray!50!black}{P6b}
    \end{scope}
    \begin{scope}[z={(-45:0.45)},canvas is zy plane at x=4.9]
        \Plate{0,0}{0.5}{gray!50!black}{P6f}
    \end{scope}
    \volume{P6b}{P6f}{gray!50!black}
    
    %Bipolar plate
    \begin{scope}[z={(-45:0.45)},canvas is zy plane at x=6]
        \BipolarPlate{0,0}{1}{blue!50!gray}{P7b}
    \end{scope}
    \begin{scope}[z={(-45:0.45)},canvas is zy plane at x=5.9]
        \BipolarPlate{0,0}{1}{blue!50!gray}{P7f}
    \end{scope}
    \volume{P7b}{P7f}{blue!50!gray}
    
    %drawing some text nodes:
    \draw(P4f-EX-NW) -- ++(0,0.5)node[anchor=-90](Imag){\includegraphics[width=2cm,]{example-image-duck}};
    \draw[->](P1f.north west) -- (Imag.180) node[P] {Bipolar plate};
    \draw[->](P2f.north west) -- (Imag) node[P] {cathode};
    \draw[->](P4f-EX-NW) -- (Imag) node[P] {Membrane};
    \draw[->](P6f.north west) -- (Imag) node[P] {anode};
    \draw[->](P7f.north west) -- (Imag.0) node[P] {Bipolar plate};

    \end{tikzpicture}   
\end{document}

You must log in to answer this question.

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