How to allow labels' anchors in TikZ to be affected by rotations without rotating the text itself?
The Anchor
key defines two coordinate with the current transformation matrix active (scaling, rotating, whatever) and from that calculates the angle between these coordinates in the canvas for an un-transformed node.
The code for the Anchor
style was inspired by another answer of mine (which could be simplified) to Small text near arrow tips.
The Anchor
style probably works best with the circle
or the ellipse
shape.
The rectangle
shape is very nonuniform.
Of course, you can define styles like Below Left/.style={Anchor=45}
if you want to use directions for the current transformation matrix.
The code uses \pgfcoordinate
which is quick version of \pgfnode
for a coordinate
.
Instead of the \pgfcoordinate
s we could have written
\path (0,0) coordinate (qrr@origin)
(#1:1) coordinate (qrr@direct);
The matrix transformation is then reset (so that we are back in coordinate system that has the same orientation as our canvas in which we place the un-transformed node) with \pgftransformreset
.
The macro \pgfmathanglebetweenpoints
is not documented in the PGF manual. It is defined in pgfmathcalc.code.tex
after a block that warns
% *** The following commands DO NOT WORK without the rest of PGF ***
%
% (a dumping ground for stuff that doesn't really belong anywhere else)
The instruction for \pgfmathanglebetweenpoints
read
% \pgfmathanglebetweenpoints
%
% Define \pgfmathresult as the angle between points #1 and #2
% Should get the quadrants right as well.
In the linked answer of mine I did practically the same as that macro but in a manual manner (and maybe not as precise).
The TeX group is necessary so that \pgftransformreset
doesn’t affect the actual placement of the node. The \pgfmath@smuggleone
(or its @
-less version \pgfmathsmuggle
) is then used to “smuggle” \pgfmathresult
out of the group. The \pgfmath@smuggleone
macro is used very often in PGF math. It’s definition in pgfmathutil.code.tex
is
% \pgfmath@smuggleone
%
% Smuggle a macro outside a group.
%
% Changed by TT: Speedup by insisting, that smuggleone is directly
% followed by \endgroup
%
\def\pgfmath@smuggleone#1\endgroup{%
\expandafter\endgroup\expandafter\def\expandafter#1\expandafter{#1}}
\let\pgfmathsmuggle=\pgfmath@smuggleone
The advance over \global
ing it is that it only affects one group and not all.
Code
\documentclass[margin=.5cm]{standalone}
\usepackage{tikz}
\tikzset{
Anchor/.code=%
\begingroup
\pgfcoordinate{qrr@origin}{\pgfpointorigin}%
\pgfcoordinate{qrr@direct}{\pgfpointpolarxy{#1}{1}}%
\pgftransformreset
\pgfmathanglebetweenpoints{\pgfpointanchor{qrr@origin}{center}}{\pgfpointanchor{qrr@direct}{center}}%
\pgfmathsmuggle\pgfmathresult
\endgroup
\tikzset{anchor/.expanded=\pgfmathresult}%
}
\newcommand{\myDraw}[2]{% \myDraw{rotation angle}{scale factor}
\begin{minipage}[t]{2.5cm}
\centering \footnotesize $\theta=#1^{\circ}$, $k=#2$ \medskip\\
\begin{tikzpicture}[rotate=#1,scale=#2]
\draw (0,1) -- (0,0) node[Anchor=45] {$O$} -- (1,0) node[midway,Anchor=90] {$1$};
\end{tikzpicture}
\end{minipage}}
\begin{document}
\myDraw{0}{0.5}
\myDraw{45}{0.7}
\myDraw{90}{1}
\myDraw{135}{1.3}
\myDraw{180}{1.5}
\end{document}
Output
I do not know if this will satisfy you, the question is not very precise.
I added the library calc
to determine the position of the text.
The texts "O" is then positioned relative to the origin, same for "I".
\documentclass[margin=.5cm]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\newcommand{\myDraw}[2]{% \myDraw{rotation angle}{scale factor}
\begin{minipage}[t]{2.5cm}
\centering \footnotesize $\theta=#1^{\circ}$, $k=#2$ \medskip\\
\begin{tikzpicture}[rotate=#1,scale=#2]
\draw (0,1) -- (0,0) coordinate (o) -- (1,0) node[midway,name=i] {$1$};
\node (O) at ($(o)+(-0.5em,-0.5em)$) {$O$};
\node (I) at ($(i)+(0,-0.5em)$) {$1$};
\end{tikzpicture}
\end{minipage}}
\begin{document}
\myDraw{0}{0.5}
\myDraw{45}{0.7}
\myDraw{90}{1}
\myDraw{135}{1.3}
\myDraw{180}{1.5}
\end{document}
another solution
Here's another solution, I use here the intersection between a line and a node (insensitive to scale) to position the text "O", the text "1" it is positioned at the intersection of the line from "O" and "i".
\documentclass[margin=.5cm]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc,positioning}
\newcommand{\myDraw}[2]{% \myDraw{rotation angle}{scale factor}
\begin{minipage}[t]{2.5cm}
\centering \footnotesize $\theta=#1^{\circ}$, $k=#2$ \medskip\\
\begin{tikzpicture}[rotate=#1,scale=#2]
\draw (0,1) -- (0,0) coordinate (o) -- (1,0) coordinate[midway,name=i];
\node[circle,minimum size=2em](circle) at (o){};
\path(o) -- (-2,-2)coordinate(b);
\path (intersection of o--b and circle) coordinate (oo)node{O};
\path (oo) -| (i) node[pos=0.5]{1};
\end{tikzpicture}
\end{minipage}}
\begin{document}
\myDraw{0}{0.5}
\myDraw{45}{0.7}
\myDraw{90}{1}
\myDraw{135}{1.3}
\myDraw{180}{1.5}
\end{document}
there is a problem with 180 °!
I've eventually came up with a solution to my problem:
\documentclass[margin=.5cm]{standalone}
\usepackage{tikz}
\newcommand{\myDraw}[2]{% \myDraw{rotation angle}{scale factor}
\begin{minipage}[t]{2.5cm}
\centering \footnotesize $\theta=#1^{\circ}$, $k=#2$ \medskip\\
\begin{tikzpicture}[rotate=#1,scale=#2]
\draw (0,1) -- (0,0) coordinate (O) -- (1,0) coordinate[midway] (I);
\begin{scope}[scale=1/#2]
\draw (O) ++ (-0.25,-0.25) node {$O$};
\draw (I) ++ (0,-0.25) node {$1$};
\end{scope}
\end{tikzpicture}
\end{minipage}}
\begin{document}
\myDraw{0}{0.5}
\myDraw{45}{0.7}
\myDraw{90}{1}
\myDraw{135}{1.3}
\myDraw{180}{1.5}
\end{document}
Among the things I've learned, I can name a point inside a path using coordinate
like this:
\draw (0,1) -- (0,0) coordinate (O);
I can also name a node with the keyword name=
so I still can use some convenient options like midway
or pos=
:
\draw (0,0) -- (1,0) node[midway,name=I] {};
But thanks to a comment of Qrrbrbirlbel below, I know now that I can simply use the previous options with coordinate
:
\draw (0,0) -- (1,0) coordinate[midway] (I);
Once I've done that, I need to manually position my labels and apply the inverse scale factor:
\begin{scope}[scale=1/#2]
\draw (O) ++ (-0.25,-0.25) node {$O$};
\draw (I) ++ (0,-0.25) node {$1$};
\end{scope}
So two issues remain:
- The scale factor must be passed as an argument to my macro.
- I need to manually position my labels which means that I can't use convenient anchors like
below left
).