Plotting arrows at the edges of a curve

后端 未结 3 1480
死守一世寂寞
死守一世寂寞 2020-12-28 10:01

Inspired by this question at ask.sagemath, what is the best way of adding arrows to the end of curves produced by Plot, ContourPlot

3条回答
  •  南方客
    南方客 (楼主)
    2020-12-28 10:45

    The following construct has the advantage of not messing with the internal structure of the Graphics structure, and is more general than the one suggested in ask.sagemath, as it manage PlotRange and infinities better.

    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}]]
    

    Edit

    As a function:

    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}]  
    

    Still thinking what is better for ListPlot & al.

提交回复
热议问题