#include "ExampleMeshAlgorithm.h"
#include <ImFusion/Base/MeshToPointCloudAlgorithm.h>
#include <ImFusion/Base/SharedImageSet.h>
#include <ImFusion/IO/MeshIO.h>
#include <ImFusion/Mesh/Mesh.h>
#include <ImFusion/Mesh/MeshProcessingAlgorithm.h>
{
ExampleMeshAlgorithm::ExampleMeshAlgorithm(
const ImFusion::Mesh* mesh)
: m_inputMesh(mesh)
{
configureDefaults();
}
ExampleMeshAlgorithm::ExampleMeshAlgorithm()
: m_inputMesh(nullptr)
{
configureDefaults();
}
ExampleMeshAlgorithm::~ExampleMeshAlgorithm() {}
bool ExampleMeshAlgorithm::createCompatible(const DataList& data, Algorithm** a)
{
auto meshes = data.getSurfaces();
if (meshes.size() == 1)
{
if (data.size() == 1 || (data.size() == 2 && dynamic_cast<SharedImageSet*>(data[1])))
{
if (a)
*a = new ExampleMeshAlgorithm(meshes[0]);
return true;
}
}
if (data.size() == 0)
{
if (a)
*a = new ExampleMeshAlgorithm();
return true;
}
return false;
}
void ExampleMeshAlgorithm::compute()
{
if (m_inputMesh)
computeMeshProcessing();
else
computeMeshImport();
}
OwningDataList ExampleMeshAlgorithm::takeOutput()
{
if (m_outputPointCloud)
{
OwningDataList res(std::move(m_outputPointCloud));
if (m_outputMesh)
res.add(std::move(m_outputMesh));
return res;
}
else if (m_outputMesh)
return OwningDataList(std::move(m_outputMesh));
else
return OwningDataList();
}
void ExampleMeshAlgorithm::configure(const Properties* p)
{
if (!p)
return;
if (m_inputMesh)
{
p->param("decimMaxEdgeLength", m_decimMaxEdgeLength);
p->param("smoothIterations", m_smoothIterations);
}
else
{
p->param("filePath", m_filePath);
}
}
void ExampleMeshAlgorithm::configuration(Properties* p) const
{
if (!p)
return;
if (m_inputMesh)
{
p->setParam("decimMaxEdgeLength", m_decimMaxEdgeLength, 15.0);
p->setParam("smoothIterations", m_smoothIterations, 30);
}
else
{
p->setParam("filePath", m_filePath, "");
p->setParamType("filePath", Properties::ParamType::Path);
}
}
void ExampleMeshAlgorithm::computeMeshImport()
{
m_status = Status::InvalidInput;
if (!m_outputMesh)
return;
vec3 bbMax = -bbMin;
vec3 com = vec3::Zero();
int numValid = 0;
for (int i = 0, numVertices = static_cast<int>(m_outputMesh->numberOfVertices()); i < numVertices; ++i)
{
if (!m_outputMesh->vertexIndexValid(i))
continue;
const vec3 v = m_outputMesh->vertex(i);
bbMin = bbMin.cwiseMin(v);
bbMax = bbMax.cwiseMax(v);
com += v;
++numValid;
}
com *= (1.0 / static_cast<double>(numValid));
double meanEdgeLength = 0.0;
double maxEdgeLength = 0.0;
numValid = 0;
for (int i = 0, numFaces = static_cast<int>(m_outputMesh->numberOfFaces()); i < numFaces; ++i)
{
if (!m_outputMesh->faceIndexValid(i))
continue;
const vec3i faceVerts = m_outputMesh->faceVertices(i);
for (const auto& j : {faceVerts[0], faceVerts[1], faceVerts[2]})
{
const vec2i verts = m_outputMesh->halfedgeVertices(j, i);
const vec3 from = m_outputMesh->vertex(verts[0]);
const vec3 to = m_outputMesh->vertex(verts[1]);
const vec3 d = to - from;
const double dl = d.norm();
meanEdgeLength += dl;
maxEdgeLength =
std::max(maxEdgeLength, dl);
minEdgeLength =
std::min(minEdgeLength, dl);
++numValid;
}
}
meanEdgeLength /= static_cast<double>(numValid);
m_outputMesh->setMatrix(Eigen::Affine3d(Eigen::Translation3d(-com)).matrix() * m_outputMesh->matrix());
const vec3 diameter = bbMax - bbMin;
LOG_INFO(
"Mesh dimensions: " << diameter[0] <<
" x " << diameter[1] <<
" x " << diameter[2]);
LOG_INFO(
"Edge lengths: Max = " << maxEdgeLength <<
"; Min = " << minEdgeLength <<
"; Average = " << meanEdgeLength);
m_status = Status::Success;
}
void ExampleMeshAlgorithm::computeMeshProcessing()
{
m_status = Status::Error;
if (!m_inputMesh)
{
m_status = Status::IncompleteInput;
return;
}
MeshProcessingAlgorithm meshProcAlg(m_outputMesh.get());
meshProcAlg.setInPlace(true);
if (m_decimMaxEdgeLength > 0)
{
meshProcAlg.setDecimationParam(m_decimMaxEdgeLength, 0.0, true);
meshProcAlg.compute();
}
if (m_smoothIterations > 0)
{
meshProcAlg.setSmoothParam(m_smoothIterations);
meshProcAlg.compute();
}
MeshToPointCloudAlgorithm meshToPointCloudAlg(m_outputMesh.get());
meshToPointCloudAlg.compute();
m_outputPointCloud = meshToPointCloudAlg.takeOutput().extractFirst<PointCloud>();
m_status = Status::Success;
}
}
Represents a triangle mesh.
Definition Mesh.h:43
@ DECIMATE
decimate mesh
Definition MeshProcessingAlgorithm.h:21
@ SMOOTH
smooth mesh
Definition MeshProcessingAlgorithm.h:20
#define LOG_INFO(...)
Emits a log message of Log::Level::Info, optionally with a category.
Definition Log.h:247
Mesh * load(const char *buffer, size_t bufferLength, const std::string &sourceFilename="", Progress *progressBar=nullptr, bool log=false)
Loads a mesh from a memory buffer.
Namespace of the ImFusion SDK.
Definition Assert.h:7