9

After a long search period, I was not able to figure out how to determine and use the len of an array like this:

\def\mar{ 1,2 }
\path let \p1=($(rec.west)-(rec.east)$),
              \p2=($(rec.north)-(rec.south)$),
              \p3=($len{\mar}$),
              \n1 = {veclen(\p1)*0.16}                  %width
              ,\n2 = {veclen(\p2)/\p3}                    %height
              in node[mynode,
                      minimum width=\n1
                      ,minimum height=\n2
                      ,anchor=north west
                      ] at (rec.north west) {foobar
                      };
Stefan Kottwitz
  • 231,401
drh
  • 91
  • \p3 needs to be a point but you are assigning a number. Also as far as I know there is no array counter yet (Maybe in the CVS version). What exactly do you want to do with \p3? – percusse Aug 06 '12 at 22:37
  • I like to divide the height by the lenght of my array. – drh Aug 06 '12 at 22:41
  • 1
    With TikZ/pgf, \mar is a simple list. An array should be defined by \def{{1,2}} (p.529, section 63.1, pgfmanual v2.10). – Paul Gaborit Aug 07 '12 at 08:11

3 Answers3

8

I'm not aware of any array length counter in TikZ (it might have been introduced in the CVS version). So getting some help from the xstring package, we count the commas and add one to it.

\documentclass{article}
\usepackage{tikz,xstring}
\usetikzlibrary{calc}
\def\mar{1,2,4,5,7}
\StrCount{\mar}{,}[\arrlength]

\begin{document}
\begin{tikzpicture}
\node[draw,minimum width=2cm,minimum height=5cm] (rec) at (2cm,1cm) {rec};
\path let \p1=($(rec.west)-(rec.east)$),
              \p2=($(rec.north)-(rec.south)$),
              \n{arrlen}={\arrlength+1},
              \n1 = {veclen(\p1)*0.16},           %width
              \n2 = {veclen(\p2)/\n{arrlen}}      %height
              in node[draw,
                      minimum width=\n1
                      ,minimum height=\n2
                      ,anchor=north west
                      ] at (rec.north west) {foobar
                      };
\end{tikzpicture}
I have found \arrlength\space commas in the array.
\end{document}

enter image description here

percusse
  • 157,807
5

Like PolGab wrote in his comment, you have some possibilities to use an array with pgfmath. Here some examples from the pgfmanual :

\def\myarray{{7,-3,4,-9,11}}
\pgfmathparse{\myarray[3]} \pgfmathresult

\def\print#1{\pgfmathparse{#1}\pgfmathresult} \def\identitymatrix{{{1,0,0},{0,1,0},{0,0,1}}} \tikz[x=0.5cm,y=0.5cm]\foreach \i in {0,1,2} \foreach \j in {0,1,2} \node at (\j,-\i) [anchor=base] {\print{\identitymatrix[\i][\j]}};

\pgfmathparse{array({9,13,17,21},2)} \pgfmathresult

Bad news : len of an array does not exist in pgfmath. It's not very complex to add this possibility to pgfmath. Here a simple way without a new package. It's not very efficient but it's simple.

\documentclass[11pt]{scrartcl}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}

\def\getlen#1{%
\pgfmathsetmacro{\lenarray}{0}% 
\foreach \i in #1{%
\pgfmathtruncatemacro{\lenarray}{\lenarray+1}% 
\global\let\lenarray\lenarray}%
}   

  \begin{tikzpicture}
    \node[draw,minimum width=2cm,minimum height=5cm,fill=blue!30,opacity=.5 ] (rec) at (2cm,1cm) {REC};
    \def\mar{1,2}
    \getlen{\mar} 
\path let \p1=($(rec.west)-(rec.east)$),
          \p2=($(rec.north)-(rec.south)$),
          \n1 = {veclen(\p1)*0.16},
          \n2 = {veclen(\p2)/\lenarray}
              in node[draw,minimum width  = \n1,
                      minimum height = \n2,
                      anchor=north west,fill=orange!30,opacity=.5
                      ] at (rec.north west) {foobar};
  \end{tikzpicture}   

\end{document}

enter image description here

Alain Matthes
  • 95,075
  • This seems not to work with {10,20,...,180} construct? If I am correct how to make that work? – Matthias Arras Jan 30 '20 at 13:16
  • @MatthiasArras I think it's normal. {10,20,...,180} construct is useful with \foreach but here it's difficult to use – Alain Matthes Jan 30 '20 at 13:55
  • 1
    Oh yes it works as expected, I was under the impression that \getlen would return the number. But \lenarray does. So indeed \getlen{{1,2,...,10}}\lenarray works and outputs 10. – Matthias Arras Jan 30 '20 at 14:35
4

The following uses a \foreach loop to count the number of members and ignores an empty members as the result of extraneous commas. So for a definition such as

\def\mar{1,2 , 4,, 5 ,7,,,}

this reports 5 members:

enter image description here

Code:

\documentclass{article}
\usepackage{tikz}
\usepackage{xstring}
\usetikzlibrary{calc}

\def\mar{1,2 , 4,, 5 ,7,,,}

\makeatletter \newcounter{@LengthOfArray}% \newcommand{\GetArrayLength}{\arabic{@LengthOfArray}}% \newcommand*{\SetArrayLength}[1]{% % Counts the number of array members. This ignore any empty % array members created by extraneous commas (such as those % as result of a double comma, or a trailing comma. \setcounter{@LengthOfArray}{0}% \foreach \x in #1 {% \IfStrEq{\x}{}{}{% only increment when non-empty \stepcounter{@LengthOfArray}% }% }% }% \makeatother

\begin{document} \SetArrayLength{\mar} \begin{tikzpicture} \node[draw,minimum width=2cm,minimum height=5cm] (rec) at (2cm,1cm) {rec}; \path let \p1=($(rec.west)-(rec.east)$), \p2=($(rec.north)-(rec.south)$), \n{arrlen}={\GetArrayLength}, \n1 = {veclen(\p1)*0.16}, %width \n2 = {veclen(\p2)/\n{arrlen}} %height in node[draw, minimum width=\n1 ,minimum height=\n2 ,anchor=north west ] at (rec.north west) {foobar }; \end{tikzpicture}

\Large There are \GetArrayLength\space members in the array. \end{document}

Peter Grill
  • 223,288