mirror of https://github.com/CGAL/cgal
CGAL Lab: Rendering polygons with ghost edges (#7898)
Polygons and meshes with non-triangular faces that have ghost edges, i.e., holes connected via two identical edges to the outer border of the polygon, are now correctly rendered. The FacetTriangulator now uses mark_domain_in_triangulation to set is_external property. ## Release Management * Affected package(s): Polyhedron/demo
This commit is contained in:
commit
61800d1be7
|
|
@ -190,13 +190,10 @@ private:
|
||||||
|
|
||||||
for(boost::graph_traits<Face_graph>::face_descriptor f : faces(*poly)) {
|
for(boost::graph_traits<Face_graph>::face_descriptor f : faces(*poly)) {
|
||||||
Vector nf = get(nf_pmap, f);
|
Vector nf = get(nf_pmap, f);
|
||||||
typedef FacetTriangulator<Face_graph, Kernel, boost::graph_traits<Face_graph>::vertex_descriptor> FT;
|
|
||||||
|
|
||||||
//compute distance with other polyhedron
|
//compute distance with other polyhedron
|
||||||
//sample facet
|
//sample facet
|
||||||
std::vector<Kernel::Point_3> sampled_points;
|
std::vector<Kernel::Point_3> sampled_points;
|
||||||
std::size_t nb_points = (std::max)((int)std::ceil(nb_pts_per_face * PMP::face_area(f,*poly,CGAL::parameters::geom_traits(Kernel()))),
|
std::size_t nb_points = (std::max)((int)std::ceil(nb_pts_per_face * PMP::face_area(f,*poly,CGAL::parameters::geom_traits(Kernel()))), 1);
|
||||||
1);
|
|
||||||
Kernel::Point_3 &p = get(vpmap,target(halfedge(f,*poly),*poly));
|
Kernel::Point_3 &p = get(vpmap,target(halfedge(f,*poly),*poly));
|
||||||
Kernel::Point_3 &q = get(vpmap,target(next(halfedge(f,*poly),*poly),*poly));
|
Kernel::Point_3 &q = get(vpmap,target(next(halfedge(f,*poly),*poly),*poly));
|
||||||
Kernel::Point_3 &r = get(vpmap,target(next(next(halfedge(f,*poly),*poly),*poly),*poly));
|
Kernel::Point_3 &r = get(vpmap,target(next(next(halfedge(f,*poly),*poly),*poly),*poly));
|
||||||
|
|
@ -207,36 +204,42 @@ private:
|
||||||
sampled_points.push_back(r);
|
sampled_points.push_back(r);
|
||||||
|
|
||||||
//triangle facets with sample points for color display
|
//triangle facets with sample points for color display
|
||||||
FT triangulation(f,sampled_points,nf,poly);
|
auto func = [&](auto& ffit, auto&) {
|
||||||
|
if (ffit.info().is_external)
|
||||||
|
return;
|
||||||
|
|
||||||
if(triangulation.cdt->dimension() != 2 )
|
for (int i = 0; i < 3; ++i)
|
||||||
{
|
|
||||||
qDebug()<<"Error : cdt not right (dimension != 2). Facet not displayed";
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//iterates on the internal faces to add the vertices to the positions
|
|
||||||
//and the normals to the appropriate vectors
|
|
||||||
|
|
||||||
for(FT::CDT::Finite_faces_iterator
|
|
||||||
ffit = triangulation.cdt->finite_faces_begin(),
|
|
||||||
end = triangulation.cdt->finite_faces_end();
|
|
||||||
ffit != end; ++ffit)
|
|
||||||
{
|
|
||||||
if(ffit->info().is_external)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (int i = 0; i<3; ++i)
|
|
||||||
{
|
{
|
||||||
total_points.push_back(ffit->vertex(i)->point());
|
total_points.push_back(ffit.vertex(i)->point());
|
||||||
m_vertices.push_back(ffit->vertex(i)->point().x());
|
m_vertices.push_back(ffit.vertex(i)->point().x());
|
||||||
m_vertices.push_back(ffit->vertex(i)->point().y());
|
m_vertices.push_back(ffit.vertex(i)->point().y());
|
||||||
m_vertices.push_back(ffit->vertex(i)->point().z());
|
m_vertices.push_back(ffit.vertex(i)->point().z());
|
||||||
|
|
||||||
normals.push_back(nf.x());
|
normals.push_back(nf.x());
|
||||||
normals.push_back(nf.y());
|
normals.push_back(nf.y());
|
||||||
normals.push_back(nf.z());
|
normals.push_back(nf.z());
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
FacetTriangulator<Face_graph, Kernel, boost::graph_traits<Face_graph>::vertex_descriptor> triangulation(f, sampled_points, nf, poly);
|
||||||
|
|
||||||
|
if (triangulation.cdt->dimension() != 2)
|
||||||
|
{
|
||||||
|
qDebug() << "Error : cdt not right (dimension != 2). Facet not displayed";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
triangulation.per_face(func);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
FacetTriangulator<Face_graph, Kernel, boost::graph_traits<Face_graph>::vertex_descriptor, CGAL::Exact_intersections_tag> triangulation(f, sampled_points, nf, poly);
|
||||||
|
|
||||||
|
if (triangulation.cdt->dimension() != 2)
|
||||||
|
{
|
||||||
|
qDebug() << "Error : cdt not right (dimension != 2). Facet not displayed";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
triangulation.per_face(func);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//compute the distances
|
//compute the distances
|
||||||
|
|
|
||||||
|
|
@ -137,80 +137,71 @@ Scene_polygon_soup_item_priv::triangulate_polygon(Polygons_iterator pit, int pol
|
||||||
if (normal == CGAL::NULL_VECTOR) // No normal could be computed, return
|
if (normal == CGAL::NULL_VECTOR) // No normal could be computed, return
|
||||||
return;
|
return;
|
||||||
|
|
||||||
typedef FacetTriangulator<SMesh, EPICK, std::size_t> FT;
|
typedef std::pair<EPICK::Point_3, std::size_t> PointAndId;
|
||||||
|
|
||||||
std::size_t it = 0;
|
std::size_t it = 0;
|
||||||
std::size_t it_end =pit->size();
|
std::size_t it_end =pit->size();
|
||||||
std::vector<FT::PointAndId> pointIds;
|
std::vector<PointAndId> pointIds;
|
||||||
do {
|
do {
|
||||||
FT::PointAndId pointId;
|
PointAndId pointId;
|
||||||
|
|
||||||
pointId.point = soup->points[pit->at(it)]+offset;
|
pointId.first = soup->points[pit->at(it)]+offset;
|
||||||
pointId.id = pit->at(it);
|
pointId.second = pit->at(it);
|
||||||
pointIds.push_back(pointId);
|
pointIds.push_back(pointId);
|
||||||
} while( ++it != it_end );
|
} while( ++it != it_end );
|
||||||
//detect degenerated faces
|
|
||||||
std::vector<FT::PointAndId> pid_stack = pointIds;
|
|
||||||
for(std::size_t i = 0; i< pointIds.size(); ++i)
|
|
||||||
{
|
|
||||||
FT::PointAndId pid = pid_stack.back();
|
|
||||||
pid_stack.pop_back();
|
|
||||||
for(FT::PointAndId poai : pid_stack)
|
|
||||||
{
|
|
||||||
if (pid.point== poai.point)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FT triangulation(pointIds,normal);
|
|
||||||
//iterates on the internal faces to add the vertices to the positions
|
//iterates on the internal faces to add the vertices to the positions
|
||||||
//and the normals to the appropriate vectors
|
//and the normals to the appropriate vectors
|
||||||
for(FT::CDT::Finite_faces_iterator
|
auto f = [&](auto& ffit, auto& v2v) {
|
||||||
ffit = triangulation.cdt->finite_faces_begin(),
|
if (ffit.info().is_external)
|
||||||
end = triangulation.cdt->finite_faces_end();
|
return;
|
||||||
ffit != end; ++ffit)
|
|
||||||
{
|
|
||||||
if(ffit->info().is_external)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
positions_poly.push_back(ffit->vertex(0)->point().x());
|
positions_poly.push_back(ffit.vertex(0)->point().x());
|
||||||
positions_poly.push_back(ffit->vertex(0)->point().y());
|
positions_poly.push_back(ffit.vertex(0)->point().y());
|
||||||
positions_poly.push_back(ffit->vertex(0)->point().z());
|
positions_poly.push_back(ffit.vertex(0)->point().z());
|
||||||
|
|
||||||
|
positions_poly.push_back(ffit.vertex(1)->point().x());
|
||||||
|
positions_poly.push_back(ffit.vertex(1)->point().y());
|
||||||
|
positions_poly.push_back(ffit.vertex(1)->point().z());
|
||||||
|
|
||||||
positions_poly.push_back(ffit->vertex(1)->point().x());
|
positions_poly.push_back(ffit.vertex(2)->point().x());
|
||||||
positions_poly.push_back(ffit->vertex(1)->point().y());
|
positions_poly.push_back(ffit.vertex(2)->point().y());
|
||||||
positions_poly.push_back(ffit->vertex(1)->point().z());
|
positions_poly.push_back(ffit.vertex(2)->point().z());
|
||||||
|
|
||||||
positions_poly.push_back(ffit->vertex(2)->point().x());
|
CGAL::IO::Color color;
|
||||||
positions_poly.push_back(ffit->vertex(2)->point().y());
|
if (!soup->fcolors.empty())
|
||||||
positions_poly.push_back(ffit->vertex(2)->point().z());
|
color = soup->fcolors[polygon_id];
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
CGAL::IO::Color color;
|
{
|
||||||
if(!soup->fcolors.empty())
|
normals.push_back(normal.x());
|
||||||
color = soup->fcolors[polygon_id];
|
normals.push_back(normal.y());
|
||||||
for(int i=0; i<3; i++)
|
normals.push_back(normal.z());
|
||||||
|
if (!soup->fcolors.empty())
|
||||||
{
|
{
|
||||||
normals.push_back(normal.x());
|
f_colors.push_back(static_cast<float>(color.red()) / 255);
|
||||||
normals.push_back(normal.y());
|
f_colors.push_back(static_cast<float>(color.green()) / 255);
|
||||||
normals.push_back(normal.z());
|
f_colors.push_back(static_cast<float>(color.blue()) / 255);
|
||||||
if(!soup->fcolors.empty())
|
|
||||||
{
|
|
||||||
f_colors.push_back(static_cast<float>(color.red())/255);
|
|
||||||
f_colors.push_back(static_cast<float>(color.green())/255);
|
|
||||||
f_colors.push_back(static_cast<float>(color.blue())/255);
|
|
||||||
}
|
|
||||||
if(!soup->vcolors.empty())
|
|
||||||
{
|
|
||||||
CGAL::IO::Color vcolor = soup->vcolors[triangulation.v2v[ffit->vertex(i)]];
|
|
||||||
v_colors.push_back(static_cast<float>(vcolor.red())/255);
|
|
||||||
v_colors.push_back(static_cast<float>(vcolor.green())/255);
|
|
||||||
v_colors.push_back(static_cast<float>(vcolor.blue())/255);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (!soup->vcolors.empty())
|
||||||
|
{
|
||||||
|
CGAL::IO::Color vcolor = soup->vcolors[v2v[ffit.vertex(i)]];
|
||||||
|
v_colors.push_back(static_cast<float>(vcolor.red()) / 255);
|
||||||
|
v_colors.push_back(static_cast<float>(vcolor.green()) / 255);
|
||||||
|
v_colors.push_back(static_cast<float>(vcolor.blue()) / 255);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
FacetTriangulator<SMesh, EPICK, std::size_t> triangulation(pointIds, normal);
|
||||||
|
triangulation.per_face(f);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
FacetTriangulator<SMesh, EPICK, std::size_t, CGAL::Exact_intersections_tag> triangulation(pointIds, normal);
|
||||||
|
triangulation.per_face(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Scene_polygon_soup_item_priv::compute_normals_and_vertices() const{
|
Scene_polygon_soup_item_priv::compute_normals_and_vertices() const{
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -282,26 +282,29 @@ Scene_polyhedron_selection_item_priv::triangulate_facet(fg_face_descriptor fit,c
|
||||||
const CGAL::qglviewer::Vec off = Three::mainViewer()->offset();
|
const CGAL::qglviewer::Vec off = Three::mainViewer()->offset();
|
||||||
EPICK::Vector_3 offset(off.x,off.y,off.z);
|
EPICK::Vector_3 offset(off.x,off.y,off.z);
|
||||||
|
|
||||||
typedef FacetTriangulator<Face_graph, EPICK, fg_vertex_descriptor> FT;
|
//iterates on the internal faces to add the vertices to the positions
|
||||||
FT triangulation(fit,normal,poly, offset);
|
//and the normals to the appropriate vectors
|
||||||
//iterates on the internal faces to add the vertices to the positions
|
auto f = [&](auto& ffit, auto& /* v2v */) {
|
||||||
//and the normals to the appropriate vectors
|
if (ffit.info().is_external)
|
||||||
for(FT::CDT::Finite_faces_iterator
|
return;
|
||||||
ffit = triangulation.cdt->finite_faces_begin(),
|
|
||||||
end = triangulation.cdt->finite_faces_end();
|
|
||||||
ffit != end; ++ffit)
|
|
||||||
{
|
|
||||||
if(ffit->info().is_external)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
push_back_xyz(ffit->vertex(0)->point(), p_facets);
|
push_back_xyz(ffit.vertex(0)->point(), p_facets);
|
||||||
push_back_xyz(ffit->vertex(1)->point(), p_facets);
|
push_back_xyz(ffit.vertex(1)->point(), p_facets);
|
||||||
push_back_xyz(ffit->vertex(2)->point(), p_facets);
|
push_back_xyz(ffit.vertex(2)->point(), p_facets);
|
||||||
|
|
||||||
push_back_xyz(normal, p_normals);
|
push_back_xyz(normal, p_normals);
|
||||||
push_back_xyz(normal, p_normals);
|
push_back_xyz(normal, p_normals);
|
||||||
push_back_xyz(normal, p_normals);
|
push_back_xyz(normal, p_normals);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
FacetTriangulator<Face_graph, EPICK, fg_vertex_descriptor> triangulation(fit, normal, poly, offset);
|
||||||
|
triangulation.per_face(f);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
FacetTriangulator<Face_graph, EPICK, fg_vertex_descriptor, CGAL::Exact_intersections_tag> triangulation(fit, normal, poly, offset);
|
||||||
|
triangulation.per_face(f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -984,62 +984,66 @@ Scene_surface_mesh_item_priv::triangulate_facet(face_descriptor fd,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef FacetTriangulator<SMesh, EPICK, boost::graph_traits<SMesh>::vertex_descriptor> FT;
|
|
||||||
const CGAL::qglviewer::Vec off = static_cast<CGAL::Three::Viewer_interface*>(CGAL::QGLViewer::QGLViewerPool().first())->offset();
|
const CGAL::qglviewer::Vec off = static_cast<CGAL::Three::Viewer_interface*>(CGAL::QGLViewer::QGLViewerPool().first())->offset();
|
||||||
EPICK::Vector_3 offset(off.x,off.y,off.z);
|
EPICK::Vector_3 offset(off.x,off.y,off.z);
|
||||||
FT triangulation(fd,normal,smesh_, offset);
|
|
||||||
//iterates on the internal faces
|
//iterates on the internal faces
|
||||||
for(FT::CDT::Finite_faces_iterator
|
auto f = [&](auto& ffit, auto& v2v) {
|
||||||
ffit = triangulation.cdt->finite_faces_begin(),
|
if (ffit.info().is_external)
|
||||||
end = triangulation.cdt->finite_faces_end();
|
return;
|
||||||
ffit != end; ++ffit)
|
|
||||||
{
|
|
||||||
if(ffit->info().is_external)
|
|
||||||
continue;
|
|
||||||
//add the vertices to the positions
|
//add the vertices to the positions
|
||||||
//adds the vertices, normals and colors to the appropriate vectors
|
//adds the vertices, normals and colors to the appropriate vectors
|
||||||
if(!index)
|
if (!index)
|
||||||
{
|
{
|
||||||
CGAL::IO::Color* color;
|
CGAL::IO::Color* color;
|
||||||
if(has_fpatch_id)
|
if (has_fpatch_id)
|
||||||
{
|
{
|
||||||
QColor c= item->color_vector()[fpatch_id_map[fd] - min_patch_id];
|
QColor c = item->color_vector()[fpatch_id_map[fd] - min_patch_id];
|
||||||
color = new CGAL::IO::Color(c.red(),c.green(),c.blue());
|
color = new CGAL::IO::Color(c.red(), c.green(), c.blue());
|
||||||
}
|
}
|
||||||
else if(has_fcolors)
|
else if (has_fcolors)
|
||||||
color = &(*fcolors)[fd];
|
color = &(*fcolors)[fd];
|
||||||
else
|
else
|
||||||
color = nullptr;
|
color = nullptr;
|
||||||
|
|
||||||
addFlatData(ffit->vertex(0)->point()-offset,
|
addFlatData(ffit.vertex(0)->point() - offset,
|
||||||
(*fnormals)[fd],
|
(*fnormals)[fd],
|
||||||
color,
|
color,
|
||||||
name);
|
name);
|
||||||
addFlatData(ffit->vertex(1)->point()-offset,
|
addFlatData(ffit.vertex(1)->point() - offset,
|
||||||
(*fnormals)[fd],
|
(*fnormals)[fd],
|
||||||
color,
|
color,
|
||||||
name);
|
name);
|
||||||
|
|
||||||
addFlatData(ffit->vertex(2)->point()-offset,
|
addFlatData(ffit.vertex(2)->point() - offset,
|
||||||
(*fnormals)[fd],
|
(*fnormals)[fd],
|
||||||
color,
|
color,
|
||||||
name);
|
name);
|
||||||
if(has_fpatch_id)
|
if (has_fpatch_id)
|
||||||
delete color;
|
delete color;
|
||||||
}
|
}
|
||||||
//adds the indices to the appropriate vector
|
//adds the indices to the appropriate vector
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(name.testFlag(Scene_item_rendering_helper::GEOMETRY))
|
if (name.testFlag(Scene_item_rendering_helper::GEOMETRY))
|
||||||
{
|
{
|
||||||
idx_data_.push_back((*im)[triangulation.v2v[ffit->vertex(0)]]);
|
idx_data_.push_back((*im)[v2v[ffit.vertex(0)]]);
|
||||||
idx_data_.push_back((*im)[triangulation.v2v[ffit->vertex(1)]]);
|
idx_data_.push_back((*im)[v2v[ffit.vertex(1)]]);
|
||||||
idx_data_.push_back((*im)[triangulation.v2v[ffit->vertex(2)]]);
|
idx_data_.push_back((*im)[v2v[ffit.vertex(2)]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
FacetTriangulator<SMesh, EPICK, boost::graph_traits<SMesh>::vertex_descriptor> triangulation(fd, normal, smesh_, offset);
|
||||||
|
triangulation.per_face(f);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
FacetTriangulator<SMesh, EPICK, boost::graph_traits<SMesh>::vertex_descriptor, CGAL::Exact_intersections_tag> triangulation(fd, normal, smesh_, offset);
|
||||||
|
triangulation.per_face(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void delete_aabb_tree(Scene_surface_mesh_item* item)
|
void delete_aabb_tree(Scene_surface_mesh_item* item)
|
||||||
{
|
{
|
||||||
QVariant aabb_tree_property = item->property(aabb_property_name);
|
QVariant aabb_tree_property = item->property(aabb_property_name);
|
||||||
|
|
@ -1356,7 +1360,6 @@ void Scene_surface_mesh_item::invalidate(Gl_data_names name)
|
||||||
QList<EPICK::Triangle_3> Scene_surface_mesh_item_priv::triangulate_primitive(face_descriptor fit,
|
QList<EPICK::Triangle_3> Scene_surface_mesh_item_priv::triangulate_primitive(face_descriptor fit,
|
||||||
EPICK::Vector_3 normal)
|
EPICK::Vector_3 normal)
|
||||||
{
|
{
|
||||||
typedef FacetTriangulator<SMesh, EPICK, boost::graph_traits<SMesh>::vertex_descriptor> FT;
|
|
||||||
//The output list
|
//The output list
|
||||||
QList<EPICK::Triangle_3> res;
|
QList<EPICK::Triangle_3> res;
|
||||||
//check if normal contains NaN values
|
//check if normal contains NaN values
|
||||||
|
|
@ -1365,23 +1368,27 @@ QList<EPICK::Triangle_3> Scene_surface_mesh_item_priv::triangulate_primitive(fac
|
||||||
qDebug()<<"Warning in triangulation of the selection item: normal contains NaN values and is not valid.";
|
qDebug()<<"Warning in triangulation of the selection item: normal contains NaN values and is not valid.";
|
||||||
return QList<EPICK::Triangle_3>();
|
return QList<EPICK::Triangle_3>();
|
||||||
}
|
}
|
||||||
FT triangulation(fit,normal,smesh_);
|
|
||||||
//iterates on the internal faces to add the vertices to the positions
|
//iterates on the internal faces to add the vertices to the positions
|
||||||
//and the normals to the appropriate vectors
|
//and the normals to the appropriate vectors
|
||||||
for( FT::CDT::Finite_faces_iterator
|
auto f = [&](auto &ffit, auto&) {
|
||||||
ffit = triangulation.cdt->finite_faces_begin(),
|
if (ffit.info().is_external)
|
||||||
end = triangulation.cdt->finite_faces_end();
|
return;
|
||||||
ffit != end; ++ffit)
|
|
||||||
{
|
|
||||||
if(ffit->info().is_external)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
|
res << EPICK::Triangle_3(ffit.vertex(0)->point(),
|
||||||
|
ffit.vertex(1)->point(),
|
||||||
|
ffit.vertex(2)->point());
|
||||||
|
};
|
||||||
|
|
||||||
res << EPICK::Triangle_3(ffit->vertex(0)->point(),
|
try {
|
||||||
ffit->vertex(1)->point(),
|
FacetTriangulator<SMesh, EPICK, boost::graph_traits<SMesh>::vertex_descriptor> triangulation(fit, normal, smesh_);
|
||||||
ffit->vertex(2)->point());
|
triangulation.per_face(f);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
catch (...) {
|
||||||
|
FacetTriangulator<SMesh, EPICK, boost::graph_traits<SMesh>::vertex_descriptor, CGAL::Exact_intersections_tag> triangulation(fit, normal, smesh_);
|
||||||
|
triangulation.per_face(f);
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2619,21 +2626,24 @@ void Scene_surface_mesh_item::fill_flat_vertex_map()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef FacetTriangulator<SMesh, EPICK, boost::graph_traits<SMesh>::vertex_descriptor> FT;
|
|
||||||
const CGAL::qglviewer::Vec off = static_cast<CGAL::Three::Viewer_interface*>(CGAL::QGLViewer::QGLViewerPool().first())->offset();
|
const CGAL::qglviewer::Vec off = static_cast<CGAL::Three::Viewer_interface*>(CGAL::QGLViewer::QGLViewerPool().first())->offset();
|
||||||
EPICK::Vector_3 offset(off.x,off.y,off.z);
|
EPICK::Vector_3 offset(off.x,off.y,off.z);
|
||||||
FT triangulation(fd,normal,face_graph(), offset);
|
|
||||||
//iterates on the internal faces
|
auto f = [&](auto ffit, auto &v2v) {
|
||||||
for(FT::CDT::Finite_faces_iterator
|
if (ffit.info().is_external)
|
||||||
ffit = triangulation.cdt->finite_faces_begin(),
|
return;
|
||||||
end = triangulation.cdt->finite_faces_end();
|
d->flat_vertices_map[v2v[ffit.vertex(0)]].push_back(counter++);
|
||||||
ffit != end; ++ffit)
|
d->flat_vertices_map[v2v[ffit.vertex(1)]].push_back(counter++);
|
||||||
{
|
d->flat_vertices_map[v2v[ffit.vertex(2)]].push_back(counter++);
|
||||||
if(ffit->info().is_external)
|
};
|
||||||
continue;
|
|
||||||
d->flat_vertices_map[triangulation.v2v[ffit->vertex(0)]].push_back(counter++);
|
try {
|
||||||
d->flat_vertices_map[triangulation.v2v[ffit->vertex(1)]].push_back(counter++);
|
FacetTriangulator<SMesh, EPICK, boost::graph_traits<SMesh>::vertex_descriptor> triangulation(fd, normal, face_graph(), offset);
|
||||||
d->flat_vertices_map[triangulation.v2v[ffit->vertex(2)]].push_back(counter++);
|
triangulation.per_face(f);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
FacetTriangulator<SMesh, EPICK, boost::graph_traits<SMesh>::vertex_descriptor, CGAL::Exact_intersections_tag> triangulation(fd, normal, face_graph(), offset);
|
||||||
|
triangulation.per_face(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
|
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
|
||||||
#include <CGAL/Triangulation_face_base_with_info_2.h>
|
#include <CGAL/Triangulation_face_base_with_info_2.h>
|
||||||
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
|
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
|
||||||
|
#include <CGAL/mark_domain_in_triangulation.h>
|
||||||
|
|
||||||
#include <CGAL/Projection_traits_3.h>
|
#include <CGAL/Projection_traits_3.h>
|
||||||
|
|
||||||
|
|
@ -22,7 +23,7 @@
|
||||||
// @todo just use PMP::triangulate_face()...?
|
// @todo just use PMP::triangulate_face()...?
|
||||||
// or at least mark_faces_in_domain()
|
// or at least mark_faces_in_domain()
|
||||||
|
|
||||||
template<class Mesh, typename Kernel, typename Index_type>
|
template<class Mesh, typename Kernel, typename Index_type, typename CDT_ITag = CGAL::Exact_predicates_tag>
|
||||||
class FacetTriangulator
|
class FacetTriangulator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -30,6 +31,8 @@ public:
|
||||||
using Point = typename Kernel::Point_3;
|
using Point = typename Kernel::Point_3;
|
||||||
using Vector = typename Kernel::Vector_3;
|
using Vector = typename Kernel::Vector_3;
|
||||||
|
|
||||||
|
using Index = Index_type;
|
||||||
|
|
||||||
using P_traits = CGAL::Projection_traits_3<Traits>;
|
using P_traits = CGAL::Projection_traits_3<Traits>;
|
||||||
|
|
||||||
using halfedge_descriptor = typename boost::graph_traits<Mesh>::halfedge_descriptor;
|
using halfedge_descriptor = typename boost::graph_traits<Mesh>::halfedge_descriptor;
|
||||||
|
|
@ -45,23 +48,14 @@ public:
|
||||||
using Fbb = CGAL::Triangulation_face_base_with_info_2<Face_info, P_traits>;
|
using Fbb = CGAL::Triangulation_face_base_with_info_2<Face_info, P_traits>;
|
||||||
using Fb = CGAL::Constrained_triangulation_face_base_2<P_traits, Fbb>;
|
using Fb = CGAL::Constrained_triangulation_face_base_2<P_traits, Fbb>;
|
||||||
using TDS = CGAL::Triangulation_data_structure_2<Vb, Fb>;
|
using TDS = CGAL::Triangulation_data_structure_2<Vb, Fb>;
|
||||||
using Itag = CGAL::Exact_predicates_tag;
|
using CDT = CGAL::Constrained_Delaunay_triangulation_2<P_traits, TDS, CDT_ITag>;
|
||||||
using CDT = CGAL::Constrained_Delaunay_triangulation_2<P_traits, TDS, Itag>;
|
|
||||||
|
|
||||||
using Vertex_handle = typename CDT::Vertex_handle;
|
using Vertex_handle = typename CDT::Vertex_handle;
|
||||||
using Face_handle = typename CDT::Face_handle;
|
using Face_handle = typename CDT::Face_handle;
|
||||||
|
|
||||||
struct PointAndId
|
|
||||||
{
|
|
||||||
Point point;
|
|
||||||
Index_type id;
|
|
||||||
PointAndId() = default;
|
|
||||||
PointAndId(const Point& point, const Index_type id) : point(point), id(id) { }
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDT* cdt;
|
CDT* cdt;
|
||||||
CGAL::Unique_hash_map<Vertex_handle, Index_type> v2v;
|
CGAL::Unique_hash_map<Vertex_handle, Index> v2v;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Constructor
|
// Constructor
|
||||||
|
|
@ -70,10 +64,10 @@ public:
|
||||||
Mesh* poly,
|
Mesh* poly,
|
||||||
Vector offset = Vector(0,0,0))
|
Vector offset = Vector(0,0,0))
|
||||||
{
|
{
|
||||||
std::vector<PointAndId> idPoints;
|
std::vector<std::pair<typename Kernel::Point_3, Index> > idPoints;
|
||||||
for(halfedge_descriptor he_circ : halfedges_around_face(halfedge(fd, *poly), *poly))
|
for(halfedge_descriptor he_circ : halfedges_around_face(halfedge(fd, *poly), *poly))
|
||||||
idPoints.emplace_back(get(CGAL::vertex_point, *poly, source(he_circ, *poly)) + offset,
|
idPoints.emplace_back(std::make_pair(get(CGAL::vertex_point, *poly, source(he_circ, *poly)) + offset,
|
||||||
source(he_circ, *poly));
|
source(he_circ, *poly)));
|
||||||
|
|
||||||
if(!triangulate(idPoints, normal))
|
if(!triangulate(idPoints, normal))
|
||||||
std::cerr << "Facet not displayed" << std::endl;
|
std::cerr << "Facet not displayed" << std::endl;
|
||||||
|
|
@ -85,22 +79,22 @@ public:
|
||||||
Mesh* poly,
|
Mesh* poly,
|
||||||
Vector offset = Vector(0,0,0))
|
Vector offset = Vector(0,0,0))
|
||||||
{
|
{
|
||||||
std::vector<PointAndId> idPoints;
|
std::vector<std::pair<typename Kernel::Point_3, Index> > idPoints;
|
||||||
for(halfedge_descriptor he_circ : halfedges_around_face(halfedge(fd, *poly), *poly))
|
for(halfedge_descriptor he_circ : halfedges_around_face(halfedge(fd, *poly), *poly))
|
||||||
idPoints.emplace_back(get(CGAL::vertex_point, *poly, source(he_circ, *poly)) + offset,
|
idPoints.emplace_back(std::make_pair(get(CGAL::vertex_point, *poly, source(he_circ, *poly)) + offset,
|
||||||
source(he_circ, *poly));
|
source(he_circ, *poly)));
|
||||||
|
|
||||||
if(!triangulate_with_points(idPoints, more_points, normal))
|
if(!triangulate_with_points(idPoints, more_points, normal))
|
||||||
std::cerr << "Facet not displayed" << std::endl;
|
std::cerr << "Facet not displayed" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
FacetTriangulator(std::vector<PointAndId>& idPoints,
|
FacetTriangulator(std::vector<std::pair<typename Kernel::Point_3, Index> >& idPoints,
|
||||||
const Vector& normal)
|
const Vector& normal)
|
||||||
{
|
{
|
||||||
if(!triangulate(idPoints, normal))
|
if(!triangulate(idPoints, normal))
|
||||||
std::cerr << "Facet not displayed" << std::endl;
|
std::cerr << "Facet not displayed" << std::endl;
|
||||||
}
|
}
|
||||||
FacetTriangulator(std::vector<PointAndId>& idPoints,
|
FacetTriangulator(std::vector < std::pair<typename Kernel::Point_3, Index> >& idPoints,
|
||||||
const std::vector<Point>& more_points,
|
const std::vector<Point>& more_points,
|
||||||
const Vector& normal)
|
const Vector& normal)
|
||||||
{
|
{
|
||||||
|
|
@ -114,36 +108,66 @@ public:
|
||||||
delete cdt;
|
delete cdt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Func>
|
||||||
|
void per_face(const Func& f) {
|
||||||
|
for (typename CDT::Finite_faces_iterator fit = cdt->finite_faces_begin(); fit != cdt->finite_faces_end(); ++fit)
|
||||||
|
f(*fit, v2v);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool triangulate(std::vector<PointAndId>& idPoints,
|
bool triangulate(std::vector<std::pair<typename Kernel::Point_3, Index> >& idPoints,
|
||||||
const Vector& normal)
|
const Vector& normal)
|
||||||
{
|
{
|
||||||
P_traits cdt_traits(normal);
|
P_traits cdt_traits(normal);
|
||||||
cdt = new CDT(cdt_traits);
|
cdt = new CDT(cdt_traits);
|
||||||
|
|
||||||
|
std::map<std::pair<Point, Point>, std::size_t> edge_map;
|
||||||
|
std::vector<bool> skip(idPoints.size(), false);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < idPoints.size(); i++) {
|
||||||
|
std::size_t prev = (i - 1 + idPoints.size()) % idPoints.size();
|
||||||
|
if (idPoints[i].first < idPoints[prev].first) {
|
||||||
|
auto it = edge_map.emplace(std::make_pair(idPoints[i].first, idPoints[prev].first), i);
|
||||||
|
if (!it.second) {
|
||||||
|
skip[i] = true;
|
||||||
|
skip[it.first->second] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto it = edge_map.emplace(std::make_pair(idPoints[prev].first, idPoints[i].first), i);
|
||||||
|
if (!it.second) {
|
||||||
|
skip[i] = true;
|
||||||
|
skip[it.first->second] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Vertex_handle previous, first, last_inserted;
|
Vertex_handle previous, first, last_inserted;
|
||||||
|
|
||||||
// Iterate the points of the facet and decide if they must be inserted in the CDT
|
// Iterate the points of the facet and decide if they must be inserted in the CDT
|
||||||
typename Kernel::FT x(0), y(0), z(0);
|
typename Kernel::FT x(0), y(0), z(0);
|
||||||
|
|
||||||
for(const PointAndId& idPoint : idPoints)
|
for(std::size_t i = 0;i<idPoints.size();i++)
|
||||||
{
|
{
|
||||||
x += idPoint.point.x();
|
const std::pair<typename Kernel::Point_3, Index>& idPoint = idPoints[i];
|
||||||
y += idPoint.point.y();
|
x += idPoint.first.x();
|
||||||
z += idPoint.point.z();
|
y += idPoint.first.y();
|
||||||
|
z += idPoint.first.z();
|
||||||
|
|
||||||
Vertex_handle vh;
|
Vertex_handle vh;
|
||||||
// Always insert the first point, then only insert if the distance with the previous is reasonable.
|
// Always insert the first point, then only insert if the distance with the previous is reasonable.
|
||||||
if(first == Vertex_handle() || idPoint.point != previous->point())
|
if(first == Vertex_handle() || idPoint.first != previous->point())
|
||||||
{
|
{
|
||||||
vh = cdt->insert(idPoint.point);
|
vh = cdt->insert(idPoint.first);
|
||||||
v2v[vh] = idPoint.id;
|
v2v[vh] = idPoint.second;
|
||||||
if(first == Vertex_handle())
|
if (first == Vertex_handle()) {
|
||||||
first = vh;
|
first = vh;
|
||||||
|
}
|
||||||
|
|
||||||
if(previous != nullptr && previous != vh)
|
if(previous != nullptr && previous != vh)
|
||||||
{
|
{
|
||||||
cdt->insert_constraint(previous, vh);
|
if (!skip[i])
|
||||||
|
cdt->insert_constraint(previous, vh);
|
||||||
last_inserted = previous;
|
last_inserted = previous;
|
||||||
}
|
}
|
||||||
previous = vh;
|
previous = vh;
|
||||||
|
|
@ -153,57 +177,69 @@ private:
|
||||||
if(last_inserted == Vertex_handle())
|
if(last_inserted == Vertex_handle())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(previous != first)
|
if(previous != first && !skip[0])
|
||||||
cdt->insert_constraint(previous, first);
|
cdt->insert_constraint(previous, first);
|
||||||
|
|
||||||
// sets mark is_external
|
// sets mark is_external
|
||||||
for(Face_handle f2 : cdt->all_face_handles())
|
for(Face_handle f2 : cdt->all_face_handles())
|
||||||
f2->info().is_external = false;
|
f2->info().is_external = false;
|
||||||
|
|
||||||
// check if the facet is external or internal
|
std::unordered_map<Face_handle, bool> in_domain_map;
|
||||||
std::queue<typename CDT::Face_handle> face_queue;
|
boost::associative_property_map< std::unordered_map<Face_handle, bool> > in_domain(in_domain_map);
|
||||||
face_queue.push(cdt->infinite_vertex()->face());
|
CGAL::mark_domain_in_triangulation<CDT>(*cdt, in_domain);
|
||||||
while(! face_queue.empty())
|
|
||||||
{
|
|
||||||
typename CDT::Face_handle fh = face_queue.front();
|
|
||||||
face_queue.pop();
|
|
||||||
if(fh->info().is_external)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
fh->info().is_external = true;
|
for (const Face_handle& fh : cdt->all_face_handles())
|
||||||
for(int i = 0; i <3; ++i)
|
fh->info().is_external = !get(in_domain, fh);
|
||||||
{
|
|
||||||
if(!cdt->is_constrained(std::make_pair(fh, i)))
|
|
||||||
face_queue.push(fh->neighbor(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool triangulate_with_points(std::vector<PointAndId >& idPoints,
|
bool triangulate_with_points(std::vector<std::pair<typename Kernel::Point_3, Index> >& idPoints,
|
||||||
const std::vector<Point>& more_points,
|
const std::vector<Point>& more_points,
|
||||||
const Vector& normal)
|
const Vector& normal)
|
||||||
{
|
{
|
||||||
P_traits cdt_traits(normal);
|
P_traits cdt_traits(normal);
|
||||||
cdt = new CDT(cdt_traits);
|
cdt = new CDT(cdt_traits);
|
||||||
|
|
||||||
|
std::map<std::pair<Point, Point>, std::size_t> edge_map;
|
||||||
|
std::vector<bool> skip(idPoints.size(), false);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < idPoints.size(); i++) {
|
||||||
|
std::size_t prev = (i - 1 + idPoints.size()) % idPoints.size();
|
||||||
|
if (idPoints[i].first < idPoints[prev].first) {
|
||||||
|
auto it = edge_map.emplace(std::make_pair(idPoints[i].first, idPoints[prev].first), i);
|
||||||
|
if (!it.second) {
|
||||||
|
skip[i] = true;
|
||||||
|
skip[it.first->second] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto it = edge_map.emplace(std::make_pair(idPoints[prev].first, idPoints[i].first), i);
|
||||||
|
if (!it.second) {
|
||||||
|
skip[i] = true;
|
||||||
|
skip[it.first->second] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Iterate the points of the facet and decide if they must be inserted in the CDT
|
// Iterate the points of the facet and decide if they must be inserted in the CDT
|
||||||
Vertex_handle previous, first, last_inserted;
|
Vertex_handle previous, first, last_inserted;
|
||||||
for(const PointAndId& idPoint : idPoints)
|
for (std::size_t i = 0; i < idPoints.size(); i++)
|
||||||
{
|
{
|
||||||
|
const std::pair<typename Kernel::Point_3, Index>& idPoint = idPoints[i];
|
||||||
Vertex_handle vh;
|
Vertex_handle vh;
|
||||||
// Always insert the first point, then only insert if the distance with the previous is reasonable.
|
// Always insert the first point, then only insert if the distance with the previous is reasonable.
|
||||||
if(first == Vertex_handle() || idPoint.point != previous->point())
|
if(first == Vertex_handle() || idPoint.first != previous->point())
|
||||||
{
|
{
|
||||||
vh = cdt->insert(idPoint.point);
|
vh = cdt->insert(idPoint.first);
|
||||||
v2v[vh] = idPoint.id;
|
v2v[vh] = idPoint.second;
|
||||||
if(first == Vertex_handle())
|
if(first == Vertex_handle())
|
||||||
first = vh;
|
first = vh;
|
||||||
|
|
||||||
if(previous != nullptr && previous != vh)
|
if(previous != nullptr && previous != vh)
|
||||||
{
|
{
|
||||||
cdt->insert_constraint(previous, vh);
|
if (!skip[i])
|
||||||
|
cdt->insert_constraint(previous, vh);
|
||||||
last_inserted = previous;
|
last_inserted = previous;
|
||||||
}
|
}
|
||||||
previous = vh;
|
previous = vh;
|
||||||
|
|
@ -213,7 +249,9 @@ private:
|
||||||
if(last_inserted == Vertex_handle())
|
if(last_inserted == Vertex_handle())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (previous != first && !skip[0])
|
||||||
cdt->insert_constraint(previous, first);
|
cdt->insert_constraint(previous, first);
|
||||||
|
|
||||||
for(const Point& point : more_points)
|
for(const Point& point : more_points)
|
||||||
cdt->insert(point);
|
cdt->insert(point);
|
||||||
|
|
||||||
|
|
@ -221,22 +259,12 @@ private:
|
||||||
for(Face_handle f2 : cdt->all_face_handles())
|
for(Face_handle f2 : cdt->all_face_handles())
|
||||||
f2->info().is_external = false;
|
f2->info().is_external = false;
|
||||||
|
|
||||||
// check if the facet is external or internal
|
std::unordered_map<Face_handle, bool> in_domain_map;
|
||||||
std::queue<typename CDT::Face_handle> face_queue;
|
boost::associative_property_map< std::unordered_map<Face_handle, bool> > in_domain(in_domain_map);
|
||||||
face_queue.push(cdt->infinite_vertex()->face());
|
CGAL::mark_domain_in_triangulation<CDT>(*cdt, in_domain);
|
||||||
while(!face_queue.empty())
|
|
||||||
{
|
for (const Face_handle& fh : cdt->all_face_handles())
|
||||||
typename CDT::Face_handle fh = face_queue.front();
|
fh->info().is_external = !get(in_domain, fh);
|
||||||
face_queue.pop();
|
|
||||||
if(fh->info().is_external)
|
|
||||||
continue;
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue