6

I wish to draw triangular pyramids of oranges. The kth layer has k(k + 1)/2 oranges, the kth triangular number. The number of oranges in the nth stack is n(n + 1)(n + 2)/6, the nth tetrahedral number. My code and the output it produces are shown below.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{3d} 
\usetikzlibrary{shadings}

\begin{document}
\begin{figure}[h]
\centering
\begin{tikzpicture}[scale=0.5]
\shade[ball color = orange] (0, 0) circle (0.866 cm);
\node at (0, -4) {\(n = 1\)};

\begin{scope}[xshift = 6 cm]
\shade[ball color = orange] (0.866, 1/2, 0) circle (0.866 cm);
\shade[ball color = orange] (-0.866, 1/2, 0) circle (0.866 cm);
\shade[ball color = orange] (0, -1, 0) circle (0.866 cm);
\shade[ball color = orange] (0, 0, 1.414) circle (0.866 cm);
\node at (0, -4) {\(n = 2\)};
\end{scope}

\begin{scope}[xshift = 15 cm]
\shade[ball color = orange] (0, 1, 0) circle (0.866 cm);
\shade[ball color = orange] (-1.732, 1, 0) circle (0.866 cm);
\shade[ball color = orange] (1.732, 1, 0) circle (0.866 cm);
\shade[ball color = orange] (-0.866, -1/2, 0) circle (0.866 cm);
\shade[ball color = orange] (0.866, -1/2, 0) circle (0.866 cm);
\shade[ball color = orange] (0, -2, 0) circle (0.866 cm);
\shade[ball color = orange] (-0.866, 1/2, 1.414) circle (0.866 cm);
\shade[ball color = orange] (0.866, 1/2, 1.414) circle (0.866 cm);
\shade[ball color = orange] (0, -1, 1.414) circle (0.866 cm);
\shade[ball color = orange] (0, 0, 2.828) circle (0.866 cm);
\node at (0, -4) {\(n = 3\)};
\end{scope}
\end{tikzpicture}
\caption{Triangular pyramids of oranges.}
\label{figure:triangular_pyramids_of_oranges}
\end{figure}  

triangular_pyramids_of_oranges

How can I rotate the stacks so that it looks like they are growing upwards rather than out of the page?

Also, I worked out the coordinates by hand using coordinate geometry and trigonometry. Is there a more efficient method for generating these pyramids?

3 Answers 3

11

While you are waiting for the TikZ-team, here is a little alternative diversion in Metapost, which you might like to explore. I adapted this from one I had done earlier. You can of course do the same sort of loops in TikZ.

four stacks of oranges

This is wrapped up in luamplib, so you need to compile it with lualatex

\documentclass[border=5mm]{standalone}
\usepackage{luamplib}
\begin{document}
\mplibtextextlabel{enable}
\begin{mplibcode}
% first set up the isometric projection
numeric alpha, beta, ipca, ipsa, ipcb, ipsb, ipscale;
alpha = -20;
beta = 10;
ipca = cosd(alpha); ipsa = sind(alpha);
ipcb = cosd(beta); ipsb = sind(beta);
ipscale := 16;

% this macro projects 3D to 2D (isometrically)
vardef p(expr x, y, z) =
    (x * ipcb - z * ipsb, y * ipca + x * ipsa * ipsb + z * ipsa * ipcb) scaled ipscale
enddef;

% now make an orange picture
color a, b; b = (0.99608,0.90196,0.80784); a = (0.54902,0.17647,0.015686);
path C, c; numeric n; n = 16;
C = fullcircle scaled ipscale;
c = fullcircle scaled 1/2 shifted (-3,3);
picture orange;
orange = image(for i=0 upto n:
    fill interpath(i/n, C, c) withcolor (i/n)[a, b];
endfor);

beginfig(1);
for n = 1 upto 4:  % draw four stacks of oranges...
    picture stack; stack = image(
        for k = n-1 downto 0:
            for j = k downto 0:
                for i = 0 upto j:
                    draw orange shifted p(i - 0.5 j, -0.866 k, -0.866 j + 0.5 k);
                endfor
            endfor
        endfor
    );
    numeric x; x = 42n * sqrt(n);
    draw stack shifted (x, 8n);
    label("$n=" & decimal n & "$", (x, -42));
endfor
endfig;
\end{mplibcode}
\end{document}

For the isometric projection, alpha defines pitch (rotation up and down) and beta defines the yaw (rotation left and right).

6

This is not my code, by marmot. I do not remember the link to marmot'code.

\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{3dtools}%https://github.com/marmotghost/tikz-3dtools
\newcounter{myi}
\begin{document}
\pgfdeclarelayer{background} 
\pgfdeclarelayer{foreground}
\pgfsetlayers{background,main,foreground} \foreach \Angle in {5,15,...,355}
{\begin{tikzpicture}[same bounding box=A]
            \begin{scope}[3d/install view={phi=\Angle,psi=0,theta=60}]
                \edef\myn{4} %<- height of the pyramid
                \pgfmathsetmacro{\myr}{sqrt(1+tan(30)*tan(30))}
                \pgfmathsetmacro{\myh}{2*sin(acos(\myr/2))}
                \pgfmathsetmacro{\myt}{2*sqrt(6)}
                \pgfmathsetmacro{\mys}{2+\myt}
                \pgfmathsetmacro{\myd}{(1+sqrt(6))/cos(30)}
                \pgfmathsetmacro{\myH}{sqrt(2/3)*\mys}
                \tikzset{step i/.code={\stepcounter{myi}}}
                \setcounter{myi}{0}
                \path foreach \Z in {1,...,\myn}
                {foreach \Y in {1,...,\Z}
                    {foreach \X in {1,...,\Y}
                        {[step i]
                            ({2*\X-1-\Y},{\Y*tan(60)-tan(60)*(1+2*\Z)/3},{-\Z*\myh+\myn*\myh})
                            coordinate (C\number\value{myi})
                }}};
                \let\mylistd\empty
                \tikzset{add screen depth/.code={%
                        \pgfmathsetmacro{\mycoor}{TD("(C##1)")}%
                        \pgfmathsetmacro{\mysd}{screendepth(\mycoor)}%
                        \ifx\mylistd\empty
                        \edef\mylistd{\mysd}%
                        \else
                        \edef\mylistd{\mylistd,\mysd}%
                        \fi}}
                \tikzset{add screen depth/.list={1,...,\number\value{myi}}}
                \pgfkeys{/my lists/.cd,
                    my initial array/.is array={\mylistd}, 
                    my values/.initial=\pgfkeysvalueof{/my lists/my initial array/content},%
                    my values/.sort numeric list={\temp}{\templ},% sort yields sorted list and index
                    my sorted array/.is array/.expanded={\temp}, 
                    my index machinery/.is array/.expanded={\templ}}%
                \foreach \X in \templ
                {
                    \shade[3d/screen coords,ball color=blue] (C\X) circle[radius=1];}
            \end{scope} 
    \end{tikzpicture}}
