In individually based modeling, "find nearest" problems often arise. For
example, if your model simulates predators and prey moving about in a 2D space,
you will want to iterate over the prey objects and for each one, find the
nearest predator, or all predators within a certain distance. The simple
solution to the "find nearest" problem (iterate through all other objects
calculating distance to each one) runs in linear time. Finding the nearest 
object to each object would then run in n-squared time. In practical
simulations this searching time can dominate the running time of the entire
simulation. Therefore we were motivated to solve write general solutions that
run faster than the obvious, simple solution. 

SearchableSpace is an object class that efficiently solves the "find nearest"
and "find all within an area" problems for objects populating a 2D space.
A SearchableSpace is a rectangle aligned with the X and Y axes. It contains
a collection of objects, each of which has a defined position. The objects
need not all be of the same type but they must all respond to the same set 
of messages. Once objects have been inserted into a SearchableSpace, the 
nearest object to a given point may be found, or an iteration over all 
of the objects within a given rectangle may be performed. These operations 
will run in constant time in the best case (running time will not depend on 
the number of objects) or in logarithmic time in the "realistic" worst case. 
It is theoretically possible for the searches to run in linear time in 
pathological cases (all objects at the same x,y location, for example).

A SearchableSpace object uses one of two possible internal data structures - 
a grid or a binary space partitioning tree. The choice of which data structure 
to use must be made during initialization and is irrevocable. The grid 
structure is preferred when the objects are relatively evenly spread, and 
when a grid cell size can be chosen such that most grid cells contain at 
least one object but not more than a few. The binary space partitioning tree 
is preferred when the objects tend to be distributed in clumps or when a 
suitable grid size cannot be selected without causing page thrashing. An 
intelligent choice between these two options will depend on understanding 
the individual modeling situation. It is advisable to try both options on a 
test model and compare performance.

The objects stored in a SearchableSpace must support an intrusive list - in 
other words, the objects must implement an internal storage location for use 
by the SearchableSpace algorithms. This is done to increase execution time 
efficiency. As a side effect, objects can be stored in only one SearchableSpace 
at a time and only one iteration over the objects in a SearchableSpace can be 
supported at a time.

Once an object has been inserted into a SearchableSpace, the object must not 
move. In other words, the object's responses to getIntX:, getIntY:, 
getDoubleX:, and getDoubleY: must be constant. If one or more of the objects 
in a space move, then they must all be removed and reinserted. Removal and 
reinsertion is an efficient operation, especially when clearAndPutObjects: 
is used.

To use these objects you must import SearchableSpace.h into your source 
files and add the following list of files to your project:

SearchableSpace.h and .m
SearchableObject.h
SearchableGridSpace.h and .m
SearchableTreeNode.h and .m
globals.h

The submitted software also includes ExampleObject.h & .m, main.m, and 
Makefile, which implement a very simple example program to demonstrate use 
of the SearchableSpace object.


The SearchableSpace object has the following interface:

/* Messages for initialization (sent once only). */
+ createBegin: aZone;
- setUseTree: (BOOL) bUse;
- setAllowDups: (BOOL) bAllow;
- setIntCoords: (BOOL) bInt;
- setMinX: (double) minx maxX: (double) maxx
     minY: (double) miny maxY: (double) maxy;
- setGridSpacing: (double) spacing;
- createEnd;

/* Messages to populate or depopulate the space (may be sent many times). 
   When the space is depopulated the objects that were added by putObjects: 
   (etc) are not harmed. */
- putObjects: (id <List>) aList; /* add a bunch of objects to space. */
- clear;                         /* clear all pointers in space. */
- clearAndPutObjects: (id <List>) aList; /* both of above. */
- clearAndFree;  /* clear all pointers and free dynamic objects (tree nodes) */
- clearFreeAndPutObjects: (id <List>) aList; /* all of above. */

/* Destroy the SearchableSpace object and any internal allocations. 
   Does not destroy the objects that were added to the SearchableSpace by 
   putObjects: etc */
- (void) drop;

/* Messages to find the nearest object to a given point. Allowed "comparison"
   values are ALL, EQ, NEQ, GT, GE, LT, LE. If GT is used, then objects are 
   returned for which ([obj getVal] > compareValue) is true. */
- getNearestObjectToX: (double) x Y: (double) y;
- getNearestObjectToX: (double) x Y: (double) y WithValue: (int) comparison
                                                To: (double) compareValue;

/* Messages used to iterate through all objects in a bounding box.
"iterate..." sets up the process. "next" gets each object in turn until
they run out, after which it returns nil.
Only one iteration can be supported by a given SearchableSpace object
at a given time. */
- iterateMinX: (double) mnX maxX: (double) mxX
         minY: (double) mnY maxY: (double) mxY;
- next;

The objects stored in a SearchableSpace must respond to these messages:

/* Return the x,y position of the object (will only be called if the 
   SearchableSpace is set to use integer coordinates). */
- (int) getIntX;
- (int) getIntY;
/* Return the x,y position of the object (will only be called if the 
   SearchableSpace is set to use double coordinates). */
- (double) getDoubleX;
- (double) getDoubleY;
/* Set or get the next object in the list of objects at a given point or 
   in a given grid cell (will only be called if the grid option is used or 
   if the allow duplicates option is used. The object must also maintain a 
   member variable for the id passed to setNext: */
- setNext: anObject;
- getNext;
/* Returns a number that can be used to classify objects. Will only be called 
   if the comparison versions of the searching routines are called. */
- (double) getVal;


