From 33ec896b100dffc55952661eddaf7157ef844954 Mon Sep 17 00:00:00 2001 From: PavelMikus Date: Wed, 15 Jun 2022 12:28:34 +0200 Subject: [PATCH] fix bugs, update tetgen libigl files --- .../igl/copyleft/tetgen/mesh_to_tetgenio.cpp | 88 ++++++++ .../igl/copyleft/tetgen/mesh_to_tetgenio.h | 32 +++ .../copyleft/tetgen/tetgenio_to_tetmesh.cpp | 164 ++++++++++++-- .../igl/copyleft/tetgen/tetgenio_to_tetmesh.h | 30 ++- .../igl/copyleft/tetgen/tetrahedralize.cpp | 202 ++++++++++++++---- .../igl/copyleft/tetgen/tetrahedralize.h | 100 +++++++-- src/slic3r/Utils/FixModelByTetrahedrons.cpp | 47 ++-- 7 files changed, 572 insertions(+), 91 deletions(-) diff --git a/src/libigl/igl/copyleft/tetgen/mesh_to_tetgenio.cpp b/src/libigl/igl/copyleft/tetgen/mesh_to_tetgenio.cpp index 78eaebb5c7..7376ec8167 100644 --- a/src/libigl/igl/copyleft/tetgen/mesh_to_tetgenio.cpp +++ b/src/libigl/igl/copyleft/tetgen/mesh_to_tetgenio.cpp @@ -13,6 +13,94 @@ // STL includes #include + +IGL_INLINE bool igl::copyleft::tetgen::mesh_to_tetgenio( + const std::vector > & V, + const std::vector > & F, + const std::vector > & H, + const std::vector > & R, + tetgenio & in) +{ + using namespace std; + in.firstnumber = 0; + in.numberofpoints = V.size(); + in.pointlist = new REAL[in.numberofpoints * 3]; + //loop over points + for(size_t i = 0; i < (size_t)V.size(); i++) + { + assert(V[i].size() == 3); + in.pointlist[i*3+0] = V[i][0]; + in.pointlist[i*3+1] = V[i][1]; + in.pointlist[i*3+2] = V[i][2]; + } + in.numberoffacets = F.size(); + in.facetlist = new tetgenio::facet[in.numberoffacets]; + in.facetmarkerlist = new int[in.numberoffacets]; + + // loop over face + for(size_t i = 0;i < (size_t)F.size(); i++) + { + in.facetmarkerlist[i] = i; + tetgenio::facet * f = &in.facetlist[i]; + f->numberofpolygons = 1; + f->polygonlist = new tetgenio::polygon[f->numberofpolygons]; + f->numberofholes = 0; + f->holelist = NULL; + tetgenio::polygon * p = &f->polygonlist[0]; + p->numberofvertices = F[i].size(); + p->vertexlist = new int[p->numberofvertices]; + // loop around face + for(int j = 0;j < (int)F[i].size(); j++) + { + p->vertexlist[j] = F[i][j]; + } + } + + in.numberofholes = H.size(); + in.holelist = new double[3 * in.numberofholes]; + // loop over holes + for(size_t holeID = 0, nHoles = H.size(); holeID < nHoles; holeID++) + { + in.holelist[holeID * 3 + 0] = H[holeID][0]; + in.holelist[holeID * 3 + 1] = H[holeID][1]; + in.holelist[holeID * 3 + 2] = H[holeID][2]; + } + + in.numberofregions = R.size(); + in.regionlist = new REAL[ 5 * in.numberofregions]; + // loop over regions + for(size_t regionID = 0, nRegions = R.size(); regionID < nRegions; regionID++) + { + in.regionlist[regionID * 5 + 0] = R[regionID][0]; + in.regionlist[regionID * 5 + 1] = R[regionID][1]; + in.regionlist[regionID * 5 + 2] = R[regionID][2]; + in.regionlist[regionID * 5 + 3] = R[regionID][3]; + in.regionlist[regionID * 5 + 4] = R[regionID][4]; + } + + return true; + +} + +template +IGL_INLINE bool igl::copyleft::tetgen::mesh_to_tetgenio( + const Eigen::PlainObjectBase& V, + const Eigen::PlainObjectBase& F, + const Eigen::PlainObjectBase& H, + const Eigen::PlainObjectBase& R, + tetgenio & in) +{ + using namespace std; + vector > vV, vH, vR; + vector > vF; + matrix_to_list(V,vV); + matrix_to_list(F,vF); + matrix_to_list(H, vH); + matrix_to_list(R, vR); + return mesh_to_tetgenio(vV,vF,vH,vR,in); +} + + IGL_INLINE bool igl::copyleft::tetgen::mesh_to_tetgenio( const std::vector > & V, const std::vector > & F, diff --git a/src/libigl/igl/copyleft/tetgen/mesh_to_tetgenio.h b/src/libigl/igl/copyleft/tetgen/mesh_to_tetgenio.h index 3295294fe5..23e00e947e 100644 --- a/src/libigl/igl/copyleft/tetgen/mesh_to_tetgenio.h +++ b/src/libigl/igl/copyleft/tetgen/mesh_to_tetgenio.h @@ -43,6 +43,38 @@ namespace igl const Eigen::PlainObjectBase& V, const Eigen::PlainObjectBase& F, tetgenio & in); + + + // Load a vertex list and face list into a tetgenio object + // Inputs: + // V #V by 3 vertex position list + // F #F list of polygon face indices into V (0-indexed) + // H #H list of seed point inside each hole + // R #R list of seed point inside each region + // Outputs: + // in tetgenio input object + // Returns true on success, false on error + IGL_INLINE bool mesh_to_tetgenio( + const std::vector > & V, + const std::vector > & F, + const std::vector > & H, + const std::vector > & R, + tetgenio & in); + + + // Wrapper with Eigen types + // Templates: + // DerivedV real-value: i.e. from MatrixXd + // DerivedF integer-value: i.e. from MatrixXi + // DerivedH real-value + // DerivedR real-value + template + IGL_INLINE bool mesh_to_tetgenio( + const Eigen::PlainObjectBase& V, + const Eigen::PlainObjectBase& F, + const Eigen::PlainObjectBase& H, + const Eigen::PlainObjectBase& R, + tetgenio& in); } } } diff --git a/src/libigl/igl/copyleft/tetgen/tetgenio_to_tetmesh.cpp b/src/libigl/igl/copyleft/tetgen/tetgenio_to_tetmesh.cpp index d61153053a..aba87da831 100644 --- a/src/libigl/igl/copyleft/tetgen/tetgenio_to_tetmesh.cpp +++ b/src/libigl/igl/copyleft/tetgen/tetgenio_to_tetmesh.cpp @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2013 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "tetgenio_to_tetmesh.h" @@ -15,7 +15,7 @@ IGL_INLINE bool igl::copyleft::tetgen::tetgenio_to_tetmesh( const tetgenio & out, - std::vector > & V, + std::vector > & V, std::vector > & T, std::vector > & F) { @@ -63,14 +63,12 @@ IGL_INLINE bool igl::copyleft::tetgen::tetgenio_to_tetmesh( assert(max_index >= 0); assert(max_index < (int)V.size()); - cout<=0) + if (out.trifacemarkerlist && out.trifacemarkerlist[i] >= 0) { vector face(3); for(int j = 0; j<3; j++) @@ -84,12 +82,13 @@ IGL_INLINE bool igl::copyleft::tetgen::tetgenio_to_tetmesh( return true; } +template IGL_INLINE bool igl::copyleft::tetgen::tetgenio_to_tetmesh( const tetgenio & out, - std::vector > & V, - std::vector > & T) + Eigen::PlainObjectBase& V, + Eigen::PlainObjectBase& T) { - std::vector > F; + Eigen::Matrix F; return tetgenio_to_tetmesh(out,V,T,F); } @@ -130,16 +129,151 @@ IGL_INLINE bool igl::copyleft::tetgen::tetgenio_to_tetmesh( return true; } -template IGL_INLINE bool igl::copyleft::tetgen::tetgenio_to_tetmesh( const tetgenio & out, - Eigen::PlainObjectBase& V, - Eigen::PlainObjectBase& T) + std::vector > & V, + std::vector > & T) { - Eigen::Matrix F; + std::vector > F; return tetgenio_to_tetmesh(out,V,T,F); } +IGL_INLINE bool igl::copyleft::tetgen::tetgenio_to_tetmesh( + const tetgenio & out, + std::vector > & V, + std::vector > & T, + std::vector > & F, + std::vector >& R, + std::vector >& N, + std::vector >& PT, + std::vector >& FT, + size_t & nR ) +{ + using namespace std; + // process points + if(out.pointlist == NULL) + { + cerr<<"^tetgenio_to_tetmesh Error: point list is NULL\n"<(3)); + // loop over points + for(int i = 0;i < out.numberofpoints; i++) + { + V[i][0] = out.pointlist[i*3+0]; + V[i][1] = out.pointlist[i*3+1]; + V[i][2] = out.pointlist[i*3+2]; + } + + // process tets + if(out.tetrahedronlist == NULL) + { + cerr<<"^tetgenio_to_tetmesh Error: tet list is NULL\n"<(out.numberofcorners)); + int min_index = 1e7; + int max_index = -1e7; + // loop over tetrahedra + for(int i = 0; i < out.numberoftetrahedra; i++) + { + for(int j = 0; j index ? index : min_index); + max_index = (max_index < index ? index : max_index); + } + } + + assert(min_index >= 0); + assert(max_index >= 0); + assert(max_index < (int)V.size()); + + // When would this not be 4? + F.clear(); + // loop over tetrahedra + for(int i = 0; i < out.numberoftrifaces; i++) + { + if(out.trifacemarkerlist[i]>=0) + { + vector face(3); + for(int j = 0; j<3; j++) + { + face[j] = out.trifacelist[i * 3 + j]; + } + F.push_back(face); + } + } + + if(out.tetrahedronattributelist) + { + R.resize(out.numberoftetrahedra, vector(1)); + unordered_map hashUniqueRegions; + for(size_t i = 0; i < out.numberoftetrahedra; i++) + { + R[i][0] = out.tetrahedronattributelist[i]; + hashUniqueRegions[R[i][0]] = i; + } + // extract region marks + nR = hashUniqueRegions.size(); + }else + { + R.clear(); + nR = 0; + } + + // extract neighbor list + if(out.neighborlist) + { + N.resize(out.numberoftetrahedra, vector(4)); + for (size_t i = 0; i < out.numberoftetrahedra; i++) + { + for (size_t j = 0; j < 4; j++) + N[i][j] = out.neighborlist[i * 4 + j]; + } + }else + { + N.clear(); + } + + // extract point 2 tetrahedron list + if(out.point2tetlist) + { + PT.resize(out.numberofpoints, vector(1)); + for (size_t i = 0; i < out.numberofpoints; i++) + { + PT[i][0] = out.point2tetlist[i]; + } + }else + { + PT.clear(); + } + + //extract face to tetrahedron list + if(out.face2tetlist) + { + FT.resize(out.numberoftrifaces, vector(2)); + int triface; + for (size_t i = 0; i < out.numberoftrifaces; i++) + { + for (size_t j = 0; j < 2; j++) + { + FT[i][j] = out.face2tetlist[0]; + } + } + }else + { + FT.clear(); + } + + return true; +} + + #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation template bool igl::copyleft::tetgen::tetgenio_to_tetmesh, Eigen::Matrix >(tetgenio const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); diff --git a/src/libigl/igl/copyleft/tetgen/tetgenio_to_tetmesh.h b/src/libigl/igl/copyleft/tetgen/tetgenio_to_tetmesh.h index 2a5575886d..0d1c523e1c 100644 --- a/src/libigl/igl/copyleft/tetgen/tetgenio_to_tetmesh.h +++ b/src/libigl/igl/copyleft/tetgen/tetgenio_to_tetmesh.h @@ -14,6 +14,7 @@ #endif #include "tetgen.h" // Defined tetgenio, REAL #include +#include #include namespace igl { @@ -34,6 +35,7 @@ namespace igl std::vector > & V, std::vector > & T, std::vector > & F); + IGL_INLINE bool tetgenio_to_tetmesh( const tetgenio & out, std::vector > & V, @@ -49,12 +51,38 @@ namespace igl Eigen::PlainObjectBase& V, Eigen::PlainObjectBase& T, Eigen::PlainObjectBase& F); + template IGL_INLINE bool tetgenio_to_tetmesh( const tetgenio & out, Eigen::PlainObjectBase& V, Eigen::PlainObjectBase& T); - } + + // Extract a tetrahedral mesh from a tetgenio object + // Inputs: + // out tetgenio output object + // Outputs: + // V #V by 3 vertex position list + // T #T by 4 list of tetrahedra indices into V + // F #F by 3 list of marked facets + // R #T list of region IDs for tetrahedra + // N #T by 2 list of neighbors for each tetrahedron + // PT #V list of incident tetrahedron for each vertex + // FT #F by 2 list of tetrahedra sharing each face + // nR number of regions in output mesh + // Returns true on success, false on error + IGL_INLINE bool tetgenio_to_tetmesh( + const tetgenio & out, + std::vector > & V, + std::vector > & T, + std::vector > & F, + std::vector > & R,// region marks for tetrahedrons + std::vector > &N, // neighborlist per tet + std::vector > &PT, // Point to tet list per point + std::vector > &FT, // face to tet list + size_t & nR); // number of regions + + } } } diff --git a/src/libigl/igl/copyleft/tetgen/tetrahedralize.cpp b/src/libigl/igl/copyleft/tetgen/tetrahedralize.cpp index fa61114103..c5f6eb29da 100644 --- a/src/libigl/igl/copyleft/tetgen/tetrahedralize.cpp +++ b/src/libigl/igl/copyleft/tetgen/tetrahedralize.cpp @@ -1,15 +1,15 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2013 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "tetrahedralize.h" #include "mesh_to_tetgenio.h" #include "tetgenio_to_tetmesh.h" -// IGL includes +// IGL includes #include "../../matrix_to_list.h" #include "../../list_to_matrix.h" #include "../../boundary_facets.h" @@ -19,11 +19,11 @@ #include IGL_INLINE int igl::copyleft::tetgen::tetrahedralize( - const std::vector > & V, - const std::vector > & F, + const std::vector > & V, + const std::vector > & F, const std::string switches, - std::vector > & TV, - std::vector > & TT, + std::vector > & TV, + std::vector > & TT, std::vector > & TF) { using namespace std; @@ -55,19 +55,19 @@ IGL_INLINE int igl::copyleft::tetgen::tetrahedralize( { return -1; } - //boundary_facets(TT,TF); + boundary_facets(TT,TF); return 0; } template < - typename DerivedV, - typename DerivedF, - typename DerivedTV, - typename DerivedTT, + typename DerivedV, + typename DerivedF, + typename DerivedTV, + typename DerivedTT, typename DerivedTF> IGL_INLINE int igl::copyleft::tetgen::tetrahedralize( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, const std::string switches, Eigen::PlainObjectBase& TV, Eigen::PlainObjectBase& TT, @@ -101,19 +101,19 @@ IGL_INLINE int igl::copyleft::tetgen::tetrahedralize( } template < - typename DerivedV, - typename DerivedF, - typename DerivedVM, - typename DerivedFM, - typename DerivedTV, - typename DerivedTT, + typename DerivedV, + typename DerivedF, + typename DerivedVM, + typename DerivedFM, + typename DerivedTV, + typename DerivedTT, typename DerivedTF, typename DerivedTM> IGL_INLINE int igl::copyleft::tetgen::tetrahedralize( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, - const Eigen::PlainObjectBase& VM, - const Eigen::PlainObjectBase& FM, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, + const Eigen::MatrixBase& VM, + const Eigen::MatrixBase& FM, const std::string switches, Eigen::PlainObjectBase& TV, Eigen::PlainObjectBase& TT, @@ -124,11 +124,11 @@ IGL_INLINE int igl::copyleft::tetgen::tetrahedralize( vector > vV,vTV; vector > vF,vTT,vTF; vector vTM; - + matrix_to_list(V,vV); matrix_to_list(F,vF); - vector vVM = matrix_to_list(VM); - vector vFM = matrix_to_list(FM); + vector vVM = matrix_to_list(VM); + vector vFM = matrix_to_list(FM); int e = tetrahedralize(vV,vF,vVM,vFM,switches,vTV,vTT,vTF,vTM); if(e == 0) { @@ -155,14 +155,15 @@ IGL_INLINE int igl::copyleft::tetgen::tetrahedralize( } return e; } + IGL_INLINE int igl::copyleft::tetgen::tetrahedralize( - const std::vector > & V, - const std::vector > & F, - const std::vector & VM, + const std::vector > & V, + const std::vector > & F, + const std::vector & VM, const std::vector & FM, const std::string switches, - std::vector > & TV, - std::vector > & TT, + std::vector > & TV, + std::vector > & TT, std::vector > & TF, std::vector & TM) { @@ -208,13 +209,138 @@ IGL_INLINE int igl::copyleft::tetgen::tetrahedralize( for (int i = 0; i < out.numberofpoints; ++i) { TM[i] = out.pointmarkerlist[i]; } - //boundary_facets(TT,TF); + boundary_facets(TT,TF); return 0; } +IGL_INLINE int igl::copyleft::tetgen::tetrahedralize( + const std::vector > & V, + const std::vector > & F, + const std::vector > & H, + const std::vector > & R, + const std::string switches, + std::vector > & TV, + std::vector > & TT, + std::vector > & TF, + std::vector > &TR, + std::vector > & TN, + std::vector > & PT, + std::vector > & FT, + size_t & numRegions) +{ + using namespace std; + tetgenio in,out; + bool success; + success = mesh_to_tetgenio(V, F, H, R, in); + if(!success) + { + return -1; + } + try + { + char * cswitches = new char[switches.size() + 1]; + strcpy(cswitches, switches.c_str()); + + ::tetrahedralize(cswitches, &in, &out); + delete[] cswitches; +}catch(int e) + { + cerr <<"^"<<__FUNCTION__<<": TETGEN CRASHED...KABOOM!!"< +IGL_INLINE int igl::copyleft::tetgen::tetrahedralize( + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, + const Eigen::MatrixBase& H, + const Eigen::MatrixBase& R, + const std::string switches, + Eigen::PlainObjectBase& TV, + Eigen::PlainObjectBase& TT, + Eigen::PlainObjectBase& TF, + Eigen::PlainObjectBase& TR, + Eigen::PlainObjectBase& TN, + Eigen::PlainObjectBase& PT, + Eigen::PlainObjectBase& FT, + size_t & numRegions) +{ + using namespace std; + vector > vV, vH, vR, vTV, vTR; + vector > vF,vTT,vTF, vTN, vPT, vFT; + matrix_to_list(V,vV); + matrix_to_list(F,vF); + matrix_to_list(H, vH); + matrix_to_list(R, vR); + + int e = tetrahedralize(vV,vF,vH,vR,switches,vTV,vTT,vTF,vTR,vTN,vPT,vFT, numRegions); + + if(e == 0) + { + bool TV_rect = list_to_matrix(vTV,TV); + if(!TV_rect) + { + return 3; + } + bool TT_rect = list_to_matrix(vTT,TT); + if(!TT_rect) + { + return 3; + } + bool TF_rect = list_to_matrix(vTF,TF); + if(!TF_rect) + { + return 3; + } + bool TR_rect = list_to_matrix(vTR, TR); + if(!TR_rect) + { + return 3; + } + bool TN_rect = list_to_matrix(vTN, TN); + if(!TN_rect) + { + return 3; + } + bool PT_rect = list_to_matrix(vPT, PT); + if(!PT_rect) + { + return 3; + } + bool FT_rect = list_to_matrix(vFT, FT); + if(!FT_rect) + { + return 3; + } + } + return e; +} + #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template int igl::copyleft::tetgen::tetrahedralize, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, std::basic_string, std::allocator >, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template int igl::copyleft::tetgen::tetrahedralize,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix >(const Eigen::PlainObjectBase > &,const Eigen::PlainObjectBase > &,const Eigen::PlainObjectBase > &,const Eigen::PlainObjectBase > &,const std::basic_string, std::allocator >,Eigen::PlainObjectBase > &,Eigen::PlainObjectBase > &,Eigen::PlainObjectBase > &, Eigen::PlainObjectBase > &); -template int igl::copyleft::tetgen::tetrahedralize, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, std::basic_string, std::allocator >, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template int igl::copyleft::tetgen::tetrahedralize, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, std::basic_string, std::allocator >, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template int igl::copyleft::tetgen::tetrahedralize,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix >(const Eigen::MatrixBase > &,const Eigen::MatrixBase > &,const Eigen::MatrixBase > &,const Eigen::MatrixBase > &,const std::basic_string, std::allocator >,Eigen::PlainObjectBase > &,Eigen::PlainObjectBase > &,Eigen::PlainObjectBase > &, Eigen::PlainObjectBase > &); +template int igl::copyleft::tetgen::tetrahedralize, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, std::basic_string, std::allocator >, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template int igl::copyleft::tetgen::tetrahedralize, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, std::basic_string, std::allocator >, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, unsigned long&); #endif diff --git a/src/libigl/igl/copyleft/tetgen/tetrahedralize.h b/src/libigl/igl/copyleft/tetgen/tetrahedralize.h index 170a3f9852..0dc0efbc08 100644 --- a/src/libigl/igl/copyleft/tetgen/tetrahedralize.h +++ b/src/libigl/igl/copyleft/tetgen/tetrahedralize.h @@ -15,7 +15,7 @@ #ifndef TETLIBRARY #define TETLIBRARY #endif -#include "tetgen.h" // Defined REAL +#include // Defined REAL namespace igl { @@ -61,19 +61,19 @@ namespace igl typename DerivedTT, typename DerivedTF> IGL_INLINE int tetrahedralize( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, const std::string switches, Eigen::PlainObjectBase& TV, Eigen::PlainObjectBase& TT, Eigen::PlainObjectBase& TF); - // Mesh the interior of a surface mesh (V,F) using tetgen + // Mesh the interior of a surface mesh (V,F) using tetgen // // Inputs: // V #V by 3 vertex position list // F #F list of polygon face indices into V (0-indexed) - // M #V list of markers for vertices + // M #V list of markers for vertices // switches string of tetgen options (See tetgen documentation) e.g. // "pq1.414a0.01" tries to mesh the interior of a given surface with // quality and area constraints @@ -82,7 +82,7 @@ namespace igl // TV #V by 3 vertex position list // TT #T by 4 list of tet face indices // TF #F by 3 list of triangle face indices - // TM #V list of markers for vertices + // TM #V list of markers for vertices // Returns status: // 0 success // 1 tetgen threw exception @@ -92,14 +92,13 @@ namespace igl IGL_INLINE int tetrahedralize( const std::vector > & V, const std::vector > & F, - const std::vector & VM, - const std::vector & FM, + const std::vector & VM, + const std::vector & FM, const std::string switches, std::vector > & TV, std::vector > & TT, std::vector > & TF, - std::vector & TM); - + std::vector & TM); // Wrapper with Eigen types // Templates: // DerivedV real-value: i.e. from MatrixXd @@ -107,23 +106,90 @@ namespace igl template < typename DerivedV, typename DerivedF, - typename DerivedVM, - typename DerivedFM, + typename DerivedVM, + typename DerivedFM, typename DerivedTV, typename DerivedTT, typename DerivedTF, typename DerivedTM> IGL_INLINE int tetrahedralize( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, - const Eigen::PlainObjectBase& VM, - const Eigen::PlainObjectBase& FM, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, + const Eigen::MatrixBase& VM, + const Eigen::MatrixBase& FM, const std::string switches, Eigen::PlainObjectBase& TV, Eigen::PlainObjectBase& TT, Eigen::PlainObjectBase& TF, Eigen::PlainObjectBase& TM); - } + // Mesh the interior of a surface mesh (V,F) using tetgen + // + // Inputs: + // V #V by 3 vertex position list + // F #F list of polygon face indices into V (0-indexed) + // H #H by 3 list of seed points inside holes + // R #R by 5 list of region attributes + // switches string of tetgen options (See tetgen documentation) e.g. + // "pq1.414a0.01" tries to mesh the interior of a given surface with + // quality and area constraints + // "" will mesh the convex hull constrained to pass through V (ignores F) + // Outputs: + // TV #TV by 3 vertex position list + // TT #TT by 4 list of tet face indices + // TF #TF by 3 list of triangle face indices + // TR #TT list of region ID for each tetrahedron + // TN #TT by 4 list of indices neighbors for each tetrahedron + // PT #TV list of incident tetrahedron for a vertex + // FT #TF by 2 list of tetrahedrons sharing a triface + // numRegions Number of regions in output mesh + // Returns status: + // 0 success + // 1 tetgen threw exception + // 2 tetgen did not crash but could not create any tets (probably there are + // holes, duplicate faces etc.) + // -1 other error + IGL_INLINE int tetrahedralize( + const std::vector > &V, + const std::vector > &F, + const std::vector > &H, + const std::vector > &R, + const std::string switches, + std::vector > & TV, + std::vector > & TT, + std::vector > & TF, + std::vector > &TR, + std::vector > &TN, + std::vector > &PT, + std::vector > &FT, + size_t & numRegions); + // Wrapper with Eigen types + // Templates: + // DerivedV real-value: i.e. from MatrixXd + // DerivedF integer-value: i.e. from MatrixXi + template < + typename DerivedV, + typename DerivedF, + typename DerivedH, + typename DerivedR, + typename DerivedTV, + typename DerivedTT, + typename DerivedTF, + typename DerivedTR> + IGL_INLINE int tetrahedralize( + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, + const Eigen::MatrixBase& H, + const Eigen::MatrixBase& R, + const std::string switches, + Eigen::PlainObjectBase& TV, + Eigen::PlainObjectBase& TT, + Eigen::PlainObjectBase& TF, + Eigen::PlainObjectBase& TR, + Eigen::PlainObjectBase& TN, + Eigen::PlainObjectBase& PT, + Eigen::PlainObjectBase& FT, + size_t & numRegions); + } } } diff --git a/src/slic3r/Utils/FixModelByTetrahedrons.cpp b/src/slic3r/Utils/FixModelByTetrahedrons.cpp index 60af26e2ac..bd46de44b4 100644 --- a/src/slic3r/Utils/FixModelByTetrahedrons.cpp +++ b/src/slic3r/Utils/FixModelByTetrahedrons.cpp @@ -6,14 +6,15 @@ #include "libigl/igl/copyleft/marching_cubes.h" #include "libigl/igl/voxel_grid.h" +#include "libigl/igl/for_each.h" #include "libigl/igl/barycenter.h" #include "libigl/igl/remove_unreferenced.h" #include "libigl/igl/copyleft/cgal/remesh_self_intersections.h" #include "libigl/igl/winding_number.h" #include "libigl/igl/boundary_facets.h" #include "libigl/igl/copyleft/cgal/convex_hull.h" +#include "libigl/igl/copyleft/cgal/outer_hull.h" #include "libigl/igl/copyleft/tetgen/tetrahedralize.h" -#include "libigl/igl/copyleft/tetgen/cdt.h" #include #include @@ -37,7 +38,6 @@ #include #include - namespace Slic3r { class RepairCanceledException: public std::exception { @@ -54,14 +54,13 @@ public: } }; - namespace detail { indexed_triangle_set fix_model_volume_mesh(const indexed_triangle_set &mesh) { //first compute convex hull Eigen::MatrixXd vertices; Eigen::MatrixXi faces; - Eigen::MatrixXi hull_faces; +// Eigen::MatrixXi hull_faces; { Eigen::MatrixXf orig_v(mesh.vertices.size(), 3); Eigen::MatrixXi orig_f(mesh.indices.size(), 3); @@ -77,37 +76,50 @@ indexed_triangle_set fix_model_volume_mesh(const indexed_triangle_set &mesh) { std::cout << "orig vertices: " << orig_v.rows() << std::endl; std::cout << "orig faces: " << orig_f.rows() << std::endl; - Eigen::VectorXi I; Eigen::MatrixXi IF; Eigen::VectorXi J; + Eigen::VectorXi IM; //resolve self intersections - igl::copyleft::cgal::remesh_self_intersections(orig_v, orig_f, { }, vertices, faces, IF, J, I); + igl::copyleft::cgal::remesh_self_intersections(orig_v, orig_f, { }, vertices, faces, IF, J, IM); std::cout << "remeshed vertices: " << vertices.rows() << std::endl; std::cout << "remeshed faces: " << faces.rows() << std::endl; - // compute hull - igl::copyleft::cgal::convex_hull(vertices, hull_faces); + // _apply_ duplicate vertex mapping IM to FF + for (int i = 0; i < faces.size(); ++i) { + faces.data()[i] = IM(faces.data()[i]); + } - std::cout << " hull faces: " << hull_faces.rows() << std::endl; + Eigen::MatrixXd tmpV; + Eigen::MatrixXi tmpF; + // remove any vertices now unreferenced after duplicate mapping. + igl::remove_unreferenced(vertices, faces, tmpV, tmpF, IM); + // Now (SV,SF) is ready to extract outer hull + Eigen::VectorXi flip; + igl::copyleft::cgal::outer_hull(tmpV, tmpF, vertices, faces, J, flip); + +// // compute hull +// igl::copyleft::cgal::convex_hull(vertices, hull_faces); + +// std::cout << " hull faces: " << hull_faces.rows() << std::endl; } std::cout << "tetrahedronize convex hull " << std::endl; Eigen::MatrixXd tets_v; Eigen::MatrixXi tets_t; Eigen::MatrixXi tets_f; - int result = igl::copyleft::tetgen::tetrahedralize(vertices, hull_faces, "pq1.414NEF", tets_v, tets_t, tets_f); + int result = igl::copyleft::tetgen::tetrahedralize(vertices, faces, "cY", tets_v, tets_t, tets_f); if (result != 0) { - std::cout << "Tetrahedronization failed " << std::endl; + std::cout << "Tetrahedronization failed " << result << std::endl; indexed_triangle_set fixed_mesh; fixed_mesh.vertices.resize(vertices.rows()); - fixed_mesh.indices.resize(hull_faces.rows()); + fixed_mesh.indices.resize(faces.rows()); for (int v = 0; v < vertices.rows(); ++v) { fixed_mesh.vertices[v] = vertices.row(v).cast(); } - for (int f = 0; f < hull_faces.rows(); ++f) { - fixed_mesh.indices[f] = hull_faces.row(f); + for (int f = 0; f < faces.rows(); ++f) { + fixed_mesh.indices[f] = faces.row(f); } return fixed_mesh; } @@ -121,7 +133,6 @@ indexed_triangle_set fix_model_volume_mesh(const indexed_triangle_set &mesh) { std::cout << "barycenters count: " << barycenters.rows() << std::endl; - // Compute generalized winding number at all barycenters from remeshed input std::cout << "Computing winding number over all " << tets_t.rows() << " tets..." << std::endl; Eigen::VectorXd W; @@ -129,8 +140,6 @@ indexed_triangle_set fix_model_volume_mesh(const indexed_triangle_set &mesh) { std::cout << "winding numbers count: " << W.rows() << std::endl; - - std::cout << "Extracting internal tetrahedra " << std::endl; Eigen::MatrixXi CT((W.array() > 0.5).count(), 4); { @@ -145,7 +154,7 @@ indexed_triangle_set fix_model_volume_mesh(const indexed_triangle_set &mesh) { std::cout << "Extracting boundary faces from " << CT.rows() << " internal tetrahedra" << std::endl; Eigen::MatrixXi new_faces; - igl::boundary_facets(tets_t, new_faces); + igl::boundary_facets(CT, new_faces); // boundary_facets seems to be reversed... new_faces = new_faces.rowwise().reverse().eval(); @@ -170,8 +179,6 @@ indexed_triangle_set fix_model_volume_mesh(const indexed_triangle_set &mesh) { } - - bool fix_model_by_tetrahedrons(ModelObject &model_object, int volume_idx, wxProgressDialog &progress_dlg, const wxString &msg_header, std::string &fix_result) { std::mutex mtx;