7
$\begingroup$

We set MeshFunctions to "ArcLength",but it is missing the boundary point,so there only two points on the contour.

con=ContourPlot[Cos[x] + Cos[y] == 1/2, {x, -Pi, Pi}, {y, -Pi, Pi}, 
 MeshFunctions -> {0 &, "ArcLength"}, Mesh -> 2, 
 MeshStyle -> Directive[AbsolutePointSize[8], Red]]

enter image description here

Although we can Cases the point from the contour,but it seems not so elegant.

Updated

It seems that MeshShading does not work in ContourPlot.

enter image description here

pts = Cases[Normal@con, Line[pts_] :> pts, -1];
ListPlot[pts, AspectRatio -> Automatic, Joined -> True, 
 MeshFunctions -> {"ArcLength"}, Mesh -> 2, 
 MeshStyle -> Directive[AbsolutePointSize[8], Red], 
 Epilog -> {Directive[AbsolutePointSize[8], Red], 
   Point@First@First@pts}, MeshShading -> ColorData[97] /@ Range[3]]
$\endgroup$
2
  • $\begingroup$ herbertfederer, can you share how you came up with the spec {0 &, "ArcLength"} ? (I have never seen it before) $\endgroup$
    – kglr
    Jun 5, 2023 at 16:38
  • 1
    $\begingroup$ @kglr In the early version, for example, 11.3, we only need to use{"ArcLength"}. but something have been change since such version. Now we have to use two MeshFunction, it maybe a feature or maybe a bug. $\endgroup$ Jun 6, 2023 at 3:47

2 Answers 2

14
$\begingroup$

1. Specify Mesh as a list

ContourPlot[Cos[x] + Cos[y] == 1/2, {x, -Pi, Pi}, {y, -Pi, Pi}, 
 MeshFunctions -> {0 &, ArcLength}, 
 Mesh -> {Subdivide @ 3}, 
 MeshStyle -> Directive[Red, PointSize@Large]]

enter image description here

Note: Curiously, if we specify the setting for Mesh as a list of {mesh, style} pairs we can get rid of 0& in MeshFunctions:

ContourPlot[Cos[x] + Cos[y] == 1/2, {x, -Pi, Pi}, {y, -Pi, Pi}, 
 MeshFunctions -> {ArcLength}, 
 Mesh -> 
  {Thread[{Subdivide@3, Directive[ Red, Opacity[1], PointSize @.03]}]}]

same picture

2. Use DisplayFunction to add the missing point

ContourPlot[Cos[x] + Cos[y] == 1/2, {x, -Pi, Pi}, {y, -Pi, Pi},
 MeshFunctions -> {0 &, ArcLength},
 Mesh -> 2,
 MeshStyle -> Directive[Red, PointSize @ Large],
 DisplayFunction -> ReplaceAll[Point@x_ :> Point[Prepend[1]@x]]]

enter image description here

3. Post-process to add the missing point

ReplaceAll[Point @ x_ :> Point[Prepend[1] @ x]]@
 ContourPlot[Cos[x] + Cos[y] == 1/2, {x, -Pi, Pi}, {y, -Pi, Pi},
  MeshFunctions -> {0 &, ArcLength},
  Mesh -> 2,
  MeshStyle -> Directive[Red, PointSize@Large]]

enter image description here

4. Use MeshStyle to add the missing mesh point

ContourPlot[Cos[x] + Cos[y] == 1/2, {x, -Pi, Pi}, {y, -Pi, Pi}, 
 MeshFunctions -> {0 &, ArcLength}, 
 Mesh -> 2, 
 MeshStyle -> ({Red, PointSize @ Large, #, Point @ 1} &)]

enter image description here

Update:

MeshShading is not an option for ContourPlot.

One way to get contours with multiple segments with different styles from ContourPlot is to extract the line coordinates and process them with a *Plot function that accepts MeshShading as an option (as done in the update in OP).

In the following, we wrap all Mesh* options (including MeshShading) in meshOptions and use ParametricPlot to process them to construct the desired graphics primitives and inject them in ContourPlot using a custom DisplayFunction:

ClearAll[meshOptions]

meshOptions[opts : OptionsPattern[]] :=
 Module[{BSF = BSplineFunction[#]},
   First[Show[ParametricPlot[BSF@t, {t, 0, 1}, opts], 
     Graphics[{MeshStyle /. FilterRules[{opts}, MeshStyle], 
       Point[BSF /@ {0, 1}]}]]]] &

meshOptions /: ContourPlot[a__, meshOptions[o___], b___] :=
 ContourPlot[a, b,
  DisplayFunction -> 
   ReplaceAll[Line[x_] :> (Dynamic @ meshOptions[o] @ x)] @* Normal]

Examples:

ContourPlot[Cos[x] + Cos[y] == 1/2, {x, -Pi, Pi}, {y, -Pi, Pi},
 meshOptions[
   MeshFunctions -> {"ArcLength"},
   Mesh -> {Subdivide @ 3},
   MeshStyle -> Directive[Red, AbsolutePointSize[10]],
   MeshShading -> (ColorData[97] /@ Range[3])]]

enter image description here

ContourPlot[{Cos[x] + Cos[y] == 1/2, Cos[x] + Cos[y] == 1, 
  Sin[x] + Cos[y] == 1/2}, {x, -Pi, Pi}, {y, -Pi, Pi},
  PlotLegends -> "Expressions",
  meshOptions[
    MeshFunctions -> {"ArcLength"},
    Mesh -> {Subdivide @ 3},
    MeshStyle -> Directive[CurrentValue @ "Color", AbsolutePointSize[10]],
    MeshShading ->
      (Directive[CurrentValue @ "Color",  AbsoluteDashing[3 #]] & /@ Range[3])]]

enter image description here

Add the option ContourStyle -> "Rainbow" to get

enter image description here

$\endgroup$
4
  • $\begingroup$ Thanks! I just found out that MeshShading cannot be used in ContourPlot, it is curious to me. See my updated. $\endgroup$ Jun 4, 2023 at 7:20
  • 1
    $\begingroup$ MeshShading is not an option for ContourPlot. Please see the update for a hack to smuggle MeshShading option into ContourPlot. $\endgroup$
    – kglr
    Jun 4, 2023 at 20:52
  • $\begingroup$ @kglr Helpful interesting answer! I tried to understand the option MeshFunctions -> {0 &, ArcLength}: I changed the first part 0& arbitrarilly to 3&, but resulting plot doesn't change? $\endgroup$ Jun 5, 2023 at 9:07
  • $\begingroup$ Ulrich, never seen this usage before. $\endgroup$
    – kglr
    Jun 5, 2023 at 16:18
7
$\begingroup$

Using arrows and arrowheads.

pt = Graphics[{Red, PointSize[Large], Point[{0, 0}]}, 
   ImageSize -> 9];
con = Normal@
   ContourPlot[Cos[x] + Cos[y] == 1/2, {x, -Pi, Pi}, {y, -Pi, Pi},
    ContourStyle -> 
     Arrowheads[{0., {.1, Automatic, pt}, {.1, Automatic, pt}, {.1, 
        Automatic, pt}}]] /. Line -> Arrow

You can also use the following, whose "points" scale with the size of the graphics.

pt = Graphics[{Red, Disk[]}];
Arrowheads[{0.,
   {.012, Automatic, pt},
   {.012, Automatic, pt},
   {.012, Automatic, pt}}]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.