Anchoring TiKZ pics
Apparently, the idea of scoping the relevant code in pic
s works.
Here is an example:
\documentclass[tikz,border=2mm]{standalone}
\usetikzlibrary{fit}
\tikzset{pic shift/.store in=\shiftcoord,
pic shift={(0,0)},
mytest/.pic = {
\begin{scope}[shift={\shiftcoord}]
\node (-A) at (0,0) {A};
\node (-B) at (0,1) {B};
\node[fit=(-A) (-B),draw] (-C) {};
\end{scope}
}
}
\begin{document}
\begin{tikzpicture}
\draw[blue!20] (0,0) grid (3,3);
\draw pic (S) at (0,0) {mytest};
\draw pic (T) at (2,1) {mytest};
\draw (S-A.north) to [out=90,in=-90] (T-B.south);
\end{tikzpicture}
\begin{tikzpicture}
\draw[blue!20] (0,0) grid (3,3);
\draw[pic shift={(1,1)}] pic (S) at (0,0) {mytest};
\draw pic (T) at (2,1) {mytest};
\draw (S-A.north) to [out=90,in=-90] (T-B.south);
\end{tikzpicture}
\end{document}
The result without shifts:
while shifting the first pic (S):
EDIT
Trying to answer to last Ignasi's comment: Can I still use your code to place any internal pic coordinate on a desired place?
Probably, the answer is: yes, to some extent. Meaning that in a tikzpicture, while referring to a pic, you are actually taking into account his origin, namely whatever is placed in the coordinate (0,0)
. In the current case, node A
. So, you can shift the complete pic with respect to this point, but I suspect you can not place any internal pic coordinate on a desired place. You can place any pic coordinate on a desired place as a consequence of having shifted the pic with respect to its origin.
Let us consider the following example:
\documentclass[tikz,border=2mm]{standalone}
\usetikzlibrary{fit,positioning}
% code by Andrew:
% https://tex.stackexchange.com/a/33765/13304
\makeatletter
\newcommand{\gettikzxy}[3]{%
\tikz@scan@one@point\pgfutil@firstofone#1\relax
\edef#2{\the\pgf@x}%
\edef#3{\the\pgf@y}%
}
\makeatother
\tikzset{pic shift/.store in=\shiftcoord,
pic shift={(0,0)},
pic-a min height/.store in=\picaminheight,
pic-a min height=0pt,
pic-a min width/.store in=\picaminwidth,
pic-a min width=0pt,
mytest/.pic = {
\begin{scope}[shift={\shiftcoord}]
\node[minimum height=\picaminheight,
minimum width=\picaminwidth,
draw] (-A) at (0,0) {A};
\node (-B) at (0,1) {B};
\node[fit=(-A) (-B),draw] (-C) {};
\end{scope}
}
}
\begin{document}
\begin{tikzpicture}
\draw[blue!20] (0,0) grid (3,3);
\draw[pic-a min height=1cm,
pic-a min width=1cm,
pic shift={(1,1)}] pic (S) at (0,0) {mytest} node[coordinate] (sn){};
\gettikzxy{(S-C.east)}{\sbx}{\sby}
\draw[red,pic shift={(\sbx,\sby)}] pic (T) at (0,0) {mytest};
\gettikzxy{(S-C.south)}{\sdx}{\sdy}
\draw[blue,pic shift={(\sdx,\sdy)}] pic (T) at (0,0) {mytest};
\gettikzxy{(S-C.east)}{\sex}{\sey}
\draw[pic-a min width=0cm,green!75!black,pic shift={(\sex,\sey)}] pic (O) at (1,0) {mytest};
\end{tikzpicture}
\end{document}
which leads to:
Recalling that the origin of mytest
is node -A
, we have the first pic (S) with increased size denoted in black. It will be our reference.
Thanks to Andrew's \gettikzxy
, we can grab coordinates of (S-C.east). The second mytest
pic (T), in red, is placed in position (0,0)
(of the general tikzpicture) and we operate a shift into (S-C.east) coordinates. As expected, (T-A) is put in (S-C.east)
. The same happens for pic M
. However, apparently it is not possible to anchor pics with respect to their C node points. What you can do, is to take advantage of both pic shift
and coordinate placement for anchoring a pic with respect to his C node (I admit, is not that elegant). For example the green (O) mytest
pic is anchored with respect to his -C.south east
point in (1,3).
As though Claudio has given a complete answer, I think there's a simpler one, which may be either a bug or an undocumented feature of TikZ (because it's not in the Manual). It's not a complete answer because you cannot use all internal coordinates of the pic
but rather just the coordinates from the node placed at the origin.
Out of curiosity I tried to put a node at the pic
's origin and access its anchors through the pic
command, and guess what? It works. So, apperantly just make a pic
with a node as bounding box and you can place it with respect to its anchors!
\documentclass[tikz,border=2mm]{standalone}
\tikzset{mytest/.pic = {\node[draw, minimum height=1.5cm, minimum width=.5cm] (-box) at (0,0) {};
\node[above] (-A) at (-box.south) {A};
\node[below] (-B) at (-box.north) {B};}
}
\begin{document}
\begin{tikzpicture}
\draw[blue!20] (0,0) grid (3,3);
\draw pic[anchor=south west] (S) at (0,0) {mytest};
\draw pic[below left=1mm] (T) at (2,2) {mytest};
\draw (S-A.north) to [out=90,in=-90] (T-B.south);
\end{tikzpicture}
\end{document}