mirror of https://github.com/CGAL/cgal
Add delaunay triangulation of faces
This commit is contained in:
parent
4bae2612d8
commit
50fabbec8d
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -58,12 +58,15 @@
|
|||
<property name="title">
|
||||
<string>&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>
|
||||
|
|
|
|||
Loading…
Reference in New Issue