|
|
- /*
- * Copyright (C) 2017 Christopher J. Howard
- *
- * This file is part of Antkeeper Source Code.
- *
- * Antkeeper Source Code 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.
- *
- * Antkeeper Source Code 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 Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
- */
-
- #include "pheromone-matrix.hpp"
- #include "../configuration.hpp"
- #include <algorithm>
- #include <cmath>
-
- PheromoneMatrix::PheromoneMatrix(int columns, int rows, const Vector2& boundsMin, const Vector2& boundsMax)
- {
- this->columns = columns;
- this->rows = rows;
- size = columns * rows;
- bufferA = new float[size];
- bufferB = new float[size];
- activeBuffer = bufferA;
- this->boundsMin = boundsMin;
- this->boundsMax = boundsMax;
- matrixWidth = boundsMax.x - boundsMin.x;
- matrixHeight = boundsMax.y - boundsMin.y;
- matrixHalfWidth = matrixWidth * 0.5f;
- matrixHalfHeight = matrixHeight * 0.5f;
- cellWidth = matrixWidth / static_cast<float>(columns);
- cellHeight = matrixHeight / static_cast<float>(rows);
-
- diffusionKernelSize = 3;
- diffusionKernelRadius = 1;
- diffusionKernel = new float*[diffusionKernelSize];
- for (int i = 0; i < diffusionKernelSize; ++i)
- {
- diffusionKernel[i] = new float[diffusionKernelSize];
- }
-
- diffusionKernel[0][0] = 0.0083333f; diffusionKernel[0][1] = 0.0166667f; diffusionKernel[0][2] = 0.0083333f;
-
- diffusionKernel[1][0] = 0.0166667f; diffusionKernel[1][1] = 0.9f; diffusionKernel[1][2] = 0.0166667f;
-
- diffusionKernel[2][0] = 0.0083333f; diffusionKernel[2][1] = 0.0166667f; diffusionKernel[2][2] = 0.0083333f;
-
- clear();
- }
-
- PheromoneMatrix::~PheromoneMatrix()
- {
- delete[] bufferA;
- delete[] bufferB;
-
- for (int i = 0; i < diffusionKernelSize; ++i)
- {
- delete[] diffusionKernel[i];
- }
- delete[] diffusionKernel;
- }
-
- void PheromoneMatrix::clear()
- {
- for (int i = 0; i < size; ++i)
- {
- activeBuffer[i] = 0.0f;
- }
- }
-
- void PheromoneMatrix::evaporate()
- {
- for (int i = 0; i < size; ++i)
- {
- activeBuffer[i] *= EVAPORATION_FACTOR;
- }
- }
-
- void PheromoneMatrix::diffuse()
- {
- float* diffusionBuffer = (activeBuffer == bufferA) ? bufferB : bufferA;
-
- int index = 0;
- for (int i = 0; i < rows; ++i)
- {
- for (int j = 0; j < columns; ++j)
- {
- float concentration = 0.0f;
-
- for (int k = -diffusionKernelRadius; k <= diffusionKernelRadius; ++k)
- {
- int row = std::max<int>(0, std::min<int>(rows - 1, i + k));
-
- for (int l = -diffusionKernelRadius; l <= diffusionKernelRadius; ++l)
- {
- int column = std::max<int>(0, std::min<int>(columns - 1, j + l));
- concentration += activeBuffer[row * columns + column] * diffusionKernel[k + diffusionKernelRadius][l + diffusionKernelRadius];
- }
- }
-
- diffusionBuffer[index++] = concentration;
- }
- }
-
- activeBuffer = diffusionBuffer;
- }
-
- float PheromoneMatrix::query(const Vector2& position) const
- {
- int column = static_cast<int>((matrixHalfWidth + position.x) / cellWidth);
- int row = static_cast<int>((matrixHalfHeight + position.y) / cellHeight);
-
- if (columns < 0 || column >= columns || row < 0 || row >= rows)
- {
- return 0.0f;
- }
-
- int index = row * columns + column;
- return activeBuffer[index];
- }
-
- float PheromoneMatrix::query(const Vector2& position, float radius) const
- {
- float radiusSquared = radius * radius;
- float concentration = 0.0f;
-
- for (float y = position.y - radius; y <= position.y + radius; y += cellHeight)
- {
- int row = static_cast<int>((matrixHalfHeight + y) / cellHeight);
- if (row < 0)
- continue;
- else if (row >= rows)
- break;
-
- float dy = y - position.y;
-
- for (float x = position.x - radius; x <= position.x + radius; x += cellWidth)
- {
- int column = floor((matrixHalfWidth + x) / cellWidth);
- if (column < 0)
- continue;
- else if (column >= columns)
- break;
-
- float dx = x - position.x;
-
- float distanceSquared = dx * dx + dy * dy;
- if (distanceSquared <= radiusSquared)
- {
- concentration += activeBuffer[row * columns + column];
- }
- }
- }
-
- return concentration;
- }
-
- void PheromoneMatrix::deposit(const Vector2& position, float concentration)
- {
- int column = static_cast<int>((matrixHalfWidth + position.x) / cellWidth);
- int row = static_cast<int>((matrixHalfHeight + position.y) / cellHeight);
-
- if (columns < 0 || column >= columns || row < 0 || row >= rows)
- {
- return;
- }
-
- int index = row * columns + column;
- activeBuffer[index] += concentration;
- }
|