1

I am trying to define a matrix of nodes programmatically but have issues regarding the step of defining the nodes of the matrix.

The nodes are of different sizes (dimensionsBigBox and dimensionsSmallBox) and I can define them but only "hardcoded" ( i.e. by defining the style of nodes by row or by column or even node by node (syntax /row 1) ). I would like to define them dynamically as I have a variable defining which style the node x needs to be.

Is this possible ?

I did an minimal working example, but the application has actually a number of nodes I don't know a priori.

\documentclass[border=2mm,tikz]{standalone}
\usetikzlibrary{matrix}

\begin{document}
\tikzset{dimensionsBigBox/.style={
        minimum height=3cm,
        rectangle, 
        fill=none, draw=blue,
        text depth=0.5em, text height=1em,
}}

\tikzset{dimensionsSmallBox/.style={
        minimum height=1cm,
        rectangle, 
        fill=none, draw=red,
        text depth=0.5em, text height=1em,
}}

\tikzset{
mygridmatrix/.style={
    matrix of nodes, 
       row sep=-\pgflinewidth, column sep=-\pgflinewidth, 
       nodes={draw, minimum size=1cm}, 
       nodes in empty cells,
    row 1/.style={
        nodes={
            dimensionsBigBox
        }
    },
    row 2/.style={
        nodes={
            dimensionsSmallBox
        }
    },
    row 3/.style={
        nodes={
            dimensionsBigBox
        }
    },
       },
}

\begin{tikzpicture}
\foreach \x/\y  in  {1/dimensionsBigBox, 2/dimensionsBigBox, 3/dimensionsBigBox, 4/dimensionsSmallBox, 5/dimensionsSmallBox, 6/dimensionsSmallBox, 7/dimensionsBigBox, 8/dimensionsBigBox, 9/dimensionsBigBox}{
    Set style \y for node  \x \\
}
\matrix (m) [mygridmatrix]
{
&&&\\
&&&\\
&&&\\
};

\end{tikzpicture}

\end{document}

Additionnal context to be added :

Currently, row 1 and 3 are BigBox. If I want to have row 1 only to be BigBox, I need to change the hardcoded style of the rows :

    row 1/.style={
        nodes={
            dimensionsBigBox
        }
    },
    row 2/.style={
        nodes={
            dimensionsSmallBox
        }
    },
    row 3/.style={
        nodes={
            dimensionsBigBox
        }
    },

I would like to have latex code that actually allows me to define each node separately, by looping on my variables defining all the nodes.

\foreach \x/\y  in  {1/dimensionsBigBox, 2/dimensionsBigBox, 3/dimensionsBigBox, 4/dimensionsSmallBox, 5/dimensionsSmallBox, 6/dimensionsSmallBox, 7/dimensionsBigBox, 8/dimensionsBigBox, 9/dimensionsBigBox}{
    Set style \y for node  \x \\
}

============ edit for follow-up on the issue ==================

I posted a more precise question regarding the issue : Append style for matrix of nodes in a loop dosn't work

  • I am not sure I understand the question but yes, as detailed in section 57.1 of the pgfmanual, you can add arbitrary nodes in the matrix. – user121799 Jun 20 '18 at 18:33
  • Sorry, I was too brief, I added more context. I checked the section 57.1, but it's about plots (p 541). I don't see where it can help, but maybe it's not the correct manual that I took ? – Aline Jun 20 '18 at 18:46
  • Thanks. Just to clarify: you are not looking for \matrix[matrix of nodes] (m) { |[dimensionsBigBox]|& |[dimensionsBigBox]| &|[dimensionsBigBox]|\\ |[dimensionsSmallBox]|& |[dimensionsSmallBox]| &|[dimensionsSmallBox]|\\ |[dimensionsBigBox]|& |[dimensionsBigBox]| &|[dimensionsBigBox]|\\ };, are you? – user121799 Jun 20 '18 at 19:06
  • I don't think so as I need the naming of the nodes. – Aline Jun 20 '18 at 19:12
  • But the nodes do have a name, just add \draw (m-1-1.center) -- (m-3-1.center); to my above code. – user121799 Jun 20 '18 at 19:14
4

It is not easy to set the style in foreach loop because it is executed in local group and the styles do not persist outside.

To overcome this you can use another loop, for example \xintFor or \xintForpair from xinttools library.

Here is an example how to do it.

