10

I am trying to create a diagram that looks roughly like this picture:

table version

Except that I want it to have rounded corners. It seems that the obvious way to do this would be to use tikz, so I have made an attempt at this:

\documentclass{standalone}
\usepackage{tikz}
\usepackage{braket}
\usetikzlibrary{matrix,fit}

\begin{document}
\newcommand{\objboxthreer}[7]{
  \begin{tikzpicture}
    \matrix (m) [nodes={inner sep=2pt},matrix of nodes, nodes in empty cells,ampersand replacement=\&, row sep=0pt, column sep=0pt]
    {
      {#1} \& \& {#2} \& {#4} \& {#6} \& \\
           \& \& {#3} \& {#5} \& {#7} \& \\
    };
    \node [
      draw,
      rounded corners=.5em,
      inner sep=0pt,
      outer sep=0pt,
      minimum size=0pt,
      fit=(m-1-2.north east)
          (m-1-2.south east)
          (m-1-3.north east)
          (m-1-3.south east)
          (m-1-4.north east)
          (m-1-4.south east)
          (m-1-5.north east)
          (m-1-5.south east)
          (m-1-6.north west)
          (m-1-6.south west)] {};
    %\draw [rounded corners=.5em] (m-1-2.south east) rectangle (m-3-6.north west);
    \draw (m-1-3.north east) -- (m-1-3.south east);
    \draw (m-1-4.north east) -- (m-1-4.south east);
  \end{tikzpicture}
}
\objboxthreer{d}{$p_s$}{$Y_d$}{$p_d$}{$Y_d'$}{$\{p\}$}{$\Set{ x \in X | x > 5}$}

\end{document}

Which produces the rather unsatisfactory result:

tikz version

The vertical lines don't reach the top or the bottom of the enclosing box.

The challenge is that the contents of all of the cells of this table are very dynamic in size. Both the height and the width of each element may change significantly (complex formulas, etc), so I cannot simply specify the height and width of each row and column. How can I emulate the first table but with rounded corners?

Here is an additional testcase that has taller elements: \documentclass{standalone} \usepackage{tikz} \usepackage{braket} \usetikzlibrary{matrix,fit}

\begin{document}
\newcommand{\objboxthreer}[7]{
  \begin{tikzpicture}
    \matrix (m) [nodes={inner sep=2pt},matrix of nodes, nodes in empty cells,ampersand replacement=\&, row sep=0pt, column sep=0pt]
    {
      {#1} \& \& {#2} \& {#4} \& {#6} \& \\
           \& \& {#3} \& {#5} \& {#7} \& \\
    };
    \node [
      draw,
      rounded corners=.5em,
      inner sep=0pt,
      outer sep=0pt,
      minimum size=0pt,
      fit=(m-1-2.north east)
          (m-1-2.south east)
          (m-1-3.north east)
          (m-1-3.south east)
          (m-1-4.north east)
          (m-1-4.south east)
          (m-1-5.north east)
          (m-1-5.south east)
          (m-1-6.north west)
          (m-1-6.south west)] {};
    %\draw [rounded corners=.5em] (m-1-2.south east) rectangle (m-3-6.north west);
    \draw (m-1-3.north east) -- (m-1-3.south east);
    \draw (m-1-4.north east) -- (m-1-4.south east);
  \end{tikzpicture}
}
\objboxthreer{d}{$p_s$}{$Y_d$}{$\left\{\frac{p}{q}\right\}$}{$Y_d'$}{$\{p\}$}{$\Set{ x \in X | x > 5}$}

\end{document}

The output of this has similar problems but cannot be solved by using \strut: enter image description here

8

While adding a \strut would fixes the problem for a basic text, if you want to allow for more variable heights than adding a \vphantom based on the height of the tallest entry is needed:

enter image description here

References:

Code:

\documentclass{standalone}
\usepackage{tikz}
\usepackage{braket}
\usetikzlibrary{matrix,fit}

\begin{document}
\newcommand{\objboxthreer}[7]{%
    \newcommand{\MyStrut}{\vphantom{#1#2#3#4#5#6#7}}%
  \begin{tikzpicture}
    \matrix (m) [nodes={inner sep=2pt},matrix of nodes, nodes in empty cells,ampersand replacement=\&, row sep=0pt, column sep=0pt]
    {
      {#1\MyStrut} \& \& {#2\MyStrut} \& {#4\MyStrut} \& {#6\MyStrut} \& \\
           \& \& {#3\MyStrut} \& {#5\MyStrut} \& {#7\MyStrut} \& \\
    };
    \node [
      draw,
      rounded corners=.5em,
      inner sep=0pt,
      outer sep=0pt,
      minimum size=0pt,
      fit=(m-1-2.north east)
          (m-1-2.south east)
          (m-1-3.north east)
          (m-1-3.south east)
          (m-1-4.north east)
          (m-1-4.south east)
          (m-1-5.north east)
          (m-1-5.south east)
          (m-1-6.north west)
          (m-1-6.south west)] {};
    %\draw [rounded corners=.5em] (m-1-2.south east) rectangle (m-3-6.north west);
    \draw (m-1-3.north east) -- (m-1-3.south east);
    \draw (m-1-4.north east) -- (m-1-4.south east);
  \end{tikzpicture}%
}
\objboxthreer{d}{$p_s$}{$Y_d$}{$\left\{ \frac{p}{q} \right\}$}{$Y_d'$}{$\{p\}$}{$\Set{ x \in X | x > 5}$}

\end{document}
  • Thanks for the suggestion, but that doesn't work for something taller than \{p\}, such as \left\{ \frac{p}{q} \right\}. I am hoping for some method that will grow all heights to the tallest height. – Arlen Cox May 21 '13 at 6:23
  • @ArlenCox: Please update the MWE with this added to the test case, and test updated solution which should meet your requirements. – Peter Grill May 21 '13 at 6:33
  • With \MyStrut all non empty cells will have same height and you can save some typing with fit=(m-1-2.east|-m-1-3.north) (m-1-6.west|-m-1-3.south) instead of enumerating all corners. – Ignasi May 21 '13 at 7:29
  • I was looking for a command like \vphantom. That's actually fairly elegant. @Ignasi: I think you're right and, in fact, I was looking for how to specify coordinates like that. Thanks! – Arlen Cox May 21 '13 at 14:25
5

A solution with minimal tools, without matrix but with shape multiple parts

 \documentclass{article}
 \usepackage{tikz}\usepackage{braket}
 \usetikzlibrary{shapes.multipart}
 \begin{document}
 \setlength{\fboxsep}{0pt}
 \begin{tikzpicture}[%
     table shape/.style={rectangle split,
                         rectangle split part align=base, 
                         rectangle split horizontal, 
                         rectangle split parts=3,
                         rounded corners},
     p3/.style={text width=18ex,align=center}]

  \node [table shape,draw] (main) 
     {$p_s$ 
     \nodepart{two}$p_d$ 
     \nodepart[p3]{three}$\{p\}$};
  \node [table shape] at ([yshift=-2em]main.center)
     {$Y_d$ 
     \nodepart{two}$Y'_d$ 
     \nodepart[p3]{three}$\Set{ x \in X | x > 5}$};
  \node at ([xshift=-3ex]main.text west) {d};
 \end{tikzpicture}
 \end{document}   

enter image description here

  • It's amazing how there is pretty much a library for everything, but this doesn't resolve one of my key problems, which is that the height (which this solution handles) and the width (which this solution does not handle) can change dramatically for any of the elements. In this solution, the width of the third cell is explicit and the second cells don't line up (they just happen to be close enough to not make a difference). I'm sure there's a way to fix this problem, and I would love to see the solution because it is pretty elegant and clean. Thanks for your suggestion. – Arlen Cox May 21 '13 at 14:29

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.