5

How to draw nearly-arbitrary curved lines simply? For example, how to draw this graph:

Source Introduction to Algorithms (3rd edition) by Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein | Page 45 | Figure 3.1

Now I have two ideas of how to draw such figures:

  1. Divide each curved line to many smaller curved lines which can be drawn by a TikZ command, for example

    \draw (0,0) to [in=80, out=-30] (3,2);
    

    This way is quite natural. However, it is difficult to divide, for instance, the lines in the above figure, in this way. Also, when I have already divided, it is very possible that I will get confused with the coordinates.

  2. Find a formula for each of the curved line, and then draw the graph of the curved line.

    This way is good for normal graphs, but for the complicated curved lines as in the above figure, it seems to be impossible.

So none of the ways stated is good enough. Do you have any idea to draw such figures? Your help is much appreciated!


Notes

  1. I'm sorry if the question is a duplicate. I have searched for a while without success.

  2. Your help will be great if you can help me draw the above figure. However, I strongly prefer a general solution for this, because the aim of the question is not just to ask how to draw the figure only.

  3. You can see that there is no MWE in my question. As I explained above, all of my idea so far are just bad, so I haven't applied any of them.

  4. I strongly prefer using TikZ. However, answers using PGF, PStricks, etc. are all very useful to me.

  • 2
    You could try with \draw plot[smooth] coordinates {<a suitable list of coordinates>}; for the curves. – Torbjørn T. Dec 1 '18 at 17:36
  • 1
    I tend to define some points on the curve first, then connect then using bezier curves making sure each connection is smooth (same tangent in and out). Each segment is made like this: (a1).. controls ++(45:1) and ++(30:0.5).. (a2) where the control points are relative polar coordinates. Somewhere on the site there is a style that will enable you to see the control vectors (i think it is called show curve controls), I use this method for most of my drawings when I'm trying to replicate or trace something. – daleif Dec 1 '18 at 17:36
7

This is an attempt to collect some key methods on one page. Clearly, this discussion is not exhaustive, so I am hoping that this post gets complemented by others, who have other methods and/or opinions. (I made zero effort to precisely reproduce your curves, sorry.)

\documentclass{article}
\usepackage[margin=1in]{geometry}
\usepackage{multicol}
\usepackage{tikz}
\usetikzlibrary{hobby}
\begin{document}
\section*{A few ideas to draw smooth curves}

\begin{multicols}{2}
\subsection*{Your idea: use \texttt{out} and \texttt{in}}
This works, and the result looks smooth if you make sure that the  \texttt{in}
of one point and the \texttt{out} of the next point differ by 180. In the
following pic, we have \texttt{\dots to[out=50,in=\textbf{210}] (1,2) circle(1pt)
to[\textbf{out=30},in=240] \dots} to illustrate this. Notice that the
\texttt{looseness} key can be of great help here.

\begin{tikzpicture}
\draw[latex-latex] (0,4) |- (6,0);
\draw[blue] (0,0) circle(1pt) to[out=50,in=210] (1,2) circle(1pt)
to[out=30,in=240,looseness=0.5] (3,3) circle(1pt);
\end{tikzpicture}

\subsection*{Your idea: find an analytic formula}
This is IMHO often the simplest way. One only needs to keep in mind a few basic
functions like $\sin$ and $\tanh$.

\begin{tikzpicture}
\draw[latex-latex] (0,4) |- (6,0);
\draw[blue] plot[variable=\x,domain=0:6,smooth]
({\x},{1+0.3*(tanh(3-\x)+1)*sin(180*\x)+0.2*\x});
\end{tikzpicture}

\subsection*{Use \texttt{plot[smooth] coordinates}}

A very convenient option, mentioned by Torj{\o}rn T.\ in the comments, is to use
\texttt{plot[smooth] coordinates}. You may want to play with the
\texttt{tension} key.

\begin{tikzpicture}
\draw[latex-latex] (0,4) |- (6,0);
\draw[blue] plot[smooth] coordinates
{(0,0) (1,2) (2,2) (3,3) (4,3)};
\draw[red] plot[smooth,tension=2] coordinates
{(0,0) (1,2) (2,2) (3,3) (4,3)};
\end{tikzpicture}

\subsection*{Use the \texttt{hobby} library}

The \texttt{hobby} library is sort of an el Dorado for smooth curve
constructors. It has way too many options to be listed here. One thing I find
very useful is the \texttt{tangent} style from the manual. 

