DGtalTools 2.0.0
Loading...
Searching...
No Matches
3dImplicitSurfaceExtractorBy4DExtension.cpp
1
33#include <iostream>
34#include <map>
35#include "CLI11.hpp"
36
37
38#include "DGtal/base/Common.h"
39#include "DGtal/base/CountedPtr.h"
40#include "DGtal/helpers/StdDefs.h"
41#include "DGtal/math/MPolynomial.h"
42#include "DGtal/io/readers/MPolynomialReader.h"
43#include "DGtal/io/viewers/PolyscopeViewer.h"
44#include "DGtal/topology/KhalimskySpaceND.h"
45#include "DGtal/topology/CubicalComplex.h"
46#include "DGtal/topology/CubicalComplexFunctions.h"
47#include "DGtal/topology/SetOfSurfels.h"
48#include "DGtal/topology/DigitalSurface.h"
49#include "DGtal/topology/helpers/Surfaces.h"
50#include "DGtal/shapes/GaussDigitizer.h"
51#include "DGtal/shapes/Mesh.h"
52#include "DGtal/shapes/implicit/ImplicitPolynomial3Shape.h"
53
55
56using namespace std;
57using namespace DGtal;
58
129template <typename TSpace3, typename TSpace4, typename TPolynomial3>
130struct ImplicitSurface4DProductExtension {
131 typedef TSpace3 Space3;
132 typedef TSpace4 Space4;
133 typedef TPolynomial3 Polynomial3;
134 typedef typename Space3::RealPoint RealPoint3;
135 typedef typename Space3::RealVector RealVector3;
136 typedef typename Space3::Integer Integer;
137 typedef typename RealPoint3::Coordinate Ring;
138 typedef typename Space4::RealPoint RealPoint4;
139 typedef typename Space4::RealVector RealVector4;
140 typedef RealPoint4 RealPoint;
141 typedef RealVector4 RealVector;
142
143 ImplicitSurface4DProductExtension( Clone<Polynomial3> poly )
144 : f( poly )
145 {
146 fx = derivative<0>( f );
147 fy = derivative<1>( f );
148 fz = derivative<2>( f );
149 fxx = derivative<0>( fx );
150 fxy = derivative<0>( fy );
151 fxz = derivative<0>( fz );
152 fyy = derivative<1>( fy );
153 fyz = derivative<1>( fz );
154 fzz = derivative<2>( fz );
155 }
156
161 Ring operator()(const RealPoint &aPoint) const
162 {
163 Ring x = aPoint[ 0 ];
164 Ring y = aPoint[ 1 ];
165 Ring z = aPoint[ 2 ];
166 Ring t = aPoint[ 3 ];
167 RealVector3 grad( fx(x)(y)(z), fy(x)(y)(z), fz(x)(y)(z) );
168 return f(x)(y)(z) - t * grad.norm();
169 }
170
175 bool isInside(const RealPoint &aPoint) const
176 {
177 return this->operator()( aPoint ) <= NumberTraits<Ring>::ZERO;
178 }
179
186 Orientation orientation(const RealPoint &aPoint) const
187 {
188 Ring v = this->operator()( aPoint );
189 if ( v > NumberTraits<Ring>::ZERO ) return OUTSIDE;
190 else if ( v < NumberTraits<Ring>::ZERO ) return INSIDE;
191 else return ON;
192 }
193
198 inline
199 RealVector gradient( const RealPoint &aPoint ) const
200 {
201 Ring x = aPoint[ 0 ];
202 Ring y = aPoint[ 1 ];
203 Ring z = aPoint[ 2 ];
204 Ring t = aPoint[ 3 ];
205 RealVector3 grad( fx(x)(y)(z), fy(x)(y)(z), fz(x)(y)(z) );
206 Ring ngrad = grad.norm();
207 grad /= ngrad;
208 RealVector d_gradx( fxx(x)(y)(z), fxy(x)(y)(z),fxz(x)(y)(z) );
209 RealVector d_grady( fxy(x)(y)(z), fyy(x)(y)(z),fyz(x)(y)(z) );
210 RealVector d_gradz( fxz(x)(y)(z), fyz(x)(y)(z),fzz(x)(y)(z) );
211 return RealVector( grad[ 0 ] - t * d_gradx.dot( grad ),
212 grad[ 1 ] - t * d_grady.dot( grad ),
213 grad[ 2 ] - t * d_gradz.dot( grad ),
214 -ngrad );
215
216 }
217
218private:
219 Polynomial3 f;
220 Polynomial3 fx;
221 Polynomial3 fy;
222 Polynomial3 fz;
223 Polynomial3 fxx;
224 Polynomial3 fxy;
225 Polynomial3 fxz;
226 Polynomial3 fyy;
227 Polynomial3 fyz;
228 Polynomial3 fzz;
229};
230
235template <typename TSpace3, typename TSpace4, typename TPolynomial3>
236struct ImplicitSurface4DExtension {
237 typedef TSpace3 Space3;
238 typedef TSpace4 Space4;
239 typedef TPolynomial3 Polynomial3;
240 typedef typename Space3::RealPoint RealPoint3;
241 typedef typename Space3::RealVector RealVector3;
242 typedef typename Space3::Integer Integer;
243 typedef typename RealPoint3::Coordinate Ring;
244 typedef typename Space4::RealPoint RealPoint4;
245 typedef typename Space4::RealVector RealVector4;
246 typedef RealPoint4 RealPoint;
247 typedef RealVector4 RealVector;
248
249 ImplicitSurface4DExtension( Clone<Polynomial3> poly )
250 : f( poly )
251 {
252 fx = derivative<0>( f );
253 fy = derivative<1>( f );
254 fz = derivative<2>( f );
255 fxx = derivative<0>( fx );
256 fxy = derivative<0>( fy );
257 fxz = derivative<0>( fz );
258 fyy = derivative<1>( fy );
259 fyz = derivative<1>( fz );
260 fzz = derivative<2>( fz );
261 }
262
267 Ring operator()(const RealPoint &aPoint) const
268 {
269 Ring x = aPoint[ 0 ];
270 Ring y = aPoint[ 1 ];
271 Ring z = aPoint[ 2 ];
272 Ring t = aPoint[ 3 ];
273 // RealVector3 grad( fx(x)(y)(z), fy(x)(y)(z), fz(x)(y)(z) );
274 return f(x)(y)(z) - t;
275 }
276
281 bool isInside(const RealPoint &aPoint) const
282 {
283 return this->operator()( aPoint ) <= NumberTraits<Ring>::ZERO;
284 }
285
292 Orientation orientation(const RealPoint &aPoint) const
293 {
294 Ring v = this->operator()( aPoint );
295 if ( v > NumberTraits<Ring>::ZERO ) return OUTSIDE;
296 else if ( v < NumberTraits<Ring>::ZERO ) return INSIDE;
297 else return ON;
298 }
299
304 inline
305 RealVector gradient( const RealPoint &aPoint ) const
306 {
307 Ring x = aPoint[ 0 ];
308 Ring y = aPoint[ 1 ];
309 Ring z = aPoint[ 2 ];
310 Ring t = aPoint[ 3 ];
311 return RealVector( fx(x)(y)(z), fy(x)(y)(z), fz(x)(y)(z), -1.0 );
312 }
313
314private:
315 Polynomial3 f;
316 Polynomial3 fx;
317 Polynomial3 fy;
318 Polynomial3 fz;
319 Polynomial3 fxx;
320 Polynomial3 fxy;
321 Polynomial3 fxz;
322 Polynomial3 fyy;
323 Polynomial3 fyz;
324 Polynomial3 fzz;
325};
326
327
328template <typename CellOutputIterator, typename DigitalSurface>
329void
330analyzeSurface( CellOutputIterator itSure, CellOutputIterator itUnsure,
331 DigitalSurface surface )
332{
333 typedef typename DigitalSurface::KSpace KSpace;
334 typedef typename DigitalSurface::Surfel Surfel;
335 typedef typename DigitalSurface::ConstIterator ConstIterator;
336 typedef typename DigitalSurface::DigitalSurfaceContainer Container;
337 typedef typename DigitalSurface::DigitalSurfaceTracker Tracker;
338 typedef typename KSpace::Integer Integer;
339 typedef typename KSpace::Cell Cell;
340 const Dimension t = KSpace::dimension - 1;
341 const Container& C = surface.container();
342 const KSpace& K = surface.container().space();
343 Surfel s2;
344 for ( ConstIterator it = surface.begin(), itE = surface.end(); it != itE; ++it )
345 {
346 Surfel s = *it;
347 Cell is = K.unsigns( s );
348 Integer s_xt = K.sKCoord( s, t );
349 if ( s_xt == 0 ) *itUnsure++ = is;
350 else if ( s_xt == -1 )
351 {
352 CountedPtr<Tracker> tracker( C.newTracker( s ) );
353 if ( tracker->adjacent( s2, t, true ) != 0 )
354 {
355 Integer s2_xt = K.sKCoord( s2, t );
356 Cell ic = K.uIncident( is, t, true );
357 if ( s2_xt > 0 ) *itSure++ = ic;
358 else *itUnsure++ = ic;
359 }
360 }
361 else if ( s_xt == 1 )
362 {
363 CountedPtr<Tracker> tracker( C.newTracker( s ) );
364 if ( tracker->adjacent( s2, t, false ) != 0 )
365 {
366 Integer s2_xt = K.sKCoord( s2, t );
367 Cell ic = K.uIncident( is, t, false );
368 if ( s2_xt < 0 ) *itSure++ = ic;
369 else *itUnsure++ = ic;
370 }
371 }
372 else cout << " " << s_xt;
373 }
374}
375
384template <typename ImplicitSurface, typename RealPoint>
385RealPoint projectNewton( const ImplicitSurface & is,
386 RealPoint x,
387 typename RealPoint::Coordinate epsilon,
388 unsigned int max_iter )
389{
390 typedef typename RealPoint::Coordinate Scalar;
391 RealPoint gx;
392 Scalar f, g2;
393 Scalar eps2 = epsilon * epsilon;
394 while ( max_iter-- != 0 )
395 {
396 f = is( x );
397 if ( abs( f ) < epsilon ) return x;
398 gx = is.gradient( x );
399 g2 = gx.dot( gx );
400 if ( g2 < eps2 ) return x;
401 x -= (f/g2) * gx;
402 }
403 return x;
404}
405
406
407template <typename CubicalComplex4, typename ImplicitShape4,
408 typename ImplicitDigitalShape4, typename ImplicitShape3>
409void projectComplex( std::vector< typename ImplicitShape3::RealPoint >& points,
410 const CubicalComplex4& complex4,
411 const ImplicitShape4& shape,
412 const ImplicitDigitalShape4& dshape,
413 const ImplicitShape3& shape3,
414 double epsilon,
415 unsigned int max_iter )
416{
417 typedef typename CubicalComplex4::Cell Cell4;
418 typedef typename CubicalComplex4::Point Point4;
419 typedef typename CubicalComplex4::CellMapConstIterator CellMapConstIterator;
420 typedef typename ImplicitShape4::RealPoint RealPoint4;
421 typedef typename ImplicitShape4::Ring Ring;
422 typedef typename ImplicitShape3::RealPoint RealPoint3;
423 points.clear();
424 for ( CellMapConstIterator it = complex4.begin( 0 ), itE = complex4.end( 0 ); it != itE; ++it )
425 {
426 Cell4 cell = it->first;
427 Point4 dp = complex4.space().uCoords( cell );
428 RealPoint4 p = dshape->embed( dp );
429 RealPoint3 p3 = RealPoint3( p[ 0 ], p[ 1 ], p[ 2 ] );
430 RealPoint3 q = projectNewton( shape3, p3, epsilon, max_iter );
431 points.push_back( q );
432 }
433}
434
435template <typename CubicalComplex4, typename ImplicitShape4,
436 typename ImplicitDigitalShape4, typename ImplicitShape3>
437void doNotProjectComplex( std::vector< typename ImplicitShape3::RealPoint >& points,
438 const CubicalComplex4& complex4,
439 const ImplicitShape4& shape,
440 const ImplicitDigitalShape4& dshape,
441 const ImplicitShape3& shape3 )
442{
443 typedef typename CubicalComplex4::Cell Cell4;
444 typedef typename CubicalComplex4::Point Point4;
445 typedef typename CubicalComplex4::CellMapConstIterator CellMapConstIterator;
446 typedef typename ImplicitShape4::RealPoint RealPoint4;
447 typedef typename ImplicitShape4::Ring Ring;
448 typedef typename ImplicitShape3::RealPoint RealPoint3;
449 for ( CellMapConstIterator it = complex4.begin( 0 ), itE = complex4.end( 0 ); it != itE; ++it )
450 {
451 Cell4 cell = it->first;
452 Point4 dp = complex4.space().uCoords( cell );
453 RealPoint4 p = dshape->embed( dp );
454 RealPoint3 p3 = RealPoint3( p[ 0 ], p[ 1 ], p[ 2 ] );
455 points.push_back( p3 );
456 }
457}
458
459
460int main( int argc, char** argv )
461{
462 typedef int Integer;
463 typedef SpaceND<3,Integer> Space3;
464 typedef KhalimskySpaceND<3,Integer> KSpace3;
465 typedef KSpace3::Cell Cell3;
466 typedef std::map<Cell3, CubicalCellData> Map3;
467 typedef CubicalComplex< KSpace3, Map3 > CC3;
468 typedef Space3::Point Point3;
469 typedef Space3::RealPoint RealPoint3;
470 typedef RealPoint3::Coordinate Ring;
471 typedef Ring Scalar;
472 typedef MPolynomial<3, Ring> Polynomial3;
473 typedef MPolynomialReader<3, Ring> Polynomial3Reader;
474 typedef ImplicitPolynomial3Shape<Space3> ImplicitShape3;
475 typedef SpaceND<4,Integer> Space4;
476 typedef KhalimskySpaceND<4,Integer> KSpace4;
477 typedef KSpace4::Cell Cell4;
478 typedef KSpace4::Cells Cells4;
479 typedef KSpace4::SCell SCell4;
480 typedef Space4::Point Point4;
481 typedef Space4::RealPoint RealPoint4;
482 typedef Space4::RealVector RealVector4;
483 typedef ImplicitSurface4DProductExtension<Space3,Space4,Polynomial3>
484 ImplicitShape4;
485 typedef GaussDigitizer< Space4, ImplicitShape4 >
486 ImplicitDigitalShape4;
487 typedef ImplicitDigitalShape4::Domain Domain4;
488 typedef std::map<Cell4, CubicalCellData> Map4;
489 typedef CubicalComplex< KSpace4, Map4 > CC4;
490 typedef CC4::CellMapIterator CellMapIterator;
491 typedef CC4::CellMapConstIterator CellMapConstIterator;
492 typedef CC4::Cells Cells4;
493
494
495 // parse command line using CLI ----------------------------------------------
496 CLI::App app;
497 string poly_str;
498 std::string outputFileName {"result.raw"};
499 DGtal::int64_t rescaleInputMin {0};
500 DGtal::int64_t rescaleInputMax {255};
501 Ring min_x {-10.0};
502 Ring max_x {10.0};
503 Ring h {1.0};
504 Ring t {0.000001};
505
506 std::string project {"Newton"};
507 double epsilon {1e-6};
508 unsigned int max_iter {500};
509 std::string view {"Normal"};
510 app.description( "Computes the zero level set of the given polynomial. Usage: 3dImplicitSurfaceExtractorBy4DExtension -p <polynomial> [options]\n Example:\n 3dImplicitSurfaceExtractorBy4DExtension -p \"-0.9*(y^2+z^2-1)^2-(x^2+y^2-1)^3\" -g 0.06125 -a -2 -A 2 -v Singular -t 0.02 \n - whitney : x^2-y*z^2 \n - 4lines : x*y*(y-x)*(y-z*x) \n - cone : z^2-x^2-y^2 \n - simonU : x^2-z*y^2+x^4+y^4 \n - cayley3 : 4*(x^2 + y^2 + z^2) + 16*x*y*z - 1 \n - crixxi : -0.9*(y^2+z^2-1)^2-(x^2+y^2-1)^3 \n Some other examples (more difficult): \n 3dImplicitSurfaceExtractorBy4DExtension -a -2 -A 2 -p \"((y^2+z^2-1)^2-(x^2+y^2-1)^3)*(y*(x-1)^2-z*(x+1))^2\" -g 0.025 -e 1e-6 -n 50000 -v Singular -t 0.5 -P Newton \n 3dImplicitSurfaceExtractorBy4DExtension -a -2 -A 2 -p \"(x^5-4*z^3*y^2)*((x+y)^2-(z-x)^3)\" -g 0.025 -e 1e-6 -n 50000 -v Singular -t 0.05 -P Newton ");
511 app.add_option("-p,--polynomial,1", poly_str, "the implicit polynomial whose zero-level defines the shape of interest." )
512 ->required();
513 app.add_option("--minAABB,-a",min_x, "the min value of the AABB bounding box (domain)" );
514 app.add_option("--maxAABB,-A",max_x, "the max value of the AABB bounding box (domain)" );
515 app.add_option("--gridstep,-g", h, "the gridstep that defines the digitization in the 4th dimension (small is generally a good idea, default is 1e-6). ");
516 app.add_option("--timestep,-t",t, "the thickening parameter for the implicit surface." );
517 app.add_option("--project,-P", project, "defines the projection: either No or Newton.")
518 -> check(CLI::IsMember({"No", "Newton"}));
519 app.add_option("--epsilon,-e", epsilon, "the maximum precision relative to the implicit surface in the Newton approximation of F=0.");
520 app.add_option("--max_iter,-n", max_iter, "the maximum number of iteration in the Newton approximation of F=0.");
521 app.add_option("--view,-v", view, "specifies if the surface is viewed as is (Normal) or if places close to singularities are highlighted (Singular), or if unsure places should not be displayed (Hide).")
522 -> check(CLI::IsMember({"Singular", "Normal", "Hide"}));
523
524 app.get_formatter()->column_width(40);
525 CLI11_PARSE(app, argc, argv);
526 // END parse command line using CLI ----------------------------------------------
527
528
529 //-------------- read polynomial and creating 4d implicit fct -----------------
530 trace.beginBlock( "Reading polynomial and creating 4D implicit function" );
531 Polynomial3 poly;
532 Polynomial3Reader reader;
533 string::const_iterator iter = reader.read( poly, poly_str.begin(), poly_str.end() );
534 if ( iter != poly_str.end() )
535 {
536 trace.error() << "ERROR reading polynomial: I read only <" << poly_str.substr( 0, iter - poly_str.begin() )
537 << ">, and I built P=" << poly << std::endl;
538 return 2;
539 }
540 // Creating implicit shape and storing it with smart pointer for automatic deallocation.
541 ImplicitShape3 shape3( poly );
542 CountedPtr<ImplicitShape4> shape( new ImplicitShape4( poly ) );
543
544
545 RealPoint4 p1( min_x, min_x, min_x, -t*h );
546 RealPoint4 p2( max_x, max_x, max_x, 0 );
547 // Creating digitized shape and storing it with smart pointer for automatic deallocation.
548 CountedPtr<ImplicitDigitalShape4> dshape( new ImplicitDigitalShape4() );
549 dshape->attach( *shape );
550 dshape->init( p1, p2, RealVector4( h, h, h, t ) );
551 Domain4 domain4 = dshape->getDomain();
552 KSpace4 K4;
553 K4.init( domain4.lowerBound(), domain4.upperBound(), true );
554 trace.info() << "- domain is " << domain4 << std::endl;
555 trace.endBlock();
556
557 //-------------- read polynomial and creating 4d implicit fct -----------------
558 trace.beginBlock( "Extracting isosurface 0 of 4D polynomial. " );
559 CC4 complex4( K4 );
560 std::vector<SCell4> surface_cells;
561 std::back_insert_iterator< std::vector<SCell4> > outItSurface( surface_cells );
562 Surfaces<KSpace4>::sWriteBoundary( outItSurface,
563 K4, *dshape, domain4.lowerBound(), domain4.upperBound() );
564 trace.info() << "- 4D surface has " << surface_cells.size() << " 3-cells." << endl;
565 typedef SetOfSurfels<KSpace4> SurfaceContainer;
566 SurfaceContainer* ptrF0 = new SurfaceContainer( K4, SurfelAdjacency< KSpace4::dimension >( false ) );
567 ptrF0->surfelSet().insert( surface_cells.begin(), surface_cells.end() );
568 DigitalSurface<SurfaceContainer> surface( ptrF0 );
569 std::vector<Cell4> sure_cells;
570 std::vector<Cell4> unsure_cells;
571 analyzeSurface( std::back_inserter( sure_cells ), std::back_inserter( unsure_cells ),
572 surface );
573 trace.info() << "- sure cells = " << sure_cells.size() << endl;
574 trace.info() << "- unsure cells = " << unsure_cells.size() << endl;
575 CubicalCellData unsure_data( 0 );
576 CubicalCellData sure_data( CC4::FIXED );
577 complex4.insertCells( sure_cells.begin(), sure_cells.end(), sure_data );
578 complex4.insertCells( unsure_cells.begin(), unsure_cells.end(), unsure_data );
579 surface_cells.clear();
580 trace.endBlock();
581
582 //-------------- Get boundary and inner cells --------------------------------
583 trace.beginBlock( "Get boundary and inner cells. " );
584 std::vector<Cell4> inner;
585 std::vector<Cell4> bdry;
586 complex4.close();
587 trace.info() << "- K=" << complex4 << endl;
588 functions::filterCellsWithinBounds
589 ( complex4, K4.uKCoords( K4.lowerCell() ), K4.uKCoords( K4.upperCell() ),
590 std::back_inserter( bdry ), std::back_inserter( inner ) );
591 trace.info() << "- there are " << inner.size() << " inner cells." << endl;
592 trace.info() << "- there are " << bdry.size() << " boundary cells." << endl;
593 trace.endBlock();
594
595 //-------------- Compute priority function -----------------------------------
596 trace.beginBlock( "Compute priority function. " );
597 Dimension d = complex4.dim();
598 for ( Dimension i = 0; i <= d; ++i )
599 {
600 for ( CellMapIterator it = complex4.begin( i ), itE = complex4.end( i ); it != itE; ++it )
601 {
602 Cell4 cell = it->first;
603 Point4 dp = K4.uCoords( cell );
604 RealPoint4 p = dshape->embed( dp );
605 Ring v = (*shape)( p );
606 v = abs( 1000.0*v );
607 if ( v > 1000000.0 ) v = 1000000.0;
608 it->second.data &= ~CC4::VALUE;
609 it->second.data |= (DGtal::uint32_t) floor( v );
610 // std::cout << " " << it->second.data;
611 }
612 }
613 trace.endBlock();
614
615 //-------------- Collapse boundary -------------------------------------------
616 trace.beginBlock( "Collapse boundary. " );
617 typename CC4::DefaultCellMapIteratorPriority priority;
618 CC4 bdry_complex4( K4 );
619 for ( std::vector<Cell4>::const_iterator it = bdry.begin(), itE = bdry.end(); it != itE; ++it )
620 {
621 Cell4 cell = *it;
622 Dimension d = K4.uDim( cell );
623 CellMapConstIterator cmIt = complex4.findCell( d, cell );
624 bdry_complex4.insertCell( d, cell, cmIt->second );
625 }
626 //bdry_complex4.insertCells( bdry.begin(), bdry.end() );
627 trace.info() << "- [before collapse] K_bdry =" << bdry_complex4 << endl;
628 functions::collapse( bdry_complex4, bdry.begin(), bdry.end(), priority, true, true, true );
629 trace.info() << "- [after collapse] K_bdry =" << bdry_complex4 << endl;
630 for ( std::vector<Cell4>::const_iterator it = bdry.begin(), itE = bdry.end(); it != itE; ++it )
631 {
632 Cell4 cell = *it;
633 Dimension d = K4.uDim( cell );
634 CellMapConstIterator cmIt = bdry_complex4.findCell( d, cell );
635 if ( cmIt != bdry_complex4.end( d ) ) {
636 CellMapIterator cmIt2 = complex4.findCell( d, cell );
637 cmIt2->second = sure_data;
638 }
639 }
640 trace.endBlock();
641
642 //-------------- Collapse all -------------------------------------------
643 trace.beginBlock( "Collapse all. " );
644 std::copy( bdry.begin(), bdry.end(), std::back_inserter( inner ) );
645 //typename CC4::DefaultCellMapIteratorPriority priority;
646 functions::collapse( complex4, inner.begin(), inner.end(), priority, true, true, true );
647 trace.info() << "- K=" << complex4 << endl;
648 trace.endBlock();
649
650 //-------------- Project complex onto surface --------------------------------
651 trace.beginBlock( "Project complex onto surface. " );
652 std::vector<RealPoint3> points;
653 if ( project == "Newton" )
654 projectComplex( points, complex4, *shape, dshape, shape3, epsilon, max_iter );
655 else
656 doNotProjectComplex( points, complex4, *shape, dshape, shape3 );
657 trace.endBlock();
658
659 //-------------- Create Mesh -------------------------------------------
660 trace.beginBlock( "Create Mesh. " );
661 bool highlight = ( view == "Singular" );
662 Mesh<RealPoint3> mesh( true );
663 std::map<Cell4,unsigned int> indices;
664 int idx = 0;
665 for ( CellMapConstIterator it = complex4.begin( 0 ), itE = complex4.end( 0 ); it != itE; ++it, ++idx )
666 {
667 Cell4 cell = it->first;
668 indices[ cell ] = idx;
669 mesh.addVertex( points[ idx ] );
670 }
671 for ( CellMapConstIterator it = complex4.begin( 2 ), itE = complex4.end( 2 ); it != itE; ++it, ++idx )
672 {
673 Cell4 cell = it->first;
674 bool fixed = it->second.data & CC4::FIXED;
675 Cells4 bdry = complex4.cellBoundary( cell, true );
676 std::vector<unsigned int> face_idx;
677 for ( Cells4::const_iterator itC = bdry.begin(), itCE = bdry.end(); itC != itCE; ++itC )
678 {
679 if ( complex4.dim( *itC ) == 0 )
680 face_idx.push_back( indices[ *itC ] );
681 }
682 Color color = highlight
683 ? ( fixed ? Color::White : Color(128,255,128) )
684 : Color::White;
685 mesh.addQuadFace( face_idx[ 0 ], face_idx[ 1 ], face_idx[ 3 ], face_idx[ 2 ], color );
686 }
687 trace.endBlock();
688
689 //-------------- View surface -------------------------------------------
690 Point4 low4 = K4.lowerBound();
691 Point4 up4 = K4.upperBound();
692 KSpace3 K3;
693 K3.init( Point3( low4[ 0 ], low4[ 1 ], low4[ 2 ] ),
694 Point3( up4 [ 0 ], up4 [ 1 ], up4 [ 2 ] ), true );
695
696 PolyscopeViewer<Space3,KSpace3> viewer( K3 );
697 viewer << mesh;
698 viewer.drawColor( highlight ? Color::Red : Color( 120, 120, 120 ) );
699 // Drawing lines
700 for ( CellMapConstIterator it = complex4.begin( 1 ), itE = complex4.end( 1 ); it != itE; ++it )
701 {
702 Cell4 cell = it->first;
703 std::vector<Cell4> dummy;
704 std::back_insert_iterator< std::vector<Cell4> > outIt1( dummy );
705 complex4.directCoFaces( outIt1, cell );
706 if ( ! dummy.empty() ) continue;
707 Cells4 vertices = complex4.cellBoundary( cell );
708 ASSERT( vertices.size() == 2 );
709 RealPoint3 p1 = points[ indices[ vertices.front() ] ];
710 RealPoint3 p2 = points[ indices[ vertices.back() ] ];
711 viewer.drawLine( p1, p2 );
712 }
713 viewer.show();
714 return 0;
715}
Definition ATu0v1.h:57