Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

In another question concerning Access to logic coordinates on

Accessing the logic values of a TikZ coordinate

I used these functions, until I came to a scaled tikzpicture and then it was off. I now have added a factor for the scaling, but I am looking for a method to make it universal. That would mean the xcoord/ycoord would take the picture's scaling into account through a tikz/pgf variable.

\makeatletter
\newcommand\xcoord[2][center]{{%
  \pgfpointanchor{#2}{#1}%
  \pgfmathparse{\pgf@x/\pgf@xx}%
  \pgfmathprintnumber{\pgfmathresult}%
}}
\newcommand\ycoord[2][center]{{%
  \pgfpointanchor{#2}{#1}%
  \pgfmathparse{\pgf@y/\pgf@yy}%
  \pgfmathprintnumber{\pgfmathresult}%
 }}
 \makeatother

Any suggestion to that effect?

An MWE is:

\documentclass{article}
\usepackage{tikz}
\usepackage{pgfplots}
\usepackage{pgffor}

\makeatletter
\newcommand\xcoorda[2][center]{{%
  \pgfpointanchor{#2}{#1}%
  \pgfmathparse{\pgf@x/\pgf@xx}%
  \pgfmathprintnumber{\pgfmathresult}%
}}

\makeatletter
\newcommand\xcoord[2][center]{{%
 \pgfpointanchor{#2}{#1}%
 \pgfmathparse{\pgf@x/\pgf@xx/.17}%
 \pgfmathprintnumber{\pgfmathresult}%
}}

\newcommand\ycoorda[2][center]{{%
  \pgfpointanchor{#2}{#1}%
  \pgfmathparse{\pgf@y/\pgf@yy}%
  \pgfmathprintnumber{\pgfmathresult}%
}}
\makeatother

\usetikzlibrary{intersections}


\begin{document}

\begin{tikzpicture}[domain=-0.01:0.55,xscale=17,yscale=0.01] 
% the scaling is also in xcoord
\draw[-stealth,name path=xline] (0,0) -- (0.55,0);
\draw[stealth-stealth,name path=yline] (0,-220) -- (0,220);
\draw[color=blue,name path=func] (0,200) parabola bend (.25,-50) (.50,200);
\path[name intersections={of=func and xline,by={i1,i2}}];
\node[above=15pt] (i1label) at(i1) {\xcoord{i1}\%};
\draw[-stealth,green] (i1label.south) -- (i1);
\node[below=20pt,text width=2cm,align=center,draw,fill=red!25] (i1label_a) 
 at(i1) {\xcoorda{i1}\%\\ sans scaling \\ wrong!};
\draw[-stealth,red] (i1label_a.north) -- (i1);
\node[above=15pt] (i2label) at(i2) {\xcoord{i2}\%};
\draw[-stealth,green] (i2label.south) -- (i2);
\node[below=20pt,text width=2cm,draw,align=center,fill=red!25] (i2label_a) 
 at(i2) {\xcoorda{i2}\%\\ sans scaling \\ wrong!};
\draw[-stealth,red] (i2label_a.north) -- (i2);
\foreach \t in {10,20,...,50} {
\pgfmathparse{\t/100}\edef\v{\pgfmathresult}
  \draw[thin] (\v,10) -- (\v,-10) node[below] {\t\%};
}
\foreach \t in {-200,-100,...,200} {
 \draw[thin] (.010,\t) -- (-0.01,\t) node[left] {\small\t};
}
\end{tikzpicture}

\end{document}

I used a parabola in the MWE and marked the scaled and unscaled xcoord's in both cases.

share|improve this question
1  
Could you add a minimal working example (MWE) that shows you it doesn't work with scaling? In my question I wanted the logical values of the coordinate system which are technically still the same after scaling, just aeh, scaled. So e.g. (2,1) is still (2,1) just placed somewhere else when you use scale. –  Martin Scharrer Jul 20 '11 at 20:15
add comment

1 Answer

up vote 6 down vote accepted

The problem arises because \xcoorda is called inside a node, which resets the transformation matrix, so \pgf@xx is not scaled correctly. What you can do to avoid this is to save the transformation matrix into a macro at the start of the tikzpicture using \pgfgettransform{<macro>}, and set it inside the \xcoorda macro using \pgfsettransform{<macro>}. In order to use the resulting coordinate in a \pgfmathparse expression, I'd recommend turning the macro into a pgfmath function. I've included this approach in the code below.

get logical coordinates

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{intersections}

\makeatletter
\newcommand\xcoorda[2][center]{{%
%
% Set the transformation matrix that was saved at the beginning of the tikzpicture
%
  \pgfsettransform{\transform}%
  \pgfpointanchor{#2}{#1}%
  \pgfmathparse{\pgf@x/\pgf@xx}%
  \pgfmathresult%
}}

\pgfmathdeclarefunction{xcoord}{1}{
  \pgfsettransform{\transform}%
  \pgfpointanchor{#1}{center}%
  \pgfmathparse{\pgf@x/\pgf@xx}%
}

\makeatother

\begin{document}

\begin{tikzpicture}[domain=-0.01:0.55,xscale=17,yscale=0.01] 

% Save the transformation matrix
\pgfgettransform{\transform}

\draw[-stealth,name path=xline] (0,0) -- (0.55,0);
\draw[stealth-stealth,name path=yline] (0,-220) -- (0,220);
\draw[color=blue,name path=func] (0,200) parabola bend (.25,-50) (.50,200);
\path[name intersections={of=func and xline,by={i1,i2}}];
\node[below=20pt,text width=2cm,align=center,draw,fill=green!25] (i1label_a) 
 at(i1) {\xcoorda{i1}\\correct};
\draw[-stealth,red] (i1label_a.north) -- (i1);
\node[below=20pt,text width=2cm,draw,align=center,fill=green!25] (i2label_a) 
 at(i2) {\pgfmathparse{xcoord("i2")*100}\pgfmathprintnumber{\pgfmathresult}\,\%\\ correct};
\draw[-stealth,red] (i2label_a.north) -- (i2);
\foreach \t in {10,20,...,50} {
\pgfmathsetmacro\v{\t/100}
  \draw[thin] (\v,10) -- (\v,-10) node[below] {\t\%};
}
\foreach \t in {-200,-100,...,200} {
 \draw[thin] (.010,\t) -- (-0.01,\t) node[left] {\small\t};
}
\end{tikzpicture}

\end{document}

If you're using PGFplots, you can avoid having to manually save and restore the coordinate transformation, since in this case you can use \pgfplotsunitxlength, which holds the length of the x unit vector multiplied by 1000, and \pgfplotspointaxisorigin, which holds the point (0,0) of the current axis:

pgfplots logical coordinates

\documentclass{article}
\usepackage{pgfplots}
\usetikzlibrary{intersections}

\newcommand\xcoord[2][center]{{%
    \pgfpointanchor{#2}{#1}%
    \pgfgetlastxy{\ix}{\iy}%
    \pgfplotspointaxisorigin%
    \pgfgetlastxy{\ox}{\oy}
    \pgfmathparse{(\ix-\ox)/\pgfplotsunitxlength/1000}
    \pgfmathprintnumber{\pgfmathresult}}
}

\begin{document}

\vspace{1cm}
\begin{tikzpicture}
\begin{axis}[
    domain=0:0.5,
    samples=100,
    no markers,
    axis lines=middle,
    enlarge x limits=upper,
    enlarge y limits=true,
    xticklabel=\pgfmathparse{\tick*100}\pgfmathprintnumber{\pgfmathresult}\,\%,
    x axis line style={{name path global=xaxis}}
    ]
\addplot +[name path global=plot] {4000*(x-0.25)^2-50};

\pgfplotsextra{
\fill [name intersections={of=xaxis and plot, name=i, total=\t}] 
    [red, every node/.style={black}] 
    (i-1) circle (2pt) node [pin={\xcoord{i-1}}] {}
    (i-2) circle (2pt) node [pin={\xcoord{i-2}}] {};
}
\end{axis}
\end{tikzpicture}
\end{document}
share|improve this answer
    
Thank you this is exactly what I needed. I did not use pgfplots as in my document where this is used I also draw cash flow diagrams and the ycomb does not do what I want -- arrow lines pointing away from the time or x-axis. –  Louis Jul 21 '11 at 7:08
1  
That sounds like an interesting application! Have you taken a look at tex.stackexchange.com/questions/20296/…? If not, you might want to consider posting a question about it, PGFplots is flexible and powerful enough to accommodate something like that, and I'm sure it would be useful for others. –  Jake Jul 21 '11 at 9:51
    
At this stage I am a bit short of time, else I would have tried to write something for PGFplots to draw cash flow diagrams and add some of the possible calculations associated, like PV,FV & Uniform series. –  Louis Jul 21 '11 at 10:24
    
I wanted also convert the coordinates to percentages, so I tried something like: \pgfmathparse{100*\xcoorda{i1}}\edef\v{\pgfmathresult}; but it does not work. –  Louis Jul 21 '11 at 10:27
1  
I've changed the answer to give an approach that properly returns the value as a number (not as a formatted string, as \pgfmathprintnumber does). –  Jake Jul 21 '11 at 11:45
show 5 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.