Skip to content

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;

    }
}