52

I have a matrix enclosed in brackets [ ] (or (), or {}, or |'s, or ||'s):

- a b c d -
| e f g h |
| i j k l |
- m n o p -

which I want to label like so:

           R
         |---|
  -- - a b c d -
 A|  | e f g h |
  -- | i j k l |
     - m n o p -  

Where the dashes by the labels are meant to be giant {'s as in this picture:
alt text
How can I do this?


Although two answers have been provided that work to an extent, I've added a bounty because I'd like to see if anyone has, or can come up with, a neat, robust solution.

4
  • 7
    Quick, someone put one of these hacky solutions into a .sty file, upload it to CTAN and claim it's an elegant package based solution!
    – Seamus
    Commented Aug 8, 2010 at 9:19
  • May I ask you for "It's easy to see" image? Handwriting perhaps. ACII art is not so instructive as simple image.
    – Crowley
    Commented Aug 8, 2010 at 23:18
  • 1
    @Crowley: Done. But my drawing ability is so bad that I think the ASCII art was clearer. That's why I need a solution in TeX!
    – Larry Wang
    Commented Aug 8, 2010 at 23:54
  • 3
    I think your paintbrush skill is not so bad as you say.
    – Crowley
    Commented Aug 9, 2010 at 12:17

5 Answers 5

29
+50

The following solution uses TikZ, but a minimal amount of hacks:

\usepackage{tikz}
\usetikzlibrary{matrix,decorations.pathreplacing}

\begin{tikzpicture}[decoration=brace]
    \matrix (m) [matrix of math nodes,left delimiter=[,right delimiter={]}] {
        a & b & c & d \\
        e & f & g & h \\
        i & j & k & l \\
        m & n & o & p \\
    };
    \draw[decorate,transform canvas={xshift=-1.5em},thick] (m-3-1.south west) -- node[left=2pt] {$A$} (m-1-1.north west);
    \draw[decorate,transform canvas={yshift=0.5em},thick] (m-1-2.north west) -- node[above=2pt] {$R$} (m-1-4.north east);
\end{tikzpicture}

First two tikz libraries are loaded (this only needs to be done once). In the tikzpicture environment a matrix called m is defined. The delimiters can be changed to anything that is acceptable after \left in math mode. Entries of the matrix can be reference by name-row-column (where in this case the name is m). I found good looking shifts (i.e. the distances between brace and matrix entry) by trail-and-error; you might have to change them. Also you might want to try removing the thick parameter.


I tried wrapping the whole stuff in nice commands. Unfortunately I only succeeded partially, because I do not know how to handle the & in the matrix without LaTeX complaining about "misplaced alignment tab character". I tweaked the spacing in the following tikz styles a bit to make the matrix look more like the usual ones. Maybe there are better ways to do this (are all the lengths the (usual) matrix environment used accessible somehow?).

Anyway, on to the commands. Put the following wall of code somewhere near the beginning of the document:

% Load TikZ
\usepackage{tikz}
\usetikzlibrary{matrix,decorations.pathreplacing,calc}

% Set various styles for the matrices and braces. It might pay off to fiddle around with the values a little bit
\pgfkeys{tikz/mymatrixenv/.style={decoration=brace,every left delimiter/.style={xshift=3pt},every right delimiter/.style={xshift=-3pt}}}
\pgfkeys{tikz/mymatrix/.style={matrix of math nodes,left delimiter=[,right delimiter={]},inner sep=2pt,column sep=1em,row sep=0.5em,nodes={inner sep=0pt}}}
\pgfkeys{tikz/mymatrixbrace/.style={decorate,thick}}
\newcommand\mymatrixbraceoffseth{0.5em}
\newcommand\mymatrixbraceoffsetv{0.2em}

% Now the commands to produce the braces. (I'll explain below how to use them.)
\newcommand*\mymatrixbraceright[4][m]{
    \draw[mymatrixbrace] ($(#1.north west)!(#1-#3-1.south west)!(#1.south west)-(\mymatrixbraceoffseth,0)$)
        -- node[left=2pt] {#4} 
        ($(#1.north west)!(#1-#2-1.north west)!(#1.south west)-(\mymatrixbraceoffseth,0)$);
}
\newcommand*\mymatrixbraceleft[4][m]{
    \draw[mymatrixbrace] ($(#1.north east)!(#1-#2-1.north east)!(#1.south east)+(\mymatrixbraceoffseth,0)$)
        -- node[right=2pt] {#4} 
        ($(#1.north east)!(#1-#3-1.south east)!(#1.south east)+(\mymatrixbraceoffseth,0)$);
}
\newcommand*\mymatrixbracetop[4][m]{
    \draw[mymatrixbrace] ($(#1.north west)!(#1-1-#2.north west)!(#1.north east)+(0,\mymatrixbraceoffsetv)$)
        -- node[above=2pt] {#4} 
        ($(#1.north west)!(#1-1-#3.north east)!(#1.north east)+(0,\mymatrixbraceoffsetv)$);
}
\newcommand*\mymatrixbracebottom[4][m]{
    \draw[mymatrixbrace] ($(#1.south west)!(#1-1-#3.south east)!(#1.south east)-(0,\mymatrixbraceoffsetv)$)
        -- node[below=2pt] {#4} 
        ($(#1.south west)!(#1-1-#2.south west)!(#1.south east)-(0,\mymatrixbraceoffsetv)$);
}

After that, you can simply use the following code to produce your example:

\[
\begin{tikzpicture}[mymatrixenv]
    \matrix[mymatrix] (m)  {
        a & b & c & d \\
        e & f & g & h \\
        i & j & k & l \\
        m & n & o & p \\
    };
    \mymatrixbraceright{1}{3}{$A$}
    \mymatrixbracetop{2}{4}{$R$}
\end{tikzpicture}
\]

The matrix definition remained pretty much the same as before, except that all the styles needed are now stored in mymatrixenv and mymatrix. No need to repeat them for every matrix!

The braces are produced with \mymatrixbraceright, \mymatrixbracetop, \mymatrixbraceleft and \mymatrixbracebottom for right, top, left and bottom braces respectively. The commands all work the same way: They have three mandatory commands for starting and ending position of the brace (in "natural" order) and the label. Additionally they have one optional argument for specifying the name of the matrix (it defaults to m). So, if you want a brace on the left of matrix foo going from the row 3 to row 417 and with label $415$ rows!, you use

\mymatrixbraceleft[foo]{3}{417}{$415$ rows!}
16
  • 1
    You beat me by 2mins this time! Well, given that I hadn't even started on an answer, you beat me by a bit longer. But as soon as I read this one I thought "TikZ can do that easily". Spelling: one -> once (first line after code). Also, I'd load the calc library as it gives very fine control over positioning and, in particular, defining offsets. Commented Aug 4, 2010 at 20:49
  • Ha, I'm getting faster! ;)
    – Caramdir
    Commented Aug 4, 2010 at 20:52
  • For using calc: I don't know how to get the position of the brackets. (m.south-west) is somewhere around the lower right(!) end of the [.
    – Caramdir
    Commented Aug 4, 2010 at 21:04
  • @Caramdir: Thanks, never used TikZ, but this appears to work. A complaint I have is that in a document containing TikZ matrices and matrices created with the array environment, there is a visible difference in the vertical spacing. I could redo all my matrices, but is there a way to make TikZ use 'standard' spacing instead? Also, it is pretty clear from the context, but it would be nice if you could add \usepackage{tikz} to the beginning of your code block for completeness' sake.
    – Larry Wang
    Commented Aug 4, 2010 at 21:50
  • Whereas if I use a matrix environment, the difference in space between the contents and the brackets becomes hugely noticeable. Also, why did you go from m-3-1 to m-1-1 rather than the other way around? I noticed that this flips the orientation of the bracket; is there some way to use { instead of } as the default shape so that the position anchors can be placed in a more natural order?
    – Larry Wang
    Commented Aug 4, 2010 at 22:04
23

edit in 2017 to fix the site bug affecting \\'s

Here is one possible way to do it. It uses the mathtools package for its \mathrlap macro. My earlier answer used also the \rotatebox of the graphicx package but after reading

Align large vertical delimiters (brackets) to rows of a table?

I realized how silly I had been for the vertical braces. So I have completely replaced my code with this version (which does not at all need graphicx anymore); it does need mathtools because I have typeset a slightly complicated case, with simpler situations one could make do without \mathrlap.

I have included an image of the result. The code pays attention that the inked area ends up entirely enclosed in its bounding box, so that it does not print over material either to the left, the right, the top or the bottom.

very cool matrix with braces all around

It's a bit hard to write a single macro to automatize it, as the mark-up is best left to the clever representatives of the homo sapiens sapiens genus. It is pretty much self-explanatory how to adapt it to any given situation.

Defects: the vertical braces extend a bit far compared to the horizontal ones. But I don't see how to fix this without playing with some of the dimensions used internally by the matrix environment. So I left the matter here.

\documentclass{article}
\usepackage{amsmath}
\usepackage{mathtools}
\pagestyle{empty}

\newcommand\coolover[2]{\mathrlap{\smash{\overbrace{\phantom{%
    \begin{matrix} #2 \end{matrix}}}^{\mbox{$#1$}}}}#2}

\newcommand\coolunder[2]{\mathrlap{\smash{\underbrace{\phantom{%
    \begin{matrix} #2 \end{matrix}}}_{\mbox{$#1$}}}}#2}

\newcommand\coolleftbrace[2]{%
#1\left\{\vphantom{\begin{matrix} #2 \end{matrix}}\right.}

\newcommand\coolrightbrace[2]{%
\left.\vphantom{\begin{matrix} #1 \end{matrix}}\right\}#2}

\begin{document}

\[ \vphantom{% phantom stuff for correct box dimensions
    \begin{matrix}
    \overbrace{XYZ}^{\mbox{$R$}}\\ \\ \\ \\ \\ \\
    \underbrace{pqr}_{\mbox{$S$}}
    \end{matrix}}%
\begin{matrix}% matrix for left braces
\vphantom{a}\\
    \coolleftbrace{A}{e \\ y\\ y}\\
    \coolleftbrace{B}{y \\i \\ m}
\end{matrix}%
\begin{bmatrix}
a & \coolover{R}{b & c & d} & x & \coolover{Z}{x & x}\\
    e & f & g & h & x & x & x \\
    y & y & y & y & y & y & y \\
    y & y & y & y & y & y & y \\
    y & y & y & y & y & y & y \\
    i & j & k & l & x & x & x \\
    m &  \coolunder{S}{n & o}  & \coolunder{W}{p & x & x} & x
\end{bmatrix}%
\begin{matrix}% matrix for right braces
    \coolrightbrace{x \\ x \\ y\\ y}{T}\\
    \coolrightbrace{y \\ y \\ x }{U}
\end{matrix}\]

\end{document}
6
  • I wanted a similar effect like the question asks for and found this answer to be useful. However, I reckon the following definition for \coolrightbrace is better: \newcommand{\coolrightbrace}[2]{\mathclap{\left.\vphantom{\begin{matrix} #1 \end{matrix}}\right\}}\quad#2} I put the brace inside a mathclap so there is minimal space between the matrix and brace.
    – thedoctar
    Commented Jul 21, 2013 at 15:11
  • @jfbu great job, but whit horizontal brace for one column there are a little problem. Moreover, the problem appears with empty entries.
    – juanuni
    Commented Jul 19, 2015 at 4:59
  • Maybe it can be solved using \phantom command in empty entries.
    – juanuni
    Commented Jul 19, 2015 at 5:18
  • For some reason, I had to change every \ to \\ . Otherwise perfect:)
    – Antoine
    Commented Mar 26, 2017 at 15:34
  • @Antoine thanks, there was a site bug which has affected hundreds even thousands of posts and some courageous people (not me, I am rarely here) have been trying to manually fix them for some weeks now. More details at tex.meta.stackexchange.com/questions/7168/…
    – user4686
    Commented Mar 26, 2017 at 20:49
7

This solution is not as elegant as a dedicated package would (hopefully) be, but I don't know of one so here goes... This example assumes that you are using the amsmath package.

You can achieve the desired effect by creating a 2x2 'super matrix' and leaving the (1,1) entry blank. Then put a horizontal brace spanning some columns in the (1,2) entry and a vertical brace spanning some rows in the (2,1) entry. Finally, put the actual matrix that these braces are spanning in the (2,2) entry.

To get the spacing right, you can use \vphantom and \hphantom to create invisible matrices in the (1,2) and (2,1) entries, and the \mspace command to decrease the spacing between the two columns of the super matrix..

Here's an example (that may look much better pasted into an editor that has syntax highlighting):

\begin{matrix} %This is the super matrix
    %(1,1) cell: Empty
  &
    %(1,2) cell: Brace spanning columns
    \begin{matrix}   %One-row matrix to hold the brace
      \hphantom{a} & %Blank space to skip over first column
      \overbrace{
        \hphantom{\begin{matrix}b & c & d\end{matrix}}
      }^{\text{\footnotesize Final three columns}}
    \end{matrix}
  \\
    %(2,1) cell: Brace spanning rows
    \begin{matrix}    %One-column matrix to hold a brace
      \vphantom{a} \\ %Blank space to skip first row
      \text{\footnotesize Middle two rows}
        \left\{\vphantom{\begin{matrix} e \\ i \end{matrix}}\right. \\
      \vphantom{m}
    \end{matrix}
    %The inter-column spacing of the super matrix looks too big by default
    \mspace{-33mu}
  &
    %(2,2) cell: Actual matrix
    \begin{pmatrix}
      a & b & c & d \\
      e & f & g & h \\
      i & j & k & l \\
      m & n & o & p
    \end{pmatrix} 
\end{matrix} 

The invisible matrices in the (1,2) and (2,1) entries of the super matrix allow you to span whichever columns you want, or even have multiple braces in either direction.

5
  • This does work, but the \!\!\!\!\!\!\!\! is a good example of the hackiness I wanted to avoid. Also the text on the upper label looks squished.
    – Larry Wang
    Commented Aug 4, 2010 at 22:05
  • I agree about the \!'s -- they're a large part of why I didn't think this was all that elegant. The rest holds together fairly well though, and you can change the size of the fonts. I'm not sure what you mean about the text looking "squished" -- if you just mean small, try putting \footnotesize inside the \text{ command (or \normalsize, etc.). I'm about to edit that in, just so the two labels in the example look the same... Commented Aug 4, 2010 at 23:13
  • I think they looked compressed vertically, but the horizontal spacing was as I would have expected. It must have been whatever you thought it was, because the current revision looks good.
    – Larry Wang
    Commented Aug 9, 2010 at 0:04
  • @Larry, I know it's a minor change but I've replaced the sequence of \!\!'s with amsmaths's \mspace command. The spacing looks pretty good to me with 33 'math units' of space taken away, but you can of course fine tune it from here. Commented Aug 9, 2010 at 20:35
  • That does look a lot better. It still has the problem of making you create a dummy array to hold the labels and the real matrix. If you could wrap that in some neat commands somehow this would be a much better answer. Of course, I will understand if you don't want to bother, since the TikZ solution also works well.
    – Larry Wang
    Commented Aug 10, 2010 at 19:55
2

A very, very ugly hack is something like this

\begin{math}
\bordermatrix{ & & \overbrace{\qquad \qquad }^{R} \cr 
A \left\{ \begin{array}{c} \\ \\ \end{array} \right.& \begin{array}{c}
v1 \\ v2 \\ v3 \end{array} & \begin{array}{ccc} f & g & h \\ g & h & f
\\ h & g & f \end{array} \cr 
& a & \begin{array}{ccc} 1 & 2 & 3\end{array} \cr}
\end{math}

It uses the TeX command \bordermatrix{} (which has no equivalent in latex as far as I know), hence the numerous appearances of \cr instead of \\, and the necessary last \cr in the command.

Also the bordermatrix produces matrix delimited by parentheses, not square brackets, so that might be not exactly what you want.

2
  • Yeah, ideally, I would like to be able to have the matrix be enclosed in any of the standard brackets: [M],{M},(M),|M|,||M||.
    – Larry Wang
    Commented Jul 26, 2010 at 23:40
  • Okay, the thing that bordermatrix produces is enclosed in (M). So it may work as a ugly hack. Commented Jul 26, 2010 at 23:58
1

I have done braces on rows the following way. First a macro has to be defined:

\newcommand{\threelinebrace}{$\left. \begin{array}{c} \\ \\ \\ \end{array} \right\rbrace$}

Then add a column for the braces and put the following code in the firs cell included by the brace:

\multirow{3}{*}{\threelinebrace your label}

You also have to include the multirow package to make it work.

Here is a minimal example extracted from a presentation I once did:

\documentclass[ngerman]{article}
\usepackage{babel}
\usepackage{multirow}
\newcommand{\threelinebrace}{$\left. \begin{array}{c} \\ \\ \\ \end{array} \right\rbrace$}

\begin{document}
\begin{tabular}{|c|l}
\cline{1-1} 
Protocol ID & \textbf{\multirow{3}{*}{\threelinebrace CPCS-PDU Payload}}\tabularnewline
\cline{1-1} 
Information & \tabularnewline
\cline{1-1} 
Padding & \tabularnewline
\cline{1-1} 
\end{tabular}
\end{document}

I know, this still is more a quick hack than a satisfying solution, but it's a start.

1
  • Thanks for the example. Your minimal example works fine, it breaks when I add more columns though. Also, this answer does not address labeling multiple columns.
    – Larry Wang
    Commented Aug 4, 2010 at 21:38

You must log in to answer this question.

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