8

How to draw a circle with radius r where you insert all possible squares of width s in it? Each square is allowed to cross the periphery at the corner/corners of the square if possible. The squares must stay side by side like a grid.

As an example, I can construct one on the right upper axis, with r = 10 and s = 1. However, I can't seem to make it work for all of other axes at the same time. Is there a way to fix it?

Moreover, in my "condition" statement it looks as if there is some part of a square that lies outside the periphery. This is difficult for me to add more conditions to ensure that ALL squares must stay within the circle. I tried to translate the figure as a help, but I don't know if this is how it should be made.

\documentclass[tikz]{standalone}

\begin{document}
\begin{tikzpicture}

\foreach \x in {0,...,10}
  \foreach \y in {0,...,10}
    {
    \pgfmathparse{(\x+1)^2+(\y+1)^2<=100} %Condition of squares to stay inside the circle. 
%This circle is translated to make it work.
    \ifnum\pgfmathresult=1
      \filldraw[fill=blue!50] (\x,\y) rectangle (\x+1,\y+1); %Colouring the squares
    \fi
    }
\draw (0,0) circle [radius=10]; %Circle
\end{tikzpicture}
\end{document}

enter image description here

4
  • Try \foreach ... in {-10,...,10} and change the condition a little bit
    – dexteritas
    Commented Feb 25, 2023 at 20:19
  • 1
    Since this is symmetric you can just place four rectangles at once by going through all combinations of (±x, ±y). Commented Feb 25, 2023 at 20:35
  • What does Each square is allowed to cross the periphery at the corner/corners of the square if possible mean? Commented Feb 25, 2023 at 21:18
  • Related: tex.stackexchange.com/questions/383422/…
    – Scott H.
    Commented Feb 26, 2023 at 7:57

3 Answers 3

9

Since your diagram is symmetric in all possible forms you can just calculate one quadrant and draw all four of them.

You also don't have to check all 100 possible squares, you just need the top square that is allowed and then draw all those that are below it.

(And technically, if you know a x strip, say between x = 0 and x = 1 it only goes up to y = 9, you also know between y = 0 and y = 1 it only goes up to x = 9.)

The at y0.0 style is there to disable the drawing of a single line when (10, 0) will be evaluated to be the corner. (Actually, the whole body of the loop could be discarded if y = 0 by wrapping it in

\unless\ifdim\y pt=0pt\relax
  …
\fi

for a more low-level approach.)


My solution below is wrapped in a macro \tikzcirclewithsquares which applies its optional argment in the /tikz/cws name space where

  • the styles for the three paths lie (circle, rect, grid)
  • the values radius and step can be set and
  • whether only squares inside the circle or also squares that lie on the circumference (outside = true) should show up.

The latter is set up such that squares that touch the circle from the outside don't show up.

It's actually almost easier to have them show up but then we have to consider those that lie to the left and the right of the circle which are currently not considered since all squares will have x < Radius.

Code

\documentclass[tikz]{standalone}
\newif\iftikzcirclewithsquaresoutside
\tikzset{cws/.cd,
  circle/.style=draw, grid/.style=draw,
  rect/.style={fill=blue!50},
  every/.style={
    /pgf/declare function={
      cwsRadius=\pgfkeysvalueof{/tikz/cws/radius};
      cwsStep=\pgfkeysvalueof{/tikz/cws/step};}},
  radius/.initial=10, step/.initial=1,
  outside/.is if=tikzcirclewithsquaresoutside}
