13

I draw a kind of box in TikZ very often, so I decide to make a macro, even though I have never done it before...

The aim is to draw a rectangle. 4 parameters (1, 7, 4, 8 in the figure) mean its bounds, which are displayed above and on the left hand of the rectangle. text is the text inside the rectangle. And I guess another 2 parameters are needed to determine the real width and height of the rectangle.

I have no clue about writing a macro, could anyone give a framework to start?

enter image description here

3 Answers 3

27

First and foremost, Peter Grill's first sentence is probably the most important piece of advice on this page (so far). First work out what you want normally, then wrap it up in a macro.

Given that this is part of a TikZ picture, you can do this using styles. This method is quite flexible. For example, here's one way to do your box:

\documentclass{standalone}
%\url{http://tex.stackexchange.com/q/27278/86}
\usepackage{tikz}
\usetikzlibrary{fit}

\tikzset{
  my funny rectangle/.style n args={4}{%
    rectangle,
    draw,
    fit={(#3,#1) (#4,#2)},
    append after command={\pgfextra{\let\mainnode=\tikzlastnode}
      node[above right] at (\mainnode.north west) {#3}%
      node[above left] at (\mainnode.north east) {#4}%
      node[below left] at (\mainnode.north west) {#1}%
      node[above left] at (\mainnode.south west) {#2}%
    },
  }
}

\begin{document}
\begin{tikzpicture}
\node[my funny rectangle={1}{7}{4}{8}] {text};
\end{tikzpicture}
\end{document}

An advantage of this method over a more normal TeX macro is that it is very easy to pass other options to the node, such as a colour or a fill or a pattern, simply by putting them in the usual place.

The code above works as follows. The fit library is used to ensure that the node contains the specified points. As it is a rectangle, we just need to include two opposite corners. Then the rest of the code puts the labels in. We use the append after command to put a node at the relevant places. The only snag is that we have to save the main node in a macro rather than using \tikzlastnode throughout (as that gets overwritten).

The above produces the following picture:

labelled rectangle

(Edit: Thanks to Jake for pointing out that five append after commands is a tad excessive.)

9
  • Very nice approach. Is there a reason why you use five append after command keys, instead of just one?
    – Jake
    Commented Sep 3, 2011 at 0:15
  • @Jake: I was having issues with the exact commands in an early version (before I figured out that it was the \tikzlastnode getting renamed) and separating them out helped me figure out what was going on. I've just tested it and there's no reason to have them separate. I'll edit. Commented Sep 3, 2011 at 14:46
  • Thanks for your reply... I tried your code... It says ERROR: LaTeX Error: File "standalone.cls" not found., do you know where I can find this file?
    – SoftTimur
    Commented Sep 3, 2011 at 20:11
  • If i use documentclass{minimal}, it gives me an ERROR: Package pgfkeys Error: I do not know the key '/tikz/my funny rectangle/.style n args' and I am going to ignore it. Perhaps you misspelled it.
    – SoftTimur
    Commented Sep 3, 2011 at 20:13
  • @SoftTimur: My apologies! The standalone class is a class developed by Martin Scharrer for producing documents just as big as their contents which makes them great for producing the pictures here. I should have changed that to article when posting the code. The minimal class should almost never be used. Try again with article. Commented Sep 3, 2011 at 21:26
14

If you want to put something into a macro, first figure out how to produce what you want. For example, say you come up with this solution to drawing what you want.

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

\begin{document}
\begin{tikzpicture}
\draw 
    (0,  0) node [left] {$7$}  --
    (1.5cm, 0) -- 
    (1.5cm,2.5cm) node [above] {$8$} --
    (0, 2.5cm) node [above] {$4$} node [left] {$1$} --
    cycle;
\draw [draw=none] (0,0)--(1.5cm,2.5cm) node [midway] {Text};
\end{tikzpicture}
\end{document}

Then to make a macro put the entire tikzpicture environment in a \newcommand and replace the approriate portions with #1, #2, etc...

\newcommand{\DrawRectangle}[6]{% length, height, labelSW, labelNW, labelWN, labelEN
\begin{tikzpicture}
\draw 
    (0,  0) node [left] {#3}  --
    (#1, 0) -- 
    (#1,#2) node [above] {#6} --
    (0, #2) node [above] {#5} node [left] {#4} --
    cycle;
\draw [draw=none] (0,0)--(#1,#2) node [midway] {Text};
\end{tikzpicture}
}

\begin{document}
\DrawRectangle{1.5cm}{2.5cm}{$7$}{$1$}{$4$}{$8$}
\end{document}

If you require a lot of flexibility you will run out of parameters (since you can only have 9). One solution is to use styles and set default values within the macro using the \providetikzstyle like macros.

9

Maybe this helps a little. It’s not perfect ;-)

\documentclass{minimal}
\usepackage{tikz}
\usetikzlibrary{positioning}

\newcommand\Rec[8]{%
    \node (tmp) [%
        draw,
        anchor=south west,
        text width={#2-0.4cm},
        inner sep=2mm,
        minimum height={#3-.4cm},
        align=center,
    ] at (#1) {#8};
    \node [left=0mm of tmp.south west, anchor=south east]{#4};
    \node [left=0mm of tmp.north west, anchor=north east]{#5};
    \node [above=0mm of tmp.north west, anchor=south west]{#6};
    \node [above=0mm of tmp.north east, anchor=south east]{#7};
}

\begin{document}
\begin{tikzpicture}
\Rec{1,1}{4cm}{5cm}{1}{2}{3}{4}{Text}
% Usage
% \Rec{<start, lower left corner>}{<size>}{<lable 1>}{<l 2>}{<l 3>}{<l 4>}{<Text>}
\end{tikzpicture}
\end{document}

example

Edit
Note that this command will only work in a TikZ-environment.

You must log in to answer this question.

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