Hi everybody, for my simulation I needed to look up the neighbors of my ObjectGrid2D in a circular neighborhood. Since ObjectGrid2D has no such function, I wrote it myself. If would like to contribute the code, but since I'm not sure how to do it, I post it here :-( The arguments are similar to the existing neighbor function. I have to pass an ObjectGrid2D, which obviously would not be necessary if the method would belong to ObjectGrid2D itself. I also have an additional argument that controlles if only occupied neighbor positions should be returned or all of them. This is sometime handy if one needs to get all coordinates that belong to a circular area. I did test it for the toroidal case, and hope it also works for the the non-toroidal situation. It would be grate if the code could somehow find its way into the next release. Best regards, Axel /** * Gets all neighbors of a location that satisfy (x-X)^2 + (y-Y)^2 <= dist^2. * This region forms a circle centered at (X,Y) and includes X,Y itself! * If includingEmpty==True, also all positions are collected, otherwise only * those that contain an agent. * Uses a modified version of the Midpoint Circle algoritm * (http://stackoverflow.com/questions/1022178/how-to-make-a-circle-on-a-grid) * to calculate the circle. Places each x and y value of these locations in the * provided IntBags xPos and yPos, clearing the bags first. Then places into * the result Bag the objects at each of those locations, clearning it first. * Returns the result Bag (constructing one if null had been passed in). * null may be passed in for the various bags. * * @param x * @param y * @param dist * @param toroidal * @param result * @param xPos * @param yPos * @param includingEmpty * @param mObj * @return * Last modified 25.06.2012 14:32:07 by Axel */ public final Bag getNeighborsCircularDistance(int x, int y, int dist, boolean toroidal, Bag result, IntBag xPos, IntBag yPos, boolean includingEmpty, ObjectGrid2D mObj) { int i,i2, d, distLocal, xLocal, yPd, yPx, yMd, yMx; int wGrid = mObj.getWidth(); int hGrid = mObj.getHeight(); d = 3 - (2 * dist); xLocal = 0; distLocal = dist; if (result==null) result = new Bag(); else result.clear(); if (xPos==null) xPos = new IntBag(); else xPos.clear(); if (yPos==null) yPos = new IntBag(); else yPos.clear(); do { // Normally the points of the circle boundary are saved here in groups of 8, // but since we want to collect all points inside the circle by saving // the points from left to right for each y value, we need for each y value // only two points (the left most & the right most). The circle algorithm // sometimes generates more than 2 points for each y value to close gaps. // We avoid these gap closing points by collecting the correct points // inside the following if/else clause. // xPx = mObj.stx(x+xLocal); // yPd = mObj.sty(y+distLocal); // xPd = mObj.stx(x+distLocal); // yPx = mObj.sty(y+xLocal); // xMx = mObj.stx(x-xLocal); // yMd = mObj.sty(y-distLocal); // xMd = mObj.stx(x-distLocal); // yMx = mObj.sty(y-xLocal); // xPos.add(xPx); // yPos.add(yPd); // result.add(mObj.get(xPx, yPd)); // xPos.add(xMx); // yPos.add(yPd); // result.add(mObj.get(xMx, yPd)); // xPos.add(xPx); // yPos.add(yMd); // result.add(mObj.get(xPx, yMd)); // xPos.add(xMx); // yPos.add(yMd); // result.add(mObj.get(xMx, yMd)); // xPos.add(xPd); // yPos.add(yPx); // result.add(mObj.get(xPd, yPx)); // xPos.add(xMd); // yPos.add(yPx); // result.add(mObj.get(xMd, yPx)); // xPos.add(xPd); // yPos.add(yMx); // result.add(mObj.get(xPd, yMx)); // xPos.add(xMd); // yPos.add(yMx); // result.add(mObj.get(xMd, yMx)); if (toroidal){ yPd = mObj.sty(y+distLocal); yPx = mObj.sty(y+xLocal); yMd = mObj.sty(y-distLocal); yMx = mObj.sty(y-xLocal); } else { // not toroidal yPd = y+distLocal; yPx = y+xLocal; yMd = y-distLocal; yMx = y-xLocal; } if (d < 0) { d = d + (4 * xLocal) + 6; // Add neighbours at yPx & yMx for (i=x-distLocal; i<=x+distLocal; i++){ i2 = i; if (toroidal){ i2 = (i+wGrid)%wGrid; } else { if (i<0 || i>=wGrid || yPx>=hGrid || yMx<=0) continue; } if (includingEmpty || mObj.get(i2, yPx)!=null){ xPos.add(i2); yPos.add(yPx); result.add(mObj.get(i2, yPx)); } if (includingEmpty || mObj.get(i2, yMx)!=null){ xPos.add(i2); yPos.add(yMx); result.add(mObj.get(i2, yMx)); } } // for } else { // Add neighbours at yPd & yMd for (i=x-xLocal; i<=x+xLocal; i++){ i2 = i; if (toroidal){ i2 = (i+wGrid)%wGrid; } else { if (i<0 || i>=wGrid || yPd>=hGrid || yMd<=0) continue; } if (includingEmpty || mObj.get(i2, yPd)!=null){ xPos.add(i2); yPos.add(yPd); result.add(mObj.get(i2, yPd)); } if (includingEmpty || mObj.get(i2, yMd)!=null){ xPos.add(i2); yPos.add(yMd); result.add(mObj.get(i2, yMd)); } } // for // Add neighbours at yPx & yMx for (i=x-distLocal; i<=x+distLocal; i++){ i2 = i; if (toroidal){ i2 = (i+wGrid)%wGrid; } else { if (i<0 || i>=wGrid || yPx>=hGrid || yMx<=0) continue; } if (includingEmpty || mObj.get(i2, yPx)!=null){ xPos.add(i2); yPos.add(yPx); result.add(mObj.get(i2, yPx)); } if (includingEmpty || mObj.get(i2, yMx)!=null){ xPos.add(i2); yPos.add(yMx); result.add(mObj.get(i2, yMx)); } } // for d = d + 4 * (xLocal - distLocal) + 10; distLocal--; } xLocal++; } while (xLocal <= distLocal); return result; } // getNeighborsCircularDistance