I have not used C++ in quite a while and looking for advice/feedback, the code below implements the Marching Squares Algorithm which is detailed here. While the implementation appears correct and gives the same result as the example on the Wikipedia page, I think that some of the code could be improved and I'm looking for general feedback on how. In particular,
- how I handle vectors
- the 2x2 sliding matrix that moves across the test data
- where I OR in a value
#include <iostream>
#include <stdio.h>
#include <tchar.h>
#include <vector>
using std::vector;
void ApplyThreshold(vector<vector<int>> &Matrix2D, int threshold);
vector<vector<int>> CreateContourMatrix(vector<vector<int>> &pMatrix);
int main()
{
const int cutOff = 2;//The value on which to base the creation of contours
vector<vector<int>> matrix;
//Setup test data
matrix.push_back(vector<int> { 1, 1, 1, 1, 1 });
matrix.push_back(vector<int> {1, 2, 3, 2, 1, });
matrix.push_back(vector<int> {1, 3, 3, 3, 1, });
matrix.push_back(vector<int> {1, 2, 3, 2, 1, });
matrix.push_back(vector<int> {1, 1, 1, 1, 1, });
vector<vector<int>> pMatrix = matrix;
ApplyThreshold(pMatrix, cutOff);//Establishthe contours
auto contourMatrix = CreateContourMatrix(pMatrix);//Build contour shapes
//Print the result
for (auto contour_row : contourMatrix)
{
for (int element : contour_row)
{
std::cout << element << '\t';
}
std::cout << std::endl;
}
return 0;
}
/*
* Move a 2x2 window across a 2d matrix, calculating contour shapes
*/
vector<vector<int>> CreateContourMatrix(vector<vector<int>> &pMatrix)
{
vector<vector<int>> contourMatrix;
//vector<int> rows[5];
for (int i =0;i<pMatrix.size() - 1;i++)
{
vector<int> row;//Should this allocation be moved out of the for loop?
for (int j=0;j<pMatrix[0].size() - 1;j++)//Assume that all rows of the image are the same size
{
int shape = 0;
if (pMatrix[i][j] == 1)
shape = shape | 8;
if (pMatrix[i][j + 1] == 1)
shape = shape | 4;
if (pMatrix[i+1][j] == 1)
shape = shape | 1;
if (pMatrix[i+1][j+1] == 1)
shape = shape | 2;
row.push_back(shape);
}
contourMatrix.push_back(row);
}
return contourMatrix;
}
void ApplyThreshold(vector<vector<int>> &Matrix2D, int threshhold)
{
for (auto rowVector : Matrix2D)
{
for (auto vectorValue : rowVector)
{
if (vectorValue >= threshhold)
vectorValue = 1;
else
vectorValue = 0;
}
}
}
This isn't supposed to be a complete implementation, i.e. I don't deal with ambiguous cases or actually create an image of the contours. Any advice appreciated.
1 Answer 1
A couple miscellaneous things.
I don't think you need the vector<int>
for the initialization. eg:
matrix.push_back({ 1, 1, 1, 1, 1, });
You can use references in the for loops, just for good measure. IMO using the type instead of auto makes it easier to read when it's a simple type too.
for (auto& contour_row : contourMatrix)
{
for (int& element : contour_row)
{
std::cout << element << '\t';
}
std::cout << std::endl;
}
In CreateContourMatrix()
the row vector can come out of the for loop. Use .clear()
or .fill()
on it inside the loop, then you aren't reallocating.