5

I have a simple cube in 3-space, 4 faces drawn in red and top and bottom in green.

 \documentclass[border=5,tikz]{standalone}

 \usepackage{tikz-3dplot}

 \begin{document}
 \foreach\s in{2,4,...,360}{
     \tdplotsetmaincoords{2.71828+\s}{2.71828+\s*2}
     \tikz[tdplot_main_coords,scale=.1]{
         \path(-15cm,-15cm)(15cm,15cm);
         \draw[ultra thick, color=black, fill=green!80!black]
             (0,0,0)--(20,0,0)--(20,20,0)--(0,20,0)--cycle        % bottom
             (0,0,20)--(20,0,20)--(20,20,20)--(0,20,20)--cycle;   % top
         \draw[ultra thick, color=black, fill=red!80!black]
             (0,0,0)--(20,0,0)--(20,0,20)--(0,0,20)--cycle
             (0,20,0)--(20,20,0)--(20,20,20)--(0,20,20)--cycle
             (0,0,0)--(0,20,0)--(0,20,20)--(0,0,20)--cycle
             (20,0,0)--(20,20,0)--(20,20,20)--(20,0,20)--cycle;
     }
 }

 \end{document}

that when seen from certain angles in TikZ, show an unexpected projection. It seems that when certain faces go on top of each other -- they become transparent!

enter image description here

Is this a bug, or there is something wrong with way the cube is built?

16
  • Try ` \foreach\s in{2,4,...,360}{% \tdplotsetmaincoords{2.71828+\s}{2.71828+\s*2} \tikz[tdplot_main_coords,scale=.1]{% \path(-15cm,-15cm)(15cm,15cm); \draw[ultra thick, color=black, fill=green!80!black] (0,0,0)--(20,0,0)--(20,20,0)--(0,20,0)--cycle; % bottom \draw[ultra thick, color=black, fill=green!80!black] (0,0,20)--(20,0,20)--(20,20,20)--(0,20,20)--cycle; % top \draw[ultra thick, color=black, fill=red!80!black] (0,0,0)--(20,0,0)--(20,0,20)--(0,0,20)--cycle; ` cont....
    – cfr
    Feb 24 '16 at 1:05
  • ... ` \draw[ultra thick, color=black, fill=red!80!black] (0,20,0)--(20,20,0)--(20,20,20)--(0,20,20)--cycle; \draw[ultra thick, color=black, fill=red!80!black] (0,0,0)--(0,20,0)--(0,20,20)--(0,0,20)--cycle; \draw[ultra thick, color=black, fill=red!80!black] (20,0,0)--(20,20,0)--(20,20,20)--(20,0,20)--cycle; }% }` ;)
    – cfr
    Feb 24 '16 at 1:05
  • If it is a bug, I'm guessing it is in tikz-3dplot rather than TikZ. This rotated coordinate system stuff is from that package rather than pgf or tikz proper. (It could be a bug in TikZ, but there's no reason to assume that is so, even if it is a bug rather than just a limitation.) There is no doubt that TikZ really isn't designed to do this and tikz-3dplot already pushes the limits on what's doable, I think. Pushing them further... well, it isn't surprising it doesn't entirely work, I don't think. (Which isn't to say it is not a bug.)
    – cfr
    Feb 24 '16 at 1:12
  • @cfr I tried your code - it seems to be just a distribution of the \draw command for each one of the face separately! Well apparently it shows another bug: one of the edges is missing!
    – Paulo Ney
    Feb 24 '16 at 1:52
  • 1
    The default filling rule is the nonzero rule and which bits end up empty in overlapping shapes in a single path is dependent on the path direction. See the manual "Graphic Parameters: Interior Rules". Feb 24 '16 at 8:04
4

Because each rectangle is filled independently, none are treated as holes. For a solid, one needs to draw the faces from the far to near, or assign a normal vector and only draw faces pointing in this direction.

math here

\documentclass[border=5,tikz]{standalone}

