2

I am trying to draw an annulus on a square grid which represents pixels of an image sensor. If the center of the pixel is on the annulus, i.e. between the outer and inner circles, it will be filled with green color. Otherwise, the pixel should be filled red color.

My current code (without checking the inner circle yet) is:

\documentclass{standalone}
\usepackage{tikz}

\begin{document}

\def\outerradius{5}
\def\innerradius{1}
\begin{tikzpicture}[y=-1cm,scale=0.35,font=\small,
  lightgreenpixel/.style={green!20!white,},
  lightredpixel/.style={red!20!white,},
  ]

  \draw[help lines,thick,] (-5,-5) grid (5, 5);
  \draw[thick] (0, 0) circle [radius=5];
  \draw[thick] (0, 0) circle [radius=1];

  \foreach \x in {-5,-4,...,5}
    \foreach \y in {-5,-4,...,5}
    {
      \pgfmathparse{((\x+0.5)*(\x+0.5)+(\y+0.5)+(\y+0.5)) < \outerradius*\outerradius ? int(1) : int(0)}
      \ifnum\pgfmathresult=1
        \fill[lightgreenpixel] (\x,\y) rectangle ++(1,1);
      \else
        \fill[lightredpixel] (\x,\y) rectangle ++(1,1);
      \fi
    }

\end{tikzpicture}
\end{document}

The result is shown below which does not look right at all.

enter image description here

I have been searching how to use if-then-else statements withing TikZ \foreach loop and got a feeling that the \pgfmathparse command is the right one to use. However I might be on the wrong boat. Any help or suggestions would be greatly appreciated!

2 Answers 2

4

You used an addition instead of a multiplication in the second term of (\x+0.5)*(\x+0.5)+(\y+0.5)*(\y+0.5) (your code had (\x+0.5)*(\x+0.5)+(\y+0.5)+(\y+0.5)). Also, the upper loop bounds needed a little adjustment, otherwise you weren't too far.

I draw the circles after the pixels so that we can see them (alternatively, you could use opacity).

\documentclass[tikz, border=0mm]{standalone}
\begin{document}

\def\outerradius{5}
\def\innerradius{1}

\begin{tikzpicture}[
  y=-1cm, scale=0.35, font=\small,
  lightgreenpixel/.style={green!20!white,},
  lightredpixel/.style={red!20!white,},
  ]

  % These can be precomputed to save time.
  \pgfmathsetmacro{\innersquared}{(\innerradius)^2}
  \pgfmathsetmacro{\outersquared}{(\outerradius)^2}

  \foreach \x in {-5,-4,...,4}
    \foreach \y in {-5,-4,...,4}
    {
      \pgfmathsetmacro{\rtwo}{(\x+0.5)^2 + (\y+0.5)^2}
      \pgfmathparse{(\rtwo < \innersquared ? 0 :
                      (\rtwo < \outersquared ? 1 : 0))}
      \ifnum\pgfmathresult=1
        \fill[lightgreenpixel] (\x,\y) rectangle ++(1,1);
      \else
        \fill[lightredpixel] (\x,\y) rectangle ++(1,1);
      \fi
    }

  \draw[help lines,thick,] (-5,-5) grid (5, 5);
  \draw[thick] (0, 0) circle [radius=5];
  \draw[thick] (0, 0) circle [radius=1];
\end{tikzpicture}

\end{document}

enter image description here

2
  • Ah, stupid me to use the wrong operator. Thanks also for the extra example on \pgfmathsetmacro and the nested x?y:z operator. I am going through the Mathematical engine chapter in the PGF/TikZ manual so hopefully I will understand more about the underlying principles.
    – Fanpeng
    Mar 16, 2020 at 2:06
  • You're welcome. \pgfmathsetmacro\yourmacro{...} is essentially a shorthand for \pgfmathparse{...}\let\yourmacro\pgfmathresult (actually, it does the \pgfmathparse inside a group and uses \pgfmath@smuggleone to... smuggle, indeed, the token defined with \let out of the group).
    – frougon
    Mar 16, 2020 at 8:48
2

A small variation of @frougon answer (+1). It differ in definition of the coloring conditions:

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

\begin{document}

\def\outerradius{5}
\def\innerradius{1}
\begin{tikzpicture}[y=-1cm,scale=0.35,font=\small,
  lightgreenpixel/.style={green!20!white,},
  lightredpixel/.style={red!20!white,},
  ]
\pgfmathsetmacro{\r}{\innerradius^2}
\pgfmathsetmacro{\R}{\outerradius^2}
  \foreach \x in {-5,...,4}
    \foreach \y in {-5,...,4}
    {
      \pgfmathparse{int((\x+0.5)^2 + (\y+0.5)^2)}
    \ifnum\pgfmathresult>\r
        \ifnum\pgfmathresult<\R
            \fill[lightgreenpixel] (\x,\y) rectangle ++(1,1);
        \else
            \fill[lightredpixel] (\x,\y) rectangle ++(1,1);
        \fi
    \else
       \fill[lightredpixel] (\x,\y) rectangle ++(1,1);
    \fi
    }
\draw[help lines,thick] (-5,-5) grid (5, 5);
\draw[thick] (0, 0) circle [radius=5] 
             (0, 0) circle [radius=1];
\end{tikzpicture}

\end{document}

Result is the same as in @frougon answer:

enter image description here

2
  • Thanks @Zarko. This is indeed another solution I would like to find as I tried to use the \ifnum command at the first place!
    – Fanpeng
    Mar 16, 2020 at 2:08
  • @Fanpeng, solution has two ˙\ifnum˙ commands in its elementary form :-)
    – Zarko
    Mar 16, 2020 at 6:39

You must log in to answer this question.

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