tikz/pgfplot——标记之间的距离总是相同的

tikz/pgfplot——标记之间的距离总是相同的

有没有办法让tikz一个 LaTeX 文档中的所有 -plot 的 s 之间的距离相同plot mark,即标记之间的距离应该与样本大小无关。如果这种变化不会干扰图例,比如改变标记的位置等,那就太好了legend。谢谢。

编辑:不幸的是,所有数据点(不是在小示例中,而是对于真实数据)的距离并不相同,因此如果我能以厘米为单位定义标记之间的距离就好了。

\documentclass[tikz,border=1mm]{standalone}
\usepackage{pgfplots}
\usetikzlibrary{decorations.markings}
\pgfplotsset{compat=1.11}
%\tikzset{mark/.style={
%        decoration={
%            markings,
%            mark= between positions 0 and 1 step 5mm with
%                {
%                %\node[circle,inner sep=2pt,fill=blue]{};
%            },
%        },
%        postaction={decorate}
%    }
%}
\begin{document}
\begin{tikzpicture}
\begin{axis}[]
\addplot[
  blue,
  domain=0:3,
  samples=100,
  mark=*
  ]
{exp(x)};
\addlegendentry{exp(x)};

\addplot[
  red,
  domain=0:3,
  samples=20,
  mark=diamond
  ]
{4*x};
\addlegendentry{4x};

\end{axis}
\end{tikzpicture}
\end{document}

编辑:是否可以将诸如mark size或之类的选项传递给 tikz mark options={solid}

    \addplot [color=black,loosely dotted,line width=1.5pt, mark=*,mark size=3pt, mark=diamond,mark options={solid}]

edit2:我知道如何solid在图例中设置标记,但如何在情节中做同样的事情?有什么想法可以solid在实际情节中获取情节标记吗?

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

在此处输入图片描述

答案1

与 Harish 的答案类似,但无需绘制两次。您基本上需要停止后操作到达图例图片,因为这是导致标记位置奇怪的原因。您可以使用我们的好答案来做到这一点对 TikZ 中的每个路径应用后动作

\documentclass[]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.11}
\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/11)*\pgfdecoratedpathlength with{%
        \tikzset{#2,every mark}\tikz@options
        \pgfuseplotmark{#1}%
      },  
    },
    postaction={decorate},
    /pgfplots/legend image post style={
        mark=#1,mark options={#2},every path/.append style={nomorepostactions}
    },
  },
}
\makeatother

\begin{document}
\begin{tikzpicture}
\begin{axis}[legend style={at={(0.5,0.95)}, anchor=north},
  legend entries={$\exp(x)$,$10\sin(5x)$},
]
\addplot[blue,dashed, domain=0:3,samples=15,mymark={o}{solid}]{exp(x)};
\addplot[red,domain=0:3, dashdotted,samples=200,
           mymark={diamond*}{draw=black,fill=yellow,solid}]{10*sin(deg(5*x))};
\end{axis}
\end{tikzpicture}
\end{document}

您还可以通过将总路径长度除以一个固定数字来添加另一个参数,以表示您想要有多少个标记。这里我选择了 11。(用距离代替可能是您希望的,但我在这里将其作为替代方案)

在此处输入图片描述

标记距离为 1 cm

在此处输入图片描述

编辑对于添加的样式问题,代码现在提供

在此处输入图片描述

答案2

legend image post styleHee 是一种使用tikz的方法decorations。我们首先定义一个装饰,然后绘制两次相同的曲线,一次只使用装饰标记,然后不使用标记。

