Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update refactoring code, new file loader #10

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions src/CloudGeneration.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#pragma once

#include <igl/read_triangle_mesh.h>
#include <igl/readOBJ.h>
#include <igl/readPLY.h>
#include <igl/per_vertex_normals.h>
#include "MyPointCloud.h"

void loadPTSObject (MyPointCloud &cloud, std::string filename){

Eigen::MatrixXd cloudV, cloudN;

std::ifstream file(filename);
if (!file.is_open()) {
std::cerr << "Could not open the file: " << filename << std::endl;
return;
}

std::string line;
// Read the first line (header)
std::getline(file, line);
std::istringstream iss(line);
std::vector<std::string> header;
std::string word;
while (iss >> word) {
header.push_back(word);
}

// Find the indices of the x, y, z, nx, ny, nz in the header
std::map<std::string, int> indices;
for (int i = 0; i < header.size(); ++i) {
if (header[i] == "x" || header[i] == "y" || header[i] == "z" || header[i] == "nx" || header[i] == "ny" || header[i] == "nz") {
indices[header[i]] = i-1;
}
}

// Read the rest of the file
while (std::getline(file, line)) {
std::istringstream iss(line);
std::vector<double> values(header.size());
for (int i = 0; i < header.size(); ++i) {
iss >> values[i];
}

// Add the read values to the matrices
cloudV.conservativeResize(cloudV.rows() + 1, 3);
cloudV.row(cloudV.rows() - 1) << values[indices["x"]], values[indices["y"]], values[indices["z"]];

cloudN.conservativeResize(cloudN.rows() + 1, 3);
cloudN.row(cloudN.rows() - 1) << values[indices["nx"]], values[indices["ny"]], values[indices["nz"]];
}

file.close();

cloud = MyPointCloud(cloudV, cloudN);
}


void loadObject (MyPointCloud &cloud, std::string filename) {

Eigen::MatrixXi meshF;
Eigen::MatrixXd cloudV, cloudN;

if (filename.substr(filename.find_last_of(".") + 1) == "pts") {
loadPTSObject(cloud, filename);
return;
}
else {
if (filename.substr(filename.find_last_of(".") + 1) == "ply"){
Eigen::MatrixXi cloudE;
Eigen::MatrixXd cloudUV;
igl::readPLY(filename, cloudV, meshF, cloudE, cloudN, cloudUV);
}
else {
igl::read_triangle_mesh(filename, cloudV, meshF);
}

if ( cloudN.rows() == 0 )
igl::per_vertex_normals(cloudV, meshF, cloudN);

}
// Check if there is mesh
if ( meshF.rows() == 0 && cloudN.rows() == 0 ) {
std::cerr << "[libIGL] The mesh is empty. Aborting..." << std::endl;
exit (EXIT_FAILURE);
}

// Check if normals have been properly loaded
int nbUnitNormal = cloudN.rowwise().squaredNorm().sum();
if ( meshF.rows() != 0 && nbUnitNormal != cloudV.rows() ) {
std::cerr << "[libIGL] An error occurred when computing the normal vectors from the mesh. Aborting..."
<< std::endl;
exit (EXIT_FAILURE);
}

cloud = MyPointCloud(cloudV, cloudN);
}
102 changes: 102 additions & 0 deletions src/GUI.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
void GUI::mainCallBack(){

// Create a window
ImGui::PushItemWidth(100);
// The size of the window, the position is set by default
ImGui::SetNextWindowSize(ImVec2(300, 600), ImGuiCond_FirstUseEver);

cloudComputing();

}

void GUI::cloudComputingUpdateAll (){
if (!all_computed) return;

pointProcessing.measureTime("[Polyscope] Update diff quantities and projection", [this](){

for (int i = 0; i < selectedQuantities.size(); ++i) {
if (selectedQuantities[i]){
std::string completeName = "[" + methodName + "] "+ quantityNames[i];
addQuantities(polyscope_mainCloud,completeName, mainCloud.getDiffQuantities().getByName(quantityNames[i]));
}
}
});

all_computed = false;
methodName = "";
}


template <typename FitT>
void GUI::methodForCloudComputing(const std::string& metName){
std::string buttonName_all = metName;
if (ImGui::Button(buttonName_all.c_str())){
methodName = metName;
all_computed = true;
pointProcessing.computeDiffQuantities<FitT>(metName, mainCloud);
}
}

