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:
Laurent Rineau 2024-01-11 14:01:52 +01:00 committed by GitHub
commit 61800d1be7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 263 additions and 228 deletions

View File

@ -190,13 +190,10 @@ private:
for(boost::graph_traits<Face_graph>::face_descriptor f : faces(*poly)) {
Vector nf = get(nf_pmap, f);
typedef FacetTriangulator<Face_graph, Kernel, boost::graph_traits<Face_graph>::vertex_descriptor> FT;
//compute distance with other polyhedron
//sample facet
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()))),
1);
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);
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 &r = get(vpmap,target(next(next(halfedge(f,*poly),*poly),*poly),*poly));
@ -207,36 +204,42 @@ private:
sampled_points.push_back(r);
//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 )
{
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)
for (int i = 0; i < 3; ++i)
{
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().y());
m_vertices.push_back(ffit->vertex(i)->point().z());
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().y());
m_vertices.push_back(ffit.vertex(i)->point().z());
normals.push_back(nf.x());
normals.push_back(nf.y());
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

View File

@ -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
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_end =pit->size();
std::vector<FT::PointAndId> pointIds;
std::vector<PointAndId> pointIds;
do {
FT::PointAndId pointId;
PointAndId pointId;
pointId.point = soup->points[pit->at(it)]+offset;
pointId.id = pit->at(it);
pointId.first = soup->points[pit->at(it)]+offset;
pointId.second = pit->at(it);
pointIds.push_back(pointId);
} 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
//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;
auto f = [&](auto& ffit, auto& v2v) {
if (ffit.info().is_external)
return;
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().z());
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().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(1)->point().y());
positions_poly.push_back(ffit->vertex(1)->point().z());
positions_poly.push_back(ffit.vertex(2)->point().x());
positions_poly.push_back(ffit.vertex(2)->point().y());
positions_poly.push_back(ffit.vertex(2)->point().z());
positions_poly.push_back(ffit->vertex(2)->point().x());
positions_poly.push_back(ffit->vertex(2)->point().y());
positions_poly.push_back(ffit->vertex(2)->point().z());
CGAL::IO::Color color;
if(!soup->fcolors.empty())
color = soup->fcolors[polygon_id];
for(int i=0; i<3; i++)
CGAL::IO::Color color;
if (!soup->fcolors.empty())
color = soup->fcolors[polygon_id];
for (int i = 0; i < 3; i++)
{
normals.push_back(normal.x());
normals.push_back(normal.y());
normals.push_back(normal.z());
if (!soup->fcolors.empty())
{
normals.push_back(normal.x());
normals.push_back(normal.y());
normals.push_back(normal.z());
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);
}
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[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
Scene_polygon_soup_item_priv::compute_normals_and_vertices() const{

View File

@ -282,26 +282,29 @@ Scene_polyhedron_selection_item_priv::triangulate_facet(fg_face_descriptor fit,c
const CGAL::qglviewer::Vec off = Three::mainViewer()->offset();
EPICK::Vector_3 offset(off.x,off.y,off.z);
typedef FacetTriangulator<Face_graph, EPICK, fg_vertex_descriptor> FT;
FT triangulation(fit,normal,poly, offset);
//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;
//iterates on the internal faces to add the vertices to the positions
//and the normals to the appropriate vectors
auto f = [&](auto& ffit, auto& /* v2v */) {
if (ffit.info().is_external)
return;
push_back_xyz(ffit->vertex(0)->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(0)->point(), p_facets);
push_back_xyz(ffit.vertex(1)->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);
}
}

View File

@ -984,62 +984,66 @@ Scene_surface_mesh_item_priv::triangulate_facet(face_descriptor fd,
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();
EPICK::Vector_3 offset(off.x,off.y,off.z);
FT triangulation(fd,normal,smesh_, offset);
//iterates on the internal faces
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;
auto f = [&](auto& ffit, auto& v2v) {
if (ffit.info().is_external)
return;
//add the vertices to the positions
//adds the vertices, normals and colors to the appropriate vectors
if(!index)
if (!index)
{
CGAL::IO::Color* color;
if(has_fpatch_id)
if (has_fpatch_id)
{
QColor c= item->color_vector()[fpatch_id_map[fd] - min_patch_id];
color = new CGAL::IO::Color(c.red(),c.green(),c.blue());
QColor c = item->color_vector()[fpatch_id_map[fd] - min_patch_id];
color = new CGAL::IO::Color(c.red(), c.green(), c.blue());
}
else if(has_fcolors)
else if (has_fcolors)
color = &(*fcolors)[fd];
else
color = nullptr;
addFlatData(ffit->vertex(0)->point()-offset,
(*fnormals)[fd],
color,
name);
addFlatData(ffit->vertex(1)->point()-offset,
(*fnormals)[fd],
color,
name);
addFlatData(ffit.vertex(0)->point() - offset,
(*fnormals)[fd],
color,
name);
addFlatData(ffit.vertex(1)->point() - offset,
(*fnormals)[fd],
color,
name);
addFlatData(ffit->vertex(2)->point()-offset,
(*fnormals)[fd],
color,
name);
if(has_fpatch_id)
addFlatData(ffit.vertex(2)->point() - offset,
(*fnormals)[fd],
color,
name);
if (has_fpatch_id)
delete color;
}
//adds the indices to the appropriate vector
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)[triangulation.v2v[ffit->vertex(1)]]);
idx_data_.push_back((*im)[triangulation.v2v[ffit->vertex(2)]]);
idx_data_.push_back((*im)[v2v[ffit.vertex(0)]]);
idx_data_.push_back((*im)[v2v[ffit.vertex(1)]]);
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)
{
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,
EPICK::Vector_3 normal)
{
typedef FacetTriangulator<SMesh, EPICK, boost::graph_traits<SMesh>::vertex_descriptor> FT;
//The output list
QList<EPICK::Triangle_3> res;
//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.";
return QList<EPICK::Triangle_3>();
}
FT triangulation(fit,normal,smesh_);
//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;
auto f = [&](auto &ffit, auto&) {
if (ffit.info().is_external)
return;
res << EPICK::Triangle_3(ffit.vertex(0)->point(),
ffit.vertex(1)->point(),
ffit.vertex(2)->point());
};
res << EPICK::Triangle_3(ffit->vertex(0)->point(),
ffit->vertex(1)->point(),
ffit->vertex(2)->point());
try {
FacetTriangulator<SMesh, EPICK, boost::graph_traits<SMesh>::vertex_descriptor> triangulation(fit, normal, smesh_);
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;
}
@ -2619,21 +2626,24 @@ void Scene_surface_mesh_item::fill_flat_vertex_map()
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();
EPICK::Vector_3 offset(off.x,off.y,off.z);
FT triangulation(fd,normal,face_graph(), offset);
//iterates on the internal faces
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;
d->flat_vertices_map[triangulation.v2v[ffit->vertex(0)]].push_back(counter++);
d->flat_vertices_map[triangulation.v2v[ffit->vertex(1)]].push_back(counter++);
d->flat_vertices_map[triangulation.v2v[ffit->vertex(2)]].push_back(counter++);
auto f = [&](auto ffit, auto &v2v) {
if (ffit.info().is_external)
return;
d->flat_vertices_map[v2v[ffit.vertex(0)]].push_back(counter++);
d->flat_vertices_map[v2v[ffit.vertex(1)]].push_back(counter++);
d->flat_vertices_map[v2v[ffit.vertex(2)]].push_back(counter++);
};
try {
FacetTriangulator<SMesh, EPICK, boost::graph_traits<SMesh>::vertex_descriptor> triangulation(fd, normal, face_graph(), offset);
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);
}
}
}

