10
$\begingroup$

I want to find all data points inside curve as given below:

data = RandomReal[{-1, 1}, {200, 2}];
ParametricPlot[{Sin[u], Sin[2 u]}, {u, 0, 2 Pi}, 
 Epilog -> {Red, Point[data]}]

Short solution is preferable

Thanks.

$\endgroup$
2

4 Answers 4

16
$\begingroup$

Using the answer by rm-f here, you can discretized the curve into a polygon and get the desired points to any arbitrary accuracy:

inPolyQ[poly_, pt_] := Graphics`Mesh`PointWindingNumber[poly, pt] =!= 0

pp = Table[{Sin[u], Sin[2 u]}, {u, 0, 2 Pi, Pi/100}];

inPoints = Select[data, inPolyQ[pp, #] &];

ParametricPlot[{Sin[u], Sin[2 u]}, {u, 0, 2 Pi}, 
 Epilog -> {Red, Point[inPoints]}]

points inside

Edit for version 10

In Mathemtica version 10, the problem of finding points inside a closed curve doesn't have to be reduced to the problem of finding points inside a Polygon obtained from that curve by discretization. Instead, you can use the following symbolic approach which requires only that the curve be specified in a suitable form that can be handled by the new Region... commands:

rf = RegionMember[
   ParametricRegion[{Sin[u], r Sin[2 u]}, {{u, 0, 2 Pi}, {r, 0, 1}}]];

ParametricPlot[{Sin[u], Sin[2 u]}, {u, 0, 2 Pi}, 
 Epilog -> {Red, Point[Pick[data, rf[data]]]}]

region

The problem is solved in one line, completely without explicitly forming a list of boundary points.

$\endgroup$
1
  • $\begingroup$ @Mr.Wizard Strange that we both waited exactly 48 minutes before answering and then did so simultaneously! $\endgroup$
    – Jens
    Jul 9, 2014 at 2:31
9
$\begingroup$

Compute the points of a polygon and use any of the methods from How to check if a 2D point is in a polygon?. I'll use Simon's inPolyQ2.

g = ParametricPlot[{Sin[u], Sin[2 u]}, {u, 0, 2 Pi}];
poly = Cases[g, Line[x_] :> x, -1][[1]];
inside = Pick[data, inPolyQ2[poly, ##] & @@@ data];
Show[g, Epilog -> {Red, Point@inside}]

enter image description here

$\endgroup$
4
  • $\begingroup$ @Jens Thanks! For what it's worth I think using the adaptive sampling of ParametricPlot (as I do here) is superior to uniform sampling of Table. Also, inclusion testing could be faster if inPolyQ2 were compiled for the specific polygon thereby eliminating significant redundancy. $\endgroup$
    – Mr.Wizard
    Jul 9, 2014 at 2:33
  • $\begingroup$ You're probably right, but I wanted to be as short as possible - that's what Algohi asked for, right? I guess it depends on whether the plot was considered to be already given or not... $\endgroup$
    – Jens
    Jul 9, 2014 at 2:35
  • $\begingroup$ @Jens In that case you might as well use ListLinePlot on pp. $\endgroup$
    – Mr.Wizard
    Jul 9, 2014 at 2:38
  • 3
    $\begingroup$ But that would have cost me precious extra seconds... $\endgroup$
    – Jens
    Jul 9, 2014 at 2:45
8
$\begingroup$

Another undocumented function (also appeared in the Q/A How to check...):

p = ParametricPlot[{ Sin[u], Sin[2 u]}, {u, 0, 2 Pi}];
Show[p, ListPlot@Pick[#, Graphics`Mesh`InPolygonQ[p[[1, 1, 3, 2, 1]], #] & /@ #] &@data]

enter image description here

$\endgroup$
2
  • $\begingroup$ for getting the points out of the plot, I think Leonid method might be more portable than depending on [[1,1,3,2,1]] indexing as this might change in future versions. As in points = Reap[ParametricPlot[{Sin[u], Sin[2 u]}, {u, 0, 2 Pi}, EvaluationMonitor :> Sow[{Sin[u], Sin[2 u]}]]][[2, 1]]; stackoverflow.com/questions/5364088/… $\endgroup$
    – Nasser
    Jul 9, 2014 at 4:05
  • $\begingroup$ @Nasser, this is specific to OP's example, and too specific to work generally. $\endgroup$
    – kglr
    Jul 9, 2014 at 4:40
7
$\begingroup$

Here is a contour integral way of determining which points lie inside a closed curve. It has the advantage that it can be applied to any parametric closed contour.

Define the curve corresponding to the parametric curve {Sin[u], Sin[2 u]}.

f[u_] := Sin[u] + I Sin[2 u];

Define the derivative of the curve.

df[u_] = D[f[u], u];

Define the contour integral around a pole at x + I y.

inside[x_, y_] := NIntegrate[df[u]/(f[u] - (x + I y)), {u, 0, 2 \[Pi]}] // Chop[#, 10^-6] & // # != 0 & // Quiet;

For this particular parametric curve this will give zero when the pole is outside the contour, and ±2 Pi I when it is inside the contour.

BTW, I tried doing this contour integral with Integrate (rather than NIntegrate) but the ConditionalExpression produced by Integrate was not correct. Is it a bug, or is it just me? I don't know.

Apply the inside function to some data.

data = RandomReal[{-1, 1}, {200, 2}];
datainside = inside @@@ data;

Plot the result.

ParametricPlot[{Sin[u], Sin[2 u]}, {u, 0, 2 Pi},
  Epilog -> MapThread[{If[#2, Red, Blue], Point[#1]} &, {data, datainside}]]

This approach will generalise straightforwardly to more complicated contours.

$\endgroup$

Your Answer

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

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