![在 PGFplots 轴环境中注释/绘制带斜率的三角形](https://linux22.com/image/311541/%E5%9C%A8%20PGFplots%20%E8%BD%B4%E7%8E%AF%E5%A2%83%E4%B8%AD%E6%B3%A8%E9%87%8A%2F%E7%BB%98%E5%88%B6%E5%B8%A6%E6%96%9C%E7%8E%87%E7%9A%84%E4%B8%89%E8%A7%92%E5%BD%A2.png)
在期刊论文中,我经常看到图中的注释,描绘具有特定斜率的三角形,以强调图中不同图形(大致)具有哪些斜率。
例如
是否有宏可以LaTeX
轻松进行此类注释?那么,给定轴上的相对位置和斜率,在轴上的相对位置绘制具有此斜率的三角形?
答案1
% Mind section '4.17 Custom annotations' of the PGFplots manual Revision 1.12 (2015/01/31).
\documentclass[margin=1cm]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
%%% START MACRO %%%
\newcommand{\slopeTriangle}[5]
{
% #1. Relative offset in x direction.
% #2. Width in x direction, so xA-xB.
% #3. Relative offset in y direction.
% #4. Slope dydx.
% #5. Plot options.
\pgfplotsextra
{
\pgfkeysgetvalue{/pgfplots/xmin}{\xmin}
\pgfkeysgetvalue{/pgfplots/xmax}{\xmax}
\pgfkeysgetvalue{/pgfplots/ymin}{\ymin}
\pgfkeysgetvalue{/pgfplots/ymax}{\ymax}
% Calculate auxilliary quantities.
\pgfmathsetmacro{\xA}{\xmin+(#1+#2)*(\xmax-\xmin)}
\pgfmathsetmacro{\yA}{\ymin+#3*(\ymax-\ymin)}
\pgfmathsetmacro{\xB}{\xmin+#1*(\xmax-\xmin)}
\pgfmathsetmacro{\yB}{\yA}
\pgfmathsetmacro{\xC}{\xA}
\pgfmathsetmacro{\yC}{\yA+(\xA-\xB)*#4}
% Define coordinates for \draw.
\coordinate (A) at (axis cs:\xA,\yA);
\coordinate (B) at (axis cs:\xB,\yB);
\coordinate (C) at (axis cs:\xC,\yC);
% Draw slope triangle.
\draw[#5] (A)-- node[pos=0.5,anchor=north] {1}
(B)--
(C)-- node[pos=0.5,anchor=west] {#4}
cycle;
}
}
%%% END MACRO %%%
\begin{document}
\begin{tikzpicture}
\begin{axis}
[
xtick={-0.1,0,1,1.1},
xlabel=$x$,
ytick={-0.2,0,2,2.2},
ylabel style={rotate=-90},
ylabel=$y$,
unit vector ratio=2 1 1,
clip=false
]
\addplot[blue,domain=0:1] {x};
\addplot[red,domain=0:1] {2*x};
\slopeTriangle{0.65}{0.1}{0.1}{1}{blue}; % USE OF MACRO.
\slopeTriangle{0.825}{0.1}{0.1}{2}{red}; % USE OF MACRO.
\end{axis}
\end{tikzpicture}
\end{document}
答案2
MetaPost 解决方案。我刚好已经为我目前正在教授的一门课程设计了这样一个宏,它可以应用于任何函数曲线。这里是它,稍加修改后应用于抛物线y = 4x-x^2
。斜率由 MetaPost 本身计算,并借助该包四舍五入为任意位数numprint
。(由于已知这里的斜率具有整数值,我已指示numprint
将它们四舍五入为最接近的整数:\nprounddigits{0}
,但可以随意更改。)
为了更加方便,MetaPost 编码已插入 LuaLaTeX 程序中:
\documentclass[border=2mm]{standalone}
\usepackage{luamplib}
\mplibsetformat{metafun}
\mplibtextextlabel{enable}
\mplibnumbersystem{double}
\usepackage{numprint}
\nprounddigits{0}
\begin{document}
\begin{mplibcode}
input mpcolornames;
% Parameters
numeric u, v, xmin, xmax, xstep, ymin, ymax;
u = v = 1cm; xmin = -2; xmax = 6; xstep = 0.1;
ymin = -6; ymax = 6;
% Graph definition
vardef f (expr x) = 4x - x**2 enddef;
path my_graph;
my_graph = function(2, "x", "f(x)", xmin, xmax, xstep);
% Macro creating triangle with slope
def triangle_with_slope(expr p, A) =
% Basis and height
h := 1; a := xpart A; b := a + h;
% Direction
pair vdir, B;
vdir = direction ((a-xmin)/xstep) of p;
B = A + vdir/xpart(vdir);
% tangent and triangle
path tangente, Delta_x, Delta_y, triangle;
Delta_x = (A -- (xpart B, ypart A)) xyscaled (u, v);
Delta_y = ((xpart B, ypart A) -- B) xyscaled (u, v);
tangente = (A -- B) xyscaled (u, v);
triangle = (A -- (xpart B, ypart A) -- B -- cycle) xyscaled (u, v);
% The drawing
drawoptions(withcolor DarkRed);
fill triangle withcolor Pink; draw tangente;
drawarrow Delta_x; drawarrow Delta_y;
drawdot A xyscaled (u, v) withpen pencircle scaled 3bp;
% Labels
string slope; slope := decimal(ypart(B-A));
labeloffset := 2bp;
label. if ypart(B-A)>0: bot else: top fi ("$1$", point .5 of Delta_x);
freelabel("$\numprint{" & slope & "}$", point .5 of Delta_y, center triangle);
drawoptions( );
enddef;
beginfig(1);
% Axes
drawarrow (xmin*u, 0) -- (xmax*u, 0);
drawarrow (0, ymin*v) -- (0, ymax*v);
% Graph and triangles with slope
for i = -1 upto 4: triangle_with_slope(my_graph, (i, f(i))); endfor
picture parabola; parabola = image(draw my_graph xyscaled (u, v));
clip parabola to
((xmin, ymin) -- (xmax, ymin) -- (xmax, ymax) -- (xmin, ymax) -- cycle)
xyscaled (u, v);
draw parabola;
% Marks
labeloffset := 5bp;
label.bot("$x$", (xmax*u, 0)); label.lft("$y$", (0, ymax*v));
for i = -2 upto 5: if i<>0: draw (i*u, -3bp) -- (i*u, 3bp); fi endfor
for j = -6 upto 5: if j<>0: draw (-3bp, j*v) -- (3bp, j*v); fi endfor
label.bot("$1$", (u, 0)); label.lft("$1$", (0, v));
endfig;
\end{mplibcode}
\end{document}
输出: