Reputation: 3066
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
accepts BSplineCurves
and BezierCurves
but 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!
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]}}]} }]
Upvotes: 9
Views: 4571
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]]
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
Arrows on both ends
Inverted arrowheads
Upvotes: 8
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
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}]]
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];
Upvotes: 7