\documentclass[tikz,border=1mm]{standalone}
\usepackage{pgfplots}
\usetikzlibrary{decorations.markings}
\usetikzlibrary{plotmarks}
\pgfplotsset{compat=1.11}
\tikzset{mymark/.style={
        decoration={
            markings,
            mark= between positions 0 and 1 step 5mm with
                {
                \pgfuseplotmark{#1};
            },
        },
        postaction={decorate}
    }
}



\begin{document}
\begin{tikzpicture}
\begin{axis}[legend style={at={(0.5,0.95)}, anchor=north}]
\addplot[
  blue,
  domain=0:3,
  samples=100,
  mymark={o},
  draw=none,
  forget plot,     %% don't consider this plot for legends
  ]
{exp(x)};
\addplot[
  blue,
  domain=0:3,
  samples=100,
  mark=none,smooth,
  legend image post style={mark=o}  %% <-----
  ]
{exp(x)};
\addlegendentry{exp(x)};

\addplot[
  red,
  domain=0:3,
  samples=20,
  mymark={diamond},
  draw=none,
  forget plot,
  ]
{4*x};
\addplot[
  red,
  domain=0:3,
  samples=20,
  mark=none,smooth,
  legend image post style={mark=diamond}
  ]
{4*x};
\addlegendentry{10 sin(x)};

\end{axis}
\end{tikzpicture}
\end{document}

在此处输入图片描述

答案3

使用 MetaPost 完成,具有实际的正弦曲线。(图例框仍有待完成。)对于标记,它是否是您希望获得的东西?

请注意,这只是我对这里一个非常相似的问题的回答的改编:Pgfplot,到达路径上的距离时显示标记

编辑现在,饰框已在此处,并进行了一些其他 (微小) 更改。

\documentclass[border=2bp]{standalone}
\usepackage{luamplib}
    \mplibsetformat{metafun}
    \mplibtextextlabel{enable}
    \mplibnumbersystem{double}
\begin{document}
\begin{mplibcode}
% Reimplementation of the `point .. of ..` binary operator
% somewhat bugged in the current metafun format: 
% http://tug.org/pipermail/metapost/2015-March/003065.html
primarydef len on pat = % no outer ( ) .. somehow fails
     (arctime if len>=0 : len else : (arclength(pat)+len) fi of pat) of pat
enddef;

% Parameters
u = 2cm; v = .3cm; pen bigdot; bigdot = pencircle scaled 3bp;
xmin = -.25; xmax = 3.25; ymin = -1; ymax = 22.5;
len = 4bp; nmarks = 20; % length and number of marks

% Function curve
vardef function(expr xmin, xmax, xstep)(text f_x) =
    save x; x := xmin;
    (x, f_x)
    forever:
        hide(x := x + xstep)
        exitunless x <= xmax;
        .. (x, f_x)
    endfor
    if x - xstep < xmax: hide(x := xmax) .. (x, f_x) fi
enddef;

% Exponential and sinusoide curve
path expcurve; expcurve = function(ceiling(xmin), floor(xmax), .1)(exp x) xyscaled (u, v);
path sincurve; sincurve = function(ceiling(xmin), floor(xmax), .1)(10sin x) xyscaled (u, v);

% Space between marks
exp_marksep = arclength expcurve / (nmarks-1);
sin_marksep = arclength sincurve / (nmarks-1);

% Cartouche management
def define_cartouche(text cartouche)(expr pos) = 
    picture cartouche; cartouche = nullpicture;
    numeric _cnt; _cnt = 0;
    def addto_cartouche (suffix cartouche)(expr wd, str) =
        addto cartouche also (image(draw pos - (wd,0) -- pos; 
            drawdot pos - (.5wd, 0) withpen bigdot;
            label.rt(str, pos) withcolor black)
                yshifted -_cnt*\mpdim{\baselineskip});
        _cnt := _cnt + 1;
    enddef;
enddef;

beginfig(1);
    define_cartouche(box)((2u, 20v));

    % Curves and marks
    drawoptions(withcolor blue); draw expcurve;
    for i = 0 upto nmarks-1:
        %drawdot point (arctime (i*exp_marksep) of expcurve) of expcurve withpen bigdot; 
        draw point (i*exp_marksep) on expcurve withpen bigdot;      
    endfor
    addto_cartouche(box, .5cm, "$\exp x$");

    drawoptions(withcolor red); draw sincurve;
    for i = 0 upto nmarks-1:
        %draw point (arctime (i*sin_marksep) of sincurve) of sincurve withpen bigdot; 
        draw point (i*sin_marksep) on sincurve withpen bigdot;
    endfor
    addto_cartouche(box, .5cm, "$10\sin x$");

    % Axes and labels
    drawoptions();
    draw ((xmin, ymin) -- (xmax, ymin) -- (xmax, ymax) -- (xmin, ymax) -- cycle) xyscaled (u, v);  
    for i = 0 upto 3:
        draw (u*i, ymin*v) -- (u*i, ymin*v+len);
        draw (u*i, ymax*v) -- (u*i, ymax*v-len);
        label.bot(decimal i, (i*u, ymin*v));
    endfor;  
    for j = 0 step 5 until 20:
        draw (xmin*u, j*v) -- (xmin*u + len, j*v);
        draw (xmax*u, j*v) -- (xmax*u - len, j*v) ;
        label.lft(decimal j, (xmin*u, j*v));
    endfor;

    draw bbox box enlarged 2bp; draw box;

endfig;
\end{mplibcode}
\end{document}

在此处输入图片描述

答案4

如果手动解决方案足以满足您的使用需求,您可以使用键mark repeat=<n>仅绘制每个n标记。在这里,我为每个samples设置添加了 1,以便事情以整数形式运行:

\documentclass[tikz,border=1mm]{standalone}
\usepackage{pgfplots}
\usetikzlibrary{decorations.markings}
\pgfplotsset{compat=1.11}

\begin{document}
\begin{tikzpicture}
\begin{axis}[]
\addplot[
  blue,
  domain=0:3,
  samples=101,
  mark=*,
  mark repeat=5, % calculated using (101-1)/(21-1) = 5
  ]
{exp(x)};
\addlegendentry{exp(x)};

\addplot[
  red,
  domain=0:3,
  samples=21,
  mark=diamond
  ]
{4*x};
\addlegendentry{10 sin(x)};

\end{axis}
\end{tikzpicture}
\end{document}

在此处输入图片描述

相关内容