dust3d/src/booleanmesh.h

110 lines
4.4 KiB
C++

#ifndef DUST3D_CGAL_MESH_H
#define DUST3D_CGAL_MESH_H
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Surface_mesh.h>
#include <QVector3D>
#include <vector>
#include <cmath>
#include "positionkey.h"
typedef CGAL::Exact_predicates_inexact_constructions_kernel CgalKernel;
typedef CGAL::Surface_mesh<CgalKernel::Point_3> 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 <class Kernel>
typename CGAL::Surface_mesh<typename Kernel::Point_3> *buildCgalMesh(const std::vector<QVector3D> &positions, const std::vector<std::vector<size_t>> &indices)
{
typename CGAL::Surface_mesh<typename Kernel::Point_3> *mesh = new typename CGAL::Surface_mesh<typename Kernel::Point_3>;
std::map<PositionKey, typename CGAL::Surface_mesh<typename Kernel::Point_3>::Vertex_index> vertexIndices;
for (const auto &face: indices) {
std::vector<typename CGAL::Surface_mesh<typename Kernel::Point_3>::Vertex_index> faceVertexIndices;
bool faceValid = true;
std::vector<PositionKey> positionKeys;
std::vector<QVector3D> positionsInKeys;
std::set<PositionKey> 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 <class Kernel>
void fetchFromCgalMesh(typename CGAL::Surface_mesh<typename Kernel::Point_3> *mesh, std::vector<QVector3D> &vertices, std::vector<std::vector<size_t>> &faces)
{
std::map<typename CGAL::Surface_mesh<typename Kernel::Point_3>::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<typename Kernel::Point_3>::Face_range faceRage = mesh->faces();
typename CGAL::Surface_mesh<typename Kernel::Point_3>::Face_range::iterator faceIt;
for (faceIt = faceRage.begin(); faceIt != faceRage.end(); faceIt++) {
CGAL::Vertex_around_face_iterator<typename CGAL::Surface_mesh<typename Kernel::Point_3>> vbegin, vend;
std::vector<size_t> 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 <class Kernel>
bool isNullCgalMesh(typename CGAL::Surface_mesh<typename Kernel::Point_3> *mesh)
{
typename CGAL::Surface_mesh<typename Kernel::Point_3>::Face_range faceRage = mesh->faces();
return faceRage.begin() == faceRage.end();
}
#endif