Arrows mess up bounding box of pics

I use pics to reuse more sophisticates images multiple times in a drawing. To easily connected them with lines/arrows I name the bounding box of each pic, so they get a bit a node-like behavior.

Now I realize that if I use an arrow in a pic the bounding box is not longer around the pic but also includes the 0/0 - point.

For a better understanding check my MWE (I am quite new to TikZ so any tips are welcomed); The dashed line is the bounding box. As you can see for a pic without arrows (red) and a scope (blue) it works as expected, but for the pic with an arrow (red) the bounding box is wrong.

\documentclass[]{standalone}

\usepackage{tikz}
\usepackage[mode=buildnew]{standalone}

\begin{document}
\begin{standaloneframe}
\begin{tikzpicture}[
withArrow/.pic = {
\begin{scope}[shift = {(-2,-2)}, local bounding box = withArrow] % the shift is for easier placing the pic.
\draw[thick] (0,2) -- (4,2) (2,0)--(2, 4);
\draw[thin, ->,] (1,1) -- (3,3);
\end{scope}
},
withoutArrow/.pic = {
\begin{scope}[shift = {(-2,-2)}, local bounding box = withoutArrow]
\draw[thick] (0,2) -- (4,2) (2,0)--(2, 4);
\end{scope}
}
]

% Mark 0/0 point just for orientation
\node[circle, draw = black] (Zero) {0/0};

% Pic without Arrow works as expected
\pic at(3,3) {withoutArrow};

% Bounding box
\draw [green, dashed] (withoutArrow.south west) rectangle (withoutArrow.north east);

% Pic with Arrow; bounding box is extended to incluce 0/0 point
\pic at(3,-3) {withArrow};

% Bounding box
\draw [red, dashed] (withArrow.south west) rectangle (withArrow.north east);

% Scope works also with arrow fine
\begin{scope}[scale = 1, shift = {(6,-2)}, local bounding box = scope]
\draw[thick] (0,2) -- (4,2) (2,0)--(2, 4);
\draw[thin, ->,] (1,1) -- (3,3);
\end{scope}

\draw [blue, dashed] (scope.south west) rectangle (scope.north east);

\end{tikzpicture}

\end{standaloneframe}
\end{document}

• It seems that the shift inside pic cause this problem. – ZhiyuanLck Jun 17 at 11:27
• Are you sure? Because I tried it without the shift and found that it makes no difference. – WitheShadow Jun 17 at 13:28
• I tried a lot, it seems that when there is a shift transformation, the arrow is drawn twice. – ZhiyuanLck Jun 17 at 13:30
• I deleted all the shift but still have the issue. But interestingly, if I put the pic after the scope, the scope has now the box issue. I am really confused... but I can now work around the if I first have a scope with an (invisible) arrow. – WitheShadow Jun 17 at 13:35
• Remove your first two examples, left only the last, you will see the problem. – ZhiyuanLck Jun 17 at 13:40

A simplified example:

\documentclass{article}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
\draw[->, xshift=1cm, local bounding box=x] (0, 0) -- (1, 1);
\draw[blue, dashed] (x.south west) rectangle (x.north east);
\end{tikzpicture}
\end{document}


In PGF 3.1.5b, the latest released PGF in Jun 2020, \pgf@path@size@hook is executed unconditionally in \pgf@protocolsizes (in order to fix this issue), and this causes your problem. The maintainer of PGF has reverted that change in the latest repository of PGF, see this commit, and this should fix your problem.

So as a workaround before the next PGF release, you can fix your problem by adding following redefinition of \pgf@protocolsizes to the preamble of your tex file:

\makeatletter
\def\pgf@protocolsizes#1#2{%
\ifpgf@relevantforpicturesize%
\ifdim#1<\pgf@picminx\global\pgf@picminx#1\fi%
\ifdim#1>\pgf@picmaxx\global\pgf@picmaxx#1\fi%
\ifdim#2<\pgf@picminy\global\pgf@picminy#2\fi%
\ifdim#2>\pgf@picmaxy\global\pgf@picmaxy#2\fi%
\ifpgf@size@hooked%
\let\pgf@size@hook@x#1\let\pgf@size@hook@y#2\pgf@path@size@hook%
\fi%
\fi%
\ifdim#1<\pgf@pathminx\global\pgf@pathminx#1\fi%
\ifdim#1>\pgf@pathmaxx\global\pgf@pathmaxx#1\fi%
\ifdim#2<\pgf@pathminy\global\pgf@pathminy#2\fi%
\ifdim#2>\pgf@pathmaxy\global\pgf@pathmaxy#2\fi%
}
\makeatother


This is not the answer, just some examples to show the problem.

• teal box: local bounding box
• brown box: current bounding box

Problem

First path with arrow seems to extend the local bounding box.

\documentclass[tikz, border=5cm]{standalone}
\usetikzlibrary{fit}

\begin{document}
\begin{tikzpicture}
\begin{scope}[scale = 1, shift = {(3 ,1)}, local bounding box = scope]
\draw[thin, ->,] (0,0) -- (1,1);
\end{scope}
\node [fit=(current bounding box.south west)(current bounding box.north east), draw=brown] {};
\draw [teal] (scope.south west) rectangle (scope.north east);
\draw[thin, ->, gray] (0,0) -- (1,1);
\draw[cyan] (0, 0) -- +(3, 1);
\end{tikzpicture}
\end{document}


If a path with arrow is constructed before:

\documentclass[tikz, border=5cm]{standalone}
\usetikzlibrary{fit}

\begin{document}
\begin{tikzpicture}
\path[->] (0, 0) -- (.1, .1);
\begin{scope}[scale = 1, shift = {(3 ,1)}, local bounding box = scope]
\draw[thin, ->,] (0,0) -- (1,1);
\end{scope}
\node [fit=(current bounding box.south west)(current bounding box.north east), draw=brown] {};
\draw [teal] (scope.south west) rectangle (scope.north east);
\draw[thin, ->, gray] (0,0) -- (1,1);
\draw[cyan] (0, 0) -- +(3, 1);
\end{tikzpicture}
\end{document}


If a path with arrow is drawn before:

\documentclass[tikz, border=5cm]{standalone}
\usetikzlibrary{fit}

\begin{document}
\begin{tikzpicture}
\path[->] (0, 0) -- (.1, .1);
\begin{scope}[scale = 1, shift = {(3 ,1)}, local bounding box = scope]
\draw[thin, ->,] (0,0) -- (1,1);
\end{scope}
\node [fit=(current bounding box.south west)(current bounding box.north east), draw=brown] {};
\draw [teal] (scope.south west) rectangle (scope.north east);
\draw[thin, ->, gray] (0,0) -- (1,1);
\draw[cyan] (0, 0) -- +(3, 1);
\end{tikzpicture}
\end{document}


• The local bounding box has been switched back and forth, see here for some backup of the statement. In the next version of pgf it will be again different. In a way the current version was to make some other user happy. So, unfortunately, whatever you find here may no longer be true in version 3.1.5. :-( – user194703 Jun 17 at 14:34