View File

@ -6,6 +6,7 @@
#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>
#include <CGAL/mark_domain_in_triangulation.h>
#include <CGAL/Projection_traits_3.h>
@ -22,7 +23,7 @@
// @todo just use PMP::triangulate_face()...?
// 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
{
public:
@ -30,6 +31,8 @@ public:
using Point = typename Kernel::Point_3;
using Vector = typename Kernel::Vector_3;
using Index = Index_type;
using P_traits = CGAL::Projection_traits_3<Traits>;
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 Fb = CGAL::Constrained_triangulation_face_base_2<P_traits, Fbb>;
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, Itag>;
using CDT = CGAL::Constrained_Delaunay_triangulation_2<P_traits, TDS, CDT_ITag>;
using Vertex_handle = typename CDT::Vertex_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:
CDT* cdt;
CGAL::Unique_hash_map<Vertex_handle, Index_type> v2v;
CGAL::Unique_hash_map<Vertex_handle, Index> v2v;
public:
// Constructor
@ -70,10 +64,10 @@ public:
Mesh* poly,
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))
idPoints.emplace_back(get(CGAL::vertex_point, *poly, source(he_circ, *poly)) + offset,
source(he_circ, *poly));
idPoints.emplace_back(std::make_pair(get(CGAL::vertex_point, *poly, source(he_circ, *poly)) + offset,
source(he_circ, *poly)));
if(!triangulate(idPoints, normal))
std::cerr << "Facet not displayed" << std::endl;
@ -85,22 +79,22 @@ public:
Mesh* poly,
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))
idPoints.emplace_back(get(CGAL::vertex_point, *poly, source(he_circ, *poly)) + offset,
source(he_circ, *poly));
idPoints.emplace_back(std::make_pair(get(CGAL::vertex_point, *poly, source(he_circ, *poly)) + offset,
source(he_circ, *poly)));
if(!triangulate_with_points(idPoints, more_points, normal))
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)
{
if(!triangulate(idPoints, normal))
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 Vector& normal)
{
@ -114,36 +108,66 @@ public:
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:
bool triangulate(std::vector<PointAndId>& idPoints,
bool triangulate(std::vector<std::pair<typename Kernel::Point_3, Index> >& idPoints,
const Vector& normal)
{
P_traits cdt_traits(normal);
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;
// 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);
for(const PointAndId& idPoint : idPoints)
for(std::size_t i = 0;i<idPoints.size();i++)
{
x += idPoint.point.x();
y += idPoint.point.y();
z += idPoint.point.z();
const std::pair<typename Kernel::Point_3, Index>& idPoint = idPoints[i];
x += idPoint.first.x();
y += idPoint.first.y();
z += idPoint.first.z();
Vertex_handle vh;
// 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);
v2v[vh] = idPoint.id;
if(first == Vertex_handle())
vh = cdt->insert(idPoint.first);
v2v[vh] = idPoint.second;
if (first == Vertex_handle()) {
first = vh;
}
if(previous != nullptr && previous != vh)
{
cdt->insert_constraint(previous, vh);
if (!skip[i])
cdt->insert_constraint(previous, vh);
last_inserted = previous;
}
previous = vh;
@ -153,57 +177,69 @@ private:
if(last_inserted == Vertex_handle())
return false;
if(previous != first)
if(previous != first && !skip[0])
cdt->insert_constraint(previous, first);
// sets mark is_external
for(Face_handle f2 : cdt->all_face_handles())
f2->info().is_external = false;
// check if the facet is external or internal
std::queue<typename CDT::Face_handle> face_queue;
face_queue.push(cdt->infinite_vertex()->face());
while(! face_queue.empty())
{
typename CDT::Face_handle fh = face_queue.front();
face_queue.pop();
if(fh->info().is_external)
continue;
std::unordered_map<Face_handle, bool> in_domain_map;
boost::associative_property_map< std::unordered_map<Face_handle, bool> > in_domain(in_domain_map);
CGAL::mark_domain_in_triangulation<CDT>(*cdt, in_domain);
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 (const Face_handle& fh : cdt->all_face_handles())
fh->info().is_external = !get(in_domain, fh);
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 Vector& normal)
{
P_traits cdt_traits(normal);
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
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;
// 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);
v2v[vh] = idPoint.id;
vh = cdt->insert(idPoint.first);
v2v[vh] = idPoint.second;
if(first == Vertex_handle())
first = vh;
if(previous != nullptr && previous != vh)
{
cdt->insert_constraint(previous, vh);
if (!skip[i])
cdt->insert_constraint(previous, vh);
last_inserted = previous;
}
previous = vh;
@ -213,7 +249,9 @@ private:
if(last_inserted == Vertex_handle())
return false;
if (previous != first && !skip[0])
cdt->insert_constraint(previous, first);
for(const Point& point : more_points)
cdt->insert(point);
@ -221,22 +259,12 @@ private:
for(Face_handle f2 : cdt->all_face_handles())
f2->info().is_external = false;
// check if the facet is external or internal
std::queue<typename CDT::Face_handle> face_queue;
face_queue.push(cdt->infinite_vertex()->face());
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(int i = 0; i <3; ++i)
{
if(!cdt->is_constrained(std::make_pair(fh, i)))
face_queue.push(fh->neighbor(i));
}
}
std::unordered_map<Face_handle, bool> in_domain_map;
boost::associative_property_map< std::unordered_map<Face_handle, bool> > in_domain(in_domain_map);
CGAL::mark_domain_in_triangulation<CDT>(*cdt, in_domain);
for (const Face_handle& fh : cdt->all_face_handles())
fh->info().is_external = !get(in_domain, fh);
return true;
}