Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I already have

\tikzstyle{block} = [draw, fill=yellow!20, text centered, rectangle,
minimum height=0.8cm,minimum width=6em, align=right]

First, I can obtain a rectangle by

\node (rect) [block] at (0,0) {test};

Second, I can also obtain a rectangle by

\draw (0,0) rectangle (1,1);

Question: I want to use the first way to create a rectangle, whose properties have been predefined using \tikzstyle. If using the second way, I have to define the properties of the rectangle again. I know the coordinates of the corners of the rectangle can be obtained by

  • rect.north east
  • rect.north wast
  • rect.south east
  • rect.south west

Can I create a rectangle using the first way and specify the four corner coordinates of the rectangle?

share|improve this question
    
You have conflicting objectives, you are providing a minimum width but then asking to be 1cm wide and high. Note that a node is not a ordinary path, it's a more complex object. –  percusse Dec 23 '12 at 1:31
1  
    
@percusse The rectangle path could not care less about the node specific styles (only the unknowing user might wonder). More interestingly, I find text centered and align=right, though my current PGF manual does not know about text centered anyway. –  Qrrbrbirlbel Dec 23 '12 at 2:07
    
@Qrrbrbirlbel Yes you have even more for example text badly ragged; check line 775 onwards in tikz.code.tex file. They are kind of the older (or maybe lower) versions of align=.... options. I know them from the auto-complete options of QTikZ. –  percusse Dec 23 '12 at 2:13
    
@percusse I have only said that my manual doesn’t know about them. ;) After all, there were no error messages, so TikZ at least knew them. And yes, they practically are align= without setting the node halign header. On that note, @Shiyu: align=right overwrites text centered. –  Qrrbrbirlbel Dec 23 '12 at 2:35
add comment

1 Answer

up vote 17 down vote accepted

Yes, you can.

Though, I limited your question to two corner coordinates, because unless you account for rotation, two coordinates suffice to specify a rectangle.

So many possibilities.

But before I divulge the actual solution to you let me give you some other ideas on positioning.

  1. The anchor= key. It can be used as for example anchor=south west (see my example below) which set the south-west corner of the to-placed node at the at part.
  2. With the positioning library you can even be more specific and could specify above right=<distance> of <coordinate> where <coordinate> can be an actual coordinate like 0,0 (enbrace the whole argument in { } when you use , in it!), a node or a node’s anchor.

    Unless <distance> is specified, none is used. This topic is a bit complex, it is best to read subsection 16.5.3 “Advanced Placement Options” of the PGF manual.

  3. The fit library and its fit= key. The fit key takes a list of coordinates (or nodes, or anchors) and fits the to-be-fitted node so that those coordinates are enclosed by that node. But be aware of the inner sep key and the usual dimension-setting keys (height, width, etc.) as they can affect the placement; usually the corners do not lie at those coordinates.

  4. My solution: the from=<coordinate 1> to <coordinate2> key. See the last point on the next list.

So many styles.

I have created four distinctive styles:

  1. block filldraw contains
    • draw and
    • fill options. It is used in the other styles and on the rectangle path.
  2. block rect contains
    • block filldraw (and inherits its option) and
    • the node-specific rectangle option (which is the default). This style can be applied to an path but doesn’t change much for the path unless it contains a node which would than inherit those node-specific styles (but not the draw and fill styles).
  3. block contains
    • block rect,
    • minimum height and
    • minimum width. Again, it does not change much for paths but for nodes.
  4. from style (that should be used on a node) takes its argument in the form

    from=<coordinate 1> to <coordinate 2>
    

    Now, those coordinates can be just arbitrary 0,0 but than the whole argument must be enclosed in { } (as I did in my example below). But they also can be nodes and their anchors. <coordinate 1> will be used as the lower left corner in the above right=of key.

    Both coordinates will be used to calculate the horizontal and vertical dimensions for the node. Note that I have used the minimum width and minimum height keys to set the needed dimensions. In this case, the node will grow with its content.

In the example I have set the opacity key to see the overlaying nodes and how they get positioned.

Code

