12 November 2015

Adaptive mark in PGFplots

It often happens that we want to draw some graphs with few traces that have sharp resonances/sharp peaks, etc. As illustrated in the below figure, flat parts of the curve get a lot of markers, while sharp parts get only few markers, if any. An illustration of the problem is in the figure below:

Too many markers in the slow area, and only few markers in the sharp area
 Matlab users often have this problem (I had this issue very often when I used it to draw graphics). This issue can be avoided in graphs drawn by pdfLaTeX and PGFplots by the following trick.

\makeatletter
\tikzset{
 nomorepostactions/.code={\let\tikz@postactions=\pgfutil@empty},
 mymark/.style 2 args={decoration={markings,
   mark= between positions 0 and 1 step (1/20)*\pgfdecoratedpathlength with{%
    \tikzset{#2,every mark}\tikz@options
    \pgfuseplotmark{#1}%
   },
  },
  postaction={decorate},
  /pgfplots/legend image post style={
   mark=#1,#2,every path/.append style={nomorepostactions}
  },
 },
}
\makeatother

Here,  we define a custom TIKZ style, and specify the maximum distance between adjacent points.
Sharp traces with equally spaced markers
This post is based on this answer from StackExchange.com. For additional info about this please see here.
A complete working example is as follows:


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
\documentclass[]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\usetikzlibrary{decorations.markings}
\makeatletter
\tikzset{
 nomorepostactions/.code={\let\tikz@postactions=\pgfutil@empty},
 mymark/.style 2 args={decoration={markings,
   mark= between positions 0 and 1 step (1/20)*\pgfdecoratedpathlength with{%
    \tikzset{#2,every mark}\tikz@options
    \pgfuseplotmark{#1}%
   },
  },
  postaction={decorate},
  /pgfplots/legend image post style={
   mark=#1,#2,every path/.append style={nomorepostactions}
  },
 },
}
\makeatother

\begin{document}
 \begin{tikzpicture}
 \begin{axis}[axis x line=middle, axis y line=left, xmax=2.5, xlabel=$x$, ylabel=$y$, ymin=-0.15]
 
 \addplot[blue, domain=0:3,samples=150,mymark={*}{dotted}]
 {exp(-400*(x-1)^2)};
 
 \addplot[red, domain=0:3,samples=150,mymark={*}{dotted}]
 {exp(-400*(x-1.5)^2)};
 \end{axis}
 \end{tikzpicture}
\end{document}

No comments:

Post a Comment