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.

I am drawing some graphs with tangents. I calculated the tangent should be centered at x=57/27 which is approximately x=2.11. I'm currently using the pos and sloped keys for nodes to draw tangents, but I'm not happy about the result; the tangents don't really align.

I think this is because the pos key calculates the actual length of the graph while the graphs don't have the same length.

I'm sure I can somehow let LaTeX do the calculations for me so as to align the slopes vertically at an x value of my choice. But how?

PS: The below document requires a working installation of gnuplot to compile.

enter image description here

\documentclass{standalone}  
\usepackage{pgfplots}
\pgfplotsset{compat=1.10}
\usetikzlibrary{arrows, decorations.markings,intersections}

\makeatletter
\tikzset{
    nomorepostaction/.code=\makeatletter\let\tikz@postactions\pgfutil@empty, 
    my axis/.style={
        postaction={
            decoration={
                markings,
                mark=at position 1 with {
                    \arrow[ultra thick]{latex}
                }
            },
            decorate,
            nomorepostaction
        },
        thin,
        -,
        every path/.append style=my axis
    }
}
\makeatother

\definecolor{headtitle}{RGB}{167,63,63}

\begin{document}
\begin{tikzpicture}
  \begin{axis}[%
      axis line style={my axis},
      xlabel = $U_A$,
      ylabel = $S$,
      xmin = 0, xmax = 3.25,
      ymin = 0,
      xtick={1,1.5},
      xticklabels={$U_{B,\mathrm{initial}}$,$U_{A,\mathrm{initial}}$},
      xticklabel style={
            inner sep=0pt,
            anchor=north east,
            rotate=35
        },
      ytick=\empty,
      height=.66\linewidth, width=\linewidth-4.5\tabcolsep,
      axis lines*=left,
      every axis y label/.style={at=(current axis.above origin),anchor=east},
      every axis x label/.style={at=(current axis.right of origin),anchor=west}]%
    \addplot+[mark={},draw=headtitle] gnuplot[raw gnuplot] {%
      set samples 51;
      plot [0:3] log(3*(3-x)+1);
      } node[sloped,above,pos=.63333,
      minimum height=1cm,minimum width=1cm] (SB) {} node[pos=0.6,pin=45:{\color{black}{$S_B$}}] {};
     \addplot+[mark={},draw=headtitle] gnuplot[raw gnuplot] {%
      set samples 51;
      plot [0:3] log(9*x^2+6*x+1);
      } node[sloped,above,pos=.83333,
      minimum height=1cm,minimum width=1cm] (SA) {} node[pos=0.25,pin=-15:{\color{black}{$S_A$}}] {};
      \addplot+[mark={},draw=headtitle] gnuplot[raw gnuplot] {%
      set samples 51;
      plot [0:3] log(9*x^2+6*x+1)+log(3*(3-x)+1);
      } node[sloped,above,pos=.775,
      minimum height=1cm,minimum width=1cm] (St) {} node[pos=0.525,pin=165:{\color{black}{$S_\mathrm{total}$}}] {};
     \path (SB.south east) edge[headtitle,very thick] node {} (SB.south west);
     \path (SA.south east) edge[headtitle,very thick] node {} (SA.south west);
     \path (St.south east) edge[headtitle,very thick] node {} (St.south west);
  \end{axis}%
\end{tikzpicture}%
\end{document}
share|improve this question
    
You mean the lines should be centered at the same x value? –  percusse Aug 24 at 16:24
    
@percusse Yeah, exactly that. –  1010011010 Aug 24 at 16:25

3 Answers 3

up vote 6 down vote accepted
+50

