2

When drawing a 2d object, it's easy to understand thy tikz works at it does: simply put the latest drawing on the top. This behavier doesn't translate so well to 3d, so is there a good way to tell tikz what object to put on top?

This:

\documentclass{standalone}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}


\usepackage{tikz}

\begin{document}
\begin{tikzpicture}[darkstyle/.style={circle,draw,fill=gray!40,minimum size=20}]

        \filldraw[fill = red!20!white,fill opacity=0.6,draw = black] (0,2,0) -- ++(0,0,3) -- ++(3,0,0) -- ++ (0,0,-3) --++(-3,0,0) -- cycle;
        \filldraw[fill = red!10!white,fill opacity=0.6,draw = black] (0,2.1,0) -- ++(0,0,3) -- ++(3,0,0) -- ++ (0,0,-3) --++(-3,0,0) -- cycle;
        \foreach \x in {0,...,3}
        \foreach \y in {0,...,3}
        \foreach \z in {0,...,3}
        \filldraw[fill = white, draw = black] (\x,\y,\z) circle (5pt) ;


        \end{tikzpicture}
\end{document}

gives this:

Planes below

but this:

\documentclass{standalone}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}


\usepackage{tikz}

\begin{document}
\begin{tikzpicture}[darkstyle/.style={circle,draw,fill=gray!40,minimum size=20}]
        \foreach \x in {0,...,3}
        \foreach \y in {0,...,3}
        \foreach \z in {0,...,3}
        \filldraw[fill = white, draw = black] (\x,\y,\z) circle (5pt) ;
        \filldraw[fill = red!20!white,fill opacity=0.6,draw = black] (0,2,0) -- ++(0,0,3) -- ++(3,0,0) -- ++ (0,0,-3) --++(-3,0,0) -- cycle;
        \filldraw[fill = red!10!white,fill opacity=0.6,draw = black] (0,2.1,0) -- ++(0,0,3) -- ++(3,0,0) -- ++ (0,0,-3) --++(-3,0,0) -- cycle;
        \end{tikzpicture}
\end{document}

gives this:

Planes on top

Is there any good way of telling tikz which balls to draw over the plane and which to draw under? Or even better is there a way to make tikz know what part of every fill should be below, and which part should be above the planes? so that half of one ball could recieve the red tint wile the other stayed white?

5
  • Very good question. +1. – Sebastiano Mar 28 '18 at 19:53
  • You absolutely must not thank me, it's a good job. As you can see, given my many commitments, I dedicate my time here to answer short questions and not long questions that would take me so long. Again my congratulations. – Sebastiano Mar 28 '18 at 20:26
  • 1
    When you are drawing 3D, you are actually drawing 2D but with a different projection. Therefore you have to reorder the stuff by hand since TikZ does not do z-ordering for you. You can use layers for that if you like. If you want to have real z-ordering, then use Asymptote or another ray tracer. – Henri Menke Mar 29 '18 at 3:35
  • How does the layers work in tikz @Menke? I like the look of tikz a lot – Thorbjørn E. K. Christensen Mar 29 '18 at 4:10
  • @HenriMenke Thanks for your comment. I tried using it, and it seems near perfect. – Thorbjørn E. K. Christensen Mar 29 '18 at 10:50
0

So using the advice of Henri Menke, I opted to use layers in Tikz for this. The layer structure is, however, not perfect, what I would like to do is have ''Layers based on coordinates'' such that everything drawn above f.eks. y=2 would be a higher layer than the stuff below, this would alove to split a circle into two layers. Something I don't think is currently possible.

I did come up with the following solution:

\documentclass{standalone}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}


\usepackage{tikz}

\pgfdeclarelayer{bottom}
\pgfdeclarelayer{middleb}
\pgfdeclarelayer{middlet}
\pgfdeclarelayer{top}
\pgfsetlayers{bottom,middleb,main,middlet,top}

\begin{document}
\begin{tikzpicture}[darkstyle/.style={circle,draw,fill=gray!40,minimum size=20}]
        \begin{pgfonlayer}{bottom}
        \foreach \x in {0,...,3}
        \foreach \y in {1}
        \foreach \z in {0,...,3}
        \filldraw[fill = white, draw = black] (\x,\y,\z) circle (0.15) ;
        \end{pgfonlayer}

        \begin{pgfonlayer}{middleb}
                \filldraw[fill = red!20!white,fill opacity=0.8,draw = black!80!red] (0,1.9,0) -- ++(0,0,3) -- ++(3,0,0) -- ++ (0,0,-3) --++(-3,0,0) -- cycle;
        \end{pgfonlayer}

        \foreach \x in {0,...,3}
        \foreach \y in {2}
        \foreach \z in {0,...,3}
        \filldraw[fill = white, draw = black] (\x,\y,\z) circle (0.15) ;

        \begin{pgfonlayer}{middlet}
        \filldraw[fill = red!30!white,fill opacity=0.8,draw = black!80!green] (0,2.2,0) -- ++(0,0,3) -- ++(3,0,0) -- ++ (0,0,-3) --++(-3,0,0) -- cycle;
        \end{pgfonlayer}

        \begin{pgfonlayer}{top}
        \foreach \x in {0,...,3}
        \foreach \y in {3}
        \foreach \z in {0,...,3}
        \filldraw[fill = white, draw = black] (\x,\y,\z) circle (0.15) ;
        \end{pgfonlayer}

        \end{tikzpicture}
\end{document}

yielding

much better than before

I still, sadly, cannot cut a circle in half. But I can now have one layer of circles above and one below each plane. It's also easy to see which circles are below a single or both layers, thanks to the use of transparancy.

I kept the \foreach \y in {n} parts there, so it would be easier to have more layers.

I also do realize that layers are not needed for the result I'm showing, since I draw the layers in the way they would show up anyways. But now I could move part of the code and gain the same result.

A better answer than this one would be to have layers within circles, or something else, that would allow half of a \draw command to be above, and half of it to be below some layer.

Thanks again to Henri Menke for this Idea ;-)

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.