Select points within a circular area in Mathematica
Please consider :
dalist = {{9, 6}, {5, 6}, {6, 0}, {0, 5}, {10, 8}, {1, 2}, {10, 4}, {1, 1}, {7, 7},
{6, 8}, {5, 3}, {6, 10}, {7, 4}, {1, 8}, {10, 0}, {10, 7}, {6, 3}, {4, 0},
{9, 2}, {4, 开发者_运维百科7}, {1, 6}, {10, 8}, {7, 8}, {0, 10}, {3, 4}, {0, 0}, {8, 5},
{4, 5}, {6,0}, {2, 9}, {2, 4}, {8, 4}, {7, 4}, {3, 6}, {7, 10}, {1, 10},
{1, 4}, {8, 0}, {8, 9}, {5, 4}, {2, 5}, {2, 9}, {3, 1}, {0, 6}, {10, 3},
{9, 6}, {8, 7}, {7, 6}, {7, 3}, {8, 9}};
frameCenter = {5, 5};
criticalRadius = 2;
Graphics[{
White, EdgeForm[Thick], Rectangle[{0, 0}, {10, 10}], Black,
Point /@ dalist,
Circle[frameCenter, 2]}];
I would like to create a test to go over dalist and reject the points that are located within or on a certain radius from the frameCenter as illustrated above. I have done that in the past with a rectangular zone but am puzzled on how to do so with a circular area
This will be pretty efficient:
In[82]:=
Pick[dalist,UnitStep[criticalRadius^2-Total[(Transpose[dalist]-frameCenter)^2]],0]
Out[82]=
{{6,0},{10,8},{10,4},{1,1},{6,10},{10,0},{10,7},{4,0},{10,8},
{0,10},{0,0},{6,0},{7,10},{1,10},{8,0},{0,6},{10,3}}
Alternatively,
In[86]:= Select[dalist, EuclideanDistance[#, frameCenter] > criticalRadius &]
Out[86]= {{6, 0}, {10, 8}, {10, 4}, {1, 1}, {6, 10}, {10, 0}, {10, 7}, {4, 0},
{10, 8}, {0, 10}, {0, 0}, {6, 0}, {7, 10}, {1, 10}, {8, 0}, {0, 6}, {10, 3}}
Nearest can be useful for such purposes as finding every set member in some radius of a given point. One uses the less-than-well-documented form of third argument that allows a pair denoting {max number, max distance}. We allow in this case as many as will fit inside the max radius, so the max number is just set to infinity.
In[9]:= DeleteCases[dalist,
Alternatives @@
Nearest[dalist, frameCenter, {Infinity, criticalRadius}]]
Out[9]= {{9, 6}, {6, 0}, {0, 5}, {10, 8}, {1, 2}, {10, 4}, {1, 1}, {7,
7}, {6, 8}, {6, 10}, {7, 4}, {1, 8}, {10, 0}, {10, 7}, {6, 3}, {4,
0}, {9, 2}, {4, 7}, {1, 6}, {10, 8}, {7, 8}, {0, 10}, {3, 4}, {0,
0}, {8, 5}, {6, 0}, {2, 9}, {2, 4}, {8, 4}, {7, 4}, {3, 6}, {7,
10}, {1, 10}, {1, 4}, {8, 0}, {8, 9}, {2, 5}, {2, 9}, {3, 1}, {0,
6}, {10, 3}, {9, 6}, {8, 7}, {7, 6}, {7, 3}, {8, 9}}
--- edit ---
Regarding the complexity of DeleteCases with pattern-free Alternatives, if the input size is n and the set of alternatives has m elements, then it is O(n+m) rather than O(n*m). This as of version 8 of Mathematica.
The examples below will bear out this claim. We start with 10^5 elements and delete around 18000 of them. Takes .17 seconds. We then use 10x as many elements, and remove more than 10x as many (so n and m both go up by a factor of 10 or more). Total time is 1.6 seconds, or a factor of around 10 bigger.
In[90]:= dalist5 = RandomInteger[{-10, 10}, {10^5, 2}];
criticalRadius5 = 5;
Timing[rest5 =
DeleteCases[dalist5,
Alternatives @@ (closest5 =
Nearest[dalist5, {0, 0}, {Infinity, criticalRadius5}])];]
Length[closest5]
Out[92]= {0.17, Null}
Out[93]= 18443
In[94]:= dalist6 = RandomInteger[{-10, 10}, {10^6, 2}];
criticalRadius6 = 6;
Timing[rest6 =
DeleteCases[dalist6,
Alternatives @@ (closest6 =
Nearest[dalist6, {0, 0}, {Infinity, criticalRadius6}])];]
Length[closest6]
Out[96]= {1.61, Null}
Out[97]= 256465
-- end edit ---
Daniel Lichtlau
Easy - Just use the center of the circle. From that (using Pythagoras theorem) calculate the distance from that centre. Compare that to the radius. Is less than or equal to the radius then it is inside the circle. Otherwise outside.
精彩评论