Skip to content

Commit

Permalink
- parallel simplify_coplanar_facets()
Browse files Browse the repository at this point in the history
- constexpr in Mesh for NO_VERTEX, NO_FACET ...
  • Loading branch information
BrunoLevy committed Dec 9, 2023
1 parent f188e27 commit b1b846e
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 85 deletions.
14 changes: 7 additions & 7 deletions src/lib/geogram/mesh/mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ namespace GEO {

class Mesh;

const index_t NO_VERTEX = index_t(-1);
const index_t NO_EDGE = index_t(-1);
const index_t NO_FACET = index_t(-1);
const index_t NO_CELL = index_t(-1);
const index_t NO_CORNER = index_t(-1);
static constexpr index_t NO_VERTEX = NO_INDEX;
static constexpr index_t NO_EDGE = NO_INDEX;
static constexpr index_t NO_FACET = NO_INDEX;
static constexpr index_t NO_CELL = NO_INDEX;
static constexpr index_t NO_CORNER = NO_INDEX;

/**
* \brief Base class for mesh sub-element storage.
Expand Down Expand Up @@ -1102,7 +1102,7 @@ namespace GEO {
* \brief Gets the local index of a facet adjacent to another one.
* \param[in] f a facet
* \param[in] f2 another facet
* \return le such that adjacent(f,le) == f2 or NO_FACET if f and f2
* \return le such that adjacent(f,le) == f2 or NO_INDEX if f and f2
* are not adjacent.
*/
index_t find_adjacent(index_t f, index_t f2) const {
Expand All @@ -1111,7 +1111,7 @@ namespace GEO {
return le;
}
}
return NO_FACET;
return NO_INDEX;
}

/**
Expand Down
13 changes: 4 additions & 9 deletions src/lib/geogram/mesh/mesh_CSG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -844,13 +844,6 @@ namespace GEO {
}

CSGMesh_var CSGBuilder::union_instr(const CSGScope& scope) {

/*
for(index_t i=0; i<scope.size(); ++i) {
mesh_save(*scope[i], String::format("scope_%05d.geogram",int(i)));
}
*/

