[Tex/LaTex] Extract x, y coordinate of an arbitrary point in TikZ

tikz-pgf

I need a macro to extract the x and y coordinates from an arbitrary point, like (3,4), or like (A), or like ([xshift=-2pt] A.north west), where A is the name of a node.

I've seen the solution

 \newdimen\mydim
 \newcommand\getx[1]{
      \pgfextractx\mydim{\pgfpointanchor{#1}{center}}
 }

elsewhere on StackExchange, but this obviously won't work for all the cases described above. I need to be able to call \getx{(3,4)} and \getx{(A)} and \getx{([xshift=-2pt] A.north west)}, and for them all to work equally well, in this case putting the x-coordinate of the argument into the variable \mydim.

I'm kind of stunned how hard this seems to be! Surely I've missed something…

Best Answer

You can use \pgfgetlastxy{\XCoord}{\YCoord} to extract the x,y coordinate of the most recently used point into the dimension registers \XCoord and {\YCoord}.

To make the point the most recently used, I use \path macro just before extraction. Here is an example where I define points, extract the x and y coordinates, and then label them via the extracted coordinates. The point C is placed at the x-coordainte of A and the y-coordiante of B.

enter image description here

Notes:

  • This has been updated to work properly when a scale= factor is applied to the tikzpicture. To see what the output is without tweaking for a scale factor uncomment the line

    %\let\ExtractCoordinate\ExtractCoordinateOld
    

Code:

\documentclass[border=2pt]{standalone}

\usepackage{tikz}
\usetikzlibrary{calc}

%% https://tex.stackexchange.com/questions/86897/recover-scaling-factor-in-tikz
\newcommand*\getscale[1]{%
  \begingroup
    \pgfgettransformentries{\scaleA}{\scaleB}{\scaleC}{\scaleD}{\whatevs}{\whatevs}%
    \pgfmathsetmacro{#1}{sqrt(abs(\scaleA*\scaleD-\scaleB*\scaleC))}%
    \expandafter
  \endgroup
  \expandafter\def\expandafter#1\expandafter{#1}%
}

\makeatletter
\newdimen\@XCoord
\newdimen\@YCoord
\newdimen\XCoord
\newdimen\YCoord
\newcommand*{\ExtractCoordinate}[1]{%
    \getscale{\@scalefactor}
    \path [transform canvas] (#1); \pgfgetlastxy{\@XCoord}{\@YCoord};
    \pgfmathsetlength{\XCoord}{\@XCoord/\@scalefactor}
    \pgfmathsetlength{\YCoord}{\@YCoord/\@scalefactor}
}
\newcommand*{\ExtractCoordinateOld}[1]{%
    \path [transform canvas] (#1); \pgfgetlastxy{\XCoord}{\YCoord};%
}%
%\let\ExtractCoordinate\ExtractCoordinateOld
\makeatother

\newcommand*{\LabelCurrentCoordinate}[2]{%
    \fill [#1] ($(\XCoord,\YCoord)$) circle (2pt) node [right] {#2}
}


\newdimen\XCoordA
\newdimen\YCoordA
\newdimen\XCoordB
\newdimen\YCoordB

\begin{document}
\begin{tikzpicture}[scale=1.5]
    \coordinate (A) at (3,2);
    \coordinate (B) at ([xshift=-2cm,yshift=-1cm] A.north west);

    \ExtractCoordinate{$(A)$};
    \LabelCurrentCoordinate{red}{A};
    \setlength\XCoordA{\XCoord}
    \setlength\YCoordA{\YCoord}

    \ExtractCoordinate{$(B)$};
    \LabelCurrentCoordinate{blue}{B};
    \setlength\XCoordB{\XCoord}
    \setlength\YCoordB{\YCoord}

    \ExtractCoordinate{$(\XCoordA,\YCoordB)$};
    \LabelCurrentCoordinate{magenta}{C};
\end{tikzpicture}
\end{document}