You can use the approach from pgfplots: Placing node on a specific x-position (which used the same basic idea as Thruston's answer: finding the intersection with a vertical line).

I've removed stuff from your example that wasn't related to the problem at hand, and used the PGF math engine instead of gnuplot, which works fine in this case.

\documentclass[border=5mm]{standalone}  
\usepackage{pgfplots}
\pgfplotsset{compat=1.10}
\usetikzlibrary{intersections}

\makeatletter
\def\parsenode[#1]#2\pgf@nil{%
    \tikzset{label node/.style={#1}}
    \def\nodetext{#2}
}

\tikzset{
    add node at x/.style 2 args={
        name path global=plot line,
        /pgfplots/execute at end plot visualization/.append={
                \begingroup
                \@ifnextchar[{\parsenode}{\parsenode[]}#2\pgf@nil
            \path [name path global = position line #1-1]
                ({axis cs:#1,0}|-{rel axis cs:0,0}) --
                ({axis cs:#1,0}|-{rel axis cs:0,1});
            \path [xshift=1pt, name path global = position line #1-2]
                ({axis cs:#1,0}|-{rel axis cs:0,0}) --
                ({axis cs:#1,0}|-{rel axis cs:0,1});
            \path [
                name intersections={
                    of={plot line and position line #1-1},
                    name=left intersection
                },
                name intersections={
                    of={plot line and position line #1-2},
                    name=right intersection
                },
                label node/.append style={pos=1}
            ] (left intersection-1) -- (right intersection-1)
            node [label node]{\nodetext};
            \endgroup
        }
    }
}
\makeatother

\begin{document}
\begin{tikzpicture}
  \begin{axis}[%
      xmin = 0, xmax = 3.25,
      ymin = 0,
      domain=0:3,
      samples=50,
      tangent/.style={
            add node at x={2}{
                [
                    sloped, 
                    append after command={(\tikzlastnode.west) edge [thick, red!75!black] (\tikzlastnode.east)},
                    minimum width=2cm
                ]
            }      
      }
      ]%
    \addplot [gray, tangent] {ln(3*(3-x)+1)};
    \addplot [gray, tangent] {ln(9*x^2+6*x+1)};
    \addplot [gray, tangent] {ln(9*x^2+6*x+1)+ln(3*(3-x)+1)};
  \end{axis}%
\end{tikzpicture}%
\end{document}
share|improve this answer
2  
Should I check the manual for this? :p –  percusse Aug 26 at 18:42

Just for fun with PSTricks. The functions are intentionally made different from your case to let you modify them by yourself as an exercise.

As the question is not easy to understand, I provide two answers. One of them should meet your requirement.

Option 1: Equidistant tangent segments

In this option, I make the tangent segments have the same length.

\documentclass[pstricks,border=12pt,12pt]{standalone}

\usepackage{pstricks-add}

\begin{document}
\begin{pspicture}[algebraic](-1,-3)(7,3)
    \psaxes(0,0)(-1,-3)(7,3)
    \foreach \f/\c in {{3-2*Euler^(-x/2)}/red,2*sin(x)/green,2*cos(x)/blue}
        {
            \psplot[linecolor=\c]{-1}{7}{\f}
            \psplotTangent[arrows=<->]{5}{1}{\f}
        }
\end{pspicture}
\end{document}

enter image description here

Option 2: Justified tangent segments

In this option, the left (and right) end point of each tangent segment is aligned with the same vertical line.

\documentclass[pstricks,border=12pt,12pt]{standalone}

\usepackage{pstricks-add}

\def\list{{3-2*Euler^(-x/2)}/red,2*sin(x)/green,2*cos(x)/blue}

\begin{document}
\begin{pspicture}[algebraic](-1,-3)(7,3)
    \psaxes(0,0)(-1,-3)(7,3)
    \foreach \f/\c in \list {\psplot[linecolor=\c]{-1}{7}{\f}}%
    \psclip{\psframe[linestyle=none,linewidth=0](2,-3)(4,3)}
        \foreach \f/\c in \list {\psplotTangent{3}{5}{\f}}%
    \endpsclip
\end{pspicture}
\end{document}

enter image description here

share|improve this answer
    
Be carefull, foreach leaves unnecessary white spaces that will interfere the drawing. So % must be appended at the end of \foreach. –  Who is crazy first Aug 26 at 18:51

Here's a way to plot what you want in Metapost. MP provides an intersectiontimes operation which finds the points where two paths cross - here I've used it to find the points where each curve intersects an invisible vertical line at x=57/27. I then used the direction t of p and point t of p constructs to find the tangent and draw it in the right place on each function curve.

enter image description here

prologues:=3;
outputtemplate:="%j%c.eps";
beginfig(1);

% the two functions we require - see the Metafont book about mlog
vardef f(expr x) = mlog(3*(3-x)+1)/256 enddef;
vardef g(expr x) = mlog(9*x**2+6*x+1)/256 enddef;

% tranformation used to scale everything up neatly 
transform t; t = identity xscaled 3cm yscaled 7mm;

xmin = 0;
xmax = 3;
tangent_point = 57/27;

% define the three paths to plot, plus one that intersects them all
path a, b, total, xx;
b     = ((0,f(0))      for x=0.1 step 0.05 until xmax+eps: -- (x,f(x))      endfor) transformed t;
a     = ((0,g(0))      for x=0.1 step 0.05 until xmax+eps: -- (x,g(x))      endfor) transformed t;
total = ((0,f(0)+g(0)) for x=0.1 step 0.05 until xmax+eps: -- (x,f(x)+g(x)) endfor) transformed t;
xx    = ((tangent_point,0) -- (tangent_point,10)) transformed t; % a vertical line shifted along a bit

% draw the functions
drawoptions(withcolor .67 red);
draw a; draw b; draw total;

% draw the tangents at the points of intersection
drawoptions(withpen pencircle scaled 1 withcolor .45 red);
forsuffixes $=a,b,total:
  (t$,tt$) = $ intersectiontimes xx; 
  draw ((left--right) scaled 1cm rotated angle direction t$ of $ shifted point t$ of $);
endfor
drawoptions();

% axes
drawarrow origin -- (1.1xmax,0) transformed t; label.rt (btex $U_A$ etex, (1.1xmax,0) transformed t);
drawarrow origin -- (0,8)       transformed t; label.lft(btex $S$   etex, (0,8)       transformed t);

% labels
label.ulft(btex $S_{\rm total}$ etex, point 20 of total);
label.ulft(btex $S_A$           etex, point 20 of a);
label.ulft(btex $S_B$           etex, point 20 of b);

endfig;
end
share|improve this answer

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.