16

Is it possible to change the Dashed Style of a curve into circles with Plot command ?

Plot[Cos[x], {x, 0, 2*Pi}, PlotStyle -> Directive[Dashed, Thickness[0.005]]]

enter image description here

Dr. belisarius
  • 115,881
  • 13
  • 203
  • 453
kamran
  • 515
  • 4
  • 10

4 Answers4

18

If you want to roll your own solution to evenly distrubute circles along the path you could use the so called arc length parametrization of the path $p(t)=(t,\cos(t))$. For this particular curve, it will need to be computed numerically.

p[t_] := {t, Cos[t]};
$Assumptions = {t > 0};
speed[t_] = Simplify[Norm[p'[t]]];
arcLength[t_?NumericQ] := NIntegrate[speed[tau], {tau, 0, t}]
phi[s_?NumericQ] := t /. FindRoot[arcLength[t] == s, {t, 1}];
p1[s_?NumericQ] := p[phi[s]];
Graphics[Table[
  Circle[p1[s], 0.05], {s, 0, arcLength[2 Pi], arcLength[2 Pi]/30}],
 Axes -> True]

enter image description here

Mark McClure
  • 32,469
  • 3
  • 103
  • 161
  • Nice. By the way, Mma can solve for the arc length exactly for this particular curve (in terms of EllipticE), but the numerical way will handle arbitrary curves better than Integrate, of course. – Michael E2 Dec 25 '13 at 16:43
  • Thanks! I was aware of the EllipticE thing, but figured the resulting function would need to be inverted numerically anyway. As I think of it further, perhaps the special function representation arcLength could be passed to InverseFunction or some such? Seems overly mysteriious, though. – Mark McClure Dec 25 '13 at 18:36
  • I think InverseFunction is just going to use FindRoot anyway. It certainly works with InverseFunction and the "exact" arc length. (Of course in graphics, even addition and multiplication are a numerical procedures, so "exact" is not as important as "accurate.") – Michael E2 Dec 25 '13 at 18:59
  • 1
    Of course, one can use MeshFunctions -> {"ArcLength"} these days. – J. M.'s missing motivation Dec 11 '15 at 17:24
11

A dash of length zero is rendered as a "dot", according to the documentation for Dashing. To get a circular dot use CapForm["Round"].

Plot[Cos[x], {x, 0, 2*Pi}, 
 PlotStyle -> Directive[CapForm["Round"], Dashing[{0, 0.05}], Thickness[0.02]]]

Mathematica graphics

Michael E2
  • 235,386
  • 17
  • 334
  • 747
8

This is an alternate compute-your-own-arc-length approach, based directly on the line produced by plot, (ie not differentiating its functional form as in Mark's answer)

p1 = Plot[Cos[x], {x, 0, 2 Pi}]
linepoints[plist_, n_] := Module[{arc, tlen},
  arc = Interpolation[
        Transpose@{{0}~Join~
                  Accumulate@(Norm@(Subtract @@ #) & /@ 
                       Partition[plist, 2, 1]), plist},
        InterpolationOrder -> 3];
  tlen = Last@First@First@(arc);
  Table[ arc[tlen iz / n], {iz, 0, n}]];
ListPlot[
       linepoints[
          First@(First@Cases[FullForm[ p1], Line[__], Infinity]),  25],
       PlotMarkers -> ({Graphics@Circle[{0, 0}], .025})]

enter image description here

A nice illustration comparing equal spaced points vs a more simple ListPlot[Table]] approach:

p1 = Plot[Cos[x^2], {x, 0, Pi}];
Show[
 {ListPlot[
     linepoints[First@(First@Cases[FullForm[ p1], Line[__], Infinity]), 
     120], PlotMarkers -> ({Graphics@Circle[{0, 0}], .025})],
  ListPlot[Table[{x, -Cos[x^2]}, {x, 0, Pi, 2 Pi/120}], 
          PlotMarkers -> ({Graphics@Rectangle[{0, 0}], .025})]}, 
    PlotRange -> All]

enter image description here

george2079
  • 38,913
  • 1
  • 43
  • 110
  • 2
    Very nice! One big advantage is that your approach is independent of the AspectRatio of the figure, while mine only works in true aspect ratio, though that shouldn't be hard to adjust. It might be work mentioning that your interpolated function arc has the form arc[s]={x,y}, where s is distance traveled along the arc and {x,y} is the resulting point, i.e. it is exactly the arc length parametrization. – Mark McClure Dec 27 '13 at 01:17
6

Perhaps this approach, using Mesh, MeshStyle, and Opacity, will give you what you looking for.

Plot[Cos[x], {x, 0, 2 Pi},
  PlotStyle -> {Opacity[0]}, Mesh -> 50, MeshStyle -> {PointSize[Medium]}]

plot.png

Update

To show two curves, one as dots and the other as a normal plot, I would make two plots and combine them with Show.

p1 = 
  Plot[Cos[x], {x, 0, 2 Pi}, 
   PlotStyle -> {Opacity[0]}, Mesh -> 30, MeshStyle -> {PointSize[Large], Blue}];
p2 = Plot[Sin[x], {x, 0, 2 Pi}, PlotStyle -> {Thick, Blue}];
Show[{p1, p2}]

show.png

You can use Show to combine as many plots as you wish.

m_goldberg
  • 107,779
  • 16
  • 103
  • 257
  • 2
    The problem is that the density isn't uniform along the curve. Any spike will give you an accumulation point – Dr. belisarius Dec 25 '13 at 05:58
  • If the OP wants open circles, the post-process with Plot[..] /. Point[pts_] :> (Circle[#, 0.05] & /@ pts). Can either change aspect ratio of the plot or use Circle[#, 0.05 {1, 1/GoldenRatio}]. – Michael E2 Dec 25 '13 at 05:59
  • 1
    @MichaelE2 As I understand it, the OP wants a circle where he has a dash. And that isn't easy (I think) – Dr. belisarius Dec 25 '13 at 06:27
  • @ m_goldberg, with the help of Plot command I want to get one curve in form if circles and other like a solid line.

    Plot[{Cos[x], Sin[x]}, {x, 0, 2 Pi}, PlotStyle -> {Opacity[0]}, Mesh -> 30, MeshStyle -> {PointSize[Large], Blue}]

    – kamran Dec 26 '13 at 09:52