-1

Let's create a rather dense grid of initial conditions

xlim = 4;
ds = 0.05;
data = Flatten[Table[{i, j}, {i, -xlim, xlim, ds}, {j, -xlim, xlim, ds}], 1];
nic = Length[data]
L0 = ListPlot[data, PlotStyle -> {Blue, PointSize[0.001]}];

Then we define a closed two-dimensional curve

C0 = ContourPlot[x^2/4 + y^2/9 == 1, {x, -5, 5}, {y, -5, 5}, 
     PlotPoints -> 100, ContourStyle -> {Black, Thick}];
d0 = C0[[1, 1]];
S0 = ListPlot[d0, PlotStyle -> {Black, Thick}, Joined -> True];

Here I would like to clarify that in my real case scenario we do not know the analytical expression of the closed curve. We only have a list of points such as d0.

P0 = Show[{L0, S0}, AspectRatio -> 1]

enter image description here

Now I would like to create a new list data2 which will contain all the points of the initial data that are inside the closed curve.

I am using version 9.0 in 32bit Win XP.

Any suggestions?

NOTE: This question point-in a polygon test looks very similar. However in my case performance over a large number of points is important.

Vaggelis_Z
  • 8,740
  • 6
  • 34
  • 79

2 Answers2

4

First you produce your data

xlim = 4;
ds = 0.25;
data = Flatten[Table[{i, j}, {i, -xlim, xlim, ds}, {j, -xlim, xlim, ds}], 1];
nic = Length[data]

Then you make your contour from arbitrary points and get the polygon out of it

pts = RandomReal[{2, 3}] {Cos[#], Sin[#]} & /@ Range[0, 2 Pi, Pi/20];
contour = ListLinePlot[pts, AspectRatio -> 1,  
                       PlotRange -> {{-xlim, xlim}, {-xlim, xlim}}]
poly = Cases[Normal@contour, Line[x_] :> x, Infinity];

enter image description here

Actually here poly is pts. This method comes handy if you want to get the points from an analytical expression. In worst case if your data is not ordered, use

poly = Sort[pts, ArcTan @@ #1 > ArcTan @@ #2 &];

And then use RegionMember to find the points.

data2 = Select[data, RegionMember[Polygon[poly], #] &];

ListPlot[{data, data2}, 
PlotStyle -> {PointSize[Medium], PointSize[Large]}, AspectRatio -> 1]

enter image description here

For Mathematica9

For MMA9 you have to use Graphics`Mesh`PointWindingNumber which I first found here. In that case,

inPolyQ[poly_, pt_] := Graphics`Mesh`PointWindingNumber[poly, pt] =!= 0
data2 = Select[data, inPolyQ[poly, #] &];

ListPlot[{data, data2}, 
 PlotStyle -> {PointSize[Medium], PointSize[Large]}, AspectRatio -> 1]

enter image description here

For details you can check my answer to Is there a simple strategy to determine whether a point is inside a boundary?

Sumit
  • 15,912
  • 2
  • 31
  • 73
  • This works only when the curve has a known analytical expression. In my real case, the curve is given only as a set of points. – Vaggelis_Z Jun 19 '16 at 09:34
  • Just make a close contour anyway. Hold on I am going to give an example with arbitrary point. – Sumit Jun 19 '16 at 09:36
  • RegionMember is introduced in V10, may need to replace it to run on OP's computer – vapor Jun 19 '16 at 09:50
  • @happyfish Sorry, I noticed that. Unfortunately now I don't have M9 in my hand, so I just describe the method for M9 without an example. – Sumit Jun 19 '16 at 10:01
  • In v9 when I evaluate data2 = Select[data, inPolyQ[poly, #] &]; I get exactly the same points as in data. – Vaggelis_Z Jun 19 '16 at 10:14
  • @Vaggelis_Z, My bad, it would be Graphics`Mesh`PointWindingNumber. I modified my answer. Let me know if it works. – Sumit Jun 19 '16 at 11:23
  • Now I get the following error message: GraphicsMeshPointWindingNumber::invpoly: -- Message text not found -- (GraphicsMeshPointWindingNumber[{{{2.88617,0.},{2.8451,0.45062},{2.42173,0.786868},<<35>>,{2.20662,-0.716976},{2.50074,-0.396078},{2.99428,0.}}},{-4.,-4.}]) – Vaggelis_Z Jun 19 '16 at 11:40
  • Check if your poly is a {n,2} array (Dimensions[poly]). Looks like there is an extra {}. In that case just use poly[[1]] in inPolyQ. – Sumit Jun 19 '16 at 12:11
  • Many thanks! Your solution in v9 works fine. I borrowed a newer laptop with v10 installed and your second solution also works like a charm! – Vaggelis_Z Jun 19 '16 at 14:58
2

In this case, at least, what you seek can be achieved by evaluating the function defining the contour at each of your test points

data1 = Select[data, Function[{xy}, xy[[1]]^2/4 + xy[[2]]^2/9 < 1]];
L1 = ListPlot[data1, PlotStyle -> {Blue, PointSize[0.001]}];
P1 = Show[{L1, S0}, AspectRatio -> Automatic]

enter image description here

mikado
  • 16,741
  • 2
  • 20
  • 54
  • No, this is not what I want. This is just a simple example. In my real case the analytical expression of the closed curve is unknown. I have only a set of $(x_0,y_0)$ points which define a closed curve. – Vaggelis_Z Jun 19 '16 at 10:39