Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

enter image description here

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

like image 512
500 Avatar asked Aug 26 '11 11:08

500


2 Answers

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}}
like image 69
Leonid Shifrin Avatar answered Sep 24 '22 00:09

Leonid Shifrin


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

like image 31
Daniel Lichtblau Avatar answered Sep 21 '22 00:09

Daniel Lichtblau