1

I am pretty new to PGFplots, but I am already loving it very much!

I want to have a plot, where the intersection of two curves or when the data reaches a certain y-value is labeled on the x-axis as an x-tick. It is possible to just put a node with text near the x-axis, but the spacing between the x-ticks is off, overlaid and the position is never the same as the actual x-tick position. Is there a way to, for example, define another extra x ticks within the code, i.e. after the options for the axis?

Also, when I am using axis y line = left and axis x line = bottom how do I make sure, that there is no tick mark directly on top of the arrow?

Furthermore, can someone explain to me the meaning of the |- in the drawing of the dashed curve, I tried out different code from stackexchange to get where I am at the moment.

\draw [dashed, name intersections={of=y-value and line2, by={intersect2}}] % What does the description of the coordinates with |- mean actually? (intersect2) -- (intersect2 |- 0,0);

Here is a picture of an example plot: PLOT

And a compilable example:

\documentclass[a4paper,11pt,twoside]{scrreprt}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}


\usepackage{graphicx}


\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
\usetikzlibrary{intersections}

\begin{document}


\begin{figure}
\centering

\begin{tikzpicture}[baseline]

\begin{axis}[
xlabel= x,
ylabel = y,
axis x line = bottom,
axis y line = left,
xmin=0, xmax=7,
ymin = 0, ymax = 2.5,
xtick = \empty,
extra x ticks = {0, 3, 6},
every axis plot/.append style={semithick},
%% Clipping needs to be disabled, otherwise I cannot draw the text
clip=false,
]
\addplot[name path global=y-value,gray, ultra thin] coordinates{(0,2) (7,2)};
\addplot[name path global=line1] coordinates{(0,0) (5,2.5)};
\addplot[name path global=line2] coordinates{(0,0) (4.7,2.5)};
\addplot[name path global=line3] coordinates{(0,0) (3,2.5)};
%
% Here I start with the code for intersections of the different lines
\draw [dashed, name intersections={of=y-value and line1, by={intersect1}}]
(intersect1) -- (intersect1 |- 0,0);
% The value -0.15 is determined by trial and error for every plot. It is never 
% perfectly at the same height as the x-ticks though.
% Especially when I change the size of the plot.
\node at (intersect1|- 0,-0.15 ) {\pgfplotspointgetcoordinates{(intersect1)}
    $
    \pgfmathprintnumber[fixed, precision=1]{\pgfkeysvalueof{/data point/x}}
    $};
%----   
\draw [dashed, name intersections={of=y-value and line2, by={intersect2}}]
(intersect2) -- (intersect2 |- 0,0);
%
\node at (intersect2|- 0,-0.15 ) {\pgfplotspointgetcoordinates{(intersect2)}
    $
    \pgfmathprintnumber[fixed, precision=1]{\pgfkeysvalueof{/data point/x}}
    $};
%-----
\draw [dashed, name intersections={of=y-value and line3, by={intersect3}}]
(intersect3) -- (intersect3 |- 0,0);
%
\node at (intersect3|- 0,-0.15 ) {\pgfplotspointgetcoordinates{(intersect3)}
    $
    \pgfmathprintnumber[fixed, precision=1]{\pgfkeysvalueof{/data point/x}}
    $};
%   
\end{axis}                                  
\end{tikzpicture}
\end{figure}

\end{document}
2
  • 1
    In this case you do not need to use intersections, you could compute the positions of the points in question analytically. Is your question about the general case? BTW (intersect2 |- 0,0) is a coordinate at the horizontal position of intersect2 and the vertical position of (0,0).
    – user121799
    Sep 3, 2018 at 15:48
  • Thanks for your answer! I understand that I theoretically could preprocess my data and then use these points as x-ticks. However, i am handling lots of data and it would be great if I wouldn't have to resort to using MATLAB every time I want to visualize something.
    – ElDoe
    Sep 3, 2018 at 21:01

2 Answers 2

1

If you really want to use [extra x ticks={...}] you will need to convert screen coordinates into axis. Also, you need to have the extra ticks ready BEFORE the axis, which can be achieved by overlaying a second axis on top with the same dimensions.

OTOH, they will still overlap.

\documentclass[a4paper,11pt,twoside]{scrreprt}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}

\usepackage{graphicx}

\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
\usetikzlibrary{intersections}

\newlength{\xscale}
\newlength{\xcoord}

\begin{document}


\begin{figure}
\centering

\begin{tikzpicture}[baseline]