void GUI::cloudComputing(){

cloudComputingParameters();

ImGui::Text("Differential estimators");

if (ImGui::Button("Dry Run")){
pointProcessing.mlsDryRun();
lastDryRun = "Last time run : " + std::to_string(pointProcessing.getMeanNeighbors()) + " number of neighbors (mean) \n";
}
ImGui::SameLine();
ImGui::Text(lastDryRun.c_str());

methodForCloudComputing<basket_planeFit>("Plane (PCA)");

ImGui::SameLine();

methodForCloudComputing<basket_AlgebraicPointSetSurfaceFit>("APSS");

ImGui::SameLine();

methodForCloudComputing<basket_AlgebraicShapeOperatorFit>("ASO");

cloudComputingUpdateAll();
}

void GUI::cloudComputingParameters(){

ImGui::Text("Neighborhood collection");
ImGui::SameLine();
if(ImGui::Checkbox("Use KnnGraph", &pointProcessing.useKnnGraph))
pointProcessing.recomputeKnnGraph();

ImGui::InputInt("k-neighborhood size", &pointProcessing.kNN);
ImGui::InputFloat("neighborhood size", &pointProcessing.NSize);
ImGui::InputInt("source vertex", &pointProcessing.iVertexSource);
ImGui::InputInt("Nb MLS Iterations", &pointProcessing.mlsIter);
ImGui::SameLine();
if (ImGui::Button("show knn")) addQuantities(polyscope_mainCloud, "knn", pointProcessing.colorizeKnn());
ImGui::SameLine();
if (ImGui::Button("show euclidean nei")) addQuantities(polyscope_mainCloud, "euclidean nei", pointProcessing.colorizeEuclideanNeighborhood());

ImGui::Separator();

}

void GUI::addQuantities(polyscope::PointCloud *pc, const std::string &name, const Eigen::MatrixXd &values){
if (values.cols() == 1){
// Make values beeing a vector
Eigen::VectorXd valuesVec = values.col(0);
auto quantity = pc->addScalarQuantity(name, valuesVec);
// Set bound [-5, 5] for the scalar quantity
if (name != "knn" && name != "euclidean nei"){
quantity->setMapRange(std::pair<double,double>(-5,5));
quantity->setColorMap("coolwarm");
}
else {
quantity->setColorMap("turbo");
}
}
else
pc->addVectorQuantity(name, values);
}
88 changes: 88 additions & 0 deletions src/GUI.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// GUI.h
#pragma once

#include <fstream>
#include <iostream>
#include <filesystem>
#include <mutex>
#include "polyscope/polyscope.h"
#include "polyscope/messages.h"
#include "polyscope/point_cloud.h"
#include "MyPointCloud.h"
#include "CloudGeneration.h"
#include "PointProcessing.h"
#include <Eigen/Dense>

class GUI {

public:

GUI(){

// Initialize polyscope
selectedQuantities.resize(7, 1);

// Initialize the point cloud
selectedFile = assetsDir + "armadillo.obj";

pointProcessing.measureTime("[Generation] Load object", [this](){
loadObject(mainCloud, selectedFile);
});

pointProcessing.update(mainCloud);
polyscope_mainCloud = polyscope::registerPointCloud(mainCloudName, mainCloud.getVertices());
addQuantities(polyscope_mainCloud, "real normals", mainCloud.getNormals());
}

void mainCallBack();


private:

// Point Cloud Informations

std::string mainCloudName = "mainCloud";
std::string assetsDir = "assets/";
std::string selectedFile = "";

Scalar pointRadius = 0.005; /// < display radius of the point cloud
polyscope::PointCloud* polyscope_mainCloud;

MyPointCloud mainCloud;
PointProcessing pointProcessing;

private:

// Point Cloud Processing

// quantities to display
// 0 : display projections
// 1 : display normals
// 2 : display min curvature direction
// 3 : display max curvature direction
// 4 : display min curvature
// 5 : display max curvature
// 6 : display mean curvature
std::vector<std::string> quantityNames = {"Projections", "Normals", "Min curvature direction", "Max curvature direction", "Min curvature", "Max curvature", "Mean curvature"};
std::vector<int> selectedQuantities; // Initialize to 1 all quantities

std::string lastDryRun = "";

bool all_computed = false;
std::string methodName = "";

void cloudComputing();

void cloudComputingUpdateAll();

template <typename FitT>
void methodForCloudComputing(const std::string &metName);

void cloudComputingParameters();

void addQuantities(polyscope::PointCloud *pc, const std::string &name, const Eigen::MatrixXd &values);


}; // class GUI

#include "GUI.cpp"
Loading