- pulling out PNG reading dependency to readPngToImageMatrix - making it header only - removing debug printing (should move into a separate header) - 2 simple testsmaster
parent
d9522e40be
commit
3ae7d3812e
@ -0,0 +1,141 @@
|
|||||||
|
#ifndef MARCHING_SQUARES_HPP
|
||||||
|
#define MARCHING_SQUARES_HPP
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
struct ImageMatrix {
|
||||||
|
enum CellType { FREE, SOLID, DESTROYABLE };
|
||||||
|
|
||||||
|
const std::size_t width_;
|
||||||
|
const std::size_t height_;
|
||||||
|
const std::vector<CellType> cells_;
|
||||||
|
ImageMatrix(std::size_t w, std::size_t h, const std::vector<CellType>& c)
|
||||||
|
: width_(w), height_(h), cells_(c) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct size_t2 {
|
||||||
|
std::size_t x, y;
|
||||||
|
constexpr size_t2 (int _x, int _y) : x(_x), y(_y) {}
|
||||||
|
size_t2 (const size_t2& o) : x(o.x), y(o.y) {}
|
||||||
|
void operator+=(const size_t2 o) { x += o.x; y += o.y; }
|
||||||
|
bool operator==(const size_t2 o) const { return x == o.x && y == o.y; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
int getMaskAt(int x, int y, const ImageMatrix& image_matrix)
|
||||||
|
{
|
||||||
|
const std::size_t width = image_matrix.width_;
|
||||||
|
const std::vector<ImageMatrix::CellType> cells = image_matrix.cells_;
|
||||||
|
|
||||||
|
const ImageMatrix::CellType quad[4] = {
|
||||||
|
cells[(y-1) * width + (x-1)], cells[(y-1) * width + x], // TL T
|
||||||
|
cells[ y * width + (x-1)], cells[ y * width + x] }; // R X
|
||||||
|
|
||||||
|
const int mask = ((quad[0] == ImageMatrix::FREE) ? 0x0 : 0x1)
|
||||||
|
| ((quad[1] == ImageMatrix::FREE) ? 0x0 : 0x2)
|
||||||
|
| ((quad[2] == ImageMatrix::FREE) ? 0x0 : 0x4)
|
||||||
|
| ((quad[3] == ImageMatrix::FREE) ? 0x0 : 0x8);
|
||||||
|
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void visitPoint(std::size_t x, std::size_t y,
|
||||||
|
int mask,
|
||||||
|
std::vector< bool >& visited,
|
||||||
|
std::vector< std::pair<size_t2, size_t2> >& lines,
|
||||||
|
const ImageMatrix& image_matrix)
|
||||||
|
{
|
||||||
|
const std::size_t width = image_matrix.width_;
|
||||||
|
const std::size_t height = image_matrix.height_;
|
||||||
|
|
||||||
|
visited[y * width + x] = true;
|
||||||
|
|
||||||
|
const bool horizontal_top = (mask == 0x7 || mask == 0x2 || mask == 0x6);
|
||||||
|
const bool horizontal_bottom = (mask == 0x8 || mask == 0x9 || mask == 0xd);
|
||||||
|
const bool vertical_left = (mask == 0x7 || mask == 0x4 || mask == 0x6);
|
||||||
|
const bool vertical_right = (mask == 0x8 || mask == 0x9 || mask == 0xb);
|
||||||
|
const bool horizontal = horizontal_top || horizontal_bottom;
|
||||||
|
const bool vertical = vertical_left || vertical_right;
|
||||||
|
|
||||||
|
if (!horizontal && !vertical)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (horizontal) {
|
||||||
|
|
||||||
|
// go left till possible
|
||||||
|
size_t2 i(x, y);
|
||||||
|
while (true) {
|
||||||
|
i += size_t2(1, 0);
|
||||||
|
int next_mask = getMaskAt(i.x, i.y, image_matrix);
|
||||||
|
if (i.x < width && i.y < height &&
|
||||||
|
( (horizontal_top && next_mask == 0x3) ||
|
||||||
|
(horizontal_bottom && next_mask == 0xc) ||
|
||||||
|
(vertical_left && next_mask == 0x5) ||
|
||||||
|
(vertical_right && next_mask == 0xa) ) &&
|
||||||
|
visited[i.y*width + i.x] == false)
|
||||||
|
visited[i.y*width + i.x] = true;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i.x != x) {
|
||||||
|
visited[i.y*width + i.x] = false;
|
||||||
|
lines.push_back(std::pair<size_t2, size_t2>(size_t2(x, y), size_t2( i.x, i.y)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vertical) {
|
||||||
|
size_t2 i(x, y);
|
||||||
|
while (true) {
|
||||||
|
i += size_t2(0, 1);
|
||||||
|
int next_mask = getMaskAt(i.x, i.y, image_matrix);
|
||||||
|
if (i.x < width && i.y < height &&
|
||||||
|
( (horizontal_top && next_mask == 0x3) ||
|
||||||
|
(horizontal_bottom && next_mask == 0xc) ||
|
||||||
|
(vertical_left && next_mask == 0x5) ||
|
||||||
|
(vertical_right && next_mask == 0xa) ) &&
|
||||||
|
visited[i.y*width + i.x] == false)
|
||||||
|
visited[i.y*width + i.x] = true;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i.y != y) {
|
||||||
|
visited[i.y*width + i.x] = false;
|
||||||
|
lines.push_back(std::pair<size_t2, size_t2>(size_t2(x, y), size_t2( i.x, i.y)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // detail namespace
|
||||||
|
|
||||||
|
|
||||||
|
std::vector< std::pair<size_t2, size_t2> > marchingSquares(const ImageMatrix& image_matrix)
|
||||||
|
{
|
||||||
|
const std::size_t width = image_matrix.width_;
|
||||||
|
const std::size_t height = image_matrix.height_;
|
||||||
|
|
||||||
|
std::vector<bool> visited(width * height, false);
|
||||||
|
std::vector< std::pair<size_t2, size_t2> > lines;
|
||||||
|
|
||||||
|
size_t2 point(1, 1);
|
||||||
|
for (point.y = 1 ;point.y < height; ++point.y) {
|
||||||
|
for (point.x = 1; point.x < width; ++point.x) {
|
||||||
|
if (visited[point.y * width + point.x] == true)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const int mask = detail::getMaskAt(point.x, point.y, image_matrix);
|
||||||
|
if (mask == 0x0 || mask == 0xf) // empty or full
|
||||||
|
continue;
|
||||||
|
|
||||||
|
detail::visitPoint(point.x, point.y, mask, visited, lines, image_matrix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // MARCHING_SQUARES_HPP
|
@ -1,240 +0,0 @@
|
|||||||
#include "marching_squares.hpp"
|
|
||||||
|
|
||||||
#include "floats.hpp"
|
|
||||||
|
|
||||||
#include <cstring> // for strerror needed by png++/error.hpp
|
|
||||||
|
|
||||||
#include <png++/png.hpp>
|
|
||||||
|
|
||||||
// #include <bitset>
|
|
||||||
#include <iostream>
|
|
||||||
#include <iomanip>
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
namespace Color {
|
|
||||||
enum Code {
|
|
||||||
FG_RED = 31,
|
|
||||||
FG_GREEN = 32,
|
|
||||||
FG_BLUE = 34,
|
|
||||||
FG_DEFAULT = 39,
|
|
||||||
BG_RED = 41,
|
|
||||||
BG_GREEN = 42,
|
|
||||||
BG_BLUE = 44,
|
|
||||||
BG_DEFAULT = 49
|
|
||||||
};
|
|
||||||
class Modifier {
|
|
||||||
Code code;
|
|
||||||
public:
|
|
||||||
Modifier(Code pCode) : code(pCode) {}
|
|
||||||
friend std::ostream&
|
|
||||||
operator<<(std::ostream& os, const Modifier& mod) {
|
|
||||||
return os << "\033[" << mod.code << "m";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
struct int2 {
|
|
||||||
int x, y;
|
|
||||||
constexpr int2 (int _x, int _y) : x(_x), y(_y) {}
|
|
||||||
int2 (const int2& o) : x(o.x), y(o.y) {}
|
|
||||||
void operator+=(const int2 o) { x += o.x; y += o.y; }
|
|
||||||
};
|
|
||||||
|
|
||||||
#define ASSERT(x) \
|
|
||||||
if (!(x)) std::cerr << __FILE__ << ":" << __LINE__ << ":" << __PRETTY_FUNCTION__ << (x) << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
MarchingSquares::MarchingSquares()
|
|
||||||
: width_(0)
|
|
||||||
, height_(0)
|
|
||||||
, cells_()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void MarchingSquares::ReadImage(const std::string& filename)
|
|
||||||
{
|
|
||||||
png::image<png::gray_pixel> image(filename); // throws std_error(filename);
|
|
||||||
|
|
||||||
width_ = image.get_width();
|
|
||||||
height_ = image.get_height();
|
|
||||||
cells_.reserve(width_ * height_);
|
|
||||||
|
|
||||||
for (size_t y = 0; y < height_; ++y) {
|
|
||||||
const png::image<png::gray_pixel>::row_type& row = image[y];
|
|
||||||
for (size_t x = 0; x < width_; ++x) {
|
|
||||||
CellType c; // map pixel luminance to cell type
|
|
||||||
if (row[x] < 16) c = SOLID; // black
|
|
||||||
else if (row[x] >= 240) c = FREE; // white
|
|
||||||
else c = DESTROYABLE; // everything else
|
|
||||||
|
|
||||||
/// @todo extend image?
|
|
||||||
// mark borders as SOLID, such that the entities in the world cannot fall off
|
|
||||||
// if (x == 0 || x == width_ - 1 || y == 0 || y == height_ - 1)
|
|
||||||
// c = SOLID;
|
|
||||||
|
|
||||||
// mark white "hole" cells sorrounded by 4 black cells as black
|
|
||||||
if (y > 1 && y < height_-1 && x > 1 && x < width_-1 &&
|
|
||||||
image[y][x] >= 240 &&
|
|
||||||
image[y-1][x] < 240 &&
|
|
||||||
image[y+1][x] < 240 &&
|
|
||||||
image[y][x-1] < 240 &&
|
|
||||||
image[y][x+1] < 240)
|
|
||||||
c = SOLID;
|
|
||||||
|
|
||||||
/// @note is it too much?
|
|
||||||
// mark black "lost" cells sorrounded by 4 white cells as white
|
|
||||||
// if (y > 1 && y < height_-1 && x > 1 && x < width_-1 &&
|
|
||||||
// image[y][x] < 240 &&
|
|
||||||
// (image[y-1][x-1] >= 240 && image[y-1][x] >= 240 && image[y-1][x+1] >= 240 && image[y][x+1] >= 240 && image[y+1][x+1] >= 240 && image[y+1][x] >= 240 && image[y+1][x-1] >= 240 && image[y][x-1] >= 240))
|
|
||||||
// c = FREE;
|
|
||||||
|
|
||||||
// // mark black "bump on the wall" cells as white
|
|
||||||
// if (y > 1 && y < height_-1 && x > 1 && x < width_-1 &&
|
|
||||||
// image[y][x] < 240 &&
|
|
||||||
// ((image[y-1][x-1] < 240 && image[y-1][x] < 240 && image[y-1][x+1] < 240 && image[y][x+1] >= 240 && image[y+1][x+1] >= 240 && image[y+1][x] >= 240 && image[y+1][x-1] >= 240 && image[y][x-1] >= 240) ||
|
|
||||||
// (image[y-1][x-1] >= 240 && image[y-1][x] >= 240 && image[y-1][x+1] < 240 && image[y][x+1] < 240 && image[y+1][x+1] < 240 && image[y+1][x] >= 240 && image[y+1][x-1] >= 240 && image[y][x-1] >= 240) ||
|
|
||||||
// (image[y-1][x-1] >= 240 && image[y-1][x] >= 240 && image[y-1][x+1] >= 240 && image[y][x+1] >= 240 && image[y+1][x+1] < 240 && image[y+1][x] < 240 && image[y+1][x-1] < 240 && image[y][x-1] >= 240) ||
|
|
||||||
// (image[y-1][x-1] < 240 && image[y-1][x] >= 240 && image[y-1][x+1] >= 240 && image[y][x+1] >= 240 && image[y+1][x+1] >= 240 && image[y+1][x] >= 240 && image[y+1][x-1] < 240 && image[y][x-1] < 240)))
|
|
||||||
// c = FREE;
|
|
||||||
|
|
||||||
cells_.push_back(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::vector< std::pair<float2, float2> >
|
|
||||||
MarchingSquares::RunMarchingSquares() {
|
|
||||||
|
|
||||||
std::vector<bool> visited(width_*height_, false);
|
|
||||||
std::vector< std::pair<float2, float2> > lines;
|
|
||||||
|
|
||||||
int2 point(1, 1);
|
|
||||||
for (point.y = 1 ;point.y < (int)height_; ++point.y) {
|
|
||||||
for (point.x = 1; point.x < (int)width_; ++point.x) {
|
|
||||||
|
|
||||||
const int mask = getMaskAt(point.x, point.y);
|
|
||||||
|
|
||||||
Color::Modifier blue(Color::FG_BLUE);
|
|
||||||
Color::Modifier def(Color::FG_DEFAULT);
|
|
||||||
if (mask != 0)
|
|
||||||
std::cout << std::left << std::setw(3) << mask;
|
|
||||||
else
|
|
||||||
std::cout << blue << mask << def << " ";
|
|
||||||
|
|
||||||
if (visited[point.y*width_ + point.x] == true)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (mask == 0x0 || mask == 0xf) // empty or full
|
|
||||||
continue;
|
|
||||||
|
|
||||||
visitPoint(point.x, point.y, mask, visited, lines);
|
|
||||||
}
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
return lines;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MarchingSquares::getMaskAt(int x, int y) const
|
|
||||||
{
|
|
||||||
const CellType quad[4] = {
|
|
||||||
cells_[(y-1) * width_ + (x-1)], cells_[(y-1) * width_ + x], // TL T
|
|
||||||
cells_[ y * width_ + (x-1)], cells_[ y * width_ + x] }; // R X
|
|
||||||
|
|
||||||
const int mask = ((quad[0] == FREE) ? 0x0 : 0x1)
|
|
||||||
| ((quad[1] == FREE) ? 0x0 : 0x2)
|
|
||||||
| ((quad[2] == FREE) ? 0x0 : 0x4)
|
|
||||||
| ((quad[3] == FREE) ? 0x0 : 0x8);
|
|
||||||
|
|
||||||
return mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MarchingSquares::visitPoint(int x, int y, int mask, std::vector< bool >& visited, std::vector< std::pair<float2, float2> >& lines) const
|
|
||||||
{
|
|
||||||
visited[y*width_ + x] = true;
|
|
||||||
|
|
||||||
const bool horizontal_top = (mask == 0x7 || mask == 0x2 || mask == 0x6);
|
|
||||||
const bool horizontal_bottom = (mask == 0x8 || mask == 0x9 || mask == 0xd);
|
|
||||||
const bool vertical_left = (mask == 0x7 || mask == 0x4 || mask == 0x6);
|
|
||||||
const bool vertical_right = (mask == 0x8 || mask == 0x9 || mask == 0xb);
|
|
||||||
const bool horizontal = horizontal_top || horizontal_bottom;
|
|
||||||
const bool vertical = vertical_left || vertical_right;
|
|
||||||
|
|
||||||
if (!horizontal && !vertical)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (mask == 0x8 || mask == 0xb) {
|
|
||||||
int2 i(x, y);
|
|
||||||
while ((getMaskAt(i.x, i.y+1) == 0xe || getMaskAt(i.x, i.y+1) == 0x6) &&
|
|
||||||
getMaskAt(i.x-1, i.y+1) == 0x8 /*&&
|
|
||||||
visited[(i.y)*width_ + i.x] == false*/) {
|
|
||||||
visited[(i.y+1)*width_ + i.x] = true;
|
|
||||||
visited[(i.y+1)*width_ + i.x-1] = true;
|
|
||||||
i += int2(-1, 1);
|
|
||||||
}
|
|
||||||
if (i.x != x || i.y != y) {
|
|
||||||
visited[(i.y-1)*width_ + i.x+1] = false;
|
|
||||||
lines.push_back(std::pair<float2, float2>(float2(x, y), float2( i.x, i.y)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mask == 1) {
|
|
||||||
int2 i(x, y);
|
|
||||||
while ((getMaskAt(i.x-1, i.y) == 0x6 || getMaskAt(i.x-1, i.y) == 0x7) &&
|
|
||||||
getMaskAt(i.x-1, i.y+1) == 0x1 /*&&
|
|
||||||
visited[(i.y)*width_ + i.x] == false*/) {
|
|
||||||
visited[i.y*width_ + i.x-1] = true;
|
|
||||||
visited[(i.y+1)*width_ + i.x-1] = true;
|
|
||||||
i += int2(-1, 1);
|
|
||||||
}
|
|
||||||
if (i.x != x || i.y != y) {
|
|
||||||
visited[(i.y-1)*width_ + i.x+1] = false;
|
|
||||||
lines.push_back(std::pair<float2, float2>(float2(x, y), float2( i.x, i.y)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (horizontal) {
|
|
||||||
|
|
||||||
// go left till possible
|
|
||||||
int2 i(x, y);
|
|
||||||
while (true) {
|
|
||||||
i += int2(1, 0);
|
|
||||||
int next_mask = getMaskAt(i.x, i.y);
|
|
||||||
if (i.x < (int)width_ && i.y < (int)height_ &&
|
|
||||||
( (horizontal_top && next_mask == 0x3) ||
|
|
||||||
(horizontal_bottom && next_mask == 0xc) ||
|
|
||||||
(vertical_left && next_mask == 0x5) ||
|
|
||||||
(vertical_right && next_mask == 0xa) ) &&
|
|
||||||
visited[i.y*width_ + i.x] == false)
|
|
||||||
visited[i.y*width_ + i.x] = true;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i.x != x) {
|
|
||||||
visited[i.y*width_ + i.x] = false;
|
|
||||||
lines.push_back(std::pair<float2, float2>(float2(x, y), float2( i.x, i.y)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vertical) {
|
|
||||||
int2 i(x, y);
|
|
||||||
while (true) {
|
|
||||||
i += int2(0, 1);
|
|
||||||
int next_mask = getMaskAt(i.x, i.y);
|
|
||||||
if (i.x < (int)width_ && i.y < (int)height_ &&
|
|
||||||
( (horizontal_top && next_mask == 0x3) ||
|
|
||||||
(horizontal_bottom && next_mask == 0xc) ||
|
|
||||||
(vertical_left && next_mask == 0x5) ||
|
|
||||||
(vertical_right && next_mask == 0xa) ) &&
|
|
||||||
visited[i.y*width_ + i.x] == false)
|
|
||||||
visited[i.y*width_ + i.x] = true;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i.y != y) {
|
|
||||||
visited[i.y*width_ + i.x] = false;
|
|
||||||
lines.push_back(std::pair<float2, float2>(float2(x, y), float2( i.x, i.y)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
#ifndef WORLD_WORLD_HPP
|
|
||||||
#define WORLD_WORLD_HPP
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
class float2;
|
|
||||||
|
|
||||||
class MarchingSquares {
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum CellType { FREE, SOLID, DESTROYABLE };
|
|
||||||
|
|
||||||
MarchingSquares();
|
|
||||||
|
|
||||||
void ReadImage(const std::string& filename);
|
|
||||||
std::vector< std::pair<float2, float2> > RunMarchingSquares();
|
|
||||||
|
|
||||||
private:
|
|
||||||
int getMaskAt(int x, int y) const;
|
|
||||||
void visitPoint(int x, int y, int mask, std::vector<bool>& visited, std::vector< std::pair<float2, float2> >& lines) const;
|
|
||||||
|
|
||||||
std::size_t width_;
|
|
||||||
std::size_t height_;
|
|
||||||
std::vector<CellType> cells_;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // WORLD_WORLD_HPP
|
|
@ -0,0 +1,27 @@
|
|||||||
|
#include "read_png_to_imagematrix.hpp"
|
||||||
|
|
||||||
|
#include <png++/png.hpp>
|
||||||
|
#include <cstring> // for strerror needed by png++/error.hpp
|
||||||
|
|
||||||
|
ImageMatrix readPngToImageMatrix(const std::string& filename)
|
||||||
|
{
|
||||||
|
png::image<png::gray_pixel> image(filename); // throws std_error(filename);
|
||||||
|
|
||||||
|
const std::size_t width = image.get_width();
|
||||||
|
const std::size_t height = image.get_height();
|
||||||
|
std::vector<ImageMatrix::CellType> cells(width * height);
|
||||||
|
|
||||||
|
for (std::size_t y = 0; y < height; ++y) {
|
||||||
|
const png::image<png::gray_pixel>::row_type& row = image[y];
|
||||||
|
for (std::size_t x = 0; x < width; ++x) {
|
||||||
|
ImageMatrix::CellType c; // map pixel luminance to cell type
|
||||||
|
if (row[x] < 16) c = ImageMatrix::SOLID; // black
|
||||||
|
else if (row[x] >= 240) c = ImageMatrix::FREE; // white
|
||||||
|
else c = ImageMatrix::DESTROYABLE; // everything else
|
||||||
|
|
||||||
|
cells.push_back(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ImageMatrix(width, height, cells);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
|||||||
|
#ifndef READ_PNG_TO_IMAGE_MATRIX_HPP
|
||||||
|
#define READ_PNG_TO_IMAGE_MATRIX_HPP
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
struct ImageMatrix {
|
||||||
|
enum CellType { FREE, SOLID, DESTROYABLE };
|
||||||
|
|
||||||
|
const std::size_t width_;
|
||||||
|
const std::size_t height_;
|
||||||
|
const std::vector<CellType> cells_;
|
||||||
|
ImageMatrix(std::size_t w, std::size_t h, const std::vector<CellType>& c)
|
||||||
|
: width_(w), height_(h), cells_(c) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
ImageMatrix readPngToImageMatrix(const std::string& filename); // throws std_error(filename);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // READ_PNG_TO_IMAGE_MATRIX_HPP
|
@ -0,0 +1,49 @@
|
|||||||
|
#include <graph/marching_squares.hpp>
|
||||||
|
|
||||||
|
#include "../catch.hpp"
|
||||||
|
|
||||||
|
#include "fixture.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
TEST_CASE( "Marching squares", "[marching_squares][algorithm]" ) {
|
||||||
|
|
||||||
|
SECTION("empty") {
|
||||||
|
const ImageMatrix empty(0, 0, std::vector<ImageMatrix::CellType>());
|
||||||
|
const std::vector< std::pair<size_t2, size_t2> > result = marchingSquares(empty);
|
||||||
|
REQUIRE ( result.size() == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("dot") {
|
||||||
|
const std::vector<ImageMatrix::CellType> dot_v {
|
||||||
|
ImageMatrix::FREE, ImageMatrix::FREE, ImageMatrix::FREE,
|
||||||
|
ImageMatrix::FREE, ImageMatrix::SOLID, ImageMatrix::FREE,
|
||||||
|
ImageMatrix::FREE, ImageMatrix::FREE, ImageMatrix::FREE
|
||||||
|
};
|
||||||
|
const ImageMatrix dot_i(3, 3, dot_v);
|
||||||
|
const std::vector< std::pair<size_t2, size_t2> > result = marchingSquares(dot_i);
|
||||||
|
REQUIRE ( result.size() == 4 );
|
||||||
|
|
||||||
|
REQUIRE ( std::find(result.begin(), result.end(), std::pair<size_t2, size_t2>(size_t2(1, 1), size_t2(2, 1)) ) != result.end() );
|
||||||
|
REQUIRE ( std::find(result.begin(), result.end(), std::pair<size_t2, size_t2>(size_t2(1, 1), size_t2(1, 2)) ) != result.end() );
|
||||||
|
REQUIRE ( std::find(result.begin(), result.end(), std::pair<size_t2, size_t2>(size_t2(2, 1), size_t2(2, 2)) ) != result.end() );
|
||||||
|
REQUIRE ( std::find(result.begin(), result.end(), std::pair<size_t2, size_t2>(size_t2(1, 2), size_t2(2, 2)) ) != result.end() );
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("horizontal line") {
|
||||||
|
const std::vector<ImageMatrix::CellType> line_v {
|
||||||
|
ImageMatrix::FREE, ImageMatrix::FREE, ImageMatrix::FREE, ImageMatrix::FREE, ImageMatrix::FREE,
|
||||||
|
ImageMatrix::FREE, ImageMatrix::SOLID, ImageMatrix::SOLID, ImageMatrix::SOLID, ImageMatrix::FREE,
|
||||||
|
ImageMatrix::FREE, ImageMatrix::FREE, ImageMatrix::FREE, ImageMatrix::FREE, ImageMatrix::FREE
|
||||||
|
};
|
||||||
|
const ImageMatrix line_i(5, 3, line_v);
|
||||||
|
const std::vector< std::pair<size_t2, size_t2> > result = marchingSquares(line_i);
|
||||||
|
REQUIRE ( result.size() == 4 );
|
||||||
|
|
||||||
|
REQUIRE ( std::find(result.begin(), result.end(), std::pair<size_t2, size_t2>(size_t2(1, 1), size_t2(4, 1)) ) != result.end() );
|
||||||
|
REQUIRE ( std::find(result.begin(), result.end(), std::pair<size_t2, size_t2>(size_t2(1, 1), size_t2(1, 2)) ) != result.end() );
|
||||||
|
REQUIRE ( std::find(result.begin(), result.end(), std::pair<size_t2, size_t2>(size_t2(4, 1), size_t2(4, 2)) ) != result.end() );
|
||||||
|
REQUIRE ( std::find(result.begin(), result.end(), std::pair<size_t2, size_t2>(size_t2(1, 2), size_t2(4, 2)) ) != result.end() );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in new issue