File bench_centroid_to_face.cpp
File List > benchmark > metrics > implementations > bench_centroid_to_face.cpp
Go to the documentation of this file
#include "bench_centroid_to_face.h"
#include "structure/AABBTree.h"
#include "../../../include/mesh/Vector3D.h"
#include <algorithm>
#include <chrono>
#include <iostream>
#include <limits>
#include <ostream>
namespace Argos {
namespace {
void aggregateCentroidDistances(const AABBTree& source,
const AABBTree& target,
double& meanDist,
double& minDist,
double& maxDist,
size_t& size)
{
meanDist = 0.0;
minDist = std::numeric_limits<double>::max();
maxDist = 0.0;
size = 0;
if (source.empty() || target.empty()) {
return;
}
for (const AABBTree::Triangle& tri : source.getTriangles()) {
// centroïde du triangle (déjà triangulé par l'arbre)
const Vector3D<double> centroid = (tri.a + tri.b + tri.c) / 3.0;
// distance au triangle le plus proche dans l'autre maillage
const double d = target.nearestDistance(centroid);
meanDist += d;
minDist = std::min(minDist, d);
maxDist = std::max(maxDist, d);
++size;
}
meanDist /= static_cast<double>(size);
}
} // namespace
BenchCentroidToFace BenchCentroidToFaceComputer::compute(const Mesh& a, const Mesh& b)
{
// Une seule construction par maillage : la triangulation des faces, le calcul
// des AABB et la subdivision spatiale ne sont effectués qu'ici.
const AABBTree treeA(a);
const AABBTree treeB(b);
BenchCentroidToFace result{};
// sens A -> B : distance de chaque centroïde de A au plus proche triangle de B
aggregateCentroidDistances(treeA, treeB, result.meanAB, result.minAB, result.maxAB, result.sizeA);
// sens B -> A
aggregateCentroidDistances(treeB, treeA, result.meanBA, result.minBA, result.maxBA, result.sizeB);
// moyenne globale (Hausdorff symétrique simplifié)
result.mean = (result.sizeA == 0 || result.sizeB == 0) ? 0.0 : (result.meanAB + result.meanBA) / 2.0;
return result;
}
void CentroidToFaceMetric::compute(const Mesh& original, const Mesh& reconstructed, benchmark::State& state) const
{
const std::string prefix = getName();
if (original.isEmpty()) {
// sans mesh original (cloud point en entrée)
std::cout << "CentroidToFaceMetric -> benchmark utilisable uniquement avec un maillage en entree." << std::endl;
//state.counters[prefix + "_TimeSeconds"] = -1.0;
//state.counters[prefix + "_NbFacesA"] = -1.0;
state.counters[prefix + "_NbFacesB"] = -1.0;
//state.counters[prefix + "_NbTrianglesA"] = -1.0;
state.counters[prefix + "_NbTrianglesB"] = -1.0;
//state.counters[prefix + "_NbTrianglesTotal"] = -1.0;
//state.counters[prefix + "_MeanAB"] = -1.0;
//state.counters[prefix + "_MaxAB"] = -1.0;
//state.counters[prefix + "_MinAB"] = -1.0;
state.counters[prefix + "_MeanBA"] = -1.0;
state.counters[prefix + "_MaxBA"] = -1.0;
state.counters[prefix + "_MinBA"] = -1.0;
return;
}
const auto start = std::chrono::high_resolution_clock::now();
const auto result = BenchCentroidToFaceComputer::compute(original, reconstructed);
const auto end = std::chrono::high_resolution_clock::now();
const std::chrono::duration<double> elapsed = end - start;
//state.counters[prefix + "_TimeSeconds"] = elapsed.count();
//state.counters[prefix + "_NbFacesA"] = static_cast<double>(original.getFaces().size());
state.counters[prefix + "_NbFacesB"] = static_cast<double>(reconstructed.getFaces().size());
//state.counters[prefix + "_NbTrianglesA"] = static_cast<double>(result.sizeA);
state.counters[prefix + "_NbTrianglesB"] = static_cast<double>(result.sizeB);
//state.counters[prefix + "_NbTrianglesTotal"] = static_cast<double>(result.sizeA + result.sizeB);
//state.counters[prefix + "_MeanAB"] = result.meanAB;
//state.counters[prefix + "_MaxAB"] = result.maxAB;
//state.counters[prefix + "_MinAB"] = result.minAB;
state.counters[prefix + "_MeanBA"] = result.meanBA;
state.counters[prefix + "_MaxBA"] = result.maxBA;
state.counters[prefix + "_MinBA"] = result.minBA;
}
}