6
$\begingroup$

When I was extracting the mesh points from a ParametricPlot, I found that it extracted the same two points twice, and I'm not sure why.

I know I can use Union to remove the duplicate points, but I'm wondering if there is a better solution?

Thanks.

Below is my code.

pts = Table[{2 Cos[t], Sin[t]}, {t, 0, 2 Pi, 0.2}];
f = BSplineFunction[pts, SplineClosed -> {True, False}];
plot = ParametricPlot[f[w], {w, 0, 1}, Mesh -> {{0}}, 
  MeshFunctions -> {#1 &}, 
  MeshStyle -> Directive[PointSize[0.03], Red], PlotRange -> All, 
  PlotPoints -> 20]
Cases[Normal@plot, Point[{x_, y_}] :> {x, y}, Infinity]

extrac mesh points

$\endgroup$
3
  • $\begingroup$ I also noticed that Cases[InputForm@plot, Point[___], Infinity] gives {Point[{564, 565}], Point[{0., 0.993351}], Point[{0., -0.993349}]} $\endgroup$
    – Nasser
    Commented May 18 at 9:04
  • 2
    $\begingroup$ try adding the option PlotHighlighting -> None in Plot[...]? $\endgroup$
    – kglr
    Commented May 18 at 12:45
  • $\begingroup$ Thanks for the comments. Actually, I'd like to know why Cases duplicats these two points? $\endgroup$
    – xinxin guo
    Commented May 18 at 14:36

2 Answers 2

5
$\begingroup$

The extra points come from the highlighting functionality added to plots. Turning the highlighting off removes one copy of the points:

pts = Table[{2  Cos[t], Sin[t]}, {t, 0, 2  Pi, 0.2}];
f = BSplineFunction[pts, SplineClosed -> {True, False}];
plot2 = ParametricPlot[f[w], {w, 0, 1}, Mesh -> {{0}}, 
   MeshFunctions -> {#1 &}, 
   MeshStyle -> Directive[PointSize[0.03], Red], PlotRange -> All, 
   PlotPoints -> 20, PlotHighlighting -> None];

Cases[plot2, Point[{x_, y_}] :> {x, y}, Infinity]
(* {{564, 565}} *)

Cases[Normal@plot2, Point[{x_, y_}] :> {x, y}, Infinity]
(* {{0., 0.993351}, {0., -0.993349}} *)

The highlighting is supported by an Annotation[] added to the graphics primitives. In this case, the annotation adds the Normal[] form of the graphics. If we replace Annotation by # &, which in effect removes the annotation from the annotated expression, we get only one pair of points;

Cases[plot /. Annotation -> (# &), Point[{x_, y_}] :> {x, y}, Infinity]
(* {{564, 565}} *)

Cases[Normal@plot /. Annotation -> (# &), 
 Point[{x_, y_}] :> {x, y}, Infinity]
(* {{0., 0.993351}, {0., -0.993349}} *)

Note that the internal structure of plots may change from version to version. It has changed several times over the years. Each change may invalidate an earlier method used on the site. It's kind of annoying to people who like to hack, but it's also an expected risk.

Note also that Annotation["foo", <|"a" -> 1|>] displays only "foo", so annotations are sometimes hard to track down. They show up in FullForm, but the FullForm of an expression is not always convenient for inspection.

$\endgroup$
1
  • $\begingroup$ Wow, this is explained so thoroughly! I learned a lot, thank you very much! $\endgroup$
    – xinxin guo
    Commented May 19 at 4:40
3
$\begingroup$

If you don't use Normal you get the two points and their indices:

Cases[plot, Point[{x_, y_}] :> {x, y}, All]

{{564, 565}, {0., 0.993351}, {0., -0.993349}}

Consequently, a "better" solution would be

Rest @ Cases[plot, Point[{x_, y_}] :> {x, y}, All]

{{0., 0.993351}, {0., -0.993349}}

Looking at the long output of Normal[plot] // FullForm you can see that the two points appear indeed twice in different "contexts".

$\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.