\begin{tikzpicture}[tangent/.style={%
 in angle={(180+#1)},Hobby finish ,
designated Hobby path=next , out angle=#1,
}]
\draw[latex-latex] (0,4) |- (6,0);
\draw[blue] plot[smooth,hobby,tension=0.3] coordinates
{(0,0) (1,1.2) (2,2) (3,3) (4,3)};
\draw [red,use Hobby shortcut] 
   (0,0)  .. ([tangent=30]1.5,1) ..  ([tangent=-10]3,2) .. (5,1);
\end{tikzpicture}

I'd also like to mention that, when it comes to decorations, in my experience
the Hobby paths are advantageous. They often do not lead to \texttt{dimension too
large} errors when their almost identically looking \texttt{plot[smooth]}
counterparts do.

\subsection*{Not sure about \texttt{controls}}

There is also the possibility of using Bezier curves (without \texttt{hobby}).
Many users are able to use that to obtain great results. Unfortunately, I am not
one of those since IMHO the relation between position of the control points and
the outcome is not too obvious. But this is of course a very subjective
statement.
\end{multicols}
\end{document}

enter image description here

2

put a coordinatesystem over the given images and choose some points:

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{pst-plot}
\begin{document}
\begin{pspicture}(-0.5,-0.5)(6.4,6.4)
\psaxes[labels=none,ticks=none]{->}(6,6)[$n$,0][,0]
\psxTick(1.8){n_0}
\pscurve[linecolor=red,linewidth=1.5pt]%
   (0,1.6)(0.4,1.1)(0.6,0.9)(0.9,1.2)(1,1.8)(1.4,3)(1.8,2.5)(2,2)(2.3,1.9)(3,2.2)(4.5,3)(6,3.4)
\pscurve[linecolor=blue,linewidth=1.5pt](0,1)(1,1.8)(1.8,2.5)(2.5,3)(3.5,3.4)(4.5,4)(6,5)
\psline[linestyle=dashed](1.8,0)(1.8,2.5)
\rput[r](6,5.2){\textcolor{blue}{$cg(n)$}}
\rput[r](6,3.5){\textcolor{red}{$f(n)$}}
\end{pspicture}
\end{document}

enter image description here

2

As suggest by marmot it is possible to use Bezier curves. For things like this I use TikzEdt, a very useful software for translate a diagram in TikZ. I import the diagram with \node{\includegraphics{YourDiagram}};and use the Bezier tool of TikzEdt to replicate exactly the diagram. For example for your first plot I get the following result:

\documentclass[10pt,a4paper]{article}
\usepackage[latin1]{inputenc}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
%\node{\includegraphics[width=2\textwidth]{YourDiagram}};%import the diagram that you want to copy in TikzEdt

%\draw [help lines, step=.1cm] (-22.8,-7.4) grid (-7.7,8.2);

\draw (-21,-1.8) .. controls (-19.9,-1.8) 
and (-19.7,-1.6) .. (-19.3,-2) .. controls (-18.5,-2.8)
and (-18.5,-1.7) .. (-18,-0.9) .. controls (-16.9,0.4) 
and (-15.6,0.6) .. (-14.2,1.2) .. controls (-13,1.6) 
and (-11.9,1.9) .. (-10.2,3.3) node[above]{{\LARGE$f(n)$}};

\draw(-21,-3.8) .. controls (-20.3,-3.1) 
and (-20,-2.8) .. (-19.7,-2.4) .. controls (-18.9,-1.4) 
and (-17.9,-1.4) .. (-17.6,-1.4) .. controls (-16.2,-1.4) 
and (-16.1,-1.1) .. (-15.8,-0.9) .. controls (-15.1,-0.2) 
and (-14.8,0.1) .. (-13.4,0.5) .. controls (-12.5,0.7) 
and (-12,0.8) .. (-10.2,1.1) node[above]{{\LARGE$c_1g(n)$}};

\draw(-21,-3.8) .. controls (-20.7,-3.2) 
and (-20.4,-2.7) .. (-19.8,-1.2) .. controls (-19.1,0.4) 
and (-18.5,1.2) .. (-17,1.1) .. controls (-16.4,1.1) 
and (-16.1,1.5) .. (-15.5,2.5) .. controls (-15.1,3.3) 
and (-14.6,4.1) .. (-13.5,4.7) .. controls (-12.7,5.1) 
and (-12.3,5.3) .. (-10.2,6.1) node[above]{{\LARGE$c_2g(n)$}};

\draw (-21,7.1) -- (-21,-3.8) -- (-10.1,-3.8) node[right]{{\LARGE$n$}};

\draw[dashed] (-18.3,0.8) -- (-18.3,-3.8) node[below] {\LARGE{$n_0$}};
\end{tikzpicture}   
\end{document}

Diagram in TikZ with TikzEdt

  • 2
    As daleif and marmot said, when you use Bezier curves it is difficult to place correctly the control points. With TikzEdt you can place exactly the control points and with the autocompilation you get immediatly the result for further adjustments. Therefore it is very easy to replicate anything and translate it in TikZ. TikzEdt is not an exportation tool. In some sense with TikzEdt you can easly realize your first idea for draw your graphs (divide the line and draw it piece by piece). I made the above picture in 10 minutes. – vi pa Dec 4 '18 at 14:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy