#pragma once#include<random>#include<Eigen/Core>#include<Eigen/Dense>namespaceshapeworks{structMultiVariateNormalRandom{Eigen::VectorXdmean;Eigen::MatrixXdtransform;// seed set as constant 42 for test repeatabilitystd::mt19937gen{42};std::normal_distribution<>dist;MultiVariateNormalRandom(Eigen::MatrixXdconst&covar):MultiVariateNormalRandom(Eigen::VectorXd::Zero(covar.rows()),covar){}MultiVariateNormalRandom(Eigen::VectorXdconst&mean,Eigen::MatrixXdconst&covar):mean(mean){Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd>eigenSolver(covar);transform=eigenSolver.eigenvectors()*eigenSolver.eigenvalues().cwiseSqrt().asDiagonal();}Eigen::MatrixXdoperator()(){returnmean+transform*Eigen::VectorXd{mean.size()}.unaryExpr([&](doublex){returndist(gen);});}};structReconstruction{doubledist;intshapeIdx;Eigen::MatrixXdrec;};// Sorts the reconstructions in place according to `dist` and saves them to the specified folder.// This generates XML files which can be opened in ShapeWorksStudiovoidSaveReconstructions(std::vector<Reconstruction>&reconstructions,conststd::vector<std::string>&srcPaths,conststd::string&saveTo){std::sort(reconstructions.begin(),reconstructions.end(),[](constReconstruction&l,constReconstruction&r){returnl.dist<r.dist;});for(inti=0;i<reconstructions.size();i++){constintpercentile=i==reconstructions.size()-1?100:std::floor(((double)i/reconstructions.size())*100.0);// Save the reconstructionconststd::stringrecPath=saveTo+"/"+std::to_string(percentile)+"perc.particles";std::ofstreamrecOF(recPath);if(!recOF){throwstd::runtime_error("Unable to open file: "+recPath);}recOF<<reconstructions[i].rec<<std::endl;recOF.close();// Create an XML fileconststd::stringxmlPath=saveTo+"/"+std::to_string(percentile)+"perc.xml";std::ofstreamxmlOF(xmlPath);if(!xmlOF){throwstd::runtime_error("Unable to open file: "+xmlPath);}xmlOF<<"<point_files>"<<srcPaths[reconstructions[i].shapeIdx]<<std::endl<<recPath<<"</point_files>"<<std::endl<<"<group_ids>"<<1<<std::endl<<2<<"</group_ids>";xmlOF.close();}}}