4

I'm trying to align 2 groups of TikZ nodes but cannot figure out how to do this. I tried wrapping each group with \tikz{...} but that didn't work (probably because of \tikz inside tikzpicture environment. Currently, I am using \matrix but it aligns the nodes horizontally at the left (and I would like center) and doesn't use equal spacing between lines (or maybe, it does, but I would like it to change to a minimum spacing?)

Anyway, I have a feeling that my goal could be accomplished with \matrix but I am open to other approaches to group nodes, too. For example, I haven't fully understood the {scope} environment.

Here is my MWE illustrating the problem (I'd be also happy to hear if the MWE could be made more minimal, i.e., my tikz coding could be improved):

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

% some style definitions:
\newcommand\scriptsize{\fontsize{7pt}{7pt}\selectfont} % because of 'minimal' documentclass
% settings for lexemes
\tikzset{font=\scriptsize}
\tikzset{mynode/.style = {rectangle,minimum width=#1,draw=black!70}}
\tikzset{mynode/.default = 2mm}
% macro for drawing multiple lexemes next to each other:
\newcommand{\lexemes}[1]{%
    \node (A) [mynode] {};
    \xdef\lastx{A}
    \foreach \x/\lbl/\d in {#1} {
      \node (\x) [mynode,label=center:\lbl,right=\d of \lastx] {};
      \xdef\lastx{\x}  
    }
}

\begin{document}

\begin{tikzpicture}[node distance=0.08 and 0.05]
  \matrix [anchor=west] at (0,3) {%  no labels, so rows very tight
    \lexemes{C//} \\
    \lexemes{C//,D//2mm,F//} \\
  };
  \matrix [anchor=west] at (0,2) {%  label in upper row, so less tight
    \lexemes{B/1/,C//} \\
    \lexemes{C//,D//2mm,F//} \\
  };
  \matrix [anchor=west] at (0,1) {%  labels in both rows, so this should be the constant row sep?
    \lexemes{B/1/,C//} \\
    \lexemes{B/3/,C//,D//2mm,F//} \\
  };
\end{tikzpicture}

\end{document}

which produces the following result:

enter image description here

Now I would like to accomplish 2 things:

  1. Center the first and second row of each pair/matrix.
  2. Have an equal vertical separation between the first and second row of each matrix independent of the node label used. I would measure between the edges of the rectangles.
2
  • 3
    I believe your code could be made more minimal by removing all the complicated instructions and producing a simplistic (i.e. boring and ugly) picture where the only thing in question is node alignment. In particular, I don't believe your new shape is relevant to the question (replace it with some oddly-sized standard shape), and neither are your styles.
    – Ryan Reich
    Commented Mar 2, 2012 at 17:44
  • 1
    By the way, about scope: its purpose is to locally set TikZ options. That's it. So for example, you could have a scope setting, say, shift = {(1,0)} to move everything right one unit, but it is (I think) much harder to arrange purely through options that the center of a scope is at a particular place.
    – Ryan Reich
    Commented Mar 3, 2012 at 19:59

1 Answer 1

3

Okay, now I understand your problem. Here are the fixes:

  1. To get the rows centered, place them in \nodes with anchors at their center. A \matrix aligns its columns by their "origin", which is rather tricky to change for complex constructions, but for a node is always where the anchor is.

  2. To get the spacing right, you have to make sure the inner sep of your labels is zero; each label is a new node, and as it turns out, its invisible extent is somewhat larger than the box you drew it in.

The \node in point 1 also has an inner sep, which I have to set to zero to avoid putting big spaces between every row. As it turns out, your style sets only minimum width and relies on inner sep to force the height, so to prevent the boxes from flattening out when they are contained in a scope with inner sep = 0, I have changed minimum width=#1 to minimum size=#1.

\documentclass{minimal}
\usepackage{tikz}
\usetikzlibrary{shapes,positioning,matrix}

% some style definitions:
\newcommand\scriptsize{\fontsize{7pt}{7pt}\selectfont} % because of 'minimal' documentclass
% settings for lexemes
\tikzset{font=\scriptsize}
% changed minimum width to minimum size
\tikzset{mynode/.style = {rectangle,minimum size=#1,draw=black!70}}
\tikzset{mynode/.default = 2mm}
% macro for drawing multiple lexemes next to each other:
\newcommand{\lexemes}[1]{%
 \node[anchor=center,inner sep=0pt]{
  \tikz{
   \node (A) [mynode] {};
   \xdef\lastx{A}
   \foreach \x/\lbl/\d in {#1} {
     \tikzset{every label/.style = {inner sep = 0}}
     \node (\x) [mynode,label=center:\lbl,right=\d of \lastx] {};
     \xdef\lastx{\x}  
   }
  }
 };
}

\begin{document}

\begin{tikzpicture}[
 node distance=0.08 and 0.05,
]
  \matrix [anchor=west] at (0,3) {%  no spaces, so rows very tight
    \lexemes{C//} \\
    \lexemes{C//,D//2mm,F//} \\
  };
  \matrix [anchor=west] at (0,2) {%  space in upper row, so less tight
    \lexemes{B/1/,C//} \\
    \lexemes{C//,D//2mm,F//} \\
  };
  \matrix [anchor=west] at (0,1) {%  spaces in both rows, so this should be the constant row sep?
    \lexemes{B/1/,C//} \\
    \lexemes{B/3/,C//,D//2mm,F//} \\
  };
\end{tikzpicture}

\end{document}
1
  • this is a great "minimal" answer. I added row sep=1mm to the matrix options to get a little bit of space between the rows (I hadn't really specified this in my question). Now that your answer makes the distance between rows equal the result is what I ultimately wanted.
    – Linda
    Commented Mar 5, 2012 at 13:49

You must log in to answer this question.

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