Skip to content

File BenchmarksContainer.cpp

File List > benchmark > BenchmarksContainer.cpp

Go to the documentation of this file

#include "BenchmarksContainer.h"


BenchmarksContainer::BenchmarksContainer(std::filesystem::path objFolder, std::filesystem::path outputFolderPath) : outputFolderPath(outputFolderPath){
    for (const auto& entry : std::filesystem::directory_iterator(objFolder))
    {
        auto ext = entry.path().extension();

        if (ext == ".obj" || ext == ".ply")
        {
            inputFilesPaths.push_back(entry.path());
        }
    }
}


void BenchmarksContainer::addBenchmark(std::string benchName, std::shared_ptr<ISurfaceReconstructor> reconstructor, const std::vector<std::shared_ptr<Metric>>& metrics) {
    auto runner = [this, reconstructor, metrics, benchName](benchmark::State& state) {
        reconstructionBenchmark(state, *reconstructor, metrics, benchName);
    };

    pipelines.push_back(Pipeline{benchName, runner });
}


void BenchmarksContainer::run(benchmark::BenchmarkReporter* reporter, std::shared_ptr<ISurfaceSampler> sampler) {
    ObjSerializer obj_serializer;
    PlySerializer ply_serializer;
    std::vector<Vector3D<double>> vertices;
    std::vector<Face> faces;

    for (size_t i = 0; i < inputFilesPaths.size(); ++i)
    {
        benchmark::ClearRegisteredBenchmarks();

        faces.clear();
        vertices.clear();

        std::ifstream inputfile(inputFilesPaths[i]);

        if (inputFilesPaths[i].extension() == ".obj")
        {
            obj_serializer.deserialize(vertices, faces, inputfile);
        }
        else if (inputFilesPaths[i].extension() == ".ply")
        {
            ply_serializer.deserialize(vertices, faces, inputfile);
        }

        inputfile.close();

        originalMesh = Mesh(vertices, faces);

        if (faces.empty())
        {
            // input file = nuage de points
            cloud = PointCloud(vertices);
            std::cout << "IF = cloud : vertices =  "<< vertices.size() << std::endl;
            std::cout << "IF = cloud : faces = " << faces.size() << std::endl;
            std::cout << "IF = cloud : cloud = " << cloud.size() << std::endl;
        }
        else
        {
            // input file = maillage
            cloud = sampler->sample(originalMesh);
        }

        auto filename = inputFilesPaths[i].stem().string();

        std::filesystem::path pointcloudOutputPath = outputFolderPath / ("Cloud_" + filename + ".obj");
        std::ofstream pointcloudOutput(pointcloudOutputPath);
        std::vector<Face> empty;
        obj_serializer.serialize(
            cloud.getPoints(),
            empty,
            pointcloudOutput
        );
        pointcloudOutput.close();

        std::cout << "Lancement des benchmarks sur le fichier :\n   -" << inputFilesPaths[i].filename() << std::endl;

        for (const auto& pipeline : pipelines)
        {
            benchmark::RegisterBenchmark(
                (pipeline.name + "_" + inputFilesPaths[i].filename().string()).c_str(),
                pipeline.runner
            )->Arg(i)->Iterations(10);
        }

        benchmark::RunSpecifiedBenchmarks(reporter);
    }
}


void BenchmarksContainer::reconstructionBenchmark(benchmark::State& state, ISurfaceReconstructor& reconstructor, const std::vector<std::shared_ptr<Metric>>& metrics, const std::string& pipelineName) {

    state.counters["NbPointsObject"] = cloud.getPoints().size();

    std::ifstream inputfile(inputFilesPaths[state.range(0)]);

    ObjSerializer serializer;
    std::vector<double> texturesCoord;

    if (!inputfile)
    {
        std::cerr << "reconstructionBenchmark : Error while opening the file : " << inputFilesPaths[state.range(0)].string() << std::endl;
        return;
    }

    bool saved = false;

    MemoryPeak memory;

    std::vector<double> metricsResults(metrics.size(), 0.0);
    for (auto _ : state)
    {
        state.PauseTiming();
        if (cloud.getPoints().size() < 5 && dynamic_cast<PoissonSurface*>(&reconstructor)) {
            state.SkipWithMessage("Nombre de points insuffisants (<5) pour l'algorithme de Poisson, passage au prochain algorithme...");
            break;
        }

        memory.start();
        state.ResumeTiming();
        Mesh reconstructed = reconstructor.reconstruct(cloud);
        memory.stop();

        benchmark::DoNotOptimize(cloud);
        benchmark::DoNotOptimize(reconstructed);

        state.PauseTiming();
        if (reconstructed.vertexCount() == 0) {
            state.SkipWithMessage("La reconstruction est vide, passage au prochain algorithme...");
            break;
        }

        if (!saved) {
            memory.compute(originalMesh, reconstructed, state);
            for (size_t i = 0; i < metrics.size(); ++i) {
                if (metrics[i]->getName() == "Heatmap") {
                    reconstructed = VertexToFace::addMidEdgeVertices(reconstructed);
                    texturesCoord = VertexToFace::compute(originalMesh, reconstructed);
                }
                metrics[i]->compute(originalMesh, reconstructed, state);
            }

            auto filename = inputFilesPaths[state.range(0)].stem().string();
            std::filesystem::path reconstructedOutputPath = outputFolderPath / (pipelineName + "_Mesh_" + filename + ".obj");
            std::ofstream reconstructedOutput(reconstructedOutputPath);
            serializer.serialize(
                reconstructed.getVertices(),
                reconstructed.getFaces(),
                texturesCoord,
                reconstructedOutput
            );

            saved = true;
        }

        state.ResumeTiming();
    }
}