4

I want to draw some curves and some special coordinates on the curves, then label the nodes on the axes. So far I have done it manually like this (it's a diagram for the Markowitz risk premium in case you have heard of it):

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usepackage{pgfplots}
\usetikzlibrary{calc,intersections,through,backgrounds}
\title{Plotty}
\date{October 2013}

\begin{document}

\begin{tikzpicture}[scale=1]
    \begin{axis}[xmin=0,ymin=0,ymax=10,xmax=10,xticklabels={,,},yticklabels={,,},axis x line=center,axis y line=center,clip=false,
                    xlabel=$w$,ylabel=$U(x)$]
        \draw[name path=ucurve] (axis cs:0,0) .. controls (axis cs:2,9) .. (axis cs:10,10) coordinate[pos=0.2](n1) coordinate[pos=0.9](n2);
        \draw[name path=eucurve] (n1) -- (n2) coordinate[pos=0.5](n3);
        \draw[dotted] let \p1 = (n3) in (n3) -- (\x1,0) node[below,blue]{$E(w)$};
        \draw[dotted,name path global=uintersect] let \p1 = (n3) in (n3) -- (0,\y1) node[left,blue]{$E(U(w))=U(E(w)-\pi)$};
        %Calculate the intersection
        \draw[dotted,name intersections={of=ucurve and uintersect,by=I}] let \p1 = (I) in (I) -- (\x1,0) node[below,blue]{$E(w)-\pi$};
        \draw[dotted] let \p1 = (n1) in (n1) -- (\x1,0) node[below,blue]{$90$};
        \draw[dotted] let \p1 = (n1) in (n1) -- (0,\y1) node[left,blue]{$U(90)$};
        \draw[dotted] let \p1 = (n2) in (n2) -- (\x1,0) node[below,blue]{$P_u$};
        \draw[dotted] let \p1 = (n2) in (n2) -- (0,\y1) node[left,blue]{$U(P_u)$};
    \end{axis}
\end{tikzpicture}
\end{document}

enter image description here

As you can see, I'm trying to do this manually by generating the paths to the axes. However, things get quite messy because I don't take into account the label size.

  1. How can I avoid the overlapping labels? I feel that there must be a plot option or something to label coordinates on the axes.

  2. How can I optimize my code? I'm just starting with pgfplots and I've found out there are hundreds of ways to achieve the same results, so maybe I'm not doing this right. Particularly the intersections library seems overkill for my needs...

Werner
  • 603,163
JavierIEH
  • 143

2 Answers2

2

An quick method is to modify this line by adding shift={(0.3cm,-0.3cm)} to fine tune the location.

    \draw[dotted,name intersections={of=ucurve and uintersect, by=I}] let \p1 = (I) in (I) -- (\x1,0) node[shift={(0.3cm,-0.3cm)},blue]{$E(w)-\pi$};

enter image description here

Jesse
  • 29,686
  • That works! but i wonder if there is a library that can handle this sort of common situation where you want to label nodes on the axes. Do you know of any? – JavierIEH Oct 29 '13 at 12:36
  • 1
    @JavierIEH -- To place labels on the axes systematically, the \foreach \x/\xtext in {...} loop is my first choice. Yet this still relies on basic nodes techniques that has [options] capability providing fine tunes for the case when the x-grid distance is not uniform. PGFmanual p. 135-136 has some examples for systematic approaches. – Jesse Oct 29 '13 at 13:21
  • Thank you, i upvoted your answer but selected the other one because gave me insight to other related matters of my question. – JavierIEH Oct 29 '13 at 17:22
  • @JavierIEH -- Yes, Indeed. – Jesse Oct 29 '13 at 18:44
2

I usually find it helpful to make the font of a graph smaller, e.g. \footnotesize. In this case, making the fonts smaller would solve your problem. I also changed the codes a bit, so that there is less repetition of the same codes.

Code

\documentclass{article}
% \usepackage[utf8]{inputenc}
\usepackage{tikz}
% \usepackage{pgfplots}
\usetikzlibrary{calc,intersections,through,backgrounds}
\title{Plotty}
\date{October 2013}

\begin{document}

\begin{tikzpicture}[font=\footnotesize]
    \tikzset{
        ylab/.style={left,text=blue},
        xlab/.style={below,text=blue},
    }
    % axis
    \draw[<->](0,11) node[left]{$U(x)$} -- (0,0) -- (10,0) node[below]{$w$};

    % utility
    \draw[name path=ucurve] (0,0) .. controls (2,9) .. (10,10) coordinate[pos=0.2](n1) coordinate[pos=0.9](n2);
    \draw[name path=eucurve] (n1) -- (n2) coordinate[pos=0.5](n3);

    % labeling
    \draw[dotted,name path=dotted_line] let \p1=(n1), \p2=(n2), \p3=(n3) in
        (0,\y1) node[ylab]{$U(90)$} -- (n1) -- (\x1,0) node[xlab]{$90$}
        (0,\y2) node[ylab]{$U(P_u)$} -- (n2) -- (\x2,0) node[xlab]{$P_u$}
        (0,\y3) node[ylab]{$E(U(w))=U(E(w))-\pi)$} -- (n3) -- (\x3,0) node[xlab]{$E(w)$}
    ;

    % uncomment to show all intersection points of ucurve and dotted_line
    % \fill [name intersections={of=ucurve and dotted_line, name=i, total=\t}]
    %     [red, opacity=0.5, every node/.style={above left, black, opacity=1}]
    %     \foreach \s in {1,...,\t}{(i-\s) circle (2pt) node {\footnotesize\s}}
    % ;

    \draw[dotted,name intersections={of=ucurve and dotted_line}] let \p4=(intersection-3) in
        (intersection-3)--(\x4,0) node[xlab]{$E(w)-\pi$}
    ;
