5

When I use scale in tikzpictures (without transform shape), the text size in nodes is not changed (which is good and well). Suppose now that I want to put some node in a scaled graph using a distance proportional to the node font; I naively supposed that I could use ex coords, but see below...

I also printed the values of the coordinates, and \pgf@yy which should give the unit vector, but there is something I miss here...

Is there a way to express a distance which is proportional to the (default) font size, independently from the scale?

\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\newdimen\mydimA\newdimen\mydimB
\makeatletter
\newcommand{\showat}[1]{%
    \pgfextracty\mydimA{\pgfpointanchor{A}{center}}
    \pgfextracty\mydimB{\pgfpointanchor{B}{center}}
    \node[red, font=\tiny,  align=left] at(#1) {Before \the\mydimA \\ After \the\mydimB \\
    Scale y \the\pgf@yy};
}
\makeatother
\begin{document}
\begin{tikzpicture}[baseline]
    \draw (0,0)  --(1,0) coordinate(A) -- (2,0);
    \path (A) ++(0,1ex) coordinate(B);
    \node [anchor=base] at (B) {$R_g$};
    \showat{1,-1}
\end{tikzpicture}
\begin{tikzpicture}[baseline, scale=2]
    \draw (0,0)  --(0.5,0) coordinate(A) -- (1,0);
    \path (A) ++(0,1ex) coordinate(B);
    \node [anchor=base] at (B) {$R_g$};
    \showat{0.5,-0.5}
\end{tikzpicture}
\begin{tikzpicture}[baseline, scale=0.01]
    \draw (0,0)  --(100,0) coordinate(A) -- (200,0);
    \path (A) ++(0,1ex) coordinate(B);
    \node [anchor=base] at (B) {$R_g$};
    \showat{100,-100}
\end{tikzpicture}
\end{document}

enter image description here

5
  • If you want to scale the whole picture you could use \resizebox -- which scales everything (line width, text spacing) Feb 21, 2019 at 12:44
  • @AubreyBlumsohn, no, it's not a matter of rescaling the whole picture. I want to be able to say that a label should be at 1ex distance from an anchor, no matter the scale of the figure... it's for a much more complex case, really (see github.com/circuitikz/circuitikz/issues/91) .
    – Rmano
    Feb 21, 2019 at 12:47
  • I didn't understand your question.
    – AndréC
    Feb 21, 2019 at 14:07
  • Coordinates are transformed by scaling while node text isn't. I'm not sure why one would expect something else. Internally, TeX does not care if it is cm or ex, it's all sp.
    – TeXnician
    Feb 21, 2019 at 14:37
  • @AndréC Basically the question is how to get all these three tikzpictures to produce the same results while using coordinate transformations based on font dimensions like ex (relative to the node font).
    – TeXnician
    Feb 21, 2019 at 14:44

4 Answers 4

5

Your 1em is being converted at read time into the coordinate system, which is then affected by the picture scale. You can use reset cm to locally reset the coordinate transformation matrix, locally cancelling the picture scale effect.

\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}[baseline]
    \draw (0,0)  --(1,0) coordinate(A) -- (2,0);
    \path (A) ++(0,1em) coordinate(B);
    \node [anchor=base] at (B) {$R_g$};
\end{tikzpicture}
\begin{tikzpicture}[baseline, scale=2]
  \draw (0,0)  --(0.5,0) coordinate(A) -- (1,0);
  \path[reset cm] (A) ++(0,1em) coordinate(B);
  \node [anchor=base] at (B) {$R_g$};
\end{tikzpicture}
\begin{tikzpicture}[baseline, scale=0.01]
  \draw (0,0)  --(100,0) coordinate(A) -- (200,0);
  \path[reset cm] (A) ++(0,1em) coordinate(B);
  \node [anchor=base] at (B) {$R_g$};
\end{tikzpicture}
\end{document}
1
  • I used this and it works as supposed... thanks a lot!
    – Rmano
    Feb 21, 2019 at 16:12
2

