3

I want to create a rectangle path and annotating node that I can parameterize with coordinates, style, and text. Currently, I'm doing this:

\draw[styA] (\Axi,\Ayi) -- (\Axi,\Ayi + \Ayii) node[midway, right] {annotation A} -- (\Axi + \Axii,\Ay + \Ayii) -- (\Axi + \Axii,\Ayi) -- cycle;
\draw[styB] (\Bxi,\Byi) -- (\Bxi,\Byi + \Byii) node[midway, right] {annotation B} -- (\Bxi + \Bxii,\By + \Byii) -- (\Bxi + \Bxii,\Byi) -- cycle;
\draw[styC] (\Cxi,\Cyi) -- (\Cxi,\Cyi + \Cyii) node[midway, right] {annotation C} -- (\Cxi + \Cxii,\Cy + \Cyii) -- (\Cxi + \Cxii,\Cyi) -- cycle;
...

What I want to do is something like this:

\foreach \sty,\annotation,\xi,\xii,\yi,\yii (<more foreachy stuff>)
  \draw[\sty] (\xi,\yi) -- (\xi,\yi + \yii) node[midway, right] {\annotation} -- (\xi + \xii,\y + \yii) -- (\xi + \xii,\yi) -- cycle;

Or this:

\MyFancyCommand{\styA,\annotationA,\Axi,\Axii,\Ayi,\Ayii}
\MyFancyCommand{\styB,\annotationB,\Bxi,\Bxii,\Byi,\Byii}
\MyFancyCommand{\styC,\annotationC,\Cxi,\Cxii,\Cyi,\Cyii}
...

Is there a way to do something like one of these, or part of one of these without having to use an external preprocessor?

9

With a slightly different syntax, you can do this:

\foreach \sty/\annotation/\xi/\xii/\yi/\yii in {%
  <sty 1>/<annotation 1>/<xi 1>/<xii 1>/<yi 1>/<yii 1>,
  <sty 2>/<annotation 2>/<xi 2>/<xii 2>/<yi 2>/<yii 2>,
  …,
  <sty n>/<annotation n>/<xi n>/<xii n>/<yi n>/<yii n>}
  \draw[style/.expand once=\sty]
        (\xi, \yi)               -- (\xi, \yi + \yii) node[midway, right] {\annotation}
     -- (\xi + \xii, \yi + \yii) -- (\xi + \xii,  \yi) -- cycle;

It also might be useful to use relative coordinates:

  \draw[style/.expand once=\sty]
          (\xi,  \yi)  -- + (up:\yii) node[midway, right] {\annotation}
     -- + (\xii, \yii) -- + (right:\xi) -- cycle;

or even

 \draw[style/.expand once=\sty]
   (\xi,  \yi) |- + (\xii, \yii) node[near start, right] {\annotation} |- + (0, 0) -- cycle;

The code below shows an example and the same example with the a to path and the to path example with a .listed key.

This allows also other coordinate systems than the cartesian one for both corners of the rectangles. (With the edges on one path, you can also specify the first corner of the rectangle as a relative coordinate to another rectangle.)

There is also the rectangle path operator, i.e (corner A) rectangle (corner B), but unfortunately, there is no proper timer setup to place the nodes, see Is It Possible to Combine TikZ Distance and Line-To Operations?

You might as well consider doing this as a node, see tikz: Can we set the corner coordinates of a rectangle?

Code

\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}
\foreach \sty/\annotation/\xi/\xii/\yi/\yii in {%
  draw                       /Foo/  0  /1/0  /2  ,
  {fill=blue!25, draw=blue}  /Bar/  1.5/2/-.5/1.5,
  {transform shape,rotate=30}/Woah!/2  /2/0.5/1  }
 \draw[style/.expand once=\sty]
  (\xi,  \yi) |- + (\xii, \yii) node[near start, right] {\annotation}
              |- + (0, 0) -- cycle;
\end{tikzpicture}

\tikzset{
  my Rect/.style={
    to path={
      |- node[near start, right] {#1} (\tikztotarget) |- (\tikztostart)}}}%
\begin{tikzpicture}
\path (0,     0) edge[my Rect=Foo]                               + (1,2)
      (1.5, -.5) edge[my Rect=Bar, fill=blue!25, draw=blue]      + (2, 1.5)
      (2,   0.5) edge[my Rect=Woah!, rotate=30, transform shape] + (2,1);
\end{tikzpicture}

\begin{tikzpicture}[my Foreach/.style args={[#1]#2:#3)#4}{
  insert path={#3) edge[my Rect={#2},#1] #4}}]
\path [my Foreach/.list={{[]                           Foo:  (0,0)     +(1,2)  },
                         {[fill=blue!25, draw=blue]    Bar:  (1.5,-.5) +(2,1.5)},
                         {[rotate=30, transform shape] Woah!:(2,0.5)   +(2,1)  }}];
\end{tikzpicture}
\end{document}
  • This is an excellent with much great information. This exchange, though, has caused me to realize that I can't simplify what I'm already doing without complicating it in another way \begin{tikzpicture} \draw (\SixteenEightyfive,1) -- (\SixteenEightyfive,2) node[midway,right] {Bach} -- (\SeventeenFifty,2) -- (\SeventeenFifty,1) -- cycle; \draw (\NinteenTwentysix,1) -- (\NinteenTwentysix,2) node[midway,right] {Coltrane} -- (\NinteenSixtyseven,2) -- (\NinteenSixtyseven,1) -- cycle; \end{tikzpicture} because the time scale is logarithmic. I guess I should have been more specific. – jxqz Oct 18 '13 at 14:30

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.