DavidC
DavidC

Reputation: 3066

How can I make a directed arc of a circle (or a directed curve)?

I'd like to display a directed circular arc in Mathematica, using something as simple as Arrow. The best I have been able to come up with is this example that nails an Arrow onto one end of a circular arc. But I suspect there is a more direct way to achieve the same effect.

start=\[Pi];
Manipulate[
Graphics[{
   Arrow[{{Cos[\[Theta] + If[\[Theta] < start, .01, -.01]], 
           Sin[\[Theta] + If[\[Theta] < start, .01, -.01]]}, 
          {Cos[\[Theta]], Sin[\[Theta]]}}],
   Circle[{0, 0}, 1, {start, \[Theta]}]},
PlotRange -> 2], 
{{\[Theta], .7 start}, 0, 2 start} 
           ]

arrow

Arrow accepts BSplineCurves and BezierCurvesbut I can't get them to stay on a circular arc. Tube accepts the formula for a curve in 3D but I can't figure out how to get it to work in 2D.

All suggestions are welcome. If your solution works for any 2D curve, all the better!


Epilogue:

I learned quite a bit from the suggestions: Mark McClure showed that Arrow itself can handle the demands when given a list of points.

yoda gave a fairly general solution using ParametricPlot.

I ended up finding belisarius' suggestions the most helpful. His approach was to work on minor variations of familiar graphical objects. In the end, I cautiously chose to define a new object, arcArrow, that employs the parameters of Circle: center, radius, {start,finish}. Unprotect still scares me! Anyway, here's what I settled with. I also stubbornly held on to some features of my original approach.

Manipulate[
 Graphics[{  
   arcArrow[center, radius, {start, end}],
   PointSize[Large], Blue, If[showCenter, Point[center]]},
  PlotRange -> p, ImageSize -> 250],
 {{start, \[Pi]/2}, -2 \[Pi], 2 \[Pi], ImageSize -> Small},
 {{end, 0}, -2 \[Pi], 2 \[Pi], ImageSize -> Small},
 {{radius, 1}, 1/2, 4, ImageSize -> Small},
 {{center, {0, 0}}, {-p, -p}, {p, p}, Slider2D},
 {showCenter, {True, False}},

 Initialization :> {p = 3;
   arcArrow[a_, r_, {start_, end_}] :=
    {Circle[a, r, {start, end}], 
     Arrowheads[Medium],
     Arrow[{a + r {Cos[end + If[end < start, .01, -.01]], 
                   Sin[end + If[end < start, .01, -.01]]}, 
            a + r {Cos[end], Sin[end]}}]} }]

final version


Upvotes: 9

Views: 4571

Answers (3)

abcd
abcd

Reputation: 42235

You can also add an arrow to the end point of an arc like so:

circle[x_] = {Cos[x], Sin[x]};
ParametricPlot[{0.9 circle[x], 0.7 circle[x + Pi/3], 0.4 circle[-x]}, 
 {x, Pi/4, Pi/2}, PlotRange -> {-1, 1}, Axes -> False] 
/.Line[x__] :> Sequence[Arrowheads[.03], Arrow[x]]

enter image description here

This is probably much easier to control, as you can set the radius and arc length programmatically and just replace the arrows in the end.

You should also take a look at the discussion on adding arrows at the edges of a curve. There are a lot of good approaches there, perhaps better than this one. I personally found Simon's answer to his own question to be a pretty nifty little function that I have in my little 'functions from the internet' collection, and have used it more than once to place arrows on graphs that continue outside the plot.

EDIT

The way I've defined it above, it places an arrow at the end of the line. For e.g., if you plot a line from L to R, it places it on the right and left otherwise. So in the example, positive increase in x is counter-clockwise and hence the arrows in that direction. Increase in the negative dir will produce a clockwise arrow. To avoid a second plot command, I simply changed x to -x in the third function in the list, which produced the same effect in the golden colored curve.

More generally, you can change orientation of the arrows by changing the inputs to Arrowheads as follows:

Arrows going the other way round

enter image description here

Arrows on both ends

enter image description here

Inverted arrowheads

enter image description here

Upvotes: 8

Mark McClure
Mark McClure

Reputation: 4964

Arrow accepts a list of points of arbitrary length. Thus, perhaps something like so.

Manipulate[Graphics[
  Arrow[Table[{Cos[t], Sin[t]}, {t, 0, T, Sign[T] Pi/100}]],
  PlotRange -> 1.1], {{T, 0}, -2 Pi, 2 Pi}]

Upvotes: 7

Dr. belisarius
Dr. belisarius

Reputation: 61046

Using Circle[ ]:

f[s_Circle] := 
 s /. Circle[a_, r_, {start_, end_}] :>
      ({s,Arrow[{# - r/10^6 {-Sin@end, Cos@end}, #}]} &[a+r {Cos@end, Sin@end}]) 

Graphics@f[Circle[{0, 0}, 1, {4 Pi/3, 2 Pi}]]

enter image description here

Edit

Redefining the default Circle[ ] behavior:

Unprotect[Circle];
Circle[a_: {0, 0}, r_: 1, {start_, end_}] :=
  Block[{$inMsg = True},
    {Circle[a, r, {start, end}],
     Circle[a, r, {start, end}] /. 
      Circle[aa_, 
        ar_, {astart_, aend_}] :> (Arrow[If[start < end, #, Reverse@#]] &@
             {# - r/10^6 {-Sin@end, Cos@end}, #} &
               [aa + ar {Cos@aend, Sin@aend}])}
    ] /; ! TrueQ[$inMsg];
Protect[Circle];

enter image description here

Upvotes: 7

Related Questions