Restructure cgal shape triangulation

This commit is contained in:
Thomas Krijnen
2023-09-13 22:03:49 +02:00
parent 0116be1386
commit 5eff7178da
@@ -1,104 +1,111 @@
#include "CgalConversionResult.h" #include "CgalConversionResult.h"
#include "CgalKernel.h" #include "CgalKernel.h"
#include <CGAL/Polygon_mesh_processing/repair.h>
#include "../../../ifcparse/IfcLogger.h" #include "../../../ifcparse/IfcLogger.h"
#include "../../../ifcgeom/IfcGeomRepresentation.h" #include "../../../ifcgeom/IfcGeomRepresentation.h"
void ifcopenshell::geometry::CgalShape::Triangulate(const IfcGeom::IteratorSettings& settings, const ifcopenshell::geometry::taxonomy::matrix4& place, IfcGeom::Representation::Triangulation* t, int surface_style_id) const { void ifcopenshell::geometry::CgalShape::Triangulate(const IfcGeom::IteratorSettings& settings, const ifcopenshell::geometry::taxonomy::matrix4& place, IfcGeom::Representation::Triangulation* t, int surface_style_id) const {
// Copy is made because triangulate_faces() does not accept a const argument // Copy is made because triangulate_faces() obviously does not accept a const argument
cgal_shape_t s = shape_; // ... also becuase of transforming the vertex positions, right?
cgal_shape_t s = shape_;
if (!place.is_identity()) { if (!place.is_identity()) {
const auto& m = place.ccomponents(); const auto& m = place.ccomponents();
// @todo check // @todo check
const cgal_placement_t trsf( const cgal_placement_t trsf(
m(0, 0), m(0, 1), m(0, 2), m(0, 3), m(0, 0), m(0, 1), m(0, 2), m(0, 3),
m(1, 0), m(1, 1), m(1, 2), m(1, 3), m(1, 0), m(1, 1), m(1, 2), m(1, 3),
m(2, 0), m(2, 1), m(2, 2), m(2, 3)); m(2, 0), m(2, 1), m(2, 2), m(2, 3));
// Apply transformation // Apply transformation
for (auto &vertex : vertices(s)) { for (auto &vertex : vertices(s)) {
vertex->point() = vertex->point().transform(trsf); vertex->point() = vertex->point().transform(trsf);
} }
} }
if (!s.is_valid()) {
Logger::Message(Logger::LOG_ERROR, "Invalid Polyhedron_3 in object (before triangulation)");
return;
}
// Triangulate the shape and compute the normals
// std::map<cgal_vertex_descriptor_t, Kernel_::Vector_3> vertex_normals;
// boost::associative_property_map<std::map<cgal_vertex_descriptor_t, Kernel_::Vector_3>> vertex_normals_map(vertex_normals);
std::map<cgal_face_descriptor_t, Kernel_::Vector_3> face_normals;
boost::associative_property_map<std::map<cgal_face_descriptor_t, Kernel_::Vector_3>> face_normals_map(face_normals);
bool success = false; std::wcout << "Triangulating " << std::distance(s.facets_begin(), s.facets_end()) << std::endl;
try {
success = CGAL::Polygon_mesh_processing::triangulate_faces(s); if (!std::all_of(s.facets_begin(), s.facets_end(), [](auto f) { return f.is_triangle(); })) {
} catch (...) {
Logger::Message(Logger::LOG_ERROR, "Triangulation crashed"); if (!s.is_valid()) {
return; Logger::Message(Logger::LOG_ERROR, "Invalid Polyhedron_3 in object (before triangulation)");
} return;
}
if (!success) {
Logger::Message(Logger::LOG_ERROR, "Triangulation failed"); CGAL::Polygon_mesh_processing::remove_degenerate_faces(s);
return;
} bool success = false;
// std::cout << "Triangulated model: " << s.size_of_facets() << " facets and " << s.size_of_vertices() << " vertices" << std::endl; try {
success = CGAL::Polygon_mesh_processing::triangulate_faces(s);
if (!s.is_valid()) { } catch (...) {
Logger::Message(Logger::LOG_ERROR, "Invalid Polyhedron_3 in object (after triangulation)"); Logger::Message(Logger::LOG_ERROR, "Triangulation crashed");
return; return;
} }
// CGAL::Polygon_mesh_processing::compute_normals(s, vertex_normals_map, face_normals_map); if (!success) {
try { Logger::Message(Logger::LOG_ERROR, "Triangulation failed");
CGAL::Polygon_mesh_processing::compute_face_normals(s, face_normals_map); return;
} catch (...) { }
Logger::Message(Logger::LOG_ERROR, "Face normal calculation failed"); // std::cout << "Triangulated model: " << s.size_of_facets() << " facets and " << s.size_of_vertices() << " vertices" << std::endl;
return;
} if (!s.is_valid()) {
Logger::Message(Logger::LOG_ERROR, "Invalid Polyhedron_3 in object (after triangulation)");
int num_faces = 0, num_vertices = 0; return;
for (auto &face: faces(s)) { }
if (!face->is_triangle()) {
std::cout << "Warning: non-triangular face!" << std::endl; }
continue;
} // std::map<cgal_vertex_descriptor_t, Kernel_::Vector_3> vertex_normals;
CGAL::Polyhedron_3<Kernel_>::Halfedge_around_facet_const_circulator current_halfedge = face->facet_begin(); // boost::associative_property_map<std::map<cgal_vertex_descriptor_t, Kernel_::Vector_3>> vertex_normals_map(vertex_normals);
int vertexidx[3];
int i = 0; // Triangulate the shape and compute the normals
do { std::map<cgal_face_descriptor_t, Kernel_::Vector_3> face_normals;
vertexidx[i++] = t->addVertex(surface_style_id, boost::associative_property_map<std::map<cgal_face_descriptor_t, Kernel_::Vector_3>> face_normals_map(face_normals);
CGAL::to_double(current_halfedge->vertex()->point().cartesian(0)),
CGAL::to_double(current_halfedge->vertex()->point().cartesian(1)), // CGAL::Polygon_mesh_processing::compute_normals(s, vertex_normals_map, face_normals_map);
CGAL::to_double(current_halfedge->vertex()->point().cartesian(2))); try {
CGAL::Polygon_mesh_processing::compute_face_normals(s, face_normals_map);
} catch (...) {
Logger::Message(Logger::LOG_ERROR, "Face normal calculation failed");
return;
}
int num_faces = 0, num_vertices = 0;
for (auto &face : faces(s)) {
if (!face->is_triangle()) {
std::cout << "Warning: non-triangular face!" << std::endl;
continue;
}
CGAL::Polyhedron_3<Kernel_>::Halfedge_around_facet_const_circulator current_halfedge = face->facet_begin();
int vertexidx[3];
int i = 0;
do {
vertexidx[i++] = t->addVertex(surface_style_id,
CGAL::to_double(current_halfedge->vertex()->point().cartesian(0)),
CGAL::to_double(current_halfedge->vertex()->point().cartesian(1)),
CGAL::to_double(current_halfedge->vertex()->point().cartesian(2)));
double nx = 0.;
double ny = 0.;
double nz = 1.;
double nx = 0.;
double ny = 0.;
double nz = 1.;
// @todo normal calculation throws divide by zero?
// try {
if (false) {
nx = CGAL::to_double(face_normals_map[face].cartesian(0)); nx = CGAL::to_double(face_normals_map[face].cartesian(0));
ny = CGAL::to_double(face_normals_map[face].cartesian(1)); ny = CGAL::to_double(face_normals_map[face].cartesian(1));
nz = CGAL::to_double(face_normals_map[face].cartesian(2)); nz = CGAL::to_double(face_normals_map[face].cartesian(2));
}
// catch (...) { t->addNormal(nx, ny, nz);
// Logger::Error("Error during normal calculation");
// }
t->addNormal(nx, ny, nz);
++num_vertices; ++num_vertices;
++current_halfedge; ++current_halfedge;
} while (current_halfedge != face->facet_begin()); } while (current_halfedge != face->facet_begin());
t->addFace(surface_style_id, vertexidx[0], vertexidx[1], vertexidx[2]); t->addFace(surface_style_id, vertexidx[0], vertexidx[1], vertexidx[2]);
++num_faces; ++num_faces;
} }
} }