// 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 "unique.h" #include "sort.h" #include "IndexComparison.h" #include "SortableRow.h" #include "sortrows.h" #include "list_to_matrix.h" #include "matrix_to_list.h" #include #include #include template IGL_INLINE void igl::unique( const std::vector & A, std::vector & C, std::vector & IA, std::vector & IC) { using namespace std; std::vector IM; std::vector sortA; igl::sort(A,true,sortA,IM); // Original unsorted index map IA.resize(sortA.size()); for(int i=0;i<(int)sortA.size();i++) { IA[i] = i; } IA.erase( std::unique( IA.begin(), IA.end(), igl::IndexEquals& >(sortA)),IA.end()); IC.resize(A.size()); { int j = 0; for(int i = 0;i<(int)sortA.size();i++) { if(sortA[IA[j]] != sortA[i]) { j++; } IC[IM[i]] = j; } } C.resize(IA.size()); // Reindex IA according to IM for(int i = 0;i<(int)IA.size();i++) { IA[i] = IM[IA[i]]; C[i] = A[IA[i]]; } } template IGL_INLINE void igl::unique( const std::vector & A, std::vector & C) { std::vector IA,IC; return igl::unique(A,C,IA,IC); } template < typename DerivedA, typename DerivedC, typename DerivedIA, typename DerivedIC> IGL_INLINE void igl::unique( const Eigen::DenseBase & A, Eigen::PlainObjectBase & C, Eigen::PlainObjectBase & IA, Eigen::PlainObjectBase & IC) { using namespace std; using namespace Eigen; vector vA; vector vC; vector vIA,vIC; matrix_to_list(A,vA); unique(vA,vC,vIA,vIC); list_to_matrix(vC,C); list_to_matrix(vIA,IA); list_to_matrix(vIC,IC); } template < typename DerivedA, typename DerivedC > IGL_INLINE void igl::unique( const Eigen::DenseBase & A, Eigen::PlainObjectBase & C) { using namespace std; using namespace Eigen; vector vA; vector vC; vector vIA,vIC; matrix_to_list(A,vA); unique(vA,vC,vIA,vIC); list_to_matrix(vC,C); } // Obsolete slow version converting to vectors // template // IGL_INLINE void igl::unique_rows( // const Eigen::PlainObjectBase& A, // Eigen::PlainObjectBase& C, // Eigen::PlainObjectBase& IA, // Eigen::PlainObjectBase& IC) // { // using namespace std; // // typedef Eigen::Matrix RowVector; // vector > rows; // rows.resize(A.rows()); // // Loop over rows // for(int i = 0;i(ri); // } // vector > vC; // // // unique on rows // vector vIA; // vector vIC; // unique(rows,vC,vIA,vIC); // // // Convert to eigen // C.resize(vC.size(),A.cols()); // IA.resize(vIA.size(),1); // IC.resize(vIC.size(),1); // for(int i = 0;i // IGL_INLINE void igl::unique_rows_many( // const Eigen::PlainObjectBase& A, // Eigen::PlainObjectBase& C, // Eigen::PlainObjectBase& IA, // Eigen::PlainObjectBase& IC) // { // using namespace std; // // frequency map // typedef Eigen::Matrix RowVector; // IC.resize(A.rows(),1); // map, int> fm; // const int m = A.rows(); // for(int i = 0;i(ri)) == 0) // { // fm[SortableRow(ri)] = i; // } // IC(i) = fm[SortableRow(ri)]; // } // IA.resize(fm.size(),1); // Eigen::VectorXi RIA(m); // C.resize(fm.size(),A.cols()); // { // int i = 0; // for(typename map , int >::const_iterator fit = fm.begin(); // fit != fm.end(); // fit++) // { // IA(i) = fit->second; // RIA(fit->second) = i; // C.row(i) = fit->first.data; // i++; // } // } // // IC should index C // for(int i = 0;i, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::PlainObjectBase >&); template void igl::unique, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::unique, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::PlainObjectBase >&); template void igl::unique, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::unique, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::PlainObjectBase >&); template void igl::unique, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::unique, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::unique, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::PlainObjectBase >&); template void igl::unique, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::unique, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::unique, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::unique(std::vector > const&, std::vector >&); template void igl::unique(std::vector > const&, std::vector >&); template void igl::unique(std::vector > const&, std::vector >&, std::vector >&, std::vector >&); template void igl::unique(std::vector > const&, std::vector >&, std::vector >&, std::vector >&); #ifdef WIN32 template void igl::unique,class Eigen::Matrix,class Eigen::Matrix<__int64,-1,1,0,-1,1>,class Eigen::Matrix<__int64,-1,1,0,-1,1> >(class Eigen::DenseBase > const &,class Eigen::PlainObjectBase > &,class Eigen::PlainObjectBase > &,class Eigen::PlainObjectBase > &); template void igl::unique<__int64>(class std::vector<__int64,class std::allocator<__int64> > const &,class std::vector<__int64,class std::allocator<__int64> > &,class std::vector > &,class std::vector > &); #endif #endif