|
|
@ -6,6 +6,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
#include <png++/png.hpp>
|
|
|
|
#include <png++/png.hpp>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// #include <bitset>
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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) {}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
int2 operator+(const int2& a, const int2& b) { return int2(a.x+b.x, a.y+b.y); }
|
|
|
|
|
|
|
|
float2 operator+(const float2& f, const int2& i) { return float2(f.x+i.x, f.y+i.y); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inline int getMaskAt(const std::vector< MarchingSquares::CellType >& cells, int width, int2 point) {
|
|
|
|
|
|
|
|
const int x = point.x;
|
|
|
|
|
|
|
|
const int y = point.y;
|
|
|
|
|
|
|
|
const MarchingSquares::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] == MarchingSquares::FREE) ? 0x0 : 0x1)
|
|
|
|
|
|
|
|
| ((quad[1] == MarchingSquares::FREE) ? 0x0 : 0x2)
|
|
|
|
|
|
|
|
| ((quad[2] == MarchingSquares::FREE) ? 0x0 : 0x4)
|
|
|
|
|
|
|
|
| ((quad[3] == MarchingSquares::FREE) ? 0x0 : 0x8);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return mask;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
MarchingSquares::MarchingSquares()
|
|
|
|
MarchingSquares::MarchingSquares()
|
|
|
|
: width_(0)
|
|
|
|
: width_(0)
|
|
|
|
, height_(0)
|
|
|
|
, height_(0)
|
|
|
@ -53,22 +82,36 @@ MarchingSquares::RunMarchingSquares() {
|
|
|
|
float2(-1, -0.5f) // L 7
|
|
|
|
float2(-1, -0.5f) // L 7
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
constexpr float2 center(0.5, 0.5);
|
|
|
|
constexpr int2 step[16] = { // clockwise, starting in top-left corner
|
|
|
|
|
|
|
|
int2(0, 0), // 0x0
|
|
|
|
|
|
|
|
int2(1, 1), // 0x1
|
|
|
|
|
|
|
|
int2(-1, 1), // 0x2
|
|
|
|
|
|
|
|
int2(1, 0), // 0x3
|
|
|
|
|
|
|
|
int2(-1, 1), // 0x4
|
|
|
|
|
|
|
|
int2(0, 1), // 0x5
|
|
|
|
|
|
|
|
int2(0, 0), // 0x6
|
|
|
|
|
|
|
|
int2(0, 0), // 0x7
|
|
|
|
|
|
|
|
int2(1, 1), // 0x8
|
|
|
|
|
|
|
|
int2(0, 0), // 0x9
|
|
|
|
|
|
|
|
int2(0, 1), // 0xa
|
|
|
|
|
|
|
|
int2(0, 0), // 0xb
|
|
|
|
|
|
|
|
int2(1, 0), // 0xc
|
|
|
|
|
|
|
|
int2(0, 0), // 0xd
|
|
|
|
|
|
|
|
int2(0, 0), // 0xe
|
|
|
|
|
|
|
|
int2(0, 0) // 0xf
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
std::vector< std::pair<float2, float2> > lines;
|
|
|
|
constexpr float2 center(0.5, 0.5);
|
|
|
|
for (size_t y = 1; y < height_; ++y) {
|
|
|
|
|
|
|
|
for (size_t x = 1; x < width_; ++x) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const CellType quad[4] = {
|
|
|
|
const int number_of_cells = width_*height_;
|
|
|
|
cells_[(y-1) * width_ + (x-1)], cells_[(y-1) * width_ + x], // TL T
|
|
|
|
std::vector<bool> visited(number_of_cells, false);
|
|
|
|
cells_[ y * width_ + (x-1)], cells_[ y * width_ + x] }; // R X
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const int mask = ((quad[0] == FREE) ? 0x0 : 0x1)
|
|
|
|
std::vector< std::pair<float2, float2> > lines;
|
|
|
|
| ((quad[1] == FREE) ? 0x0 : 0x2)
|
|
|
|
int2 point(1, 1);
|
|
|
|
| ((quad[2] == FREE) ? 0x0 : 0x4)
|
|
|
|
for (point.y = 1 ;point.y < height_; ++point.y) {
|
|
|
|
| ((quad[3] == FREE) ? 0x0 : 0x8);
|
|
|
|
for (point.x = 1; point.x < width_; ++point.x) {
|
|
|
|
|
|
|
|
|
|
|
|
const float2 point(x, y);
|
|
|
|
const int mask = getMaskAt(cells_, width_, point);
|
|
|
|
|
|
|
|
|
|
|
|
// these are the marching squares cases
|
|
|
|
// these are the marching squares cases
|
|
|
|
int s = -1, e = -1;
|
|
|
|
int s = -1, e = -1;
|
|
|
@ -76,14 +119,14 @@ MarchingSquares::RunMarchingSquares() {
|
|
|
|
case 0x0: /* all free, nothing to do */ break;
|
|
|
|
case 0x0: /* all free, nothing to do */ break;
|
|
|
|
|
|
|
|
|
|
|
|
case 0x1: /* TL = TL */ s = 7; e = 1; break;
|
|
|
|
case 0x1: /* TL = TL */ s = 7; e = 1; break;
|
|
|
|
case 0x2: /* TR = TR */ s = 1; e = 3; break;
|
|
|
|
case 0x2: /* TR = TR */ s = 3; e = 1; break;
|
|
|
|
case 0x4: /* BL = BL */ s = 5; e = 7; break;
|
|
|
|
case 0x4: /* BL = BL */ s = 5; e = 7; break;
|
|
|
|
case 0x8: /* BR = BR */ s = 3; e = 5; break;
|
|
|
|
case 0x8: /* BR = BR */ s = 5; e = 3; break;
|
|
|
|
|
|
|
|
|
|
|
|
case 0x3: /* TLTR = top */ s = 7; e = 3; break;
|
|
|
|
case 0x3: /* TLTR = top */ s = 7; e = 3; break;
|
|
|
|
case 0x5: /* TL BL = left */ s = 1; e = 5; break;
|
|
|
|
case 0x5: /* TL BL = left */ s = 1; e = 5; break;
|
|
|
|
case 0xa: /* TR BR = right */ s = 5; e = 1; break;
|
|
|
|
case 0xa: /* TR BR = right */ s = 1; e = 5; break;
|
|
|
|
case 0xc: /* BLBR = bottom */ s = 3; e = 7; break;
|
|
|
|
case 0xc: /* BLBR = bottom */ s = 7; e = 3; break;
|
|
|
|
|
|
|
|
|
|
|
|
// two lines
|
|
|
|
// two lines
|
|
|
|
case 0x6: /* TRBL = left desc diagonal */ s = 1 | 5 << 4; e = 3 | 7 << 4; break;
|
|
|
|
case 0x6: /* TRBL = left desc diagonal */ s = 1 | 5 << 4; e = 3 | 7 << 4; break;
|
|
|
@ -97,11 +140,37 @@ MarchingSquares::RunMarchingSquares() {
|
|
|
|
case 0xf: /* all blocked, nothing to do */ break;
|
|
|
|
case 0xf: /* all blocked, nothing to do */ break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::cout << mask << " ";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (visited[point.y*width_ + point.x] == true)
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
if (s == -1) {
|
|
|
|
if (s == -1) {
|
|
|
|
// assert: e == -1
|
|
|
|
// assert: e == -1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if (mask == 0x7)
|
|
|
|
|
|
|
|
// continue;
|
|
|
|
|
|
|
|
|
|
|
|
else if ((s & 0xf) == s) {
|
|
|
|
else if ((s & 0xf) == s) {
|
|
|
|
// assert: (e & 0xf) == e
|
|
|
|
// assert: (e & 0xf) == e
|
|
|
|
|
|
|
|
// lines.push_back(std::pair<float2, float2>(points[s]+center+point, points[e]+center+point));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mask == 0x3 || mask == 0x5 || mask == 0xa || mask == 0xc
|
|
|
|
|
|
|
|
// || mask == 0x1 || mask == 0x2 || mask == 0x4 || mask == 0x8
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
int2 i = point;
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
|
|
|
|
int2 next = i + step[mask];
|
|
|
|
|
|
|
|
if (next.x < width_ && point.y < height_ && getMaskAt(cells_, width_, next) == mask && visited[next.y*width_ + next.x] == false) {
|
|
|
|
|
|
|
|
visited[next.y*width_ + next.x] = true;
|
|
|
|
|
|
|
|
i = next;
|
|
|
|
|
|
|
|
} else
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
lines.push_back(std::pair<float2, float2>(points[s]+center+point, points[e]+center+i));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
lines.push_back(std::pair<float2, float2>(points[s]+center+point, points[e]+center+point));
|
|
|
|
lines.push_back(std::pair<float2, float2>(points[s]+center+point, points[e]+center+point));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else {
|
|
|
@ -110,7 +179,10 @@ MarchingSquares::RunMarchingSquares() {
|
|
|
|
lines.push_back(std::pair<float2, float2>(points[s1]+center+point, points[e1]+center+point));
|
|
|
|
lines.push_back(std::pair<float2, float2>(points[s1]+center+point, points[e1]+center+point));
|
|
|
|
lines.push_back(std::pair<float2, float2>(points[s2]+center+point, points[e2]+center+point));
|
|
|
|
lines.push_back(std::pair<float2, float2>(points[s2]+center+point, points[e2]+center+point));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
visited[point.y*width_ + point.x] = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::cout << std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// build quadtree and combine lines (there are many, many small pieces around now, combine to longer lines)
|
|
|
|
// build quadtree and combine lines (there are many, many small pieces around now, combine to longer lines)
|
|
|
|