% Uses \nearx, \neary and \nearz
% #1=x, #2=y, #3=z, #4={code to be executed}
\def\ifnear(#1,#2,#3)#4 
  {\pgfmathparse{#1*\nearx+#2*\neary+#3*\nearz}%
  \ifdim\pgfmathresult pt>0pt\relax #4\fi}

 \usepackage{tikz-3dplot}

 \begin{document}
 \foreach\s in{2,4,...,360}{
   \pgfmathsetmacro{\aTheta}{2.71828+\s}
   \pgfmathsetmacro{\aPhi}{2.71828+\s*2}
   \pgfmathsetmacro{\nearx}{sin(\aPhi)*sin(\aTheta)}
   \pgfmathsetmacro{\neary}{-cos(\aPhi)*sin(\aTheta)}
   \pgfmathsetmacro{\nearz}{cos(\aTheta)}
   \begin{tikzpicture}[scale=.1]
     \path(-15cm,-15cm)(15cm,15cm);
     \tdplotsetmaincoords{\aTheta}{\aPhi}
     \begin{scope}[tdplot_main_coords]
       \ifnear(0,0,-1){\draw[fill=green!80!black]
             (0,0,0)--(20,0,0)--(20,20,0)--(0,20,0)--cycle;}       % bottom
       \ifnear(0,0,1){\draw[fill=green!80!black]
             (0,0,20)--(20,0,20)--(20,20,20)--(0,20,20)--cycle;}   % top
       \ifnear(0,-1,0){\draw[fill=red!80!black]
             (0,0,0)--(20,0,0)--(20,0,20)--(0,0,20)--cycle;}
       \ifnear(0,1,0){\draw[fill=red!80!black]
             (0,20,0)--(20,20,0)--(20,20,20)--(0,20,20)--cycle;}
       \ifnear(-1,0,0){\draw[fill=red!80!black]
             (0,0,0)--(0,20,0)--(0,20,20)--(0,0,20)--cycle;}
       \ifnear(1,0,0){\draw[fill=red!80!black]
             (20,0,0)--(20,20,0)--(20,20,20)--(20,0,20)--cycle;}
     \end{scope}
   \end{tikzpicture}
 }

 \end{document}

If you reverse the signs on \nearx, \neary and \nearz it will show the other side of the cube.

The normal vector is a line perpendicular to the face and (for our purposes) pointing away from the center. For regular polyhedrals one can use the vector from the center of the object to the center of the face.

The center of the cube is at (10,10,10). Since the center of the bottom face was at (10,10,0), the (normalized) normal vector for that face was (0,0,-1).

9
  • I see that the transparent part is gone, even though not all green faces are drawn correctly! Would you care to comment what your code is doing differently? As far as I can see in the manual they are supposed to be equivalent!
    – Paulo Ney
    Feb 24 '16 at 4:15
  • BTW, I added a direction test. Feb 24 '16 at 18:41
  • Agreed that your new answer solves the problem of -- how to draw it! I even tried it on a more complex example (a truncated icosahedron from here: tex.stackexchange.com/questions/269108/…) and it works well. Would you be able to factor the \dotproduct test in a macro so we can use in a larger set of examples for test? But the larger question looms -- the first example I showed is almost certain a bug -- because any projection, filled from the back or not, should be a convex polygon in th end - with no holes!
    – Paulo Ney
    Feb 24 '16 at 20:58
  • @PauloNey Did you read the part of the manual Mark referred you to? TikZ is not filling/drawing a projection in 3D. It is filling/drawing a path in 2D. You are thinking in 3D terms, perhaps, whereas TikZ ONLY thinks in 2D terms. Maybe you could say that it is a bug in tikz-3dplot but I don't think that package claims to do away with the drawing-order requirement. At least, it probably shouldn't. The kind of manipulation you're talking about requires software which deals with 3D. Then your example should be trivial. But in 2D it is far from trivial. Does that make sense?
    – cfr
    Feb 24 '16 at 22:01
  • @cfr I have to disagree! This is NOT a problem of 3D at all. It is just a bunch of filled polygons drawn on top of one another and -- in this case -- the result should always be a convex polygon (no holes) -- and you can see it is not! Now on the issue of being a bug in TikZ vs. TikZ-3dplot it is hard to say because of how closely linked they are - I imagine all rendering is done by TikZ. And yes! I did read the Mark's reference!
    – Paulo Ney
    Feb 24 '16 at 22:26

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.