if(scope.size() == 1) {
return scope[0];
}
Expand Down Expand Up @@ -968,8 +961,10 @@ namespace GEO {
CSGMesh_var result = new CSGMesh;
result->vertices.set_dimension(3);

if(scope.size() > 32) {
Logger::warn("CSG") << "Scope with more than 32 children"
if(scope.size() > max_arity_) {
Logger::warn("CSG") << "Scope with more than "
<< max_arity_
<< " children"
<< std::endl;
}

Expand Down
94 changes: 47 additions & 47 deletions src/lib/geogram/mesh/mesh_surface_intersection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1931,8 +1931,8 @@ namespace GEO {
if(verbose_) {
Logger::out("Intersect") << "Simplifying coplanar facets" << std::endl;
}
CoplanarFacets coplanar(*this);
Attribute<index_t> facet_group(mesh_.facets.attributes(), "group");
vector<index_t> group_facet;
for(index_t f: mesh_.facets) {
facet_group[f] = index_t(-1);
}
Expand All @@ -1941,60 +1941,60 @@ namespace GEO {
keep_vertex[v] = false;
}
index_t current_group = 0;
for(index_t f: mesh_.facets) {
if(facet_group[f] == index_t(-1)) {
coplanar.get(f, current_group);
coplanar.mark_vertices_to_keep();
++current_group;
// CoplanarFacets coplanar(*this);
{
CoplanarFacets coplanar(*this, true); // true: clear attributes
for(index_t f: mesh_.facets) {
if(facet_group[f] == NO_INDEX) {
coplanar.get(f, current_group); // This sets facet_group_[f]
coplanar.mark_vertices_to_keep();
group_facet.push_back(f);
++current_group;
}
}
}

vector<index_t> remove_f(mesh_.facets.nb(), 0);
index_t nb_groups = current_group;
vector<bool> visited_group(nb_groups, false);
for(index_t f: mesh_.facets) {
current_group = facet_group[f];
if(!visited_group[current_group]) {
coplanar.get(f,current_group);
geo_assert(nb_groups == group_facet.size());

if(coplanar.facets.size() < 2) {
continue;
}

coplanar.triangulate();
visited_group[current_group] = true;

for(index_t t=0; t<coplanar.CDT.nT(); ++t) {
index_t v1 = coplanar.CDT.vertex_id(coplanar.CDT.Tv(t,0));
index_t v2 = coplanar.CDT.vertex_id(coplanar.CDT.Tv(t,1));
index_t v3 = coplanar.CDT.vertex_id(coplanar.CDT.Tv(t,2));
// If one of these assertions fails,
// it means that v1,v2 or v3 was one of the four
// vertices of the external quad.
// It means that there was probably an
// inside/outside classification error.
geo_assert(v1 != index_t(-1));
geo_assert(v2 != index_t(-1));
geo_assert(v3 != index_t(-1));
}

for(index_t ff: coplanar.facets) {
remove_f[ff] = true;
}

for(index_t t=0; t<coplanar.CDT.nT(); ++t) {
index_t v1 = coplanar.CDT.vertex_id(coplanar.CDT.Tv(t,0));
index_t v2 = coplanar.CDT.vertex_id(coplanar.CDT.Tv(t,1));
index_t v3 = coplanar.CDT.vertex_id(coplanar.CDT.Tv(t,2));
geo_assert(v1 != index_t(-1));
geo_assert(v2 != index_t(-1));
geo_assert(v3 != index_t(-1));
index_t new_f = mesh_.facets.create_triangle(v1,v2,v3);
facet_group[new_f] = current_group;
// Triangulate coplanar facet groups in parallel
Process::spinlock lock = GEOGRAM_SPINLOCK_INIT;
parallel_for_slice(
0, nb_groups, [&](index_t b, index_t e) {
Process::acquire_spinlock(lock); // Attribute ctor not thread safe ?
CoplanarFacets coplanar(*this,false); // false: do not clear attribs
Process::release_spinlock(lock);
for(index_t group=b; group<e; ++group) {
coplanar.get(group_facet[group],group);
if(coplanar.facets.size() < 2) {
continue;
}
coplanar.triangulate();
for(index_t ff: coplanar.facets) {
remove_f[ff] = true;
}
Process::acquire_spinlock(lock);
for(index_t t=0; t<coplanar.CDT.nT(); ++t) {
index_t v1 = coplanar.CDT.vertex_id(coplanar.CDT.Tv(t,0));
index_t v2 = coplanar.CDT.vertex_id(coplanar.CDT.Tv(t,1));
index_t v3 = coplanar.CDT.vertex_id(coplanar.CDT.Tv(t,2));
// If one of these assertions fails,
// it means that v1,v2 or v3 was one of the four
// vertices of the external quad.
// It means that there was probably an
// inside/outside classification error.
geo_assert(v1 != index_t(-1));
geo_assert(v2 != index_t(-1));
geo_assert(v3 != index_t(-1));
index_t new_f = mesh_.facets.create_triangle(v1,v2,v3);
facet_group[new_f] = current_group;
}
Process::release_spinlock(lock);
}
}
}

);
remove_f.resize(mesh_.facets.nb(),0);
mesh_.facets.delete_elements(remove_f);
mesh_.facets.connect();
Expand Down
68 changes: 47 additions & 21 deletions src/lib/geogram/mesh/mesh_surface_intersection_internal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -990,17 +990,22 @@ namespace GEO {

/*****************************************************************************/

CoplanarFacets::CoplanarFacets(MeshSurfaceIntersection& I) :
CoplanarFacets::CoplanarFacets(
MeshSurfaceIntersection& I, bool clear_attributes
) :
intersection_(I),
mesh_(I.target_mesh()),
facet_group_(I.target_mesh().facets.attributes(),"group"),
keep_vertex_(I.target_mesh().vertices.attributes(),"keep")
{
for(index_t f: mesh_.facets) {
facet_group_[f] = index_t(-1);
}
for(index_t v: mesh_.vertices) {
keep_vertex_[v] = false;
if(clear_attributes) {
for(index_t f: mesh_.facets) {
facet_group_[f] = index_t(-1);
}
for(index_t v: mesh_.vertices) {
keep_vertex_[v] = false;
}
find_coplanar_facets();
}
f_visited_.assign(mesh_.facets.nb(),false);
v_visited_.assign(mesh_.vertices.nb(),false);
Expand All @@ -1009,10 +1014,44 @@ namespace GEO {
v_idx_.resize(mesh_.vertices.nb());
}

void CoplanarFacets::find_coplanar_facets() {
c_is_coplanar_.assign(mesh_.facet_corners.nb(), false);
parallel_for(
0, mesh_.facet_corners.nb(),
[&](index_t c1) {
index_t f1 = (c1 / 3);
index_t le1 = (c1 % 3);
index_t f2 = mesh_.facet_corners.adjacent_facet(c1);
if(f2 != NO_INDEX) {
index_t le2 = mesh_.facets.find_adjacent(f2,f1);
index_t c2 = mesh_.facets.corner(f2,le2);
if(c1 < c2) {
ExactPoint p1=intersection_.exact_vertex(
mesh_.facets.vertex(f1,le1)
);
ExactPoint p2=intersection_.exact_vertex(
mesh_.facets.vertex(f1,(le1+1)%3)
);
ExactPoint p3=intersection_.exact_vertex(
mesh_.facets.vertex(f1,(le1+2)%3)
);
ExactPoint p4=intersection_.exact_vertex(
mesh_.facets.vertex(f2,(le2+2)%3)
);
if(triangles_are_coplanar(p1,p2,p3,p4)) {
c_is_coplanar_[c1] = true;
c_is_coplanar_[c2] = true;
}
}
}
}
);
}

void CoplanarFacets::get(index_t f, index_t group_id) {
facets.resize(0);
vertices.resize(0);
if(facet_group_[f] == index_t(-1)) {
if(facet_group_[f] == NO_INDEX) {
// Get facets, first call (facet_group not initialized)
std::stack<index_t> S;
facet_group_[f] = group_id;
Expand All @@ -1024,20 +1063,7 @@ namespace GEO {
for(index_t le1=0; le1<3; ++le1) {
index_t f2 = mesh_.facets.adjacent(f1,le1);
if(f2 != NO_INDEX && facet_group_[f2] == NO_INDEX) {
ExactPoint p1=intersection_.exact_vertex(
mesh_.facets.vertex(f1,le1)
);
ExactPoint p2=intersection_.exact_vertex(
mesh_.facets.vertex(f1,(le1+1)%3)
);
ExactPoint p3=intersection_.exact_vertex(
mesh_.facets.vertex(f1,(le1+2)%3)
);
index_t le2 = mesh_.facets.find_adjacent(f2,f1);
ExactPoint p4=intersection_.exact_vertex(
mesh_.facets.vertex(f2,(le2+2)%3)
);
if(triangles_are_coplanar(p1,p2,p3,p4)) {
if(c_is_coplanar_[mesh_.facets.corner(f1,le1)]) {
facet_group_[f2] = facet_group_[f1];
S.push(f2);
facets.push_back(f2);
Expand Down
11 changes: 10 additions & 1 deletion src/lib/geogram/mesh/mesh_surface_intersection_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -653,8 +653,9 @@ namespace GEO {
* MeshSurfaceIntersection
* \details No set of facets is identified. One needs to call get().
* \param[in] I a reference to the MeshSurfaceIntersection
* \param[in] clear_attributes if set, resets facet_chart and keep_vertex
*/
CoplanarFacets(MeshSurfaceIntersection& I);
CoplanarFacets(MeshSurfaceIntersection& I, bool clear_attributes);

/**
* \brief Gets the set of coplanar facets from a given facet and
Expand Down Expand Up @@ -698,6 +699,13 @@ namespace GEO {

protected:

/**
* \brief Finds all the pairs of coplanar facets
* \details Initializes c_is_coplanar_[], a vector of booleans indexed
* by facet corners.
*/
void find_coplanar_facets();

/**
* \brief Gets the coordinate along which one can project a triangle
* without creating degeneracies.
Expand Down Expand Up @@ -740,6 +748,7 @@ namespace GEO {
vector<bool> f_visited_;
vector<bool> v_visited_;
vector<index_t> v_idx_;
vector<bool> c_is_coplanar_;
};

/**********************************************************************/
Expand Down

0 comments on commit b1b846e

Please sign in to comment.