Print

Print


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