// This file is part of libigl, a simple c++ geometry processing library. // // Copyright (C) 2015 Qingnan Zhou // // 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 "propagate_winding_numbers.h" #include "../../extract_manifold_patches.h" #include "../../extract_non_manifold_edge_curves.h" #include "../../facet_components.h" #include "../../unique_edge_map.h" #include "../../writeOBJ.h" #include "../../writePLY.h" #include "order_facets_around_edge.h" #include "outer_facet.h" #include "closest_facet.h" #include "assign_scalar.h" #include "extract_cells.h" #include #include #include #include #include namespace propagate_winding_numbers_helper { template< typename DerivedF, typename DeriveduE, typename uE2EType > bool is_orientable( const Eigen::PlainObjectBase& F, const Eigen::PlainObjectBase& uE, const std::vector >& uE2E) { const size_t num_faces = F.rows(); const size_t num_edges = uE.rows(); auto edge_index_to_face_index = [&](size_t ei) { return ei % num_faces; }; auto is_consistent = [&](size_t fid, size_t s, size_t d) { if ((size_t)F(fid, 0) == s && (size_t)F(fid, 1) == d) return true; if ((size_t)F(fid, 1) == s && (size_t)F(fid, 2) == d) return true; if ((size_t)F(fid, 2) == s && (size_t)F(fid, 0) == d) return true; if ((size_t)F(fid, 0) == d && (size_t)F(fid, 1) == s) return false; if ((size_t)F(fid, 1) == d && (size_t)F(fid, 2) == s) return false; if ((size_t)F(fid, 2) == d && (size_t)F(fid, 0) == s) return false; throw "Invalid face!!"; }; for (size_t i=0; i IGL_INLINE void igl::copyleft::cgal::propagate_winding_numbers( const Eigen::PlainObjectBase& V, const Eigen::PlainObjectBase& F, const Eigen::PlainObjectBase& labels, Eigen::PlainObjectBase& W) { const size_t num_faces = F.rows(); //typedef typename DerivedF::Scalar Index; Eigen::MatrixXi E, uE; Eigen::VectorXi EMAP; std::vector > uE2E; igl::unique_edge_map(F, E, uE, EMAP, uE2E); if (!propagate_winding_numbers_helper::is_orientable(F, uE, uE2E)) { std::cerr << "Input mesh is not orientable!" << std::endl; } Eigen::VectorXi P; const size_t num_patches = igl::extract_manifold_patches(F, EMAP, uE2E, P); DerivedW per_patch_cells; const size_t num_cells = igl::copyleft::cgal::extract_cells( V, F, P, E, uE, uE2E, EMAP, per_patch_cells); typedef std::tuple CellConnection; std::vector > cell_adjacency(num_cells); for (size_t i=0; i faces; for (size_t i=0; i path; path.push_back(idx); while ((size_t)parents[path.back()] != path.back()) { path.push_back(parents[path.back()]); } return path; }; for (size_t i=0; i Q; Q.push(i); parents[i] = i; while (!Q.empty()) { size_t curr_idx = Q.front(); Q.pop(); int curr_label = cell_labels[curr_idx]; for (const auto& neighbor : cell_adjacency[curr_idx]) { if (cell_labels[std::get<0>(neighbor)] == 0) { cell_labels[std::get<0>(neighbor)] = curr_label * -1; Q.push(std::get<0>(neighbor)); parents[std::get<0>(neighbor)] = curr_idx; } else { if (cell_labels[std::get<0>(neighbor)] != curr_label * -1) { std::cerr << "Odd cell cycle detected!" << std::endl; auto path = trace_parents(curr_idx); path.reverse(); auto path2 = trace_parents(std::get<0>(neighbor)); path.insert(path.end(), path2.begin(), path2.end()); for (auto cell_id : path) { std::cout << cell_id << " "; std::stringstream filename; filename << "cell_" << cell_id << ".ply"; save_cell(filename.str(), cell_id); } std::cout << std::endl; } assert(cell_labels[std::get<0>(neighbor)] == curr_label * -1); } } } } } } #endif size_t outer_facet; bool flipped; Eigen::VectorXi I; I.setLinSpaced(num_faces, 0, num_faces-1); igl::copyleft::cgal::outer_facet(V, F, I, outer_facet, flipped); const size_t outer_patch = P[outer_facet]; const size_t infinity_cell = per_patch_cells(outer_patch, flipped?1:0); Eigen::VectorXi patch_labels(num_patches); const int INVALID = std::numeric_limits::max(); patch_labels.setConstant(INVALID); for (size_t i=0; i Q; Q.push(infinity_cell); while (!Q.empty()) { size_t curr_cell = Q.front(); Q.pop(); for (const auto& neighbor : cell_adjacency[curr_cell]) { size_t neighbor_cell, patch_idx; bool direction; std::tie(neighbor_cell, direction, patch_idx) = neighbor; if ((per_cell_W.row(neighbor_cell).array() == INVALID).any()) { per_cell_W.row(neighbor_cell) = per_cell_W.row(curr_cell); for (size_t i=0; i, -1, -1, 0, -1, -1>, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); #endif