You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have been trying to implement TetGen in libigl and am struggling to produce an .ele file similar to what TetGen produces as a standalone program. Specifically, I would like the tetrahedra to have accurate region IDs. When I run the following code, the .ele file that is produced has exactly one tetrahedron with region ID = 2, with all others equal to 1. I am using the seed point to initialize the two regions as I understand it, but this might be the issue. The "Trabeculae_shell.obj" and "Endosteum_shell_inner.obj" are watertight, non-intersecting nested meshes, with the latter enveloping the former (both attached). Any help would be much appreciated.
#include <igl/read_triangle_mesh.h>
#include <igl/copyleft/cgal/CSGTree.h>
#include <igl/opengl/glfw/Viewer.h>
#include <igl/jet.h>
#include <Eigen/Core>
#include <igl/copyleft/tetgen/tetrahedralize.h>
int main(int argc, char * argv[])
{
using namespace Eigen;
using namespace igl::copyleft::cgal;
using namespace std;
using namespace igl;
// Define Mesh structure
struct Mesh {
Eigen::MatrixXd V;
Eigen::MatrixXi F;
};
// Load meshes using read_triangle_mesh
std::vector<std::string> mesh_files = {"Trabeculae_shell.obj", "Endosteum_shell_inner.obj"};
std::vector<Mesh> meshes;
for (const auto& file : mesh_files) {
Mesh mesh;
igl::read_triangle_mesh(file, mesh.V, mesh.F);
meshes.push_back(mesh);
}
Eigen::MatrixXd V_all;
Eigen::MatrixXi F_all;
// Merge all meshes into V_all and F_all
for (auto &mesh : meshes) {
int offset = V_all.rows();
V_all.conservativeResize(V_all.rows() + mesh.V.rows(), 3);
F_all.conservativeResize(F_all.rows() + mesh.F.rows(), 3);
V_all.block(offset, 0, mesh.V.rows(), 3) = mesh.V;
F_all.block(offset, 0, mesh.F.rows(), 3) = mesh.F.array() + offset;
}
Eigen::MatrixXd V_tet;
Eigen::MatrixXi T;
Eigen::VectorXi VM,FM;
Eigen::MatrixXd H;
Eigen::MatrixXd R(2, 5);
Eigen::VectorXi TM,TR,PT;
Eigen::MatrixXi FT,TN;
int num_regions;
Eigen::RowVector3d trabec_point(0.146617, 0.09489, 0.204463);
Eigen::RowVector3d endo_point(0.00708, 0.065277, 0.058339);
R.row(0) << trabec_point(0), trabec_point(1), trabec_point(2), 1, 0;
R.row(1) << endo_point(0), endo_point(1), endo_point(2), 2, 0;
// Tetrahedralize
igl::copyleft::tetgen::tetrahedralize(V_all, F_all, H, VM, FM, R, "pYA", V_tet, T, F_all, TM, TR, TN, PT, FT, num_regions);
std::cout << "number of regions: " << num_regions << std::endl;
int x = 0;
int num_reg_1 = 0;
int num_reg_2 = 0;
for (int i = 0; i < T.rows(); ++i) {
if (TR(i) != x) {
std::cout << "Tetrahedron " << i << " is in Region " << TR(i) << std::endl;
x = TR(i);
}
if (TR(i) == 1) {
num_reg_1++;
}
else if (TR(i) == 2) {
num_reg_2++;
}
}
std::cout << "number of tetrahedra in region 1: " << num_reg_1 << std::endl;
std::cout << "number of tetrahedra in region 2: " << num_reg_2 << std::endl;
// Prepare the TetGenIO structure for saving
tetgenio outmesh;
// Fill with vertices
outmesh.numberofpoints = V_tet.rows();
outmesh.pointlist = new REAL[outmesh.numberofpoints * 3];
for (int i = 0; i < V_tet.rows(); ++i) {
for (int j = 0; j < 3; ++j) {
outmesh.pointlist[i * 3 + j] = V_tet(i, j);
}
}
// Fill with tetrahedra
outmesh.numberoftetrahedra = T.rows();
outmesh.tetrahedronlist = new int[outmesh.numberoftetrahedra * 4];
for (int i = 0; i < T.rows(); ++i) {
for (int j = 0; j < 4; ++j) {
outmesh.tetrahedronlist[i * 4 + j] = T(i, j) + 1; // TetGen is 1-indexed
}
}
outmesh.numberofregions = num_regions;
outmesh.regionlist = new REAL[outmesh.numberofregions * 5];
for (int i = 0; i < outmesh.numberofregions; ++i) {
for (int j = 0; j < 5; ++j) {
outmesh.regionlist[i * 5 + j] = R(i, j);
}
}
outmesh.numberoftetrahedronattributes = 1;
outmesh.tetrahedronattributelist = new REAL[outmesh.numberoftetrahedra];
for (int i = 0; i < outmesh.numberoftetrahedra; ++i) {
outmesh.tetrahedronattributelist[i] = TR(i);
}
// Save to .node and .ele files
outmesh.save_nodes("output_file");
outmesh.save_elements("output_file");
// Cleanup
delete[] outmesh.pointlist;
delete[] outmesh.tetrahedronlist;
delete[] outmesh.regionlist;
delete[] outmesh.tetrahedronattributelist;
igl::opengl::glfw::Viewer viewer;
viewer.data().set_mesh(V_tet, F_all);
viewer.data().add_points(trabec_point, Eigen::RowVector3d(1,0,0)); // red for trabec_point
viewer.data().add_points(endo_point, Eigen::RowVector3d(0,1,0)); // green for endo_point
viewer.launch();
}
I have been trying to implement TetGen in libigl and am struggling to produce an .ele file similar to what TetGen produces as a standalone program. Specifically, I would like the tetrahedra to have accurate region IDs. When I run the following code, the .ele file that is produced has exactly one tetrahedron with region ID = 2, with all others equal to 1. I am using the seed point to initialize the two regions as I understand it, but this might be the issue. The "Trabeculae_shell.obj" and "Endosteum_shell_inner.obj" are watertight, non-intersecting nested meshes, with the latter enveloping the former (both attached). Any help would be much appreciated.
Endosteum_shell_inner.zip
Trabeculae_shell.zip
The text was updated successfully, but these errors were encountered: