Tangent Circles using TikZ

I am trying to use TikZ to draw tangent circles contained in a rectangle, but I have encountered some difficulties. I am also soliciting general feedback on using TikZ better, so I am giving a fair amount of detail about my approach here.

I started by making the outer rectangle using \draw (0,0) -- ++(0,-6) -- ++(10,0) -- ++(0,6) -- cycle;. Then I made the first row of circles using \tikz\foreach \x in {0,2,4,6} \draw (\x,0) circle (1);. I noticed that the circles were placed on the top line of the rectangle, so I assumed that the coordinates (\x,0) were for the bottom of each circle, not the center as I would have expected (although even if they were for the center, I would have still needed to move them down). I changed the first coordinate of the rectangle to (0,3) since I also wanted an inset before the circles. But then the drawing encroached on the text above it. I changed the first coordinate back to (0,0) and instead adjusted the coordinates of the circles to (\x,-3). But then the circles were above the rectangle again, and the whole drawing moved up the page considerably. Why did this happen?

I changed the coordinates of the circles back to (\x,0) and the rectangle back to (0,3). I then attempted to make the second row of circles. Since I wanted them packed in a hexagonal lattice, I wrote foreach \x in {1,3,5,7 \draw (\x,{-sqrt(3)}) circle (1);, which I thought would produce four more circles, one unit to the right of and √3 units below the first row. Instead, they were lined up horizontally with the first row and quite a bit farther down than I wanted. I rewrote the coordinates as (\x+1,{-sqrt(3)+1}), which worked, but why? I guessed that this meant the \x in the coordinates must be relative to its position in the series {1,3,5,7}, so I expected that interchanging the series with {0,2,4,6} would have the same result, but nope, it did not. And the vertical position is given by a fixed value in the coordinates, and I know that the second row of circles should be √3 units below the first, not (√3 - 1) units below. What am I doing wrong?

Ultimately, I want to draw a third row of circles, mark the center of each circle, have the edges of the rectangle clip the overhanging semicircles, and add some annotations for the radius and other things, so I was also wondering if these steps would be shorter if I made the circles as nodes or something else. I have already spent a good deal of time looking through the TikZ manual. I saw some possible solutions like using the intersections library or tangent from the calc library, but I'm not sure how I would use them. Since the manual is more than 1,300 pages, it can be difficult for a TikZ novice to look up answers to specific questions. I also checked answers on Stack Exchange but still couldn't figure out what to do.

My Code

\documentclass[12pt]{article}
\usepackage[margin=1.25in]{geometry}
\usepackage{amsmath,amsfonts,amsthm,amssymb}
\usepackage{pgf,tikz}
\usetikzlibrary{calc,intersections}

\begin{document}
\begin{flushleft}

\begin{figure}[h]
\begin{tikzpicture}
\draw (0,3) -- ++(0,-6) -- ++(10,0) -- ++(0,6) -- cycle;
\tikz\foreach \x in {0,2,4,6}
\draw (\x,0) circle (1);
\foreach \x in {1,3,5,7}
\draw (\x+1,{-sqrt(3)+1}) circle (1);
\end{tikzpicture}
\end{figure}

\end{flushleft}
\end{document}


Output

• You are nesting tikzpictures which causes the problems.
– user194703
Commented Apr 26, 2020 at 4:09
• @Schrödinger'scat I'm not sure I understand. I think I used the tikzpicture "environment" just once. Commented Apr 26, 2020 at 4:12
• No, you have \tikz\foreach  inside the tikzpicture. \tikz starts a new tikzpicture.
– user194703
Commented Apr 26, 2020 at 4:15
• Ohhhh! Oops. I think that's the problem. Commented Apr 26, 2020 at 4:18

Your math is right but by using \tikz\foreach you nest tikzpictures, which explains the inconsistency.

This draws a third row and fixes the positions of the other circles. For the rectangle you can just use the rectangle path construction.

\documentclass[12pt]{article}
\usepackage[margin=1.25in]{geometry}
\usepackage{tikz}

\begin{document}
\begin{figure}[h]
\begin{tikzpicture}
\draw (0,3) rectangle ++(10,-6);
\draw foreach \x in {0,2,4,6}
\draw foreach \x in {1,3,5,7}
\end{tikzpicture}
\end{figure}
\end{document}


And this adds more circles, marks the centers and clips the circles against the rectangle.

\documentclass[12pt]{article}
\usepackage[margin=1.25in]{geometry}
\usepackage{tikz}

\begin{document}
\begin{figure}[h]
\begin{tikzpicture}[bullet/.style={fill,circle,inner sep=1.2pt}]
\draw[clip] (0,3) rectangle ++(10,-6);
\draw foreach \X in {-1,0,...,9}
{\ifodd\X
\else
\fi};
\end{tikzpicture}
\end{figure}
\end{document}


• Thank you so much! This is what I was trying to do! Commented Apr 26, 2020 at 4:28

Is this what you are looking for?

You can use \clip[draw] to draw a rectangle and clip to the rectangle. Apart from this I have use two \foreach loops, and, like Schrödinger's cat, deleted the extraneous internal \tikz.

\documentclass[12pt]{article}
\usepackage[margin=1.25in]{geometry}
\usepackage{amsmath,amsfonts,amsthm,amssymb}
\usepackage{pgf,tikz}
\usetikzlibrary{calc,intersections}

\begin{document}
\begin{flushleft}

\begin{figure}[h]
\begin{tikzpicture}
\pgfmathsetmacro\top{2+2*sqrt(3)}
\clip[draw](0,0) rectangle (10,\top);
\foreach \x in {1,3,5,7,9} {
\foreach \row [
evaluate=\row as \yrow using {1+sqrt(3)*\row},
evaluate=\row as \xrow using {isodd(\row) ? \x+1: \x}
] in {0,1,2} {
\draw (\xrow,\yrow) circle (1);
}
}
\end{tikzpicture}
\end{figure}

\end{flushleft}
\end{document}


I also used \pgfmathsetmarco to set the height of the rectangle to 2+2\sqrt(3).

• Yes, that is exactly what I meant by clipping. Thank you so much! Commented Apr 26, 2020 at 4:29