8

I try to show a huge number as dots in a beamer presentation. Since I'm not too familar with foreach I'm running into several problems.

First the code I tried:

\documentclass{standalone}
   \usepackage{tikz}
   \begin{document}

   \begin{tikzpicture}
     \foreach \x in {0,1,...,96}
       \foreach \y in {0,1,...,95}
         {
           \draw (\x,\y) circle (0.2cm);
           \fill (\x,\y) circle (0.1cm);
         }
   \end{tikzpicture}
   \end{document}

This results in a square of 9120 dots. Unfortunately the number I try to show is only 9050 so the last line should only contain 26 dots.

What I also like to achive is that some dots are colored different. For example shall the dots 2036 to 2148 be colored red.

Is that solvable with foreach or am I following the wrong direction? Do you know a somewhat elegant solution for that?

For Something like this I wanna achieve

4
  • On a somewhat unrelated note, that presentation is going to be quite useless for anyone with Deuteranopia (red/green colorblindness).
    – Grant
    Aug 22 '16 at 16:28
  • I really hope this is not for presenting any data but a weird logo or something else
    – percusse
    Aug 22 '16 at 21:51
  • I am fully aware that this is not the right way to present data. But in this case it is absolutely the effect I wanna achieve. It is to show that there are 9050 arguments on my side and the "opponents" arguments will blur amongst the others. Usually one takes his one argument and tries to give it the power to overtake the discussion especially when one only has this single argument. With this "comparision" I hope to demonstrate the whole discussion is pointless right from the beginning. You see I do this with a purpose ;-) Aug 23 '16 at 8:18
  • I already changed the colors and switched from dots to squares to give it the look of the defragmentation process of old windows systems. ;-) Aug 23 '16 at 8:22
3

I reduced the number of dots for this example, but it will work the same way. The hardest part is that you're using pure filling shapes, which do not have a name so they cannot be referenced.

So I switched to nodes, and added a custom counter. Therefore now each node has a number assigned to it, from 0 to the maximum number. I think in my case there are 702 of them.

To stop drawing any of them, as in your case, you can tell Tikz to draw only the nodes below a certain number. And for the coloring of the nodes, you can use boolean with pgfmath which allows you to verify two conditions, so that everything between those two parameters will have a different color, etc.

Output

enter image description here

Code

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

\newcounter{nonu}
\setcounter{nonu}{0}

\begin{document}
\begin{tikzpicture}

\foreach \y in {0,1,...,26}{
\foreach \x in {0,1,...,25}{

% don't draw more than this
\ifnum\thenonu>689\relax
\else
    \node[fill, circle, inner sep=1mm] (\thenonu) at (\x,\y) {\stepcounter{nonu}};
\fi

% Fill between two numbers
\pgfmathsetmacro\param{\thenonu>80 && \thenonu<142 ?int(1):int(0)}
\ifnum\param=1\relax
    \node[fill=red, circle, inner sep=1mm] at (\x,\y) {};
\fi
}
}
\end{tikzpicture}
\end{document}
2
  • Thank you. This is almost, what I need. Is there a way to start the counting from top left instead of bottom left? Aug 22 '16 at 12:17
  • 1
    @schmendrich Sure, you can either: invert the foreach for the \y as in 26,25,...,0, or you can make all the \y in the code negative, by adding -\y. However, I think the first solution is the best and most appropriate.
    – Alenanno
    Aug 22 '16 at 12:31
3

It is really a lot of circles so if you need to change the style of a few, it is not very efficient though certainly possible to check the current number of the iteration and style it accordingly. But overdrawing the circles saves a lot of compilation time.

\documentclass{article}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}[]

\def\mytotaldots{9050}
\def\mycolno{95}

\pgfmathsetmacro\myresidue{Mod(\mytotaldots,\mycolno)}
\pgfmathparse{\myresidue ==0 ? int(1) : int(0)}
\ifnum\pgfmathresult>0\relax%
  \pgfmathtruncatemacro\myrows{\mytotaldots/\mycolno}%
\else
  \pgfmathtruncatemacro\myrows{\mytotaldots/\mycolno + 1}%
\fi

\foreach \x in {0,1,...,\myrows}{
    \ifnum\x<\myrows\relax\else\let\mycolno\myresidue\fi
    \foreach \y in {0,1,...,\mycolno}{
        \fill[] (\y pt,-\x pt) circle (0.1pt);
    }
}
\end{tikzpicture}
\end{document} 

enter image description here

Second method is orders of magnitude faster as it uses the dotted line instead of drawing explicit circles. The trick is to make the dots align with the path. First example requires LuaTeX, but the following is basically works regardless.

Hence you have much better options to overprint.

\documentclass[margin=5pt,tikz]{standalone}
\begin{document}
\begin{tikzpicture}[
    aligned dots/.style={line width=#1, line cap=round, 
        dash pattern=on 0pt off 2\pgflinewidth
    },
    aligned dots/.default=3pt
    ]

\draw [aligned dots] 
       (0,0) -- (6*95 pt,0) 
        \foreach \x in {0,...,95}{
        --++ (0,-6 pt) -- ++({ifthenelse(Mod(\x,2)==1,94,-94)*6pt},0)}
        ++ (-95*6pt,-6 pt) -- ++(48pt,0pt)
        ;
\draw [aligned dots,draw=yellow] (45*6pt,-15*6pt) -- ++(6*40 pt,0) ;
\draw [aligned dots,draw=red] (30*6pt,-15*6pt) -- ++(0,-6*40 pt) ;    

\end{tikzpicture}
\end{document} 
3
  • The first and the last dot in your is not aligned when I compile your code. Aug 23 '16 at 8:42
  • @schmendrich which one ?
    – percusse
    Aug 23 '16 at 8:50
  • the second one. Aug 23 '16 at 10:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.