\begin{axis}[
xlabel= x,
ylabel = y,
axis x line = bottom,
axis y line = left,
xmin=0, xmax=7,
ymin = 0, ymax = 2.5,
xtick = {0, 3, 6},
%extra x ticks = {0, 3, 6},
every axis plot/.append style={semithick},
%% Clipping needs to be disabled, otherwise I cannot draw the text
clip=false,
]
\addplot[name path global=y-value,gray, ultra thin] coordinates{(0,2) (7,2)};
\addplot[name path global=line1] coordinates{(0,0) (5,2.5)};
\addplot[name path global=line2] coordinates{(0,0) (4.7,2.5)};
\addplot[name path global=line3] coordinates{(0,0) (3,2.5)};
%
% Here I start with the code for intersections of the different lines
\draw [dashed, name intersections={of=y-value and line1, by={intersect1}}]
(intersect1) -- (intersect1 |- 0,0);
\draw [dashed, name intersections={of=y-value and line2, by={intersect2}}]
(intersect2) -- (intersect2 |- 0,0);
%
\draw [dashed, name intersections={of=y-value and line3, by={intersect3}}]
(intersect3) -- (intersect3 |- 0,0);
%
\coordinate (scale) at (1,0);% assume lower left at (0,0)
\pgfplotsextra{% wait until scale determined
  \pgfextractx{\xscale}{\pgfpointanchor{scale}{center}}%
  \pgfextractx{\xcoord}{\pgfpointanchor{intersect1}{center}}%
  \pgfmathdivide{\xcoord}{\xscale}%
  \xdef\ticks{\pgfmathresult}%
  \pgfextractx{\xcoord}{\pgfpointanchor{intersect2}{center}}%
  \pgfmathdivide{\xcoord}{\xscale}%
  \xdef\ticks{\ticks,\pgfmathresult}%
  \pgfextractx{\xcoord}{\pgfpointanchor{intersect3}{center}}%
  \pgfmathdivide{\xcoord}{\xscale}%
  \xdef\ticks{\ticks,\pgfmathresult}%
}%
\end{axis}%
\begin{axis}[% overlay new axis on top of old
axis x line = bottom,
axis y line = left,
xmin=0, xmax=7,
ymin = 0, ymax = 2.5,
xtick=\empty,
ytick=\empty,
extra x ticks = {\ticks}
]\end{axis}  
\end{tikzpicture}
\end{figure}

\end{document}

demo

2

This is an attempt towards a more automatized version. I use \pgfplotsinvokeforeach to avoid duplication. Then I add the labels in such a way that they do not interfere. You can shift them up or down by redefining the coordinate (L). Both the maximal x value of the labels and the distance between them are hardcoded. One could easily improve on this, but for that I'd need more input on how may of these labels exist in the "real life situation".

\documentclass[a4paper,11pt,twoside]{scrreprt}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
\usetikzlibrary{intersections}

\begin{document}

\begin{figure}
\centering

\begin{tikzpicture}[baseline]

\begin{axis}[
xlabel= x,
ylabel = y,
axis x line = bottom,
axis y line = left,
xmin=0, xmax=7,
ymin = 0, ymax = 2.5,
xtick = \empty,
extra x ticks = {0, 3, 6},
every axis plot/.append style={semithick},
%% Clipping needs to be disabled, otherwise I cannot draw the text
clip=false,
]
\addplot[name path global=y-value,gray, ultra thin] coordinates{(0,2) (7,2)};
\addplot[name path global=line-1] coordinates{(0,0) (5,2.5)};
\addplot[name path global=line-2] coordinates{(0,0) (4.7,2.5)};
\addplot[name path global=line-3] coordinates{(0,0) (3,2.5)};
%
% Here I start with the code for intersections of the different lines
\path (0,0) coordinate (O) (0,-0.6) coordinate (L);
%   
\pgfplotsinvokeforeach{1,2,3}{%
\draw [dashed, name intersections={of=y-value and line-#1, by={intersect-#1}}]
(intersect-#1) -- (intersect-#1 |- O) coordinate (X-#1);
\node (L-#1) at (5-#1,0 |- L){\pgfplotspointgetcoordinates{(intersect-#1)}
    $
    \pgfmathprintnumber[fixed, precision=1]{\pgfkeysvalueof{/data point/x}}
    $};
\draw[-latex] (L-#1) to[out=90,in=-90] (X-#1);
}                        
\end{axis}    

\end{tikzpicture}
\end{figure}

\end{document}

enter image description here

You must log in to answer this question.

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