# Transform defined coordinates in TikZ

Say I have a triangle with vertices defined using

\coordinate (a) at (0,0);
\coordinate (b) at (1,0);
\coordinate (c) at (0,1);


Let us denote by T(x,y) the triangle defined by (a),(b) and (c) which is translated by a vector (x,y). I can now easily draw T(0,0) as follows:

\draw (a) -- (b) -- (c) -- cycle;


So far so good. Now, lets say that I want to plot the triangle T(2,3). Ideally, I would like to do something like:

\begin{scope}[shift={(2,3)}]
\draw (a) -- (b) -- (c) -- cycle;
\end{scope}


However, as the coordinates were defined outside of the scope the transformation (translation in this case) won't effect them. See this answer. What would be the smart way to do it? Or more generally:

What is the best way to reuse coordinates that are defined once under varying transformations?

Possible solution: Basing on the comment of @Qrrbrbirlbel I posted an answer. This answer however, is very limited and local - is the something more general?

-
Depending on your use-case, shifting every coordinate (\draw ([shift={(2,3)}] a) -- ([shift={(2,3)}] b) -- ([shift={(2,3)}] c) -- cycle;) or using a canvas transformation can be the solution. See the top part of another answer. –  Qrrbrbirlbel Feb 19 '13 at 13:18

As the other questions linked have explained the issue, I'll not go over old ground. Looking at the code there does not seem to be an easy way to say "Apply the following style (say, shift={(2,3)}) to all of the following points.". There is no every point style (contrast the many every path or every node or ...). Moreover, adding one in would not be simple as the coordinate parser needs to see the [ to invoke the bit that does the transformation (the code here has the illuminating comment uhoh... options! at this point).

So there's not a really, really simple solution. But there is a way to make the proper way to do this a little simpler using styles.

\documentclass{article}
%\url{http://tex.stackexchange.com/q/98924/86}
\usepackage{tikz}

\tikzset{
c/.style={every coordinate/.try}
}

\begin{document}
\begin{tikzpicture}
\coordinate (a) at (0,0);
\coordinate (b) at (1,0);
\coordinate (c) at (0,1);
\draw (a) -- (b) -- (c) -- cycle;
\begin{scope}[every coordinate/.style={shift={(2,3)}}]
\draw ([c]a) -- ([c]b) -- ([c]c) -- cycle;
\end{scope}
\end{tikzpicture}
\end{document}


-

What about defining a generic anchor (r for relative) which applies the transformation? EDIT: Now a version that really works!

Two problems:

• the code that calls the generic anchor expects the coordinates in the node's cs.
• that same code applies the inverse of the outer transformation --- this is what makes the named coordinates absolute!

Out job is to do the inverses of all these operations (in the reverse order).

\documentclass{article}
\usepackage{tikz}

\makeatletter
\pgfdeclaregenericanchor{r}{%
% 1. get (x,y) in the node's cs
\pgf@sh@reanchor{\csname pgf@sh@ns@\pgfreferencednodename\endcsname}{center}%
{% 2. apply the node transformation
\pgfsettransform{\csname pgf@sh@nt@\pgfreferencednodename\endcsname}%
\pgf@pos@transform{\pgf@x}{\pgf@y}%
\global\pgf@x=\pgf@x%
\global\pgf@y=\pgf@y%
}%
% 3. *don't* apply the inverse of the outer transformation! We want
%    relative coordinates!
{% 4. apply the inverse of the inverse of the outer transform
%    (cancels the inverse of the outer transformation done by \pgfpointanchor)
\pgf@pos@transform{\pgf@x}{\pgf@y}%
\global\pgf@x=\pgf@x%
\global\pgf@y=\pgf@y%
}%
{% 5. apply the inverse of the nodes transformation (cancels the node
%    transformation done by \pgfpointanchor)
\pgfsettransform{\csname pgf@sh@nt@\pgfreferencednodename\endcsname}%
\pgftransforminvert
\pgf@pos@transform{\pgf@x}{\pgf@y}%
\global\pgf@x=\pgf@x%
\global\pgf@y=\pgf@y%
}%
}
\makeatother

\begin{document}

\begin{tikzpicture}
\coordinate (a) at (0,0);
\coordinate (b) at (1,0);
\coordinate (c) at (0,1);
\draw[blue,ultra thick] (a) -- (b) -- (c) -- cycle;
\begin{scope}[shift={(2,0)},scale=2]
\draw[red] (a.r) -- (b.r) -- (c.r) -- cycle;
\end{scope}
\end{tikzpicture}

\end{document}


-

It isn't straightforward at all to add a general every coordinate style. But, a \iftikztransformnodecoordinates is fairly simply to hack.

\documentclass{standalone}
\usepackage{tikz}

\makeatletter
\newif\iftikztransformnodecoordinates
\tikzset{transform node coordinates/.is if=tikztransformnodecoordinates}

\def\tikz@parse@node#1(#2){%
\pgfutil@in@.{#2}%
\ifpgfutil@in@
\tikz@calc@anchor#2\tikz@stop%
\else%
\tikz@calc@anchor#2.center\tikz@stop%
\expandafter\ifx\csname pgf@sh@ns@#2\endcsname\tikz@coordinate@text%
\else
\tikz@shapebordertrue%
\def\tikz@shapeborder@name{#2}%
\fi%
\fi%
\iftikztransformnodecoordinates%
\pgf@pos@transform{\pgf@x}{\pgf@y}%
\fi
\edef\tikz@marshal{\noexpand#1{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}}%
\tikz@marshal%
}

\begin{document}

\begin{tikzpicture}

\coordinate (a) at (0,0);
\coordinate (b) at (1,0);
\coordinate (c) at (0,1);

\draw (a) -- (b) -- (c) -- cycle;

\draw [red, transform node coordinates, rotate=10]
(a) -- (b) -- (c) -- cycle;

\draw [green, transform node coordinates, shift={(1,1)}]
(a) -- (b) -- (c) -- cycle;

\draw [blue, transform node coordinates, rotate=10, shift={(1,1)}]
(a) -- (b) -- (c) -- cycle;

\end{tikzpicture}

\end{document}


Not sure if it is 100% robust though.

-

In TikZ/pgf, transformations are applied only to numeric coordinates. To retrieve original numeric coordinates from nodes or coordinates, you may use a let operation:

\documentclass[tikz]{standalone}
\usetikzlibrary{calc,scopes}
\begin{document}
\begin{tikzpicture}
\coordinate (a) at (0,0);
\coordinate (b) at (1,0);
\coordinate (c) at (0,1);
\draw (a) -- (b) -- (c) -- cycle;

\draw[blue] let \p{a}=(a),\p{b}=(b),\p{c}=(c) in
{[rotate=30] (\p{a}) -- (\p{b}) -- (\p{c}) -- cycle}
{[shift={(2,3)}] (\p{a}) -- (\p{b}) -- (\p{c}) -- cycle};
\end{tikzpicture}
\end{document}

-
\newcommand*{\drawT}[1]{%

Now, calling \drawT{(2,3)} will draw T(2,3) as per the OP definitions.