\end{tikzpicture}

\end{document}

Output

enter image description here

Herr K.
  • 17,946
  • 4
  • 61
  • 118
  • If the axes labels still overlap (say, after scaling), then the answers to this question will be useful. – Herr K. Oct 29 '13 at 04:01
  • That graph looks way better than mine! Its amazing how whitespace makes diagrams easier to the eye... So i take it that there is no library or option for node labels that puts them on axes automaticaly?

  • Your code is far better than mine. Can you give me some references to the commands you used? namely "[<->]" option and style settings.

  • 3)Is there something like "best practices" on pgfplots/tikz? For instance, best way to define styles? Separating curves, nodes and labeling makes sense? Does it make the compiler take more time?

    – JavierIEH Oct 29 '13 at 12:38
  • I can't edit the comment for some reason. I forgot, whats the best way to scale the graph so that longer labels fit well? I can imagine that increasing the coordinates of the graph one by one is not the best way to do that – JavierIEH Oct 29 '13 at 12:54
  • @JavierIEH: 1) I'm not aware of any library that implements drawing lines from axes to a point on a curve. 2) The main reference is TikZ/PGF Manual and A very minimal introduction to TikZ. The [<->] in particular means adding arrows on both ends of a line. – Herr K. Oct 29 '13 at 15:05
  • @JavierIEH: 3) "Best practices" of TikZ is very broad, and possibly have a very long answer. A quick search on the tikz-pgf tag on this site shows this, this, and this related posts. Part of a "best practice" for me is to browse the Q&A here on TeX.SX and learn bits and pieces from them :) – Herr K. Oct 29 '13 at 15:08
  • @JavierIEH: With most drawings, one compilation is usually sufficient. But some functionalities, like remember picture and tikzmark (which uses remember picture) will require two compilations. I think you're right that scaling is not the best way to make long labels fit. Answers to this question propose some solutions to this problem. Basically in involves lowering the long label (and possibly use a "pin" to attach it to the right position.) BTW, you cannot edit a comment after posting it for 5 minutes. – Herr K. Oct 29 '13 at 15:15
  • Thanks for all your answers, that minimal introduction to tikz was just what i needed. I needed an entry level guide because the manual is a bit extense and goes into detail for every aspect of the package. – JavierIEH Oct 29 '13 at 17:26