Add delaunay triangulation of faces

This commit is contained in:
Guillaume Damiand 2015-06-15 22:59:00 +02:00
parent 4bae2612d8
commit 50fabbec8d
3 changed files with 279 additions and 6 deletions

View File

@ -27,6 +27,11 @@
#include "MainWindow.moc"
#include "import_moka.h"
#include <CGAL/Triangulation_2_filtered_projection_traits_3.h>
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
#include <CGAL/Triangulation_face_base_with_info_2.h>
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
// 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: "
<<timer.time()<<" seconds."<<std::endl;
#endif
QApplication::restoreOverrideCursor ();
Q_EMIT (sceneChanged ());
statusBar()->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<Dart_handle> 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<LCC, 1>(*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<LCC, 1>(*scene.lcc, it, treated);
edges.push_back(it);
}
}
}
for (std::vector<Dart_handle>::iterator it=edges.begin(),
itend=edges.end(); it!=itend; ++it)
{
if ( !CGAL::belong_to_same_cell<LCC, 2>(*scene.lcc, *it, scene.lcc->beta<2>(*it)) )
CGAL::remove_cell<LCC, 1>(*scene.lcc, *it);
else
CGAL::unmark_cell<LCC, 1>(*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: "
<<timer.time()<<" seconds."<<std::endl;
#endif
recreate_whole_volume_list();
QApplication::restoreOverrideCursor ();
Q_EMIT (sceneChanged ());
statusBar()->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<Mytraits> P_traits;
typedef CGAL::Triangulation_vertex_base_with_info_2<Dart_handle,P_traits> Vb;
struct Face_info {
bool exist_edge[3];
bool is_external;
};
typedef CGAL::Triangulation_face_base_with_info_2<Face_info,P_traits> Fb1;
typedef CGAL::Constrained_triangulation_face_base_2<P_traits, Fb1> Fb;
typedef CGAL::Triangulation_data_structure_2<Vb,Fb> TDS;
typedef CGAL::No_intersection_tag Itag;
typedef CGAL::Constrained_Delaunay_triangulation_2<P_traits, TDS,
Itag> 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<CDT::Face_handle> 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<LCC::Dart_handle> 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<LCC::Dart_handle>::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: "
<<timer.time()<<" seconds."<<std::endl;
#endif
recreate_whole_volume_list();
QApplication::restoreOverrideCursor ();
Q_EMIT (sceneChanged ());
statusBar()->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)

View File

@ -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();

View File

@ -58,12 +58,15 @@
<property name="title">
<string>&amp;Operations</string>
</property>
<addaction name="actionInsert_center_vertices"/>
<addaction name="actionTriangulate_all_facets"/>
<addaction name="actionSew3_same_facets"/>
<addaction name="actionUnsew3_all"/>
<addaction name="actionMerge_coplanar_faces"/>
<addaction name="actionMerge_all_volumes"/>
<addaction name="actionRemove_filled_volumes"/>
<addaction name="separator"/>
<addaction name="actionSew3_same_facets"/>
<addaction name="actionUnsew3_all"/>
<addaction name="separator"/>
<addaction name="actionSubdivide"/>
<addaction name="actionSubdivide_pqq"/>
<addaction name="actionClose_volume"/>
@ -240,6 +243,16 @@
<string>Import Moka</string>
</property>
</action>
<action name="actionMerge_coplanar_faces">
<property name="text">
<string>Merge coplanar faces</string>
</property>
</action>
<action name="actionInsert_center_vertices">
<property name="text">
<string>Insert center vertices in faces</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>