\end{document}  

enter image description here

4

Inspired by Thruston's beautiful Metapost example, I figured out that I had to first load tikz, then load tikz-3dplot so that I could rotate my diagram. The command \tdplotsetmaincoords{60}{-10} rotates the coordinate system 60 degrees about the x-axis and -10 degrees about the z-axis. My solution relies on actually working out the coordinates of the centers of the spheres. Perhaps somebody with more programming experience will find a more efficient method of producing the piles of oranges. The output is shown below the code.

 \documentclass{article}
 \usepackage{tikz}
 \usepackage{tikz-3dplot}
 \usetikzlibrary{3d} 
 \usetikzlibrary{shadings}

\begin{document}

\begin{figure}[h]
\centering
\tdplotsetmaincoords{60}{-10}   
\begin{tikzpicture}[scale=0.25, tdplot_main_coords]
\shade[ball color = orange] (0, 0) circle (0.866 cm);
\node at (0, 0, -4) {\(n = 1\)};
\begin{scope}[xshift = 7 cm]
\shade[ball color = orange] (0.866, 1/2, 0) circle (0.866 cm);
\shade[ball color = orange] (-0.866, 1/2, 0) circle (0.866 cm);
\shade[ball color = orange] (0, -1, 0) circle (0.866 cm);
\shade[ball color = orange] (0, 0, 1.414) circle (0.866 cm);
\node at (0, 0, -4) {\(n = 2\)};
\end{scope}

\begin{scope}[xshift = 15 cm]
\shade[ball color = orange] (0, 1, 0) circle (0.866 cm);
\shade[ball color = orange] (-1.732, 1, 0) circle (0.866 cm);
\shade[ball color = orange] (1.732, 1, 0) circle (0.866 cm);
\shade[ball color = orange] (-0.866, -1/2, 0) circle (0.866 cm);
\shade[ball color = orange] (0.866, -1/2, 0) circle (0.866 cm);
\shade[ball color = orange] (0, -2, 0) circle (0.866 cm);
\shade[ball color = orange] (-0.866, 1/2, 1.414) circle (0.866 cm);
\shade[ball color = orange] (0.866, 1/2, 1.414) circle (0.866 cm);
\shade[ball color = orange] (0, -1, 1.414) circle (0.866 cm);
\shade[ball color = orange] (0, 0, 2.828) circle (0.866 cm);
\node at (0, 0, -4) {\(n = 3\)};
\end{scope}

\begin{scope}[xshift= 25 cm]
\shade[ball color = orange] (-2.598, 3/2, 0) circle (0.866 cm);
\shade[ball color = orange] (-0.866, 3/2, 0) circle (0.866 cm);
\shade[ball color = orange] (0.866, 3/2, 0) circle (0.866 cm);
\shade[ball color = orange] (2.598, 3/2, 0) circle (0.866 cm); 
\shade[ball color = orange] (-1.732, 0, 0) circle (0.866 cm);
\shade[ball color = orange] (0, 0, 0) circle (0.866 cm);
\shade[ball color = orange] (1.732, 0, 0) circle (0.866 cm);
\shade[ball color = orange] (-0.866, -3/2, 0) circle (0.866 cm);
\shade[ball color = orange] (0.866, -3/2, 0) circle (0.866 cm);
\shade[ball color = orange] (0, -3, 0) circle (0.866 cm);
\shade[ball color = orange] (0, 1, 1.414) circle (0.866 cm);
\shade[ball color = orange] (-1.732, 1, 1.414) circle (0.866 cm);
\shade[ball color = orange] (1.732, 1, 1.414) circle (0.866 cm);
\shade[ball color = orange] (-0.866, -1/2, 1.414) circle (0.866 cm);
\shade[ball color = orange] (0.866, -1/2, 1.414) circle (0.866 cm);
\shade[ball color = orange] (0, -2, 1.414) circle (0.866 cm);
\shade[ball color = orange] (-0.866, 1/2, 2.828) circle (0.866 cm);
\shade[ball color = orange] (0.866, 1/2, 2.828) circle (0.866 cm);
\shade[ball color = orange] (0, -1, 2.828) circle (0.866 cm);
\shade[ball color = orange] (0, 0, 4.242) circle (0.866 cm);
\node at (0, 0, -4) {\(n = 4\)};
\end{scope}
\end{tikzpicture}
\caption{Triangular pyramids of oranges.}
\label{figure:triangular_pyramids_of_oranges}
\end{figure}

\end{document}

triangular_pyramids_of_oranges

You must log in to answer this question.

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