loopspace / tikzmark

The dread tikzmark arrives on github
14 stars 3 forks source link

\tikzmarknode issue with parenthesis inside a matrix #11

Closed jrmsmith closed 4 years ago

jrmsmith commented 4 years ago

Matrices whose entries contain parenthesis become too big when using \tikzmarknode to highlight an entry.

Follows a minimal code that reproduces the issues.

\documentclass{article}
\usepackage{amsmath}
\usepackage{tikz}
\usetikzlibrary{tikzmark,calc}
\usepackage{eso-pic}
\begin{document}

$\begin{bmatrix}(a)\end{bmatrix}$, $\begin{bmatrix}(a)(a)\end{bmatrix}$, $\begin{bmatrix}\tikzmarknode[circle]{entry1}{(a)}\end{bmatrix}$, $\begin{bmatrix}\tikzmarknode[circle]{entry2}{(a)(a)}\end{bmatrix}$
\AddToShipoutPictureBG*{%
\begin{tikzpicture}[overlay,remember picture]
  \draw let  \p1=($(entry1.north)-(entry1.center)$),
  \p2=($(entry1.north)-(entry1.center)$), \n1={2*max(\y1,\y2)-2pt} in
  [opacity=.4,line width=\n1,line cap=round,
  shorten >=-\y2/3,shorten <=-\y1/3] (entry1.center) -- (entry1.center);
  \draw let  \p1=($(entry2.north)-(entry2.center)$),
  \p2=($(entry2.north)-(entry2.center)$), \n1={2*max(\y1,\y2)-2pt} in
  [opacity=.4,line width=\n1,line cap=round,
  shorten >=-\y2/3,shorten <=-\y1/3] (entry2.center) -- (entry2.center);
\end{tikzpicture}}

\end{document}
loopspace commented 4 years ago

Tikzmark's nodes are designed to fit snugly about their contents with ideally no additional space. However, since TeX's basic shape is a rectangle, a tikzmark node can only fit tightly if it is also a rectangle. Otherwise, the node has to be big enough to fit a rectangle inside whatever shape it is, and then TeX treats the node as if it itself were contained in a rectangle. In particular, by passing the option circle to \tikzmarknode you are asking TikZ to place a circle around the contents, which TeX then in turn places a rectangle around. This makes the bounding box bigger than the contents.

To achieve the same effect but without changing the effective size of the content, use \tikzmarknode to place a snug rectangular node around the text and then in the tikzpicture environment create a new node which is circular and "fits" the original node, using the fit library.

My philosophy on using tikzmark has always been to use the tikzmark stuff merely to mark where things are on the page and then do everything else in a separate tikzpicture, and while I have no desire to be prescriptive, it may help to keep that in mind when using tikzmark as it was originally designed to fit in with how I used it!

Anyway, here's your adapted code:

\documentclass{article}
%\url{https://github.com/loopspace/tikzmark/issues/11}
\usepackage{amsmath}
\usepackage{tikz}
\usetikzlibrary{tikzmark,calc,fit}
\usepackage{eso-pic}
\begin{document}

$\begin{bmatrix}(a)\end{bmatrix}$,
$\begin{bmatrix}(a)(a)\end{bmatrix}$,
$\begin{bmatrix}\tikzmarknode{entry1-mk}{(a)}\end{bmatrix}$,
$\begin{bmatrix}\tikzmarknode{entry2-mk}{(a)(a)}\end{bmatrix}$
\AddToShipoutPictureBG*{%
  \begin{tikzpicture}[overlay,remember picture]
  \node[circle,inner sep=0pt,fit=(entry1-mk)] (entry1) {};
  \node[circle,inner sep=0pt,fit=(entry2-mk)] (entry2) {};
  \draw let  \p1=($(entry1.north)-(entry1.center)$),
  \p2=($(entry1.north)-(entry1.center)$), \n1={2*max(\y1,\y2)-2pt} in
  [opacity=.4,line width=\n1,line cap=round,
  shorten >=-\y2/3,shorten <=-\y1/3] (entry1.center) -- (entry1.center);
  \draw let  \p1=($(entry2.north)-(entry2.center)$),
  \p2=($(entry2.north)-(entry2.center)$), \n1={2*max(\y1,\y2)-2pt} in
  [opacity=.4,line width=\n1,line cap=round,
  shorten >=-\y2/3,shorten <=-\y1/3] (entry2.center) -- (entry2.center);
\end{tikzpicture}}

\end{document}

I changed the original tikzmark node names and then recreated the larger nodes in the tikzpicture, this meant I didn't have to change anything in the rest of the code.

jrmsmith commented 4 years ago

Many thanks, loopspace.

Your code did solve the most important problem and I have managed to tweak it to produce what I was really looking for

\documentclass{article}
%\url{https://github.com/loopspace/tikzmark/issues/11}
\usepackage{amsmath}
\usepackage{tikz}
\usetikzlibrary{tikzmark,calc,fit}
\usepackage{eso-pic}
\begin{document}

$\begin{bmatrix}\tikzmarknode{entry1-mk}{(a},\tikzmarknode{entry2-mk}{b)}{\cdot}\tikzmarknode{entry3-mk}{(c},\tikzmarknode{entry4-mk}{d)}\end{bmatrix}$
\AddToShipoutPictureBG*{%
  \begin{tikzpicture}[overlay,remember picture]
  \node[circle,inner sep=0pt,fit=(entry1-mk)] (entry1) {};
  \node[circle,inner sep=0pt,fit=(entry2-mk)] (entry2) {};
  \node[circle,inner sep=0pt,fit=(entry3-mk)] (entry3) {};
  \node[circle,inner sep=0pt,fit=(entry4-mk)] (entry4) {};
  \draw let  \p1=($(entry1.north)-(entry1.center)$),
  \p2=($(entry2.north)-(entry2.center)$), \n1={2*max(\y1,\y2)-2pt} in
  [opacity=.4,line width=\n1,line cap=round] (entry1.center) -- (entry2.center);
  \draw let  \p1=($(entry3.north)-(entry3.center)$),
  \p2=($(entry4.north)-(entry4.center)$), \n1={2*max(\y1,\y2)-2pt} in
  [opacity=.4,line width=\n1,line cap=round] (entry3.center) -- (entry4.center);
\end{tikzpicture}}

\end{document}

There is still a minor problem to solve: the shade overlap around the dot product. But that it is not the fault of tikzmark.

Concerning

My philosophy on using tikzmark has always been to use the tikzmark stuff merely to mark where things are on the page and then do everything else in a separate tikzpicture, and while I have no desire to be prescriptive, it may help to keep that in mind when using tikzmark as it was originally designed to fit in with how I used it!

That is precisely why I find your approach so useful.

loopspace commented 4 years ago

Great! Glad that worked.