/******************************************************************************* * TurtleKit 3 - Agent Based and Artificial Life Simulation Platform * Copyright (C) 2011-2014 Fabien Michel * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package turtlekit.pheromone; import java.nio.FloatBuffer; public class CPU_SobelPheromone extends DefaultCPUPheromoneGrid { final float[] values; final double[] sobelGradientValues; final float[] tmp; final private int[] neighborsIndexes; public CPU_SobelPheromone(String name, int width, int height, int evaporationPercentage, int diffusionPercentage, int[] neighborsIndexes2) { this(name, width, height, evaporationPercentage / 100f, diffusionPercentage / 100f, neighborsIndexes2); } public CPU_SobelPheromone(String name, int width, int height, float evaporationPercentage, float diffusionPercentage, int[] neighborsIndexes2) { super(name, width, height, evaporationPercentage, diffusionPercentage, neighborsIndexes2); values = new float[width*height]; sobelGradientValues = new double[width*height]; tmp = new float[width*height]; neighborsIndexes = neighborsIndexes2; } /* (non-Javadoc) * @see pheromone.Pheromone#getValue(int) */ @Override public float get(int index) { return values[index]; } public FloatBuffer getValuesFloatBuffer(){ return FloatBuffer.allocate(getWidth()*getHeight()).put(values); } @Override public void set(int index, float value) { values[index] = value; if(value > getMaximum()) setMaximum(value); } private void diffusionUpdate(){ for (int i=getWidth()-1; i >=0 ; i--) for (int j=getHeight()-1; j >=0 ; j--){ values[get1DIndex(i,j)] += getTotalUpdateFromNeighbors(i, j); } } private void diffusionUpdateThenEvaporation(){ float evapCoef = getEvaporationCoefficient(); for (int i=getWidth()-1; i >=0 ; i--) for (int j=getHeight()-1; j >=0 ; j--){ int k = get1DIndex(i,j); values[k] += getTotalUpdateFromNeighbors(i, j); values[k] -= values[k] * evapCoef; computeSobel(i, j); } } // float getTotalUpdateFromNeighbors(int i, int j){ // return // tmp[get1DIndex(i, normeValue(j-1,height))] + // tmp[get1DIndex(i, normeValue(j+1,height))] + // tmp[get1DIndex(normeValue(i-1,width), normeValue(j-1,height))] + // tmp[get1DIndex(normeValue(i-1,width), j)] + // tmp[get1DIndex(normeValue(i-1,width), normeValue(j+1,height))] + // tmp[get1DIndex(normeValue(i+1,width), normeValue(j-1,height))] + // tmp[get1DIndex(normeValue(i+1,width), j)] + // tmp[get1DIndex(normeValue(i+1,width), normeValue(j+1,height))]; // } float getTotalUpdateFromNeighbors(int i, int j){ int index = get1DIndex(i, j)*8; return tmp[neighborsIndexes[index]] + tmp[neighborsIndexes[++index]] + tmp[neighborsIndexes[++index]] + tmp[neighborsIndexes[++index]] + tmp[neighborsIndexes[++index]] + tmp[neighborsIndexes[++index]] + tmp[neighborsIndexes[++index]] + tmp[neighborsIndexes[++index]]; } private void computeSobel(int x, int y){ float eValue = get(normeValue(x + 1, getWidth()), y); float neValue = get(normeValue(x + 1, getWidth()), normeValue(y + 1, height)); float nValue = get(x, normeValue(y + 1, getHeight())); float nwValue = get(normeValue(x - 1, getWidth()), normeValue(y - 1, height)); float wValue = get(normeValue(x - 1, getWidth()), y); float swValue = get(normeValue(x - 1, getWidth()), normeValue(y - 1, height)); float sValue = get(x, normeValue(y - 1, getHeight())); float seValue = get(normeValue(x + 1, getWidth()), normeValue(y - 1, height)); sobelGradientValues[get1DIndex(x, y)] = Math.toDegrees(Math.atan2( nwValue + 2 * nValue + neValue - seValue - 2 * sValue - swValue, //filter Y neValue + 2 * eValue + seValue - swValue - 2 * wValue - nwValue //filter X )); } @Override public int getMaxDirection(int xcor, int ycor) { return (int) sobelGradientValues[get1DIndex(xcor, ycor)]; } @Override public int getMinDirection(int i, int j) { return (int) sobelGradientValues[get1DIndex(i, j)] + 180; } int normeValue(int x, int width){ if(x < 0) //-1 return width - 1; if(x == width) return 0; return x; } @Override public void diffusion() { diffuseValues(); diffusionUpdate(); // if (env.wrap) { // for (int i=getWidth()-1; i >=0 ; i--) // for (int j=getHeight()-1; j >=0 ; j--){ // final int index = getIndex(i, j); // tmp[index] = (values[index] * diffCoef) / 8; // } // for (int i=getWidth()-1; i >=0 ; i--) // for (int j=getHeight()-1; j >=0 ; j--){ // } // } // } else // for (int i=env.x-1; i >=0 ; i--) // for (int j=env.y-1; j >=0 ; j--){ // env.grid[i][j].diffusion=gridValues[i][j]*(diffCoef/env.grid[i][j].neighbors.length); // gridValues[i][j]-=gridValues[i][j]*diffCoef; // } // for (int i=env.x-1; i >=0 ; i--) // for (int j=env.y-1; j >=0 ; j--){ // final Patch[] p=env.grid[i][j].neighbors; // for (int a=p.length-1;a>=0;a--) // gridValues[i][j]+=p[a].diffusion; // } // } } private void diffuseValues() { float diffCoef = getDiffusionCoefficient(); for (int i = values.length - 1; i >= 0 ; i--) { float give = values[i] * diffCoef; float giveToNeighbor = give / 8; values[i] -= give;//TODO a[k] = value - give tmp[i] = giveToNeighbor; } } public int[] getNeighborsIndexes() { return neighborsIndexes; } }