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.
Mathematica Stack Exchange is a question and answer site for users of Wolfram Mathematica. It only takes a minute to sign up.
Sign up to join this communityI 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_] := 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]}]
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.
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}]
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$
Jul 9, 2014 at 2:33
ListLinePlot
on pp
.
$\endgroup$
Jul 9, 2014 at 2:38
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]
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$
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.