# Anchoring TiKZ pics

Is it possible to anchor a TiKZ-pic on an internal anchor?

I know (more or less) how to use TiKZ pics and know that they are draw arround their origin. What I would like to be sure is that it's not possible to use another internal coordinate as origin.

As an example consider next code.

\tikzset{
mytest/.pic = {
\node  (-A) at (0,0) {A};
\node  (-B) at (0,1) {B};
\node[fit=(-A) (-B),draw] (-C) {};
}
}


It defines a pic with three nodes: A, B and C being A.center the pic origin. A command like

\draw pic (T) at (2,1) {mytest};


draws the pic with A.center at (2,1).

Now, I would like to draw this pic but selecting B.center (or any other internal anchor like C.120) as anchoring (pic-origin) point. Is it possible?

In case you needed, there is some complete code:

\documentclass[tikz,border=2mm]{standalone}
\usetikzlibrary{fit}

\tikzset{
mytest/.pic = {
\node  (-A) at (0,0) {A};
\node  (-B) at (0,1) {B};
\node[fit=(-A) (-B),draw] (-C) {};
}
}

\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}
\end{document}


• I would like a general solution. For this particular case I know that node B.center is 1cm above A.center and it's easy to shift the whole picture, but it's more difficult to shitf it if the origin must be at C.120 or C.100-|B.35. Consider also some pic with variable size nodes.
• The example is just an example. I'm not trying to solve a particular problem. The question is more ... conceptual(?).
• The answer could be no, it's not possible. But, please, with some explanation as I always ask to my students ;-)
-
What about scoping the pic code with a shift option? –  Claudio Fiandrino Jun 17 '14 at 12:39
How "dynamic" are your anchors? As far as I'm aware, the way to do this is to internally shift the whole pic so that a given point is now at (0,0) (in the pics coordinate system). But doing this involved knowing at the start of the pic where the desired anchor point is going to be. Is that easily computable in your use-cases (as it is in your example)? –  Loop Space Jun 17 '14 at 12:41
@ClaudioFiandrino Imagin a pic with not fixed dimensions, can I also shift it? I've updated the question. –  Ignasi Jun 17 '14 at 12:59
@LoopSpace My user-case doesn't exist but the first time I thought about it was trying to replace avoid using a pgfnewshape and using a pic. –  Ignasi Jun 17 '14 at 13:02
@Ignasi: I posted as answer what I was proposing. If this is what you are looking for, I can add more details. –  Claudio Fiandrino Jun 17 '14 at 13:10

Apparently, the idea of scoping the relevant code in pics 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:
% http://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}


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).
Thanks for the code. It's nice but I'm not sure if it solves all problems. Can I use it to place C.south west (from a third pic) on right=2cm and 3mm of S-A.30? –  Ignasi Jun 17 '14 at 13:31
@Ignasi: you're welcome! I'm not sure to understand 100% the question. Are you looking for a way to place only part of your pic (C node fitting A and B)? In the answer, shifting operation always need a pair of coordinates, namely you can't set pic shift={(S-A.north)} because, you know, a pic prefixes his name. –  Claudio Fiandrino Jun 17 '14 at 13:39
Let me try again. How can I use your code to place a complete pic with its internal -C.30 anchor on (2,3)? More complex, imagin a pic with args which modifiy A (or B) width and height, C will vary accordingly and I don't know exact dimensions. Can I still use your code to place any internal pic coordinate on a desired place? –  Ignasi Jun 17 '14 at 14:09
Thank you again for your effort. I'll need some time to understand it but I think it doesn't solve my intended question. Although I admit that my written question could be different from my intended one. That's the problem when someone tries to express ideas in a non mother tongue. I'll study your code and if I need more help will make a follow-up question. –  Ignasi Jun 18 '14 at 9:02