18

I need to draw an image of the first three triangular numbers inscribed in a square.

The first three triangular numbers

Now, I have two problems constructing this image.

  • Construct the circles perfectly centered
  • The shading

It is acceptable to answer only my first question (in order to correspond to the one question, one post policy) although I would be glad if someone answered both.

Now I have no minimal example, but in order to construct this image any packages would suffice, although my preference is for TikZ.

I am using a variety of packages, although I doubt any of them would interfere in the construction of this image.

  • Does anyone have any tips or suggestions for how to construct the first n triangular numbers inside a square (with "correct" shading)?
5
  • Looks like golf balls on a blue background. Dec 9, 2011 at 13:26
  • 1
    By "shading" do you mean the shadows that each casts on the others, or just a colouring of the balls themselves to give a 3d effect. Dec 9, 2011 at 14:12
  • Both prefferably, if this is too much work. Just the latter =) Dec 9, 2011 at 14:23
  • Before I post an answer that may be pointless, does this look horrible? Dec 9, 2011 at 15:07
  • It looks good =) Other than the colours are wrong (I gueess grey and white would be better?). Impressive ^^ Dec 9, 2011 at 15:25

5 Answers 5

29

Try something like:

\documentclass{article}
\usepackage{tikz}

\newlength\radius
\pgfmathsetlength{\radius}{0.5cm}
\newcommand\drawballs[2][]{%
    \foreach \y [evaluate=\y as \yy using #2+1-\y] in {1,...,#2} {%
        \foreach \x in {1,...,\yy} {%
            \shade[shading=ball,ball color=white,#1] 
                ({(2*\x-2+\y)*\radius},{sqrt(3)*\y*\radius}) circle (\radius); 
        };
    }%
}

\begin{document}

\begin{tikzpicture}
    \drawballs{1}
    \drawballs[xshift=2cm]{2}
    \drawballs[xshift=5cm]{3}
\end{tikzpicture}

\end{document}

output of code

2
14

You can do this straight in TikZ. Here's a reasonably complete sample that has some arbitrary default options to control the appearance. You can make triangles of any size, too:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shadings,calc}

\newcommand\shadedball[1]{% #1 = (coordinates)
 \shadedraw [shading = ball] #1 circle [radius = 1]
}

\newcommand\triangleloweredge[1]{% #1 = length
 \foreach \n [evaluate = \n using \n - 1] in {1,...,#1} {
  \shadedball{(2*\n,0)};
 }
}

\newcommand\triangleofballs[1]{% #1 = side length
 \foreach \m [count = \c from 0] in {#1,...,1} {
  \tikzset{shift = {(60:2*\c)}}
  \triangleloweredge{\m}
 }
}

\newcommand\squaredtriangleofballs[2][]{% #1 = global options, #2 = side length
 \begin{scope}[#1]
  \path[square border] (0,0) rectangle (${2*(#2)}*(1,1)$);
  \node[anchor = south west, inner sep = 0] {\tikz[shaded ball, #1] \triangleofballs{#2};};
 \end{scope}
}

\tikzset{
 square border/.style = {
  draw, ultra thick, red, fill = gray
 },
 shaded ball/.style = {
  color = violet, ball color = green
 }
}

\begin{document}
 \begin{tikzpicture}
  \squaredtriangleofballs[scale = 0.75]{3}
 \end{tikzpicture}
\end{document}

enter image description here

Sort of like Martin Heller's response, which I see appeared while I was testing. It may have some slight advantages in the programming: it uses the polar coordinate system rather than coordinate computations, uses a "lemma" for each part of the operation, and does everything with TikZ options rather than TeX macros/dimensions. I also give one possible way to draw the box; in this new version, it draws an actual square, not the fitting rectangle.

1
  • Well, I'm nearly embarrassed by my own answer ... This should definitely have more votes than mine. Dec 9, 2011 at 19:00
12

You could adapt the example with Pascal's triangle. The below is not perfect, and the alignment could be done more elegantly, but it's a start.

A big thanks goes of course to Paul Gaborit, for doing the hard work.

The grid is added to make it easier to see how they are aligned in relation to each other. I tried calculating the xshift and including that into \trianglenumber, but my initial attempt failed miserably, hence the manual shifting with scopes.

There is some shifty stuff going on. I removed the little space between the rows by adding +\row*0.1 at two places, for the y-coordinate (the 0.1 value vas just a lucky guess):

\node[ball,yshift=0.45cm*#1] (p-\row-0) at (-\row/2,-\row+\row*0.1) {};

and in

\coordinate (pos) at (-\row/2+\col,-\row+\row*0.1+0.45*#1);

Further, to have them aligned vertically by their centers, the second and third are shifted by 0.45cm*<number of additional rows>. As the argument to \trianglenumber defines just the number of additional rows, you see this in the two lines above, in the option for the node – yshift=0.45cm*#1 – and in the y-coordinate of pos+0.45*#1.

Not very elegant perhaps, but it mostly does the job.

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning,shadows,backgrounds,calc}

\newcommand{\trianglenumber}[1]{%
  \node[ball,yshift=0.45cm*#1] (p-0-0) at (0,0) {};
  \foreach \row in {1,...,#1} {
     % col #0 =&gt; value is 1
    \node[ball,yshift=0.45cm*#1] (p-\row-0) at (-\row/2,-\row+\row*0.1) {};
    \pgfmathsetmacro{\value}{1};
    \foreach \col in {1,...,\row} {
      % iterative formula : val = precval * (row-col+1)/col
      % (+ 0.5 to bypass rounding errors)
      \pgfmathtruncatemacro{\value}{\value*((\row-\col+1)/\col)+0.5};
      \global\let\value=\value
      % position of each value
      \coordinate (pos) at (-\row/2+\col,-\row+\row*0.1+0.45*#1);
      \pgfmathtruncatemacro{\rest}{mod(\value,2)}
      \ifnum \rest=0
        \node[ball] (p-\row-\col) at (pos) {};
      \else
        \node[ball] (p-\row-\col) at (pos) {};
      \fi
    }
  }
}


  % some styles
  \tikzset{
    ball/.style={
      minimum size=10mm,
      draw=black,
      circle,
      shade=ball,
      ball color=gray!20,
    },
  }

\begin{document}
\centering

\begin{tikzpicture}
\begin{scope}
  \node [ball] {};
\end{scope}
\begin{scope}[xshift=2.5cm]
  \trianglenumber{1}
\end{scope}
\begin{scope}[xshift=6cm]
 \trianglenumber{2}
\end{scope}
\draw (current bounding box.south west) grid (current bounding box.north east);
\end{tikzpicture}

\end{document}

enter image description here

12

Update version with tkz-euclide with square

It's possible to write a code more concise but it's difficult to get something better than Martin' code. I use the same ideas of my first code.

\documentclass[11pt]{scrartcl}
\usepackage{tkz-euclide}
\usetkzobj{all}     

\begin{document}

\newcommand{\ballgolf}[1]{
\begin{tikzpicture} 
\tkzDefPoint(1,-1){S1}  
\tkzDefPoint(#1*2+1,-1){S2} 
\tkzDrawSquare[fill=blue!30!black](S1,S2) 
\foreach \i in {1,...,#1}{%
  \tkzDefPoint(2*\i,0){O\i}
  \tkzDrawCircle[R,ball color=gray!20](O\i,1cm)}
 \ifnum #1=1 \else
\foreach \j [evaluate=\j as \j ] in {#1-1,...-1,2-1}{%
   \foreach \i in {1,...,\j}{%
      \tkzDefShiftPoint[O\i](60:2){O\i} 
      \tkzDrawCircle[R,ball color=gray!20](O\i,1cm)
   }%
}%
\fi  
\end{tikzpicture}}

\ballgolf{1} \ballgolf{2} \ballgolf{3} 
\end{document} 

enter image description here

Same version with tikz

\documentclass[11pt]{scrartcl}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}

\newcommand{\ballgolf}[1]{
\begin{tikzpicture} 
\draw[fill=blue!30!black] (1,-1) rectangle (#1*2+1,#1*2-1);
\foreach \i in {1,...,#1}{%
  \coordinate (O\i) at  (2*\i,0);
  \draw[ball color=gray!20] (O\i) circle(1cm);}
\ifnum #1=1 \else
\foreach \j [evaluate=\j as \j ] in {#1-1,...-1,2-1}{%
   \foreach \i in {1,...,\j}{%
      \coordinate (O\i) at  ($(O\i)+(60:2)$);
      \draw[ball color=gray!20] (O\i) circle(1cm);
   }%
}%
\fi    
\end{tikzpicture}
}%

\ballgolf{1} \ballgolf{2} \ballgolf{3} 
\end{document}
1
  • I forgot the square but it's not very diffcult Dec 9, 2011 at 16:00
3

I forgot that I created tkz-berge

\documentclass[11pt]{scrartcl}
\usepackage{tkz-berge}

\newcommand{\ballgolf}[1]{%
\SetVertexNoLabel
\foreach \i [evaluate=\i as \j using #1-\i] in {0,...,\number\numexpr#1 - 1\relax}{% 
     \pgfmathsetmacro\k{\i*sqrt(3)/2}
      \begin{scope}[shift={(\i*.5 cm,\k cm)}]
         \grEmptyPath[RA=1]{\j}   
       \end{scope}}}     

\begin{document}
\tikzset{VertexStyle/.style ={circle,ball color= gray!80!yellow,minimum size = 1cm}}      
\tikz{\ballgolf{4}}
\end{document} 

enter image description here

The same but only with tikz

\documentclass[11pt]{scrartcl}
\usepackage{tikz}

\newcommand{\ballgolftikz}[1]{%
\foreach \i  in {0,...,\number\numexpr#1 - 1\relax}{% 
   \pgfmathsetmacro\k{\i*sqrt(3)/2}
   \begin{scope}[shift={(\i*.5 cm,\k cm)}]
     \foreach \t in {1,...,\number\numexpr #1-\i\relax}{
        \shade[ball color= gray] (\t,0) circle (.5cm);}
   \end{scope}}
   }    
\begin{document}
\tikz{\ballgolftikz{3}}
\end{document}

You must log in to answer this question.

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