7

So the question is a tikz one!

Assume that you are drawing things inside two nested foreach loops in tikz, and the iterator variables are \x and \y. What I'd like to obtain is to be able to specify a list of (x,y) pairs, s.t when drawing inside my two nested loops, I can apply one predefined style "A" if (\x,\y) matches a pair in the list, otherwise applies style "B".

Any ideas on how I can obtain this?

Simple example could be the following code, which draws 16 lines on a sheet. I might want the condition that when \x is even, then it should use style "B" instead of style "A", but in all generality, I want to be able to specify the specific (\x,\y) pairs that will use style "B" rather than "A".

\documentclass{article}
\usepackage{tikz}
\begin{document}
    \begin{tikzpicture}[
        A/.style={draw,color=red},
        B/.style={draw,color=blue}
    ]
    \foreach \x in {0,1,2,3} {
        \foreach \y in {0,1,2,3} {
            \draw[A] (2*\x,4*\y) -- (4*\y,3*\x);
        }
    }
    \end{tikzpicture}
\end{document}
2
  • 3
    Can you introduce a simple red blue example? It doesn't have to be functional but complete in terms of copy/paste. It's great to play around with questions but setting them up with documentclass etc. is pretty dull.
    – percusse
    Mar 6 '13 at 15:05
  • 1
    As requested, I added an example. I hope this is what you mean by "red blue example" :) Mar 6 '13 at 15:23
3

Update: using xstring

My original solution used stringstrings package which is extremely slow. Package xstring provides the same functionality, with a cleaner syntax, and it is much faster.

The following example (which uses xstring) takes 0.902s to compile in my box. The same example using stringstrings requires 16.575s!

This example is the same you posted in your question.

\documentclass{standalone}
\usepackage{xstring}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[
A/.style={draw,color=red},
B/.style={draw,color=blue}
]
\def\mylist{(0,1) (0,2) (0,3) (0,4) (2,1) (2,2) (2,3) (2,4)}
\foreach \x in {0,1,2,3} {
\foreach \y in {0,1,2,3} {
     \IfSubStr{\mylist}{(\x,\y)}{\def\mystyle{B}}{\def\mystyle{A}}
     \draw[\mystyle] (2*\x,4*\y) -- (4*\y,3*\x);
}
}
\end{tikzpicture}
\end{document}

Result

Original answer:

An easy solution using stringstrings package (perhaps not the more adequate to deal with lists, but it's easy to use and does the work in this case):

\documentclass{standalone}
\usepackage{stringstrings}
\usepackage{tikz}

\tikzset{
 a/.style = {fill=yellow!20, ultra thick},
 b/.style = {fill=black!20}
}

\def\mylist{(3,2) (2,1) (4,1)}

\begin{document}
\begin{tikzpicture}
\foreach \x in {1,...,4} {
  \foreach \y in {1,...,3} {
     \whereisword{\mylist}{(\x,\y)}
     \ifnum\theresult=0\def\mystyle{b}\else\def\mystyle{a}\fi
     \node[draw, circle, \mystyle] at (\x,\y) {\x,\y};
  }
}
\end{tikzpicture}
\end{document}

Result:

Result

3
  • This is definately a solution! However, using this trick seems to slow compilation A LOT. It takes about 10-15 seconds just to compile this single tikz figure now, and I will be having several of those in my paper. Can I optimize it in any way, or do you know a faster solution? Mar 6 '13 at 15:51
  • @MartinLauridsen Updated answer :-)
    – JLDiaz
    Mar 6 '13 at 16:02
  • Thank you, that improved quite a bit! Great answer, kudos. Mar 6 '13 at 16:18

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.