\documentclass[tikz,border=7pt]{standalone}
\usetikzlibrary{matrix}
\usepackage{xinttools}

\xintForpair #1#2 in  {(1,red), (2,blue), (3,purple), (4,orange),(7,pink)} \do {
  \pgfmathsetmacro\row{int(div(#1-1,4)+1)}
  \pgfmathsetmacro\col{int(mod(#1-1,4)+1)}
  \tikzstyle{row \row\space column \col}=[nodes={fill=#2}]
}
\begin{document}
  \begin{tikzpicture}
    \matrix (m)[
      matrix of nodes,
       row sep=-\pgflinewidth, column sep=-\pgflinewidth,
       nodes={draw, minimum size=1cm},
       nodes in empty cells
    ]
    {
      &&&\\
      &&&\\
      &&&\\
    };
  \end{tikzpicture}
\end{document}

enter image description here

Note: I use tikzstyle just to test the patience of tikzset-ayatollahs ;)

  • Hi, thx for the proposal. I have tried it, but it doesn't apply to my case : I am trying to modify the definition of the nodes, not the filling or the style of the nodes. In your example, the position of the nodes are fixed and outside tikzset. The other reason I need to use tikzset is that I have my own labelling/naming for the nodes, hence I can't have a "\matrix [matrix of nodes]" – Aline Jun 20 '18 at 23:13
  • @Aline Sorry I do not understand your question. I was answering your last request \foreach \x/\y in {1/dimensionsBigBox,...}{Set style \y for node \x} by supposing that your nodes are in a matrix as in your MWE. You can replace fill=#2 by #2 and the colors red, blue,... by dimensionsBigBox, dimensionsSmallBox,... . – Kpym Jun 21 '18 at 5:16
  • Actually, your answer was helping since I didn't know about xintFor : I have been using it to loop append to the style (" \tikzset{mygridmatrix/.append style={row \row\space column \col/.style={nodes={#2}}}} ") ; unfortunately, the change of style only happens to the last node, I guess that the "append" overwrite each other. – Aline Jun 21 '18 at 7:37
1

I am still confused about the question. Instead of defining an array to define the nodes of a matrix, why not just put the nodes directly into that matrix? And I do not understand the statement about node names either, they do have names and you can work with alias. It would be nice if you could tell me what is wrong with the following such that someone can finally answer the question.

\documentclass[border=2mm,tikz]{standalone}
\usetikzlibrary{matrix}

\begin{document}
\tikzset{dimensionsBigBox/.style={
        minimum height=3cm,
        rectangle, 
        fill=none, draw=blue,
        text depth=0.5em, text height=1em,
}}

\tikzset{dimensionsSmallBox/.style={
        minimum height=1cm,
        rectangle, 
        fill=none, draw=red,
        text depth=0.5em, text height=1em,
}}


\begin{tikzpicture}[every node/.append style={minimum width=6mm}]
\matrix[matrix of nodes] (m) {%
|[dimensionsBigBox,alias=topleft]|& |[dimensionsBigBox]| &|[dimensionsBigBox]|\\ 
|[dimensionsSmallBox]|& |[dimensionsSmallBox]| &|[dimensionsSmallBox]|\\ 
|[dimensionsBigBox]|& |[dimensionsBigBox]| &|[dimensionsBigBox,alias=bottomright]|\\ };
\draw[blue,-latex] (topleft.center) -- (bottomright.center);
\end{tikzpicture}

\end{document}

enter image description here

  • I built code that defines matrix programmatically : nothing is hardcoded and a matrix is defined according to specification decided at the call/compilation. – Aline Jun 21 '18 at 7:40
  • (Continuation of the comment) All the nodes are accessible by their name so that changes are made easily. I didn't know about alias of nodes, it could be useful, but the reason I need a matrix of nodes is because I have tried with matrix of nodes directly (by opposition to matrix of nodes in a style) and it was impossible to achieve what I want (like anchor and style of each node). Hence my decision to go with matrix of nodes within tikzset. – Aline Jun 21 '18 at 7:47
  • @Aline I still don't understand your point. When you are saying nothing is hardcoded, at a given point you need to specify the information what the style of each entry is. If you get this information from an external program, say, you could equally well write the matrix itself with that program. – user121799 Jun 21 '18 at 14:23
  • I could but then I would need to migrate all the existing code, which is not easy task. – Aline Jun 21 '18 at 16:47

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.