From 5d9d1957715c95d64a9dbcecd411f40618100e94 Mon Sep 17 00:00:00 2001 From: LarsBrubaker Date: Thu, 25 Apr 2019 19:53:02 -0700 Subject: [PATCH] Make sure we have a copy of the libigl main we are using to build boolean operations --- main.cpp | 310 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 310 insertions(+) create mode 100644 main.cpp diff --git a/main.cpp b/main.cpp new file mode 100644 index 000000000..222b21cbb --- /dev/null +++ b/main.cpp @@ -0,0 +1,310 @@ +#include +#include +#include +//#undef IGL_STATIC_LIBRARY +#include +#include + +#include +#include + +#include "tutorial_shared_path.h" + + + +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include + + + + + +#include + +#define DBOUT( s ) \ +{ \ + std::ostringstream os_; \ + os_ << s; \ + OutputDebugString( os_.str().c_str() ); \ +} + +Eigen::MatrixXd VA, VB, VC; +Eigen::MatrixXd NA, NB, NC; +Eigen::VectorXi J, I; +Eigen::MatrixXi FA, FB, FC; +igl::MeshBooleanType boolean_type( + igl::MESH_BOOLEAN_TYPE_UNION); + +void update(igl::opengl::glfw::Viewer &viewer) +{ + Eigen::MatrixXd C(FC.rows(), 3); + for (size_t f = 0; f < C.rows(); f++) + { + if (J(f) < FA.rows()) + { + C.row(f) = Eigen::RowVector3d(1, 0, 0); + } + else + { + C.row(f) = Eigen::RowVector3d(0, 1, 0); + } + } + viewer.data().clear(); + viewer.data().set_mesh(VC, FC); + viewer.data().set_colors(C); +} + +extern "C" +{ + __declspec(dllexport) void DoBooleanOperation(double* pVA, int sizeVA, int* pFA, int sizeFA, + double* pVB, int sizeVB, int* pFB, int sizeFB, + int opperation, + double** ppVC, int* pSizeVC, int** ppFC, int* pSizeFC) + { + using namespace Eigen; + + igl::MeshBooleanType booleanType(igl::MESH_BOOLEAN_TYPE_UNION); + if (opperation == 1) + { + booleanType = igl::MESH_BOOLEAN_TYPE_MINUS; + } + else if (opperation == 2) + { + booleanType = igl::MESH_BOOLEAN_TYPE_INTERSECT; + } + + // make local data to hold our arrays + Eigen::MatrixXd VA, VB, VC; + Eigen::MatrixXi FA, FB, FC; + VA = Map >(pVA, sizeVA / 3, 3); + FA = Map >(pFA, sizeFA / 3, 3); + VB = Map >(pVB, sizeVB / 3, 3); + FB = Map >(pFB, sizeFB / 3, 3); + + //DBOUT("The value of x is " << VA); + + igl::copyleft::cgal::mesh_boolean(VA, FA, VB, FB, booleanType, VC, FC, J); + + //igl::writeSTL("c:\\Temp\\test.stl", VC, FC, true); + + int count = VC.rows() * VC.cols(); + *pSizeVC = count; + *ppVC = new double[count]; + int VCcols = VC.cols(); + for (int row = 0; row < VC.rows(); row++) + { + for (int col = 0; col < VCcols; col++) + { + ppVC[0][row*VCcols + col] = VC(row, col); + } + } + + count = FC.rows() * FC.cols(); + *pSizeFC = count; + *ppFC = new int[count]; + int FCcols = FC.cols(); + for (int row = 0; row < FC.rows(); row++) + { + for (int col = 0; col < FCcols; col++) + { + ppFC[0][row*FCcols + col] = FC(row, col); + } + } + } + + __declspec(dllexport) void DeleteDouble(double** data) + { + delete(*data); + } + + __declspec(dllexport) void DeleteInt(int** data) + { + delete(*data); + } + + __declspec(dllexport) int add(int a, int b) + { + return a + b; + } + __declspec(dllexport) int subtract(int a, int b) + { + return a - b; + } +} + +//bool clean( +// const Eigen::MatrixXd & V, +// const Eigen::MatrixXi & F, +// Eigen::MatrixXd & CV, +// Eigen::MatrixXi & CF, +// Eigen::VectorXi & IM) +//{ +// using namespace igl; +// using namespace igl::copyleft::tetgen; +// using namespace igl::copyleft::cgal; +// using namespace Eigen; +// using namespace std; +// //writeOBJ("VF.obj",V,F); +// const auto & validate_IM = []( +// const Eigen::MatrixXd & V, +// const Eigen::MatrixXd & CV, +// const Eigen::VectorXi & IM) +// { +// assert(IM.size() >= CV.rows()); +// for (int i = 0; i < CV.rows(); i++) +// { +// if (IM(i) < V.rows() && IM(i) >= 0) +// { +// double diff = (V.row(IM(i)) - CV.row(i)).norm(); +// if (diff > 1e-6) +// { +// cout << i << ": " << IM(i) << " " << diff << endl; +// } +// } +// } +// }; +// { +// MatrixXi _1; +// VectorXi _2; +// cout << "clean: remesh_self_intersections" << endl; +// remesh_self_intersections(V, F, { false,false,false }, CV, CF, _1, _2, IM); +// for_each(CF.data(), CF.data() + CF.size(), [&IM](int & a) {a = IM(a); }); +// //validate_IM(V,CV,IM); +// cout << "clean: remove_unreferenced" << endl; +// { +// MatrixXi oldCF = CF; +// unique_simplices(oldCF, CF); +// } +// MatrixXd oldCV = CV; +// MatrixXi oldCF = CF; +// VectorXi nIM; +// remove_unreferenced(oldCV, oldCF, CV, CF, nIM); +// // reindex nIM through IM +// for_each(IM.data(), IM.data() + IM.size(), [&nIM](int & a) {a = a >= 0 ? nIM(a) : a; }); +// //validate_IM(V,CV,IM); +// } +// MatrixXd TV; +// MatrixXi TT; +// { +// MatrixXi _1; +// // c convex hull +// // Y no boundary steiners +// // p polygon input +// // T1e-16 sometimes helps tetgen +// cout << "clean: tetrahedralize" << endl; +// writeOBJ("CVCF.obj", CV, CF); +// CDTParam params; +// params.flags = "CYT1e-16"; +// params.use_bounding_box = true; +// if (cdt(CV, CF, params, TV, TT, _1) != 0) +// { +// cout << REDRUM("CDT failed.") << endl; +// return false; +// } +// //writeMESH("TVTT.mesh",TV,TT,MatrixXi()); +// } +// { +// MatrixXd BC; +// barycenter(TV, TT, BC); +// VectorXd W; +// cout << "clean: winding_number" << endl; +// winding_number(V, F, BC, W); +// W = W.array().abs(); +// const double thresh = 0.5; +// const int count = (W.array() > thresh).cast().sum(); +// MatrixXi CT(count, TT.cols()); +// int c = 0; +// for (int t = 0; t < TT.rows(); t++) +// { +// if (W(t) > thresh) +// { +// CT.row(c++) = TT.row(t); +// } +// } +// assert(c == count); +// boundary_facets(CT, CF); +// //writeMESH("CVCTCF.mesh",TV,CT,CF); +// cout << "clean: remove_unreferenced" << endl; +// // Force all original vertices to be referenced +// MatrixXi FF = F; +// for_each(FF.data(), FF.data() + FF.size(), [&IM](int & a) {a = IM(a); }); +// int ncf = CF.rows(); +// MatrixXi ref(ncf + FF.rows(), 3); +// ref << CF, FF; +// VectorXi nIM; +// remove_unreferenced(TV, ref, CV, CF, nIM); +// // Only keep boundary faces +// CF.conservativeResize(ncf, 3); +// cout << "clean: IM.minCoeff(): " << IM.minCoeff() << endl; +// // reindex nIM through IM +// for_each(IM.data(), IM.data() + IM.size(), [&nIM](int & a) {a = a >= 0 ? nIM(a) : a; }); +// cout << "clean: IM.minCoeff(): " << IM.minCoeff() << endl; +// //validate_IM(V,CV,IM); +// } +// return true; +//} + +int main(int argc, char *argv[]) +{ + using namespace Eigen; + using namespace std; + + double t1[] = { 90, 115, 10, 90, 135, 10, 90, 115, 0, 90, 115, 0, 90, 135, 10, 90, 135, 0, 90, 115, 10, 110, 115, 10, 110, 135, 10, 90, 135, 10, 90, 115, 10, 110, 135, 10, 90, 115, 0, 110, 115, 0, 110, 115, 10, 90, 115, 10, 90, 115, 0, 110, 115, 10, 90, 135, 0, 110, 135, 0, 90, 115, 0, 90, 115, 0, 110, 135, 0, 110, 115, 0, 90, 135, 10, 110, 135, 10, 90, 135, 0, 90, 135, 0, 110, 135, 10, 110, 135, 0, 110, 115, 0, 110, 135, 0, 110, 135, 10, 110, 115, 10, 110, 115, 0, 110, 135, 10 }; + int t2[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 }; + double t3[] = { 100, 102, 10, 100, 122, 10, 100, 102, 0, 100, 102, 0, 100, 122, 10, 100, 122, 0, 100, 102, 10, 120, 102, 10, 120, 122, 10, 100, 122, 10, 100, 102, 10, 120, 122, 10, 100, 102, 0, 120, 102, 0, 120, 102, 10, 100, 102, 10, 100, 102, 0, 120, 102, 10, 100, 122, 0, 120, 122, 0, 100, 102, 0, 100, 102, 0, 120, 122, 0, 120, 102, 0, 100, 122, 10, 120, 122, 10, 100, 122, 0, 100, 122, 0, 120, 122, 10, 120, 122, 0, 120, 102, 0, 120, 122, 0, 120, 122, 10, 120, 102, 10, 120, 102, 0, 120, 122, 10 }; + int t4[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 }; + + double* pVC = 0; + int vc = 0; + int* pFC = 0; + int fc = 0; + DoBooleanOperation(t1, 108, t2, 36, t3, 108, t4, 36, 1, &pVC, &vc, &pFC, &fc); + + if (argc != 5) + { + cout << + "In STL A" << endl << + "In STL B" << endl << + "Out STL" << endl << + "Operation [+,-,&] (union, subtract, intersect)" << endl; + + return -1; + } + + igl::readSTL(argv[1], VA, FA, NA); + igl::readSTL(argv[2], VB, FB, NB); + + igl::MeshBooleanType booleanType(igl::MESH_BOOLEAN_TYPE_UNION); + if (strcmp(argv[4], "-") == 0) + { + booleanType = igl::MESH_BOOLEAN_TYPE_MINUS; + } + else if (strcmp(argv[4], "&") == 0) + { + booleanType = igl::MESH_BOOLEAN_TYPE_INTERSECT; + } + + igl::copyleft::cgal::mesh_boolean(VA, FA, VB, FB, booleanType, VC, FC, J); + + igl::writeSTL(argv[3], VC, FC, true); + + if(false) + { + // Plot the mesh with pseudocolors + igl::opengl::glfw::Viewer viewer; + + // Initialize + update(viewer); + + viewer.data().show_lines = true; + viewer.core.camera_dnear = 3.9; + viewer.launch(); + } +} \ No newline at end of file