#ifndef DUST3D_CGAL_MESH_H #define DUST3D_CGAL_MESH_H #include #include #include #include #include #include "positionkey.h" typedef CGAL::Exact_predicates_inexact_constructions_kernel CgalKernel; typedef CGAL::Surface_mesh CgalMesh; inline bool validatePosition(const QVector3D &position) { if (std::isnan(position.x())) return false; if (std::isnan(position.y())) return false; if (std::isnan(position.z())) return false; if (std::isinf(position.x())) return false; if (std::isinf(position.y())) return false; if (std::isinf(position.z())) return false; return true; } template typename CGAL::Surface_mesh *buildCgalMesh(const std::vector &positions, const std::vector> &indices) { typename CGAL::Surface_mesh *mesh = new typename CGAL::Surface_mesh; std::map::Vertex_index> vertexIndices; for (const auto &face: indices) { std::vector::Vertex_index> faceVertexIndices; bool faceValid = true; std::vector positionKeys; std::vector positionsInKeys; std::set existedKeys; for (const auto &index: face) { const auto &position = positions[index]; if (!validatePosition(position)) { faceValid = false; break; } auto positionKey = PositionKey(position); if (existedKeys.find(positionKey) != existedKeys.end()) { continue; } existedKeys.insert(positionKey); positionKeys.push_back(positionKey); positionsInKeys.push_back(position); } if (!faceValid) continue; if (positionKeys.size() < 3) continue; for (size_t index = 0; index < positionKeys.size(); ++index) { const auto &position = positionsInKeys[index]; const auto &positionKey = positionKeys[index]; auto findIndex = vertexIndices.find(positionKey); if (findIndex != vertexIndices.end()) { faceVertexIndices.push_back(findIndex->second); } else { auto newIndex = mesh->add_vertex(typename Kernel::Point_3(position.x(), position.y(), position.z())); vertexIndices.insert({positionKey, newIndex}); faceVertexIndices.push_back(newIndex); } } mesh->add_face(faceVertexIndices); } return mesh; } template void fetchFromCgalMesh(typename CGAL::Surface_mesh *mesh, std::vector &vertices, std::vector> &faces) { std::map::Vertex_index, size_t> vertexIndicesMap; for (auto vertexIt = mesh->vertices_begin(); vertexIt != mesh->vertices_end(); vertexIt++) { auto point = mesh->point(*vertexIt); float x = (float)CGAL::to_double(point.x()); float y = (float)CGAL::to_double(point.y()); float z = (float)CGAL::to_double(point.z()); vertexIndicesMap[*vertexIt] = vertices.size(); vertices.push_back(QVector3D(x, y, z)); } typename CGAL::Surface_mesh::Face_range faceRage = mesh->faces(); typename CGAL::Surface_mesh::Face_range::iterator faceIt; for (faceIt = faceRage.begin(); faceIt != faceRage.end(); faceIt++) { CGAL::Vertex_around_face_iterator> vbegin, vend; std::vector faceIndices; for (boost::tie(vbegin, vend) = CGAL::vertices_around_face(mesh->halfedge(*faceIt), *mesh); vbegin != vend; ++vbegin){ faceIndices.push_back(vertexIndicesMap[*vbegin]); } faces.push_back(faceIndices); } } template bool isNullCgalMesh(typename CGAL::Surface_mesh *mesh) { typename CGAL::Surface_mesh::Face_range faceRage = mesh->faces(); return faceRage.begin() == faceRage.end(); } #endif