7

Recently I have discovered pgfplots and I am impressed by the capabilities of this package. There is however one type of plots which I cannot figure out how to define conveniently using pgfplots.

Basically I would like to plot a square grid with a subset of squares marked (I'm sorry, as a new user I'm not allowed to post images). I am aware that I can follow/modify the example from the manual in which a closed shape is drawn:

% Preamble: \pgfplotsset{width=7cm,compat=1.6}
\begin{tikzpicture}
\begin{axis}
\addplot+[fill] coordinates
{(0,1) (1,2) (0,3) (-1,2)} --cycle;
\end{axis}
\end{tikzpicture}

But I'm wondering - is it possible to define such plot passing only the integer coordinates of squares to mark, rather than lists of four precise corners of each square?

5
  • You have the grid option.
    – Sigur
    Commented Aug 25, 2012 at 14:30
  • I'm not talking about the grid, but coordinate input. Commented Aug 25, 2012 at 14:50
  • the rectangle command needs only the left-down and right-up coordinates. You can try \foreach \x in {1,2,...,5}{ \draw (0,0) rectangle (\x,\x); } You can use other values to produce the non square rectangles.
    – Sigur
    Commented Aug 25, 2012 at 15:01
  • @PrzemysławPietrzkiewicz: You can post a link to your image, then a user with enough rep can edit your question to include the picture.
    – Count Zero
    Commented Aug 25, 2012 at 15:13
  • @Sigur: I didn't know about the \foreach construct; it looks handy. Many thanks! Commented Aug 25, 2012 at 19:36

1 Answer 1

5

I wasn't sure if you wanted stacks or slabs, so here is both:

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}
\usepackage{arrayjobx}
\usepackage{trimspaces}
\usepackage{xifthen}

\makeatletter
\def\trimspace#1{\trim@spaces@in{#1}}
\makeatother

