The easy was is to make boxes and only look in the boxes that are near the unit you are testing. Here is some code that does that. It is for stars that don't move so you will need to optimize for moving objects but it does give you the idea.
Also the question who is closer is different from how far is B1 from B2 Distance = square root (B1-B2) But who is closer can be found by b1-b2 import random import math import time from time import time def gamma(n): if n < 1: return 0 if n == 1: return 1 if n == 1.5: return math.sqrt(math.pi) / 2 return (n-1) * gamma(n-1) def sphere_multiplier(n): return math.pow(math.pi, n/2.0) / gamma(n/2.0 + 1) class Star: "Object representing a star" def __init__(self): self.coords = [] for i in range(dimensions): self.coords.append(random.uniform(0, universe_size)) def wrap_diff(self, c1, c2): return min(abs(c1 - c2), universe_size - abs(c1 - c2)) def get_distance(self, coords): return math.sqrt(sum([ math.pow(self.wrap_diff(x, y), 2) for x,y in zip(self.coords, coords)])) class Grid: "A spatial grid to make it faster to find nearby objects" def __init__(self, step): self.step = step self.cells = {} def make_key(self, coords): return tuple([math.floor(x / self.step) for x in coords]) def add(self, obj): key = self.make_key(obj.coords) if self.cells.has_key(key): self.cells[key].append(obj) else: self.cells[key] = [obj] def remove(self, obj): key = self.make_key(obj.coords) self.cells[key].remove(obj) if len(self.cells[key]) == 0: del self.cells[key] def _print(self): for key in self.cells.keys(): print "Cell", [ x * self.step for x in key ] for obj in self.cells[key]: print " ", obj.coords def is_empty(self): return len(self.cells) == 0 def pop(self): for key in self.cells.iterkeys(): cell = self.cells[key] break obj = cell[0] self.remove(obj) return obj def get_near(self, centre): keys = [ self.make_key(centre) ] for i in xrange(0,dimensions): new_keys = keys[:] for key in keys: new_key = list(key) new_key[i] = key[i] - 1; new_keys.append(tuple(new_key)) new_key = list(key) new_key[i] = key[i] + 1; new_keys.append(tuple(new_key)) keys = new_keys neighbours = [] for key in keys: if not self.cells.has_key(key): continue neighbours += self.cells[key] neighbours = [ star for star in neighbours if star.get_distance(centre) <= self.step ] return neighbours def pop_near(self, centre): neighbours = self.get_near(centre) for star in neighbours: self.remove(star) return neighbours t1=time() random.seed(3245) #density, universe_size, dimensions = 0.33, 250, 2 density, universe_size, dimensions = 0.02, 80, 3 #density, universe_size, dimensions = 0.025, 30, 4 jump = 2 dist = jump + 0.5 # Make comparable to hex grids, which allow jumps from center to outer edge print "Average stars within range", sphere_multiplier(dimensions) * math.pow(dist, dimensions) * density # Find the actual number of stars (Poisson distribution) num_stars = 0 vol_remaining = pow(universe_size, dimensions) star_vol = random.expovariate(density) # Each item has exponential distribution while vol_remaining >= star_vol: num_stars += 1 vol_remaining -= star_vol star_vol = random.expovariate(density) # Generate random star positions stars = [] for i in xrange(num_stars): stars.append(Star()) print "Generated", num_stars, "stars in universe size", universe_size, "dimension", dimensions # Make a grid to ease searching for nearest stars grid = Grid(dist) for star in stars: grid.add(star) # Build up groups of stars reachable from each other by repeated jumps groups = [] while not grid.is_empty(): seed = grid.pop() # Find stars reachable from the seed, removing them from the grid interior_stars = set() border_stars = set([seed]) while len(border_stars) > 0: origin = border_stars.pop() interior_stars.add(origin) border_stars |= set(grid.pop_near(origin.coords)) groups.append(interior_stars) print "Found", len(groups), "groups of stars connected by jump", jump reachability = sum([ len(group) * (len(group) - 1.0) for group in groups ]) print "Average reachability was", reachability / (num_stars * (num_stars - 1)) print "Largest group had", max([len(group) for group in groups]), "stars" print "Run time:",time()-t1 On 1/21/09, Patrick Mullen <saluk64...@gmail.com> wrote: > On Tue, Jan 20, 2009 at 10:21 PM, René Dudfield <ren...@gmail.com> wrote: >> I forgot to mention this quadtree code too: >> http://www.pygame.org/wiki/QuadTree >> >> >> cu, >> >> >> On Wed, Jan 21, 2009 at 5:06 PM, René Dudfield <ren...@gmail.com> wrote: >>> hi, >>> >>> you'll want to use a spacial hash. >>> >>> Like this quadtree for example: >>> http://www.pygame.org/project/752/ >>> >>> cu! >>> > > > Those suggestions are good. Also, even in the original case, you > probably don't need a squareroot at all. You can use the manhattan > distance instead for relative distances. But even that will not scale > well enough if your collection gets big enough. The real problem is > comparing everything to everything else, which some kind of > partitioning will help you avoid. > -- Douglas E Knapp Amazon Gift Cards; let them choose!! http://www.amazon.com/gp/product/B001078FFE?ie=UTF8&tag=seattlebujinkand&linkCode=as2&camp=1789&creative=9325&creativeASIN=B001078FFE