From 4adb72365ed4c00c95e7703b0409b64056a12e64 Mon Sep 17 00:00:00 2001 From: "Giraldeau, Francis" Date: Thu, 15 Aug 2024 16:53:53 -0400 Subject: [PATCH 1/3] Add basic cmake file --- CMakeLists.txt | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..8d711b5 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 3.8) + +project(quartet LANGUAGES CXX) + +option(QUARTET_ENABLE_VIEWER "Build the mesh viewer" ON) + +add_library(quartetcore + src/predicates.cpp + src/geometry_queries.cpp + src/sdf.cpp + src/trimesh.cpp + src/tet_mesh.cpp + src/feature.cpp + src/read_obj.cpp + src/tet_quality.cpp + src/match_features.cpp + src/optimize_tet_mesh.cpp + src/make_signed_distance.cpp + src/make_tet_mesh.cpp +) + +add_executable(quartet src/main.cpp) +target_link_libraries(quartet quartetcore) + +if (QUARTET_ENABLE_VIEWER) + + set(Open_GL_PREFERENCE "GLVND") + find_package(OpenGL REQUIRED) + find_package(GLUT REQUIRED) + + add_library(quartetview src/gluvi.cpp) + target_link_libraries(quartetview PUBLIC OpenGL::OpenGL OpenGL::GLU GLUT::GLUT) + + add_executable(view-tet src/view_tet.cpp) + target_link_libraries(view-tet quartetcore quartetview) +endif() From d98c22f61a162a823e1deb883180d91549e0f9f4 Mon Sep 17 00:00:00 2001 From: "Giraldeau, Francis" Date: Thu, 15 Aug 2024 16:54:50 -0400 Subject: [PATCH 2/3] add save to vtk function --- src/tet_mesh.cpp | 43 +++++++++++++++++++++++++++++++++++++++++++ src/tet_mesh.h | 2 ++ 2 files changed, 45 insertions(+) diff --git a/src/tet_mesh.cpp b/src/tet_mesh.cpp index b0ee117..d13021f 100644 --- a/src/tet_mesh.cpp +++ b/src/tet_mesh.cpp @@ -436,6 +436,49 @@ bool TetMesh::writeToFile(const char* filename) const return true; } +bool TetMesh::writeToFileVTK(const char *filename) const +{ + std::ofstream file(filename); + if (!file.is_open()) { + // Handle error: file could not be opened + return false; + } + + // Write header + file << "# vtk DataFile Version 2.0\n"; + file << "quartet\n"; + file << "ASCII\n"; + file << "DATASET UNSTRUCTURED_GRID\n"; + + // Write number of points + file << "POINTS " << v.size() << " double\n"; + + // Write point coordinates + for (const Vec3f& point : v) { + file << point[0] << " " << point[1] << " " << point[2] << "\n"; + } + + // Write number of cells + int numCells = t.size(); + int numCellPoints = 1 + 4; + int totalNumCellPoints = numCells * numCellPoints; + file << "CELLS " << numCells << " " << totalNumCellPoints << "\n"; + + // Write cell connectivity + for (const Vec4i& tet : t) { + file << "4 " << tet[0] << " " << tet[1] << " " << tet[2] << " " << tet[3] << "\n"; + } + + // Write cell types (all tetrahedra) + int cellType = 10; // VTK cell type for tetrahedron + file << "CELL_TYPES " << numCells << "\n"; + for (int i = 0; i < numCells; ++i) { + file << cellType << "\n"; + } + + file.close(); + return true; +} bool TetMesh::writeInfoToFile(const char* filename) const { diff --git a/src/tet_mesh.h b/src/tet_mesh.h index 6c203f0..5754a1f 100644 --- a/src/tet_mesh.h +++ b/src/tet_mesh.h @@ -106,6 +106,8 @@ struct TetMesh // etc.) and write it to the file with the given name. bool writeInfoToFile(const char* filename) const; + + bool writeToFileVTK(const char *filename) const; private: std::vector v; std::vector t; From 1604fed03568c3a5127a84f45e0af2bdf16e3d42 Mon Sep 17 00:00:00 2001 From: "Giraldeau, Francis" Date: Thu, 15 Aug 2024 17:23:46 -0400 Subject: [PATCH 3/3] add support for vtk --- src/main.cpp | 155 ++++++++++++++++++++++++++------------------------- 1 file changed, 80 insertions(+), 75 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 2bdf421..935fbd6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,17 +1,16 @@ -#include "make_tet_mesh.h" -#include "make_signed_distance.h" -#include "read_obj.h" -#include "feature.h" -#include "trimesh.h" -#include -#include #include #include #include +#include +#include -int -main(int argc, - char **argv) +#include "feature.h" +#include "make_signed_distance.h" +#include "make_tet_mesh.h" +#include "read_obj.h" +#include "trimesh.h" + +int main(int argc, char** argv) { // // Parse input arguments @@ -20,7 +19,7 @@ main(int argc, bool usage = false, failure = false; bool feature = false, automatic = false, surface = false, intermediate = false, optimize = false, unsafe = false; - char* featureFile = NULL, *surfaceFile = NULL; + char *featureFile = NULL, *surfaceFile = NULL; float angleThreshold; if (argc < 4 || argc > 12) { @@ -64,7 +63,7 @@ main(int argc, automatic = true; } else { std::printf("Error interpreting [%s] as angle threshold\n", - argv[arg]); + argv[arg]); usage = true; --arg; } @@ -116,6 +115,29 @@ main(int argc, } } + // + // Check and prepare output filename before the actual computation. There + // is nothing more frustrating than doing a long computation just to find + // out that we cannot write the output because the output name is wrong. + // + std::string outfile(argv[3]); + size_t extpos = outfile.find_last_of("."); + std::string outformat; + + if (extpos == std::string::npos) { + failure = true; + std::printf("Error: output file extension required\n"); + } else { + outformat = outfile.substr(extpos); + if (!(outformat == ".vtk" || outformat == ".tet")) { + std::printf("Error: supported output formats are .tet or .vtk\n"); + failure = true; + } + } + + // Strip off file extension for creating other files. + std::string filenameStr = outfile.substr(0, outfile.find_last_of('.')); + if (feature && automatic) { std::printf("Error: Feature file and automatic feature generation " "selected. Disabling automatic feature generation " @@ -124,7 +146,7 @@ main(int argc, } if (usage) { - std::printf("usage: quartet " + std::printf("usage: quartet " "[-f ] [-a ] " "[-s ] [-i] [-o] \n" " -f -- Match the features in the given " @@ -143,7 +165,6 @@ main(int argc, return 1; } - // // Run quartet mesh generation // @@ -161,46 +182,42 @@ main(int argc, } // Get the grid spacing - float dx=1; + float dx = 1; if (sscanf(argv[2], "%f", &dx) != 1) { - std::printf("error interpreting [%s] as a float grid spacing\n", - argv[2]); + std::printf("error interpreting [%s] as a float grid spacing\n", argv[2]); return 4; } // Find bounding box - Vec3f xmin=surf_x[0], xmax=surf_x[0]; - for (size_t i=1; i dihedralAngles; - dihedralAngles.reserve(mesh.tSize()*6); - for (size_t tIdx = 0; tIdx < mesh.tSize(); ++tIdx) - { + dihedralAngles.reserve(mesh.tSize() * 6); + for (size_t tIdx = 0; tIdx < mesh.tSize(); ++tIdx) { Tet currTet = mesh.getTet(tIdx); std::vector currAngles; currTet.dihedralAngles(currAngles); - for (size_t i = 0; i < currAngles.size(); ++i) - { + for (size_t i = 0; i < currAngles.size(); ++i) { dihedralAngles.push_back(currAngles[i] * 180.0 / M_PI); } } std::stringstream ss2; ss2 << filenameStr << "_hist.m"; std::ofstream out(ss2.str().c_str()); - if (out.good()) - { + if (out.good()) { std::printf("Writing histogram to file: %s\n", ss2.str().c_str()); out << "histValues = [ "; - for (size_t i = 0; i < dihedralAngles.size(); ++i) - { + for (size_t i = 0; i < dihedralAngles.size(); ++i) { out << dihedralAngles[i] << " "; } out << "];" << std::endl; - } - else - { + } else { std::printf("Failed to write histogram file: %s\n", ss2.str().c_str()); } // Write out the exterior as a trimesh, if desired. - if (surface) - { + if (surface) { std::vector surf_verts; std::vector surf_tris; mesh.getBoundary(surf_verts, surf_tris); std::printf("Writing surface mesh to file: %s\n", surfaceFile); result = write_objfile(surf_verts, surf_tris, surfaceFile); - if (!result) - { + if (!result) { std::printf("ERROR: Failed to write surface mesh file.\n"); } } return 0; } -