Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I am trying to find first nearest neighbour distributions of randomly dispersed point-like objects in an infinite system. To do this I make a finite sized box unit cell with a chosen concentration of points which are allocated X and Y coordinates, however it is clear that any points along the edge of the box do not see neighbours on the "outside" of the unit cell, skewing their nearest neighbour data.

To avoid this I can repeat the box 8 times around the edges, artificially inducing a boundary condition whereby the top points on the box can "see" the bottom ones. As the system is randomly generated and can be made quite large, this seems to work well.

The only drawback with my method is that it seems to take a long time to run, I would think as 9N*N, as the nearest neighbour search function in mathematica must run through the list of ALL points in the system, that is the X and Y coordinates of all points in the original cell plus the 8 neighbouring cells.

Is it possible to introduce a boundary condition more directly (so without repeating the unit cell box), thereby reducing the computation to N*N?

share|improve this question
    
Your question, as currently posed without any Mathematica code, comes across as a mathematics question, not a Mathematica question. Please reformulate it. –  m_goldberg Oct 14 '13 at 12:19
    
if you replicate the whole point set you need only check 4 cells not 8, think about it. stackoverflow.com with computational-geometry tag would be a good place for this. –  george2079 Oct 14 '13 at 12:40
    
If you preprocess by first creating a NearestFunction, either as @Michael E2 does in a response or using your augmentation by 8 neighbors, then the algorithmmic complexity will be more like 9n*log(n). Check documentation on Nearest, in particular the one argument variant. –  Daniel Lichtblau Oct 14 '13 at 19:31

1 Answer 1

up vote 12 down vote accepted

You can use Mod to create a periodic distance function, with a period of, say, d0 (in each coordinate direction). This approach could be altered to have different periods in different directions. Then Nearest will create a NearestFunction that will return the nearest points modulo the period.

In the animation below, the square on the left shows the points whose coordinates have been mapped mod 10 to {0, 10} square. The square on the right are the raw points with an x, y range of {0, 100}. The gridlines show cells of width 10, which shows where the relative location they are mapped to in the square on the left.

One can see in the animation that the NearestFunction wraps around the boundary.

SeedRandom[1];
pts = RandomReal[100, {200, 2}];
dist[a_, b_, d0_] := Norm @ Mod[a - b, d0, -d0/2];
nf = Nearest[pts, DistanceFunction -> (dist[##, 10.] &)];

Manipulate[
 With[{near = nf[pt0, n]},
  Row[{
    Graphics[{Point@Mod[pts, 10], Red, Point@Mod[near, 10]},
     PlotRange -> {{0, 10}, {0, 10}},
     ImageSize -> 250],
    Spacer[20],
    Graphics[{Point@pts, Red, PointSize[Large], Point@near},
     PlotRange -> {{0, 100}, {0, 100}}, 
     GridLines -> {Range[0, 100, 10], Range[0, 100, 10]}, 
     GridLinesStyle -> Directive[Thin, Darker@LightBlue],
     ImageSize -> 250]
    }]
  ],
 {{pt0, {5, 5}}, {0, 0}, {10, 10}, Locator},
 {{n, 8}, 1, 20, 1}
 ]

Manipulate animation

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.