在曲线的边缘绘制箭头

时间:2011-02-22 06:42:13

标签: wolfram-mathematica plot

在ask.sagemath的this question启发,在PlotContourPlot等产生的曲线末尾添加箭头的最佳方式是什么? ...?这些是高中看到的情节类型,表明曲线在页面末尾继续。

经过一番搜索后,我无法找到内置方式或最新的软件包来执行此操作。 (有ArrowExtended,但它已经很老了。

ask.sagemath问题中给出的解决方案依赖于函数及其端点的知识以及(可能)获取衍生物的能力。它翻译成Mathematica是

f[x_] := Cos[12 x^2]; xmin = -1; xmax = 1; small = .01; 
Plot[f[x],{x,xmin,xmax}, PlotLabel -> y==f[x], AxesLabel->{x,y},
  Epilog->{Blue,
    Arrow[{{xmin,f[xmin]},{xmin-small,f[xmin-small]}}],
    Arrow[{{xmax,f[xmax]},{xmax+small,f[xmax+small]}}]
  }]

arrow cos(12 x^2)

另一种方法是简单地将Line[]生成的Plot[]对象替换为Arrow[]。例如

Plot[{x^2, Sin[10 x], UnitStep[x]}, {x, -1, 1}, 
  PlotStyle -> {Red, Green, {Thick, Blue}},
  (*AxesStyle -> Arrowheads[.03],*) PlotRange -> All] /. 
 Line[x__] :> Sequence[Arrowheads[{-.04, .04}], Arrow[x]]

multiple plots

但是这有一个问题,即线条中的任何不连续都会产生你不想要它们的箭头(这通常可以通过选项Exclusions -> None来修复)。更重要的是,CountourPlot s这种方法毫无希望。例如,尝试

ContourPlot[x^2 + y^3 == 1, {x, -2, 2}, {y, -2, 1}] /. 
  Line[x__] :> Sequence[Arrowheads[{-.04, .04}], Arrow[x]]

(上述情况中的问题可由规则修正,例如{a___, l1_Line, l2_Line, b___} :> {a, Line[Join[l2[[1]], l1[[1]]]], b}或使用适当的单头箭头。)。

正如您所看到的,上述(快速黑客)都不是特别强大或灵活。有谁知道这种做法?

3 个答案:

答案 0 :(得分:4)

以下似乎可行,首先对片段进行排序:

f[x_] := {E^-x^2, Sin[10 x], Sign[x], Tan[x], UnitBox[x], 
             IntegerPart[x], Gamma[x],
             Piecewise[{{x^2, x < 0}, {x, x > 0}}], {x, x^2}}; 

arrowPlot[f_] := 
 Plot[{#}, {x, -2, 2}, Axes -> False, Frame -> True, PlotRangePadding -> .2] /.

 {Hue[qq__], a___, x___Line} :> {Hue[qq], a, SortBy[{x}, #[[1, 1, 1]] &]} /. 

 {a___,{Line[x___], d___, Line[z__]}} :> 
                           List[Arrowheads[{-.06, 0}], a, Arrow[x], {d}, 
                                             Arrowheads[{0, .06}], Arrow[z]] /. 

 {a___,{Line[x__]}}:> List[Arrowheads[{-.06, 0.06}], a, Arrow[x]] & /@ f[x];  

arrowPlot[f]

enter image description here

答案 1 :(得分:2)

受Alexey的评论和belisarius的回答的启发,这是我的尝试。

makeArrowPlot[g_Graphics, ah_: 0.06, dx_: 1*^-6, dy_: 1*^-6] := 
 Module[{pr = PlotRange /. Options[g, PlotRange], gg, lhs, rhs},
  gg = g /. GraphicsComplex -> (Normal[GraphicsComplex[##]] &);
  lhs := Or@@Flatten[{Thread[Abs[#[[1, 1, 1]] - pr[[1]]] < dx], 
                      Thread[Abs[#[[1, 1, 2]] - pr[[2]]] < dy]}]&;
  rhs := Or@@Flatten[{Thread[Abs[#[[1, -1, 1]] - pr[[1]]] < dx], 
                      Thread[Abs[#[[1, -1, 2]] - pr[[2]]] < dy]}]&;
  gg = gg /. x_Line?(lhs[#]&&rhs[#]&) :> {Arrowheads[{-ah, ah}], Arrow@@x};
  gg = gg /. x_Line?lhs :> {Arrowheads[{-ah, 0}], Arrow@@x};
  gg = gg /. x_Line?rhs :> {Arrowheads[{0, ah}], Arrow@@x};
  gg
  ]

我们可以在某些功能上测试这个

Plot[{x^2, IntegerPart[x], Tan[x]}, {x, -3, 3}, PlotStyle -> Thick]//makeArrowPlot

Normal plots

在一些等高线图上

ContourPlot[{x^2 + y^2 == 1, x^2 + y^2 == 6, x^3 + y^3 == {1, -1}}, 
   {x, -2, 2}, {y, -2, 2}] // makeArrowPlot

contour plots

失败的地方是地块边缘有水平或垂直线;

Plot[IntegerPart[x],{x,-2.5,2.5}]//makeArrowPlot[#,.03]&

fail!

可以通过PlotRange->{-2.1,2.1}Exclusions->None等选项修复此问题。

最后,添加一个选项会很好,这样每个“曲线”只能在其边界上显示箭头。这将给出像Belisarius的回答中的情节(它也可以避免上面提到的问题)。但这是一个品味问题。

答案 2 :(得分:2)

以下构造的优点是不会弄乱Graphics结构的内部结构,并且比ask.sagemath中建议的更通用,因为它更好地管理PlotRange和infinities。

f[x_] = Gamma[x]

{plot, evals} = 
  Reap[Plot[f[x], {x, -2, 2}, Axes -> False, Frame -> True, 
    PlotRangePadding -> .2, EvaluationMonitor :> Sow[{x, f[x]}]]];

{{minX, maxX}, {minY, maxY}} = Options[plot, PlotRange] /. {_ -> y_} -> y; 
ev = Select[evals[[1]], minX <= #[[1]] <= maxX && minY <= #[[2]] <= maxY &];
seq = SortBy[ev, #[[1]] &];
arr = {Arrow[{seq[[2]], seq[[1]]}], Arrow[{seq[[-2]], seq[[-1]]}]};

enter image description here

Show[plot, Graphics[{Red, arr}]]

修改

作为一项功能:

arrowPlot[f_, interval_] := Module[{plot, evals, within, seq, arr},
   within[p_, r_] :=
    r[[1, 1]] <= p[[1]] <= r[[1, 2]] &&
     r[[2, 1]] <= p[[2]] <= r[[2, 2]];

   {plot, evals} = Reap[
     Plot[f[x], Evaluate@{x, interval /. List -> Sequence},
      Axes -> False,
      Frame -> True,
      PlotRangePadding -> .2,
      EvaluationMonitor :> Sow[{x, f[x]}]]];

   seq = SortBy[Select[evals[[1]],
      within[#, 
        Options[plot, PlotRange] /. {_ -> y_} -> y] &], #[[1]] &];

   arr = {Arrow[{seq[[2]], seq[[1]]}], Arrow[{seq[[-2]], seq[[-1]]}]};
   Show[plot, Graphics[{Red, arr}]]
   ];

arrowPlot[Gamma, {-3, 4}]  

仍然在想ListPlot&amp;人