\newcommand{\getslab}[2]{\checkdrawsquares(#1,#2)\trimspace\cachedata}

\newcommand{\drawstacks}[3]% fillheights, baroptions, gridoptions
{   \draw[#3] (0,0) grid (\gridwidth,\gridheight);
    \foreach \x [count=\c] in {#1}
    {   \fill[#2] (\c-1,0) rectangle (\c,\x);
    }
}

\newcommand{\drawslabs}[3]% dataarray, slaboptions, gridoptions
{   \draw[#3] (0,0) grid (\gridwidth,\gridheight);
    \foreach \x in {1,...,\gridwidth}
    { \foreach \y in {1,...,\gridheight}
        {   \pgfmathtruncatemacro{\colnum}{\x}
            \pgfmathtruncatemacro{\rownum}{\gridheight+1-\y}
            \getslab{\rownum}{\colnum}
            \ifthenelse{\cachedata>0}
                {\fill[#2] (\x-1,\y-1) rectangle (\x,\y);}
                {}
        }
    }
}

\begin{document}

\pgfmathtruncatemacro{\gridwidth}{13}
\pgfmathtruncatemacro{\gridheight}{7}

\newarray\drawsquares
\readarray{drawsquares}{%
1 & 1 & 1 & 1 & 0 & 1 & 0 & 0 & 1 & 0 & 1 & 1 & 1 &%
0 & 0 & 1 & 1 & 1 & 1 & 0 & 1 & 0 & 1 & 1 & 0 & 0 &%
1 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 1 & 1 & 1 & 0 & 1 &%
1 & 1 & 1 & 0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 &%
1 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 &%
1 & 1 & 1 & 0 & 1 & 1 & 0 & 0 & 1 & 0 & 0 & 1 & 0 &%
0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 0 & 1 & 1 & 1}
\dataheight=\gridwidth%

\begin{tikzpicture}
    \drawstacks{1,7,5,0,3,0,0,2,3,4,6,4,7}{red!50!gray,fill opacity=0.5,draw=red!50!gray,thick}{gray,densely dashed}
\end{tikzpicture}

\begin{tikzpicture}
    \drawslabs{drawsquares}{red!50!gray,fill opacity=0.5,draw=red!50!gray,thick}{gray,densely dashed}{red}{gray}
\end{tikzpicture}

\end{document}

enter image description here


Edit 1: I managed it, only forgot the \expandafter before \csname yesterday.

Updated \getslab

\newcommand{\getslab}[3]{\expandafter\csname check#1\endcsname(#2,#3)\trimspace\cachedata}

Updated \drawslabs

\newcommand{\drawslabs}[3]% arraname, slaboptions, gridoptions
{   \draw[#3] (0,0) grid (\gridwidth,\gridheight);
    \foreach \x in {1,...,\gridwidth}
    { \foreach \y in {1,...,\gridheight}
        {   \pgfmathtruncatemacro{\colnum}{\x}
            \pgfmathtruncatemacro{\rownum}{\gridheight+1-\y}
            \getslab{#1}{\rownum}{\colnum}
            \ifthenelse{\cachedata>0}
                {\fill[#2] (\x-1,\y-1) rectangle (\x,\y);}
                {}
        }
    }
}

New sample input

\pgfmathtruncatemacro{\gridwidth}{13}
\pgfmathtruncatemacro{\gridheight}{7}

\newarray\drawsquares
\readarray{drawsquares}{%
1 & 1 & 1 & 1 & 0 & 1 & 0 & 0 & 1 & 0 & 1 & 1 & 1 &%
0 & 0 & 1 & 1 & 1 & 1 & 0 & 1 & 0 & 1 & 1 & 0 & 0 &%
1 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 1 & 1 & 1 & 0 & 1 &%
1 & 1 & 1 & 0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 &%
1 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 &%
1 & 1 & 1 & 0 & 1 & 1 & 0 & 0 & 1 & 0 & 0 & 1 & 0 &%
0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 0 & 1 & 1 & 1}
\dataheight=\gridwidth%

\begin{tikzpicture}
    \drawstacks{1,7,5,0,3,0,0,2,3,4,6,4,7}{red!50!gray,fill opacity=0.5,draw=red!50!gray,thick}{gray,densely dashed}
\end{tikzpicture}

\begin{tikzpicture}
    \drawslabs{drawsquares}{red!50!gray,fill opacity=0.5,draw=red!50!gray,thick}{gray,densely dashed}{red}{gray}
\end{tikzpicture}

\delarray\drawsquares% Deleting the old array; don't reuse names of deleted arrays!

% define a "new array" by just interchanging width and height

\pgfmathtruncatemacro{\gridwidth}{7}% changed from 13 to 7
\pgfmathtruncatemacro{\gridheight}{13}% changed from 7 to 13

\newarray\verticalarray% new name
\readarray{verticalarray}{%
1 & 1 & 1 & 1 & 0 & 1 & 0 & 0 & 1 & 0 & 1 & 1 & 1 &%
0 & 0 & 1 & 1 & 1 & 1 & 0 & 1 & 0 & 1 & 1 & 0 & 0 &%
1 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 1 & 1 & 1 & 0 & 1 &%
1 & 1 & 1 & 0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 &%
1 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 &%
1 & 1 & 1 & 0 & 1 & 1 & 0 & 0 & 1 & 0 & 0 & 1 & 0 &%
0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 0 & 1 & 1 & 1}
\dataheight=\gridwidth% similar array as before, but this time interpreted as 7x13 instead of 13x7

\begin{tikzpicture}
    \drawslabs{verticalarray}{red!50!gray,fill opacity=0.5,draw=red!50!gray,thick}{gray,densely dashed}{red}{gray}
\end{tikzpicture}

New sample output (with geometry option a3paper)

enter image description here

7
  • I am genuinely impressed; this is exactly what I needed. Many thanks for your time! Commented Aug 25, 2012 at 19:40
  • Thanks! As I didn't explain how it works and hope that the code is well readable, please feel free to ask if anything is unclear. Commented Aug 25, 2012 at 19:44
  • You can also have a look at this question, there I did something comparable to this problem. Commented Aug 25, 2012 at 19:56
  • I have just one question for now - do I understand correctly, that \drawslabs does not really make use of its first parameter, as the name of the array is hardcoded in form of "\checkdrawsquares" call? Is there any way to effectively parametrize \drawslabs with the array being drawn? Commented Aug 25, 2012 at 23:55
  • Yes, I tried to do something like \check#1 which obviousely does not work. It should probably be something like \csname check#1 \endcsname. I'll try this tomorrow and let you know of the results. Commented Aug 26, 2012 at 0:21

You must log in to answer this question.

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