# How to find all data points within closed curve

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.

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_] := GraphicsMeshPointWindingNumber[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]}]


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]]]}]


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

• @Mr.Wizard Strange that we both waited exactly 48 minutes before answering and then did so simultaneously! – Jens Jul 9 '14 at 2:31

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}]


• @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. – Mr.Wizard Jul 9 '14 at 2:33
• 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... – Jens Jul 9 '14 at 2:35
• @Jens In that case you might as well use ListLinePlot on pp. – Mr.Wizard Jul 9 '14 at 2:38
• But that would have cost me precious extra seconds... – Jens Jul 9 '14 at 2:45

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[#, GraphicsMeshInPolygonQ[p[[1, 1, 3, 2, 1]], #] & /@ #] &@data]


• 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/… – Nasser Jul 9 '14 at 4:05
• @Nasser, this is specific to OP's example, and too specific to work generally. – kglr Jul 9 '14 at 4:40

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.