31 #include <QtGui/qapplication.h>
32 #include "DGtal/base/Common.h"
33 #include "DGtal/io/viewers/Viewer3D.h"
34 #include "DGtal/helpers/StdDefs.h"
35 #include "DGtal/topology/helpers/Surfaces.h"
36 #include "ConfigExamples.h"
40 using namespace DGtal;
45 template <
typename Vector>
48 return Vector( v1[ 1 ] * v2[ 2 ] - v1[ 2 ] * v2[ 1 ],
49 v1[ 2 ] * v2[ 0 ] - v1[ 0 ] * v2[ 2 ],
50 v1[ 0 ] * v2[ 1 ] - v1[ 1 ] * v2[ 0 ] );
53 template <
typename Vector>
58 const std::vector< Vector > &
pts;
60 const std::vector< Vector > & aPts )
61 : N( aN ), P( aP ), pts( aPts )
63 inline bool operator()(
unsigned int i1,
unsigned int i2 )
const
65 return N.dot( wedge( pts[ i1 ] - P, pts[ i2 ] - P ) ) > 0;
71 template <
typename Vector>
73 ( std::vector< std::vector< unsigned int > > & indices,
74 const std::vector<Vector> & points,
bool left_handed )
78 unsigned int faces = 0;
79 std::vector< unsigned int > aFace;
80 for (
unsigned int i1 = 0; i1 < points.size(); ++i1 )
81 for (
unsigned int i2 = 0; i2 < points.size(); ++i2 )
83 for (
unsigned int i3 = i1 > i2 ? i1+1 : i2+1; i3 < points.size(); ++i3 )
85 Vector P12 = points[ i2 ] - points[ i1 ];
86 Vector P13 = points[ i3 ] - points[ i1 ];
87 Vector N = wedge( P12, P13 );
88 if ( N == Vector::zero )
continue;
90 unsigned int nbBadPos = 0;
91 for (
unsigned int i4 = 0; i4 < points.size(); ++i4 )
93 Vector P14 = points[ i4 ] - points[ i1 ];
94 Scalar c = N.
dot( P14 );
95 if ( c == 0 ) aFace.push_back( i4 );
96 else if ( ( left_handed && ( c > 0 ) )
97 || ( ! left_handed && ( c < 0 ) ) )
103 std::sort( ++aFace.begin(), aFace.end(), LTOF );
104 indices.push_back( aFace );
109 for (
unsigned int i = 0; i < indices.size(); ++i )
111 unsigned int s = indices[ i ].size();
112 for (
unsigned int j = i+1; j < indices.size(); )
114 if ( indices[ j ].size() == s )
117 for (
unsigned int k = 0; equal && ( k < s ); ++k )
118 if ( indices[ i ][ k ] != indices[ j ][ k ] )
122 std::swap( indices[ j ], indices.back() );
141 double rescale(
double x )
143 return ( x - 1.0 ) * 0.5 + 0.5;
146 template <
typename Viewer,
151 const std::vector< std::vector< unsigned int > > & indices,
152 const std::vector<Vector> & points )
154 typedef typename Viewer::pointD3D pointD3D;
156 std::vector<pointD3D> pts3d;
157 for (
unsigned int f = 0; f < indices.size(); ++f )
168 for (
unsigned int v = 0; v < indices[ f ].size(); ++v )
170 unsigned int i = indices[ f ][ v ];
171 P.x = rescale( points[ i ][ 0 ] );
172 P.y = rescale( points[ i ][ 1 ] );
173 P.z = rescale( points[ i ][ 2 ] );
174 pts3d.push_back( P );
176 viewer.addPolygon( pts3d, color );
180 template <
typename Vector>
181 unsigned int dim(
const Vector & z )
184 for (
unsigned int i = 0; i < Vector::dimension; ++i )
185 if ( ( z[ i ] % 2 ) == 1 ) ++d;
189 template <
typename Vector>
190 unsigned int openDim(
const Vector & z )
192 for (
unsigned int i = 0; i < Vector::dimension; ++i )
193 if ( ( z[ i ] % 2 ) == 1 )
return i;
194 return Vector::dimension;
196 template <
typename Vector>
203 template <
typename Vector>
211 template <
typename Vector>
212 unsigned int nbLighted( std::map< Vector, bool > & f,
215 unsigned int d = dim( z );
216 if ( d == 0 )
return f[ z ] ? 1 : 0;
217 unsigned int i = openDim( z );
218 return nbLighted( f, lower( z, i ) )
219 + nbLighted( f, upper( z, i ) );
224 template <
typename Vector>
225 bool lightBetween( std::map< Vector, bool > & f,
228 unsigned int d = dim( z );
229 if ( d == 0 )
return f[ z ];
232 unsigned int i = openDim( z );
233 return f[ lower( z, i ) ] || f[ upper( z, i ) ];
238 for (
unsigned int i = 0; i < Vector::dimension; ++i )
240 v1[ i ] = ( ( z[ i ] % 2 ) == 1 ) ? z[ i ] - 1 : z[ i ];
241 v2[ i ] = ( ( z[ i ] % 2 ) == 1 ) ? z[ i ] + 1 : z[ i ];
247 if ( *it == z )
break;
248 Point zp = z*2 - *it;
250 if ( lightBetween( f, *it ) && lightBetween( f, zp ) )
259 template <
typename Vector>
260 bool lightMax( std::map< Vector, bool > & f,
263 unsigned int d = dim( z );
264 if ( d == 0 )
return f[ z ];
267 unsigned int i = openDim( z );
268 return f[ lower( z, i ) ] || f[ upper( z, i ) ];
272 unsigned int n = nbLighted( f, z );
276 template <
typename Vector>
277 bool lightMinMax( std::map< Vector, bool > & f,
280 unsigned int d = dim( z );
281 if ( d == 0 )
return f[ z ];
286 for (
unsigned i = 0; i < d; ++i )
288 unsigned int k = openDim( tmp );
289 tmp = lower( tmp, k );
290 val = val && ( lightMinMax( f, lower( z, k ) ) || lightMinMax( f, upper( z, k ) ) );
295 template <
typename Vector>
296 bool lightMaxMin( std::map< Vector, bool > & f,
299 unsigned int d = dim( z );
300 if ( d == 0 )
return f[ z ];
305 for (
unsigned i = 0; i < d; ++i )
307 unsigned int k = openDim( tmp );
308 tmp = lower( tmp, k );
309 val = val || ( lightMaxMin( f, lower( z, k ) ) && lightMaxMin( f, upper( z, k ) ) );
315 template <
typename Vector>
316 bool lightEpsilon( std::map< Vector, bool > & f,
318 unsigned int epsilon )
320 unsigned int d = dim( z );
321 if ( d == 0 )
return f[ z ];
325 bool eps_d = ( ( epsilon >> (d-1)) & 1 ) != 0;
326 bool val = eps_d ?
true :
false;
327 for (
unsigned i = 0; i < d; ++i )
329 unsigned int k = openDim( tmp );
330 tmp = lower( tmp, k );
332 val = val && ( lightEpsilon( f, lower( z, k ), epsilon )
333 || lightEpsilon( f, upper( z, k ), epsilon ) );
335 val = val || ( lightEpsilon( f, lower( z, k ), epsilon )
336 && lightEpsilon( f, upper( z, k ), epsilon ) );
343 template <
typename Vector>
344 void fillCfg( std::map< Vector, bool > & f,
348 unsigned int d = dim( z );
356 unsigned n = 1 << ( d - 1 );
357 unsigned int cfgLow = 0;
358 unsigned int cfgUp = 0;
359 for (
unsigned int j = 0; j < n; ++j )
361 cfgLow += ( cfg & 1 ) << j;
363 cfgUp += ( cfg & 1 ) << j;
366 unsigned int i = openDim( z );
367 fillCfg( f, lower( z, i ), cfgLow );
368 fillCfg( f, upper( z, i ), cfgUp );
372 template <
typename Vector>
373 void localDualVolume( std::vector<Vector> & points,
374 std::map< Vector, bool > & f,
382 if ( f[ *it ] ) points.push_back( *it );
386 template <
typename Vector>
389 std::map< Vector, bool > &
fct;
392 : fct( aFct ), base( aBase ) {}
393 bool operator()(
const Vector & p )
const
395 return fct[ p * 2 + base];
399 int main(
int argc,
char** argv )
402 QApplication application(argc,argv);
410 std::vector<Vector> pts;
424 unsigned int cfg = argc > 1 ? atoi( argv[1] ) : 0;
425 unsigned int cfg2 = argc > 2 ? atoi( argv[2] ) : 255;
426 std::map< Vector, bool > f;
427 for (
unsigned int y = 0; (y < 16) && (cfg <= cfg2); ++y )
428 for (
unsigned int x = 0; (x < 16) && (cfg <= cfg2); ++x, ++cfg )
430 Vector offset( x*6, y*6, 0 );
431 fillCfg( f, offset +
Vector( 1, 1, 1 ), cfg );
438 for ( CellSet::const_iterator it = aBoundary.begin(), itE = aBoundary.end();
448 f[ *it ] = lightBetween( f, *it );
451 std::vector< std::vector< unsigned int > > indices;
456 localDualVolume( pts, f, *it );
458 naiveConvexHull( indices, pts,
false );
459 viewPolygons( viewer, fillColor, indices, pts );
462 viewer << Viewer3D::updateDisplay;
464 return application.exec();