// 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 // obtain one at http://mozilla.org/MPL/2.0/. #include "adjacency_list.h" #include "verbose.h" #include template IGL_INLINE void igl::adjacency_list( const Eigen::MatrixBase & F, std::vector >& A, bool sorted) { A.clear(); A.resize(F.maxCoeff()+1); // Loop over faces for(int i = 0;i d int s = F(i,j); int d = F(i,(j+1)%F.cols()); A.at(s).push_back(d); A.at(d).push_back(s); } } // Remove duplicates for(int i=0; i<(int)A.size();++i) { std::sort(A[i].begin(), A[i].end()); A[i].erase(std::unique(A[i].begin(), A[i].end()), A[i].end()); } // If needed, sort every VV if (sorted) { // Loop over faces // for every vertex v store a set of ordered edges not incident to v that belongs to triangle incident on v. std::vector > > SR; SR.resize(A.size()); for(int i = 0;i d int s = F(i,j); int d = F(i,(j+1)%F.cols()); // Get index of opposing vertex v int v = F(i,(j+2)%F.cols()); std::vector e(2); e[0] = d; e[1] = v; SR[s].push_back(e); } } for(int v=0; v<(int)SR.size();++v) { std::vector& vv = A.at(v); std::vector >& sr = SR[v]; std::vector > pn = sr; // Compute previous/next for every element in sr for(int i=0;i<(int)sr.size();++i) { int a = sr[i][0]; int b = sr[i][1]; // search for previous int p = -1; for(int j=0;j<(int)sr.size();++j) if(sr[j][1] == a) p = j; pn[i][0] = p; // search for next int n = -1; for(int j=0;j<(int)sr.size();++j) if(sr[j][0] == b) n = j; pn[i][1] = n; } // assume manifoldness (look for beginning of a single chain) int c = 0; for(int j=0; j<=(int)sr.size();++j) if (pn[c][0] != -1) c = pn[c][0]; if (pn[c][0] == -1) // border case { // finally produce the new vv relation for(int j=0; j<(int)sr.size();++j) { vv[j] = sr[c][0]; if (pn[c][1] != -1) c = pn[c][1]; } vv.back() = sr[c][1]; } else { // finally produce the new vv relation for(int j=0; j<(int)sr.size();++j) { vv[j] = sr[c][0]; c = pn[c][1]; } } } } } template IGL_INLINE void igl::adjacency_list( const std::vector > & F, std::vector >& A) { A.clear(); // Find maxCoeff Index maxCoeff = 0; for(const auto &vec : F) { for(int coeff : vec) { maxCoeff = std::max(coeff, maxCoeff); } } A.resize(maxCoeff + 1); // Loop over faces for(int i = 0;i d int s = F[i][j]; int d = F[i][(j+1)%F[i].size()]; A.at(s).push_back(d); A.at(d).push_back(s); } } // Remove duplicates for(int i=0; i<(int)A.size();++i) { std::sort(A[i].begin(), A[i].end()); A[i].erase(std::unique(A[i].begin(), A[i].end()), A[i].end()); } } #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh template void igl::adjacency_list, int>(Eigen::MatrixBase > const&, std::vector >, std::allocator > > >&, bool); // generated by autoexplicit.sh template void igl::adjacency_list, int>(Eigen::MatrixBase > const&, std::vector >, std::allocator > > >&, bool); template void igl::adjacency_list, int>(Eigen::MatrixBase > const&, std::vector >, std::allocator > > >&, bool); template void igl::adjacency_list, unsigned int>(class Eigen::MatrixBase > const &, class std::vector >, class std::allocator > > > &, bool); template void igl::adjacency_list(std::vector >, std::allocator > > > const&, std::vector >, std::allocator > > >&); #endif