@ -8,9 +8,32 @@
// #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 ) { }
@ -71,37 +94,57 @@ void MarchingSquares::ReadImage(const std::string& filename)
std : : vector < std : : pair < float2 , float2 > >
MarchingSquares : : RunMarchingSquares ( ) {
constexpr float2 points [ 8 ] = { // clockwise, starting in top-left corner
float2 ( - 1 , - 1 ) , // TL 0
float2 ( - 0.5f , - 1 ) , // T 1
float2 ( 0 , - 1 ) , // TR 2
float2 ( 0 , - 0.5f ) , // R 3
float2 ( 0 , 0 ) , // BR 4
float2 ( - 0.5f , 0 ) , // B 5
float2 ( - 1 , 0 ) , // BL 6
float2 ( - 1 , - 0.5f ) // L 7
} ;
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
} ;
constexpr float2 center ( 0.5 , 0.5 ) ;
// constexpr float2 points[8] = { // clockwise, starting in top-left corner
// float2(-1, -1 ), // TL 0
// float2(-0.5f, -1 ), // T 1
// float2(0, -1 ), // TR 2
// float2(0, -0.5f), // R 3
// float2(0, 0 ), // BR 4
// float2(-0.5f, 0 ), // B 5
// float2(-1, 0 ), // BL 6
// float2(-1, -0.5f) // L 7
// };
// constexpr int2 step[16] = { // clockwise, starting in top-left corner
// int2(0, 0), // 0x0
// int2(1, 1), // 0x1
// int2(1, 0), // 0x2
// int2(1, 0), // 0x3
// int2(-1, 1), // 0x4
// int2(0, 1), // 0x5
// int2(0, 0), // 0x6
// int2(1, 0), // 0x7
// int2(1, 0), // 0x8
// int2(0, 0), // 0x9
// int2(0, 1), // 0xa
// int2(0, 0), // 0xb
// int2(1, 0), // 0xc
// int2(1, 0), // 0xd
// int2(0, 0), // 0xe
// int2(0, 0) // 0xf
// };
// constexpr int next[16] = {
// 0x0, // x0x0
// 0x0, // x0x1
// 0x3, // x0x2
// 0x0, // x0x3 // DC
// 0x0, // x0x4
// 0x0, // x0x5
// 0x0, // x0x6
// 0x3, // x0x7
// 0xc, // x0x8
// 0x0, // x0x9
// 0x0, // x0xa
// 0x0, // x0xb
// 0x0, // x0xc
// 0xc, // x0xd
// 0x0, // x0xe
// 0x0 // x0xf // DC
// };
// constexpr float2 center(0.5, 0.5);
// constexpr float2 center(0.0, 0.0);
const int number_of_cells = width_ * height_ ;
std : : vector < bool > visited ( number_of_cells , false ) ;
@ -113,71 +156,86 @@ MarchingSquares::RunMarchingSquares() {
const int mask = getMaskAt ( cells_ , width_ , point ) ;
// these are the marching squares cases
int s = - 1 , e = - 1 ;
switch ( mask ) {
case 0x0 : /* all free, nothing to do */ break ;
case 0x1 : /* TL = TL */ s = 7 ; e = 1 ; break ;
case 0x2 : /* TR = TR */ s = 3 ; e = 1 ; break ;
case 0x4 : /* BL = BL */ s = 5 ; e = 7 ; break ;
case 0x8 : /* BR = BR */ s = 5 ; e = 3 ; break ;
case 0x3 : /* TLTR = top */ s = 7 ; e = 3 ; break ;
case 0x5 : /* TL BL = left */ s = 1 ; e = 5 ; break ;
case 0xa : /* TR BR = right */ s = 1 ; e = 5 ; break ;
case 0xc : /* BLBR = bottom */ s = 7 ; e = 3 ; break ;
// two lines
case 0x6 : /* TRBL = left desc diagonal */ s = 1 | 5 < < 4 ; e = 3 | 7 < < 4 ; break ;
case 0x9 : /* TL BR = right asc diagonal */ s = 7 | 3 < < 4 ; e = 1 | 5 < < 4 ; break ;
case 0x7 : /* TLTRBL = BR free */ s = 3 ; e = 5 ; break ;
case 0xb : /* TLTR BR = BL free */ s = 5 ; e = 7 ; break ;
case 0xd : /* TL BLBR = TR free */ s = 1 ; e = 3 ; break ;
case 0xe : /* TRBLBR = TL free */ s = 7 ; e = 1 ; break ;
case 0xf : /* all blocked, nothing to do */ break ;
}
std : : cout < < mask < < " " ;
// // these are the marching squares cases
// int s = -1, e = -1;
// switch (mask) {
// case 0x0: /* all free, nothing to do */ break;
//
// case 0x1: /* TL = TL */ s = 7; e = 1; break;
// case 0x2: /* TR = TR */ s = 3; e = 1; break;
// case 0x4: /* BL = BL */ s = 5; e = 7; break;
// case 0x8: /* BR = BR */ s = 5; e = 3; break;
//
// case 0x3: /* TLTR = top */ s = 7; e = 3; break;
// case 0x5: /* TL BL = left */ s = 1; e = 5; break;
// case 0xa: /* TR BR = right */ s = 1; e = 5; break;
// case 0xc: /* BLBR = bottom */ s = 7; e = 3; break;
//
// // two lines
// case 0x6: /* TRBL = left desc diagonal */ s = 1 | 5 << 4; e = 3 | 7 << 4; break;
// case 0x9: /* TL BR = right asc diagonal */ s = 7 | 3 << 4; e = 1 | 5 << 4; break;
//
// case 0x7: /* TLTRBL = BR free */ s = 3; e = 5; break;
// case 0xb: /* TLTR BR = BL free */ s = 5; e = 7; break;
// case 0xd: /* TL BLBR = TR free */ s = 1; e = 3; break;
// case 0xe: /* TRBLBR = TL free */ s = 7; e = 1; break;
//
// case 0xf: /* all blocked, nothing to do */ break;
// }
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 ( s = = - 1 ) {
// assert: e == -1
}
// if (mask == 0x7)
// continue;
if ( mask = = 0x0 | | mask = = 0xf ) // empty or full
continue ;
else if ( ( s & 0xf ) = = s ) {
// assert: (e & 0xf) == e
// lines.push_back(std::pair<float2, float2>(points[s]+center+point, points[e]+center+point));
// vertical lines start with an edge
assert ( mask ! = 3 ) ;
assert ( mask ! = 12 ) ;
assert ( mask ! = 5 ) ;
assert ( mask ! = 10 ) ;
if ( mask = = 0x3 | | mask = = 0x5 | | mask = = 0xa | | mask = = 0xc
// || mask == 0x1 || mask == 0x2 || mask == 0x4 || mask == 0x8
) {
if ( mask = = 0x7 | | mask = = 0x2 | | mask = = 0x8 | | mask = = 0xd | | mask = = 0x6 | | mask = = 0x9 ) {
int2 i = point ;
int counter = 0 ;
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 ;
int2 n = int2 ( i . x + 1 , i . y ) ;
int next_mask = getMaskAt ( cells_ , width_ , n ) ;
if ( n . x < width_ & & point . y < height_ & &
( next_mask = = 0x3 | | next_mask = = 0xc ) & &
visited [ n . y * width_ + n . x ] = = false ) {
visited [ n . y * width_ + n . x ] = true ;
i = n ;
+ + counter ;
} else
break ;
}
lines . push_back ( std : : pair < float2 , float2 > ( points [ s ] + center + point , points [ e ] + center + i ) ) ;
lines . push_back ( std : : pair < float2 , float2 > ( float2( point . x , point . y ) , float2 ( i . x + 1 , i . y ) ) ) ;
}
else
lines . push_back ( std : : pair < float2 , float2 > ( points [ s ] + center + point , points [ e ] + center + point ) ) ;
if ( mask = = 0x7 | | mask = = 0xb | | mask = = 0x4 | | mask = = 0x8 | | mask = = 0x6 | | mask = = 0x9 ) {
int2 i = point ;
int counter = 0 ;
while ( true ) {
int2 n = int2 ( i . x , i . y + 1 ) ;
int next_mask = getMaskAt ( cells_ , width_ , n ) ;
if ( n . x < width_ & & point . y < height_ & &
( next_mask = = 0xa | | next_mask = = 0x5 ) & &
visited [ n . y * width_ + n . x ] = = false ) {
visited [ n . y * width_ + n . x ] = true ;
i = n ;
+ + counter ;
} else
break ;
}
else {
int s1 = s & 0xf , e1 = e & 0xf ;
int s2 = s > > 4 , e2 = e > > 4 ;
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 > ( float2 ( point . x , point . y ) , float2 ( i . x , i . y + 1 ) ) ) ;
}
visited [ point . y * width_ + point . x ] = true ;