We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpSyntax Questions › particle grouping
Page Index Toggle Pages: 1
particle grouping (Read 761 times)
particle grouping
Jun 15th, 2008, 3:28pm
 
Hi
I need some help to get my head around organizing my particles. The thing i'm trying to do, is find a way to get some particles with dynamic coordinates to group together if they are close together.
The particles are instances of a class, and I can therefore check the x and y position of them all. I want to have an array containing a list of all the particles which are close together so i can start to mess arround with them in the groups.

I feel i'm beginning to go round in circles, so any help would be apreciated.
Re: particle grouping
Reply #1 - Jun 16th, 2008, 9:49pm
 
A good way to identify these groups is through the use of a suitable clustering algorithm.  This is something that computers do not do as easily our brain and eyes do naturally, so specialized algorithms have been developed to get the computer to identify groups from a set of points.  One that I'm somewhat familiar with is called K-means clustering.  The Wikipedia description is fairly technical, but there are several good links at the bottom of the article if you need more details.  A Google search for java k-means clustering will also give you some tutorials and possibly useful sample code.
Re: particle grouping
Reply #2 - Jun 17th, 2008, 2:12am
 
I guess the first stage of this process is to provide an efficient way of checking how close each particle is to the others in order to know if it forms part of a cluster.

This can be done by comparing each particle with all the others and measuring their distance of separation. However, this would be a very inefficient O(n2) process and since your scenario involves dynamically changing particles, this would be impractically slow for more than a few 10s of particles.

Much better would be to use some kind of spatial indexing method that sorts your particles into groups before measuring distances. That way, only a subset of particle pairs need be compared during each iteration. There are many hundreds of spatial indexing methods available, some of which are quite complicated.

A relatively simple and effective one for the task you have would be to create a HashGrid that superimposes a coarse grid over your particles. When measuring distances between particles, only those in the same coarse grid cell need be compared.  An example Processing class to represent a hash grid is given below:

Quote:

// Divides a set of 2d spatial objects into a coarser grid for efficient spatial indexing.
// V1.1 Jo Wood, 17th June, 2008.

class HashGrid
{
 // ------ Object variables ------
 
 int numRows,numCols;
 float maxX,maxY;
 HashMap hm;
 
 // Creates a grid capable of storing items located within (0,0) to (maxX,maxY).
 // numRows and numCols determines the resoluton of the coarse grid.
 HashGrid(float maxX, float maxY, int numCols, int numRows)
 {
   this.maxX = maxX;
   this.maxY = maxY;  
   this.numCols = numCols;
   this.numRows = numRows;
   hm = new HashMap();
 }
 
 // Add an object at the given coorindates to the grid.
 void add(Object obj, float x, float y)
 {
   // Put the same object in the centre and up to 2 of the 4 adjacent grid cells to
   // avoid boundary problems.
   float halfGridX = maxX/(numCols*2);
   float halfGridY = maxY/(numRows*2);
   
   addToGrid(obj,x+halfGridX,y);
   addToGrid(obj,x-halfGridX,y);
   addToGrid(obj,x,y+halfGridY);
   addToGrid(obj,x,y-halfGridY);
 }
 
 // Private version of the add() method that does not add object to neighbouring grid cells.
 private void addToGrid(Object obj, float x, float y)
 {
   if ((x < 0) || (y < 0) || (x>maxX) || (y > maxY))
   {
     // Do nothing when out of bounds.
     return;
   }
   
   int coordHash = getCoordHash(x,y);
   Vector objects = (Vector)hm.get(coordHash);
   if (objects == null)
   {
     // Nothing currently stored in this grid cell.
     objects = new Vector();
   }
   // Update list of objects stored in this grid cell.
   objects.add(obj);
   hm.put(coordHash,objects);
 }
 
 // Returns a list of objects that share the same grid cell as the one
 // in which the given coordinates lie.
 Vector get(float x, float y)
 {
   int coordHash = getCoordHash(x,y);
   return (Vector)hm.get(coordHash);
 }
 
 // Clears out the contents of the grid.
 void clear()
 {
   hm.clear();
 }
 
 // Calculates the hash of the grid cell in which the given coordinates lie.
 private int getCoordHash(float x, float y)
 {
   // Bin coordinates into coarse (col,row) grid.
   int col = round((numCols-1)*x/maxX);
   int row = round((numRows-1)*y/maxY);
   
   // Convert (col,row) coordinate into single unique hash number.
   return row*numCols + col;
 }  
}


You can see an example Processing sketch (with source) to allow 1000 Ants to wander around, turning red when they are close to other ants. There is plenty of scope to further optimise this class, but it should give you a start.
Page Index Toggle Pages: 1