\newcommand*\tikzcirclewithsquares[1][]{%
  \scope[cws/.cd,every,#1]
    \foreach[
      parse=true,
      remember=\notY as \lastNotY (initially cwsRadius/cwsStep),% sqrt(R²)/Step
      evaluate={
        \cwsX = cwsStep*\step;
        \notY = sqrt(cwsRadius*cwsRadius-\cwsX*\cwsX)/cwsStep;
        \cwsY = \iftikzcirclewithsquaresoutside ceil\else floor\fi
              (\iftikzcirclewithsquaresoutside\lastNotY\else\notY\fi)*cwsStep;},
      /tikz/at y0.0/.style=\unless\iftikzcirclewithsquaresoutside path only\fi,
    ] \step in {1,...,0+cwsRadius/cwsStep} {
      \fill[cws/rect, at y\cwsY/.try]
        ( \cwsX-cwsStep,-\cwsY) rectangle ( \cwsX,\cwsY)
        (-\cwsX+cwsStep,-\cwsY) rectangle (-\cwsX,\cwsY);
      \draw[step=cwsStep, cws/grid, at y\cwsY/.try]
        ( \cwsX-cwsStep,-\cwsY) grid      ( \cwsX,\cwsY)
        (-\cwsX+cwsStep,-\cwsY) grid      (-\cwsX,\cwsY);
    }
    \draw[radius=cwsRadius,cws/circle] circle[];
  \endscope
}
\begin{document}
\begin{tikzpicture}[column sep=5mm, row sep=5mm]
\matrix{
  \tikzcirclewithsquares[]
& \tikzcirclewithsquares[circle/.append style=thick, outside]
\\
  \tikzcirclewithsquares[radius=5, step=.5, rect/.style=green, outside]
& \tikzcirclewithsquares[radius=7.5, rect/.style=path only, step/.evaluated=abs(random)]
\\};
\end{tikzpicture}
\end{document}

Output

enter image description here

5
  • I am curious to know: If you want the squares to stay both inside the circle and on the periphery of the circle, what would you do?
    – UnknownW
    Commented Feb 25, 2023 at 22:59
  • @UnknownW I've updated my answer so that it is possible to toggle the squares that get crossed by the circle show up but not those that touch the circle from the outside. Commented Feb 26, 2023 at 0:57
  • @Qrrbrbirlbel Have you written a tutorial on how to use advanced TikZ techniques? If not, it would be great to have such a document.
    – projetmbc
    Commented Feb 26, 2023 at 8:27
  • @projetmbc I did not. I'm also not sure if I'm the right person for it (the number besides my name is an imaginary one). I just like generalized solutions which often times come with PGFKeys and a more convoluted way to solve a problem. This answer is almost totally powered by actual math (this can be reduced to simple math after all). There a a few weird things in this answer though: I'm declaring PGFmath functions for a constant (radius and step) even though it would be better to evaluate those once and save them in a macro – speedwise. Commented Feb 28, 2023 at 21:40
  • The other thing is the low-level \if… inside a PGFmath function even though it could've been a ifthenelse. Here I opted for the faster (and easier to implement) approach. I struggle between a top-level TikZ approach (no @ in macro names, no undocumented usage of things) and an optimized hard to follow and adapt low-level solution. Commented Feb 28, 2023 at 21:42
8

Adaptations

  • set for range to {-10,...,10}
  • I added a parameter \radius
  • use ++(1,1) to specify the size of the rectangle without having to repeat the origin coordinates
  • extend condition to check all 4 corners:
\pgfmathparse{
    (\x+1)^2 + (\y+1)^2 <= \radius^2 &&
    (\x+1)^2 + (\y)^2   <= \radius^2 &&
    (\x)^2   + (\y+1)^2 <= \radius^2 &&
    (\x)^2   + (\y)^2   <= \radius^2
}
  • or shorter version:
max( (\x)^2, (\x+1)^2 ) + max( (\y)^2, (\y+1)^2 ) <= \radius^2

Result

enter image description here

Code

\documentclass[tikz, margin=2mm]{standalone}

\begin{document}
\begin{tikzpicture}
    \def\radius{10}
    \foreach \x in {-\radius,...,\radius} {
        \foreach \y in {-\radius,...,\radius} {
            \pgfmathparse{
                (\x+1)^2 + (\y+1)^2 <= \radius^2 &&
                (\x+1)^2 + (\y)^2   <= \radius^2 &&
                (\x)^2   + (\y+1)^2 <= \radius^2 &&
                (\x)^2   + (\y)^2   <= \radius^2
            } %Condition of squares to stay inside the circle. 
            %This circle is translated to make it work.
            \ifnum\pgfmathresult=1
                \filldraw[fill=blue!50] (\x,\y) rectangle ++(1,1); %Colouring the squares
            \fi
        }
    }
    \draw (0,0) circle [radius=\radius]; %Circle
\end{tikzpicture}
\end{document}

Extension

To make it more interesting and not completely symmetric you could add some x and y shift to the rectangles (with parameters \squaresXshift and \squaresYshift in [0,1]).

Code

\documentclass[tikz, margin=2mm]{standalone}

\begin{document}
\begin{tikzpicture}
    \def\radius{6}
    \def\squaresXshift{.3}
    \def\squaresYshift{.1}
    \foreach \x [evaluate=\x as \xp using {\x+\squaresXshift}] in {-\radius,...,\radius} {
        \foreach \y [evaluate=\y as \yp using {\y+\squaresYshift}] in {-\radius,...,\radius} {
            \pgfmathparse{
                (\xp+1)^2 + (\yp+1)^2 <= \radius^2 &&
                (\xp+1)^2 + (\yp)^2   <= \radius^2 &&
                (\xp)^2   + (\yp+1)^2 <= \radius^2 &&
                (\xp)^2   + (\yp)^2   <= \radius^2
            } %Condition of squares to stay inside the circle. 
            %This circle is translated to make it work.
            \ifnum\pgfmathresult=1
                \filldraw[fill=blue!50] (\xp,\yp) rectangle ++(1,1); %Colouring the squares
            \fi
        }
    }
    \draw (0,0) circle [radius=\radius]; %Circle
\end{tikzpicture}
\end{document}

Result

enter image description here

4
  • Is it also possible to add a parameter \side to make squares smaller for better comparision? I believe one should simply write (\x+\side,\y+\side) instead of (\x+1,\y+1)
    – UnknownW
    Commented Feb 25, 2023 at 20:52
  • If you use the square as unit square, you don't need to change that. You could just decrease the size of the circle, to make them bigger in relation.
    – dexteritas
    Commented Feb 25, 2023 at 20:55
  • I would also like to construct another figure, where the squares stay both inside the circle and on the periphery of the circle. I have tried one by modifying radius and "for each" into \def\radius{12} \foreach \x in {-10,...,9} { \foreach \y in {-10,...,9}, but then there are still some squares that are outside the circle that need to be removed.
    – UnknownW
    Commented Feb 25, 2023 at 23:11
  • For that you could check if at least one corner is within the circle, so use "or" || instead of "and" && in the condition.
    – dexteritas
    Commented Feb 26, 2023 at 11:34
5

Due to the symmetry, there are two options: either the center of the circle coincides with the corner of a square or with the center of a square. A priori it is not clear which option wins. However, a simple computation reveals which option is far more plausible to win.

enter image description here

It turns out that either of the options can win (though the first one is more frequent).

enter image description here

enter image description here

This is the code with examples.

\documentclass{article}
\usepackage[fleqn]{mathtools}
\usepackage{enumitem}
\usepackage{cleveref}
\usepackage{geometry}
\usepackage{tikz}
\usepackage{xfp}
\newlist{options}{enumerate}{1}
\setlist[options]{label=\roman*.,ref=\roman*}
\crefname{optionsi}{option}{options}
\begin{document}
Due to the symmetry of the problem, there are only two options: the center of the circle coincides with
\begin{options}
 \item the corner of one of the squares\label{option1}, or 
 \item the center of one of the squares\label{option2}.   
\end{options}    
\begin{figure}[htb]
    \centering\begin{tikzpicture}[declare function={R=2.5;phi=15;}]
        \draw circle[radius=R];
        \draw (0,0) -- node[above]{$R$} (phi:R) -- node[right]{$b=\begin{dcases}
           a & (\text{\cref{option1}}) \\
           \frac{a}{2}& (\text{\cref{option2}})
        \end{dcases}$} ({cos(phi)*R},0) -- node[below]{$R\sqrt{1-(b/R)^2}$} cycle;   
       \end{tikzpicture}
    \caption{Setup.}    
    \label{fig:setup}   
\end{figure}

Call the edge length of the square $a$ and the radius of the circle $R$. The requirement is then that $a$ (see \Cref{fig:setup}) fulfills
\begin{align}
    R\sqrt{1-\frac{a^2}{R^2}}&\ge n\,a\,,\tag{\text{\cref{option1}}}\\
    R\sqrt{1-\frac{a^2}{4R^2}}&\ge (n+\tfrac{1}{2})\,a\,.\tag{\text{\cref{option2}}}
\end{align}
In both cases, $n$ denotes the number of squares which are entirely right of the center. Therefore, 
\begin{equation}
    n=\begin{dcases}
        \left\lfloor \frac{R}{a}\sqrt{1-(a/R)^2}\right\rfloor\,,&(\text{\cref{option1}})\\
        \left\lfloor \frac{R}{a}\sqrt{1-(a/2R)^2}-\frac{1}{2}\right\rfloor\,.&(\text{\cref{option2}})
    \end{dcases}\label{eq:n}
\end{equation}
Unfortunately, if we know $n$, it is not obvious what the total number of squares, $N$, is. However, it appears reasonable to assume that it scales with the square of the number of squares in the widest row,
\begin{equation}
 N\sim  \begin{dcases}
    4n^2\,,&(\text{\cref{option1}})\\
    (2n+1)^2\,.&(\text{\cref{option2}})  
\end{dcases} \label{eq:N}
\end{equation}
We now can fill the circle with square depending on which option leads to the larger $N$.
\begingroup
\def\R{6}
\foreach \ff in {1,...,7}  
{\clearpage\begin{tikzpicture}
  \pgfmathsetmacro{\a}{\R*exp(-0.5*\ff)}  
  \pgfmathtruncatemacro{\ni}{\fpeval{floor(\R*sqrt(1-\a*\a/(\R*\R))/\a)}} % this locally overwrites the macro \ni
  \pgfmathtruncatemacro{\nii}{\fpeval{floor(\R*sqrt(1-\a*\a/(\R*\R))/\a-0.5)}}
  \pgfmathtruncatemacro{\Ni}{\fpeval{4*\ni*\ni}}
  \pgfmathtruncatemacro{\Nii}{\fpeval{(2*\nii+1)^2}}
  \draw circle[radius=\R] (90:\R)node[above]{$a=\a$}
  (-90:\R) node[below]{\ifnum\Ni>\Nii\relax 
    \cref{option1} wins: $n=\ni$\else
    \cref{option2} wins: $n=\nii$
  \fi};
  \ifnum\Ni>\Nii\relax
    \foreach \Y in {1,...,\ni} 
    {\pgfmathtruncatemacro{\nx}{floor(\R*sqrt(1-(\a*\Y)^2/(\R*\R))/\a)}
    \foreach \X in {1,...,\nx}
    {\draw (\X*\a,\Y*\a) rectangle ++ (-\a,-\a)
        (-\X*\a,\Y*\a) rectangle ++ (\a,-\a)
        (-\X*\a,-\Y*\a) rectangle ++ (\a,\a)
        (\X*\a,-\Y*\a) rectangle ++ (-\a,\a); }}
  \else
    
    \foreach \Y in {1,...,\nii} 
    {\draw ({0.5*\a},{(\Y+0.5)*\a}) rectangle ++ (-\a,-\a)
    ({-(\Y+0.5)*\a},{0.5*\a}) rectangle ++ (\a,-\a)
    ({(\Y+0.5)*\a},{0.5*\a}) rectangle ++ (-\a,-\a)
    ({0.5*\a},{-(\Y+0.5)*\a}) rectangle ++ (-\a,\a);
    \pgfmathtruncatemacro{\nx}{floor(\R*sqrt(1-(\a*\Y)^2/(\R*\R))/\a-0.5)-1}
    \ifnum\nx>0\relax
    \foreach \X in {1,...,\nx}
    {\draw ({(\X+0.5)*\a},{(\Y+0.5)*\a}) rectangle ++ (-\a,-\a)
        ({-(\X+0.5)*\a},{(\Y+0.5)*\a}) rectangle ++ (\a,-\a)
        ({-(\X+0.5)*\a},{-(\Y+0.5)*\a}) rectangle ++ (\a,\a)
        ({(\X+0.5)*\a},{-(\Y+0.5)*\a}) rectangle ++ (-\a,\a); 
    }
    \fi}
\fi
\end{tikzpicture}\par}
\endgroup    
\end{document}

You must log in to answer this question.

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