From 50fabbec8d3a87bd4123c3c84813c0ce8cda505e Mon Sep 17 00:00:00 2001 From: Guillaume Damiand Date: Mon, 15 Jun 2015 22:59:00 +0200 Subject: [PATCH] Add delaunay triangulation of faces --- .../demo/Linear_cell_complex/MainWindow.cpp | 264 +++++++++++++++++- .../demo/Linear_cell_complex/MainWindow.h | 4 +- .../demo/Linear_cell_complex/MainWindow.ui | 17 +- 3 files changed, 279 insertions(+), 6 deletions(-) diff --git a/Linear_cell_complex/demo/Linear_cell_complex/MainWindow.cpp b/Linear_cell_complex/demo/Linear_cell_complex/MainWindow.cpp index 610dfdfe557..97ed18e2d49 100644 --- a/Linear_cell_complex/demo/Linear_cell_complex/MainWindow.cpp +++ b/Linear_cell_complex/demo/Linear_cell_complex/MainWindow.cpp @@ -27,6 +27,11 @@ #include "MainWindow.moc" #include "import_moka.h" +#include +#include +#include +#include + // Function defined in Linear_cell_complex_3_subivision.cpp void subdivide_lcc_3 (LCC & m); @@ -928,7 +933,7 @@ void MainWindow::on_actionRemove_filled_volumes_triggered() DELAY_STATUSMSG); } -void MainWindow::on_actionTriangulate_all_facets_triggered() +void MainWindow::on_actionInsert_center_vertices_triggered() { QApplication::setOverrideCursor (Qt::WaitCursor); @@ -950,17 +955,83 @@ void MainWindow::on_actionTriangulate_all_facets_triggered() #ifdef CGAL_PROFILE_LCC_DEMO timer.stop(); - std::cout<<"Time to triangulate all filled faces: " + std::cout<<"Time to insert center vertices in all filled faces: " <showMessage - (QString ("Facets of visible and filled volume(s) triangulated"), + (QString ("Vertices are inserted in center of facets of visible and filled volume(s)"), DELAY_STATUSMSG); } +double compute_angle3d(const Vector_3& v1, const Vector_3& v2) +{ + double a = CGAL::to_double( (v1*v2) / + ( sqrt(v1.squared_length()) * sqrt(v2.squared_length()) ) ) ; + + if (a < -1.0) return acos(-1.0)/M_PI*180.0; + else if (a > 1.0) return acos(1.0)/M_PI*180.0; + else return acos(a)/M_PI*180.0; +} + +void MainWindow::on_actionMerge_coplanar_faces_triggered() +{ + QApplication::setOverrideCursor (Qt::WaitCursor); + +#ifdef CGAL_PROFILE_LCC_DEMO + CGAL::Timer timer; + timer.start(); +#endif + + std::vector edges; + int treated = scene.lcc->get_new_mark(); + + for ( typename LCC::Dart_range::iterator it= scene.lcc->darts().begin(), + itend = scene.lcc->darts().end(); it!=itend; ++it ) + { + if (!scene.lcc->is_marked(it, treated) && + CGAL::is_removable(*scene.lcc, it) ) + { + LCC::Vector normal1 = CGAL::compute_normal_of_cell_2(*scene.lcc,it); + LCC::Vector normal2 = CGAL::compute_normal_of_cell_2(*scene.lcc, scene.lcc->beta<2>(it) ); + double angle = compute_angle3d(normal1, normal2); + + if ( ((angle<5.0 or angle>355.0) or (angle<185.0 and angle>175.0)) ) + { + CGAL::mark_cell(*scene.lcc, it, treated); + edges.push_back(it); + } + } + } + + for (std::vector::iterator it=edges.begin(), + itend=edges.end(); it!=itend; ++it) + { + if ( !CGAL::belong_to_same_cell(*scene.lcc, *it, scene.lcc->beta<2>(*it)) ) + CGAL::remove_cell(*scene.lcc, *it); + else + CGAL::unmark_cell(*scene.lcc, *it, treated); + } + + assert(scene.lcc->is_whole_map_unmarked(treated)); + scene.lcc->free_mark(treated); + +#ifdef CGAL_PROFILE_LCC_DEMO + timer.stop(); + std::cout<<"Time to merge all coplanar faces: " + <showMessage + (QString ("Coplanar face(s) merged"), DELAY_STATUSMSG); +} + void MainWindow::on_actionMerge_all_volumes_triggered() { QApplication::setOverrideCursor (Qt::WaitCursor); @@ -1006,6 +1077,193 @@ void MainWindow::on_actionMerge_all_volumes_triggered() (QString ("Visible and filled volume(s) merged"), DELAY_STATUSMSG); } +typedef CGAL::Triangulation_2_filtered_projection_traits_3 P_traits; +typedef CGAL::Triangulation_vertex_base_with_info_2 Vb; + +struct Face_info { + bool exist_edge[3]; + bool is_external; +}; + +typedef CGAL::Triangulation_face_base_with_info_2 Fb1; + +typedef CGAL::Constrained_triangulation_face_base_2 Fb; +typedef CGAL::Triangulation_data_structure_2 TDS; +typedef CGAL::No_intersection_tag Itag; +typedef CGAL::Constrained_Delaunay_triangulation_2 CDT; + +bool is_external(CDT::Face_handle fh) +{ + return fh->info().is_external; +} + +int number_of_existing_edge(CDT::Face_handle fh) +{ + unsigned res=0; + for (int i=0; i<3; ++i) + if (fh->info().exist_edge[i]) ++res; + return res; +} + +int get_free_edge(CDT::Face_handle fh) +{ + CGAL_assertion( number_of_existing_edge(fh)==2 ); + for (int i=0; i<3; ++i) + if (!fh->info().exist_edge[i]) return i; + + CGAL_assertion(false); + return -1; +} + +void constrained_delaunay_triangulation(LCC &lcc, Dart_handle d1) +{ + Vector_3 normal = CGAL::compute_normal_of_cell_2(lcc,d1); + P_traits cdt_traits(normal); + CDT cdt(cdt_traits); + + //inserting the constraints edge by edge + LCC::Dart_of_orbit_range<1>::iterator + it(lcc.darts_of_orbit<1>(d1).begin()); + + CDT::Vertex_handle previous=LCC::null_handle, first=LCC::null_handle, + vh=LCC::null_handle; + + for (LCC::Dart_of_orbit_range<1>::iterator + itend(lcc.darts_of_orbit<1>(d1).end()); it!=itend; ++it) + { + vh = cdt.insert(lcc.point(it)); + vh->info()=it; + if( first==NULL ) + { + first=vh; + } + if( previous!=NULL) + { + CGAL_assertion( previous !=vh ); + cdt.insert_constraint(previous,vh); + } + + previous=vh; + } + cdt.insert_constraint(previous,first); + CGAL_assertion(cdt.is_valid()); + + // sets mark is_external + for( CDT::All_faces_iterator fit = cdt.all_faces_begin(), + fitend = cdt.all_faces_end(); fit != fitend; ++fit) + { + fit->info().is_external = false; + fit->info().exist_edge[0]=false; + fit->info().exist_edge[1]=false; + fit->info().exist_edge[2]=false; + } + + std::queue face_queue; + + face_queue.push(cdt.infinite_vertex()->face()); + while(! face_queue.empty() ) + { + CDT::Face_handle fh = face_queue.front(); + face_queue.pop(); + if(!fh->info().is_external) + { + fh->info().is_external = true; + for(int i = 0; i <3; ++i) + { + if(!cdt.is_constrained(std::make_pair(fh, i))) + { + face_queue.push(fh->neighbor(i)); + } + } + } + } + for( CDT::Finite_edges_iterator eit = cdt.finite_edges_begin(), + eitend = cdt.finite_edges_end(); eit != eitend; ++eit) + { + CDT::Face_handle fh = eit->first; + int index = eit->second; + CDT::Face_handle opposite_fh = fh->neighbor(index); + if(cdt.is_constrained(std::make_pair(fh, index))) + { + fh->info().exist_edge[index]=true; + opposite_fh->info().exist_edge[cdt.mirror_index(fh,index)]=true; + + if ( !fh->info().is_external && number_of_existing_edge(fh)==2 ) + face_queue.push(fh); + if ( !opposite_fh->info().is_external && + number_of_existing_edge(opposite_fh)==2 ) + face_queue.push(opposite_fh); + } + } + + while( !face_queue.empty() ) + { + CDT::Face_handle fh = face_queue.front(); + face_queue.pop(); + CGAL_assertion( number_of_existing_edge(fh)>=2 ); // i.e. ==2 or ==3 + CGAL_assertion( !fh->info().is_external ); + + if (number_of_existing_edge(fh)==2) + { + int index = get_free_edge(fh); + CDT::Face_handle opposite_fh = fh->neighbor(index); + + CGAL_assertion( !fh->info().exist_edge[index] ); + CGAL_assertion( !opposite_fh->info(). + exist_edge[cdt.mirror_index(fh,index)] ); + const CDT::Vertex_handle va = fh->vertex(cdt. cw(index)); + const CDT::Vertex_handle vb = fh->vertex(cdt.ccw(index)); + + Dart_handle ndart= + CGAL::insert_cell_1_in_cell_2(lcc,va->info(),vb->info()); + va->info()=lcc.beta<2>(ndart); + + fh->info().exist_edge[index]=true; + opposite_fh->info().exist_edge[cdt.mirror_index(fh,index)]=true; + + if ( !opposite_fh->info().is_external && + number_of_existing_edge(opposite_fh)==2 ) + face_queue.push(opposite_fh); + } + } +} + +void MainWindow::on_actionTriangulate_all_facets_triggered() +{ + QApplication::setOverrideCursor (Qt::WaitCursor); + +#ifdef CGAL_PROFILE_LCC_DEMO + CGAL::Timer timer; + timer.start(); +#endif + + std::vector v; + for (LCC::One_dart_per_cell_range<2>::iterator + it(scene.lcc->one_dart_per_cell<2>().begin()); it.cont(); ++it) + { + if ( scene.lcc->info<3>(it).is_filled_and_visible() ) + v.push_back(it); + } + + for (std::vector::iterator itv(v.begin()); + itv!=v.end(); ++itv) + constrained_delaunay_triangulation(*scene.lcc, *itv); + +#ifdef CGAL_PROFILE_LCC_DEMO + timer.stop(); + std::cout<<"Time to triangulate all filled faces: " + <showMessage + (QString ("All visible and filled faces were triangulated"), DELAY_STATUSMSG); +} + bool MainWindow::is_volume_in_list(LCC::Attribute_handle<3>::type ah) { for(int row=0; row < volumeList->rowCount(); ++row) diff --git a/Linear_cell_complex/demo/Linear_cell_complex/MainWindow.h b/Linear_cell_complex/demo/Linear_cell_complex/MainWindow.h index 94ece0289c1..2e58379a474 100644 --- a/Linear_cell_complex/demo/Linear_cell_complex/MainWindow.h +++ b/Linear_cell_complex/demo/Linear_cell_complex/MainWindow.h @@ -133,11 +133,13 @@ public Q_SLOTS: void on_actionSubdivide_pqq_triggered(); void on_actionDual_3_triggered(); void on_actionClose_volume_triggered(); - void on_actionTriangulate_all_facets_triggered(); void on_actionSew3_same_facets_triggered(); void on_actionUnsew3_all_triggered(); + void on_actionMerge_coplanar_faces_triggered(); void on_actionMerge_all_volumes_triggered(); void on_actionRemove_filled_volumes_triggered(); + void on_actionInsert_center_vertices_triggered(); + void on_actionTriangulate_all_facets_triggered(); // View menu void on_actionExtend_filled_volumes_triggered(); diff --git a/Linear_cell_complex/demo/Linear_cell_complex/MainWindow.ui b/Linear_cell_complex/demo/Linear_cell_complex/MainWindow.ui index 33291ca159e..321dc4f3bc1 100644 --- a/Linear_cell_complex/demo/Linear_cell_complex/MainWindow.ui +++ b/Linear_cell_complex/demo/Linear_cell_complex/MainWindow.ui @@ -58,12 +58,15 @@ &Operations + - - + + + + @@ -240,6 +243,16 @@ Import Moka + + + Merge coplanar faces + + + + + Insert center vertices in faces + +