Resetting the scale locally is one option (see Marsden's answer), but there is a better way to go about things.

With scale=factor, all coordinates are scaled by factor, regardless of their dimension (while the unit vectors are unchanged, as you discovered). Instead, redefine the length of the unit vectors according to the desired scaling. For example, with y={(0cm,2cm)}, while (0,0) -- (1,0) will be twice the usual distance, coordinates with dimensions, such as (0,1ex), will be unchanged:

\begin{document}
\begin{tikzpicture}[baseline]
    \draw (0,0)  --(1,0) coordinate(A) -- (2,0);
    \path (A) ++(0,1ex) coordinate(B);
    \node [anchor=base] at (B) {$R_g$};
    \showat{1,-1cm}
\end{tikzpicture}
\begin{tikzpicture}[baseline, x={(2cm,0cm)},y={(0cm,2cm)}]
    % Identical code to previous picture:
    \draw (0,0)  --(1,0) coordinate(A) -- (2,0);
    \path[scale=1] (A) ++(0,1ex) coordinate(B);
    \node [anchor=base] at (B) {$R_g$};
    \showat{1,-1cm}
\end{tikzpicture}
\end{document}

Output:

output

Note how the distance between A and B is unchanged, while \the\pgf@yy has doubled, as expected.

2

Why don't you place B as itself a node (with relative placement)?

That would solve all your problems.

\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{positioning}
\newdimen\mydimA\newdimen\mydimB
\makeatletter
\newcommand{\showat}[1]{%
    \pgfextracty\mydimA{\pgfpointanchor{A}{center}}
    \pgfextracty\mydimB{\pgfpointanchor{B}{center}}
    \node[red, font=\tiny,  align=left] at(#1) {Before \the\mydimA \\ After \the\mydimB \\
    Scale y \the\pgf@yy};
}
\makeatother
\begin{document}
\tikzset{node distance=1ex}
\begin{tikzpicture}[baseline]
    \draw (0,0)  --(1,0) coordinate(A) -- (2,0);
    \node[above=of A,anchor=base](B){$R_g$};
    \showat{1,-1}
\end{tikzpicture}
\begin{tikzpicture}[baseline, scale=2]
    \draw (0,0)  --(0.5,0) coordinate(A) -- (1,0);
    %\path (A) ++(0,1ex) coordinate(B)node{y};
    \node[above=of A,anchor=base] (B) {$R_g$};
    \showat{0.5,-0.5}
\end{tikzpicture}
\begin{tikzpicture}[baseline, scale=0.01]
    \draw (0,0)  --(100,0) coordinate(A) -- (200,0);
    %\path (A) ++(0,1ex) coordinate(B)node{y};
    \node[above=of A,anchor=base] (B) {$R_g$};
    \showat{100,-100}
\end{tikzpicture}
\end{document}

screenshot

2

Eric Marsden's answer explains nicely what's going on. However, I would just read out the relevant entry of the transformation matrix (it is the 22 entry) and "invert" it. This is a trick that I also used (without inversion, of course) to scale the line width with a shape because by default it doesn't scale.

\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\newdimen\mydimA\newdimen\mydimB
\makeatletter
\newcommand{\showat}[1]{%
    \pgfextracty\mydimA{\pgfpointanchor{A}{center}}
    \pgfextracty\mydimB{\pgfpointanchor{B}{center}}
    \node[red, font=\tiny,  align=left] at(#1) {Before \the\mydimA \\ After \the\mydimB \\
    Scale y \the\pgf@yy};
}
\makeatother
\begin{document}
\begin{tikzpicture}[baseline]
    \draw (0,0)  --(1,0) coordinate(A) -- (2,0);
    \pgfgettransformentries{\tmp}{\tmp}{\tmp}{\myscale}{\tmp}{\tmp}
    \path  (A) ++(0,1ex/\myscale) coordinate(B);
    \node [anchor=base] at (B) {$R_g$};
    \showat{1,-1}
\end{tikzpicture}
\begin{tikzpicture}[baseline, scale=2]
    \draw (0,0)  --(0.5,0) coordinate(A) -- (1,0);
    \pgfgettransformentries{\tmp}{\tmp}{\tmp}{\myscale}{\tmp}{\tmp}
    \path  (A) ++(0,1ex/\myscale) coordinate(B);
    \node [anchor=base] at (B) {$R_g$};
    \showat{0.5,-0.5}
\end{tikzpicture}
\begin{tikzpicture}[baseline, scale=0.01]
    \draw (0,0)  --(100,0) coordinate(A) -- (200,0);
    \pgfgettransformentries{\tmp}{\tmp}{\tmp}{\myscale}{\tmp}{\tmp}
    \path  (A) ++(0,1ex/\myscale) coordinate(B);
    \node [anchor=base] at (B) {$R_g$};
    \showat{100,-100}
\end{tikzpicture}
\end{document}

enter image description here

2
  • 1
    Thanks @marmot, +1! I already accepted Eric's answer (and implemented it), but I think both are valid.
    – Rmano
    Feb 21, 2019 at 16:13
  • 1
    @Rmano Yes, Eric was the first to point out what the problem is and provided an elegant way to fix it. You should definitely accept his nice answer.
    – user121799
    Feb 21, 2019 at 17:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .