I have a 2D Environment where I want to get for some cells the Moore neighborhood (east, west, north and east cells). Sometimes a cell can only have 3 or 2 neighbors (if we check from a border or a corner of the grid).
Above this, I'd like to differentiate the case where there is no border (torus world, what goes up reappears down...). In such case, every cells have exactly 4 neighbors.
Hence I made 2 versions of this algorithm, one using a std::vector of coordinates, and another one using std::array of optional coordinates (I refer to coordinates as pair of short ints). See below :
version with a vector of pairs
std::vector<std::pair<uint16_t, uint16_t>>* Environment::getMooreNeighborhood(uint16_t x, uint16_t y) const{
std::vector<std::pair<uint16_t, uint16_t>>* neighborhood = new std::vector<std::pair<uint16_t, uint16_t>>();
std::pair<uint16_t, uint16_t> west_cell(x - 1, y);
std::pair<uint16_t, uint16_t> east_cell(x + 1, y);
std::pair<uint16_t, uint16_t> north_cell(x, y - 1);
std::pair<uint16_t, uint16_t> south_cell(x, y + 1);
if(this->torus){
if(x == this->width - 1){
east_cell.first = 0;
}
else if(x == 0){
west_cell.first = this->width - 1;
}
if(y == 0){
north_cell.second = this->height - 1;
}
else if(y == this->height - 1){
south_cell.second = 0;
}
neighborhood->push_back(east_cell);
neighborhood->push_back(west_cell);
neighborhood->push_back(south_cell);
neighborhood->push_back(north_cell);
}else{
if(x > 0){
neighborhood->push_back(east_cell);
}
if(x < this->width - 1){
neighborhood->push_back(west_cell);
}
if(y > 0){
neighborhood->push_back(north_cell);
}
if(y < this->height - 1){
neighborhood->push_back(south_cell);
}
}
return neighborhood;
}
version with an array of optional pairs
std::array<std::optional<std::pair<uint16_t,uint16_t>>, 4> Environment::getMooreNeighborhood(uint16_t x, uint16_t y) const {
std::array<std::optional<std::pair<uint16_t,uint16_t>>, 4> neighborhood;
std::optional<std::pair<uint16_t, uint16_t>> west_cell;
std::optional<std::pair<uint16_t, uint16_t>> east_cell;
std::optional<std::pair<uint16_t, uint16_t>> north_cell;
std::optional<std::pair<uint16_t, uint16_t>> south_cell;
if(this->torus){
if(x == this->width - 1){
east_cell = std::pair<uint16_t, uint16_t>(0, y);
}
else if(x == 0){
west_cell = std::pair<uint16_t, uint16_t>(this->width - 1, y);
}
if(y == 0){
north_cell = std::pair<uint16_t, uint16_t>(x, this->height - 1);
}
else if(y == this->height - 1){
south_cell = std::pair<uint16_t, uint16_t>(x, 0);
}
}else{
if(x > 0){
east_cell = std::pair<uint16_t, uint16_t>(x - 1, y);
}
if(x < this->width - 1){
west_cell = std::pair<uint16_t, uint16_t>(x + 1, y);
}
if(y > 0){
north_cell = std::pair<uint16_t, uint16_t>(x, y - 1);
}
if(y < this->height - 1){
north_cell = std::pair<uint16_t, uint16_t>(x, y + 1);
}
}
neighborhood[0] = west_cell;
neighborhood[1] = east_cell;
neighborhood[2] = north_cell;
neighborhood[3] = south_cell;
return neighborhood;
}
I have to perform this operation a very high number of times, and I don't want to shoot myself in the foot by having a bad implementation. Is one choice over the other better or am I absolutely wrong and there is another way to do efficiently ?