From 5eff7178dadd83ef58adc050e298d021bf6fa217 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Wed, 13 Sep 2023 22:03:49 +0200 Subject: [PATCH] Restructure cgal shape triangulation --- .../kernels/cgal/CgalConversionResult.cpp | 173 +++++++++--------- 1 file changed, 90 insertions(+), 83 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp index 4b6fe74ed8..ee83f9d66d 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp @@ -1,104 +1,111 @@ #include "CgalConversionResult.h" #include "CgalKernel.h" +#include + #include "../../../ifcparse/IfcLogger.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 { - // Copy is made because triangulate_faces() does not accept a const argument - cgal_shape_t s = shape_; + // Copy is made because triangulate_faces() obviously does not accept a const argument + // ... also becuase of transforming the vertex positions, right? + cgal_shape_t s = shape_; - if (!place.is_identity()) { - const auto& m = place.ccomponents(); + if (!place.is_identity()) { + const auto& m = place.ccomponents(); - // @todo check - const cgal_placement_t trsf( - 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(2, 0), m(2, 1), m(2, 2), m(2, 3)); + // @todo check + const cgal_placement_t trsf( + 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(2, 0), m(2, 1), m(2, 2), m(2, 3)); - // Apply transformation - for (auto &vertex : vertices(s)) { - 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 vertex_normals; -// boost::associative_property_map> vertex_normals_map(vertex_normals); - std::map face_normals; - boost::associative_property_map> face_normals_map(face_normals); + // Apply transformation + for (auto &vertex : vertices(s)) { + vertex->point() = vertex->point().transform(trsf); + } + } - bool success = false; - try { - success = CGAL::Polygon_mesh_processing::triangulate_faces(s); - } catch (...) { - Logger::Message(Logger::LOG_ERROR, "Triangulation crashed"); - return; - } - - if (!success) { - Logger::Message(Logger::LOG_ERROR, "Triangulation failed"); - return; - } - // std::cout << "Triangulated model: " << s.size_of_facets() << " facets and " << s.size_of_vertices() << " vertices" << std::endl; - - if (!s.is_valid()) { - Logger::Message(Logger::LOG_ERROR, "Invalid Polyhedron_3 in object (after triangulation)"); - return; - } - -// CGAL::Polygon_mesh_processing::compute_normals(s, vertex_normals_map, face_normals_map); - 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::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))); + std::wcout << "Triangulating " << std::distance(s.facets_begin(), s.facets_end()) << std::endl; + + if (!std::all_of(s.facets_begin(), s.facets_end(), [](auto f) { return f.is_triangle(); })) { + + if (!s.is_valid()) { + Logger::Message(Logger::LOG_ERROR, "Invalid Polyhedron_3 in object (before triangulation)"); + return; + } + + CGAL::Polygon_mesh_processing::remove_degenerate_faces(s); + + bool success = false; + try { + success = CGAL::Polygon_mesh_processing::triangulate_faces(s); + } catch (...) { + Logger::Message(Logger::LOG_ERROR, "Triangulation crashed"); + return; + } + + if (!success) { + Logger::Message(Logger::LOG_ERROR, "Triangulation failed"); + return; + } + // std::cout << "Triangulated model: " << s.size_of_facets() << " facets and " << s.size_of_vertices() << " vertices" << std::endl; + + if (!s.is_valid()) { + Logger::Message(Logger::LOG_ERROR, "Invalid Polyhedron_3 in object (after triangulation)"); + return; + } + + } + + // std::map vertex_normals; + // boost::associative_property_map> vertex_normals_map(vertex_normals); + + // Triangulate the shape and compute the normals + std::map face_normals; + boost::associative_property_map> face_normals_map(face_normals); + + // CGAL::Polygon_mesh_processing::compute_normals(s, vertex_normals_map, face_normals_map); + 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::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)); ny = CGAL::to_double(face_normals_map[face].cartesian(1)); nz = CGAL::to_double(face_normals_map[face].cartesian(2)); - } - // catch (...) { - // Logger::Error("Error during normal calculation"); - // } - t->addNormal(nx, ny, nz); + + t->addNormal(nx, ny, nz); - ++num_vertices; - ++current_halfedge; - } while (current_halfedge != face->facet_begin()); + ++num_vertices; + ++current_halfedge; + } 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; + } }