\documentclass[tikz,border=2pt]{standalone}
\usetikzlibrary{positioning}
\tikzset{
    block filldraw/.style={% only the fill and draw styles
        draw,
        fill=yellow!20,
    },
    block rect/.style={% fill, draw + rectangle (without measurements)
        block filldraw,
        rectangle,
    },
    block/.style={% fill, draw, rectangle + minimum measurements
        block rect,
        minimum height=0.8cm,
        minimum width=6em,
    },
    from/.style args={#1 to #2}{
        above right={0cm of #1},% needs positioning library
        to={#1}{#2},
        minimum width=\xdiff,
        minimum height=\ydiff,
    },
    to/.code 2 args={%
        \gettikzxy{\xfirst}{\yfirst}{#1}%
        \gettikzxy{\xsecond}{\ysecond}{#2}%
        \pgfmathsetmacro\xdiff{\xsecond-\xfirst}%
        \pgfmathsetmacro\ydiff{\ysecond-\yfirst}%
    }
}
\makeatletter
\newcommand*{\gettikzxy}[3]{%
    \tikz@scan@one@point\pgfutil@firstofone(#3)\relax
    \edef#1{\the\pgf@x}%
    \edef#2{\the\pgf@y}%
}
\makeatother
\begin{document}
\begin{tikzpicture}[opacity=.4]
\draw[block filldraw]              (0,0) rectangle (1,1)       ;
\node[block] (rect)             at (0,0)                 {test};
\node[block, anchor=south west] at (0,0)                 {test};
\node[block rect, from={0,0 to 2,.5}]                 {from-to};

\foreach \x/\y/\pos in {0/0/below,1/1/above,2/.5/right}{
    \fill[opacity=1] (\x,\y) circle (1pt) node [\pos] {$\x,\y$};
}
\end{tikzpicture}
\end{document}

Output

enter image description here

Code with fit and animation

\documentclass[tikz,border=2pt]{standalone}
\usetikzlibrary{positioning,fit}
\tikzset{
    block filldraw/.style={% only the fill and draw styles
        draw,
        fill=yellow!20,
    },
    block rect/.style={% fill, draw + rectangle (without measurements)
        block filldraw,
        rectangle,
    },
    block/.style={% fill, draw, rectangle + minimum measurements
        block rect,
        minimum height=0.8cm,
        minimum width=6em,
    },
    from/.style args={#1 to #2}{
        above right={0cm of #1},
        to={#1}{#2},
        minimum width=\xdiff,
        minimum height=\ydiff,
    },
    to/.code 2 args={%
        \gettikzxy{\xfirst}{\yfirst}{#1}%
        \gettikzxy{\xsecond}{\ysecond}{#2}%
        \pgfmathsetmacro\xdiff{\xsecond-\xfirst}%
        \pgfmathsetmacro\ydiff{\ysecond-\yfirst}%
    }
}
\makeatletter
\newcommand*{\gettikzxy}[3]{%
    \tikz@scan@one@point\pgfutil@firstofone(#3)\relax
    \edef#1{\the\pgf@x}%
    \edef#2{\the\pgf@y}%
}
\makeatother
\def\hideme#1{\ifnum\iCount<#1\relax\tikzset{every node/.style={opacity=0}}\fi}
\begin{document}
\foreach \iCount in {0,...,4}{
\begin{tikzpicture}[opacity=.6]
\draw[block filldraw]              (0,0) rectangle (1,1)       ;
\hideme1
\node[block] (rect)             at (0,0)                 {test};
\hideme2
\node[block, anchor=south west] at (0,0)                 {test};
\hideme3
\node[block rect, from={0,0 to 2,.5}]                 {from-to};
\hideme4
\node[block rect, fit={(0,0)(1,1)}]                       {fit};

\foreach \x/\y/\pos in {0/0/below,1/1/above,2/.5/right}{
    \fill[opacity=1] (\x,\y) circle (1pt) node [opacity=1, \pos] {$\x,\y$};
}
\end{tikzpicture}
}
\end{document}

Output with fit and animation

enter image description here

share|improve this answer
    
Nice. You can also get the same effect by \node[block,fit={(0,0)(1,1)}] {test}; with inner and outer sep dimensions reset to zero and minimum size removed (via fit library). –  percusse Dec 23 '12 at 3:08
    
@percusse Well, now that you have mentioned it, I’ll add fit to my answer. Though I find the need to set the seps to zero as a disadvantage. Nonetheless, it is a valid option and, in other cases, a good alternative. –  Qrrbrbirlbel Dec 23 '12 at 3:31
    
Dear Lord! So many solutions. Tikz is always much more complicated than I think. Thanks a lot! Excellent answer! –  Shiyu Dec 23 '12 at 4:25
    
+1 good answer (I added the animation). –  Paul Gaborit Dec 23 '12 at 8:21
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.