开发者

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

Select points within a circular area in Mathematica

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