diff --git a/include/igl/ismember.cpp b/include/igl/ismember.cpp new file mode 100644 index 000000000..3a3f927eb --- /dev/null +++ b/include/igl/ismember.cpp @@ -0,0 +1,96 @@ +// This file is part of libigl, a simple c++ geometry processing library. +// +// Copyright (C) 2016 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 "ismember.h" +#include "colon.h" +#include "list_to_matrix.h" +#include "sort.h" +#include "unique.h" + +template < + typename DerivedA, + typename DerivedB, + typename DerivedIA, + typename DerivedLOCB> +IGL_INLINE void igl::ismember( + const Eigen::PlainObjectBase & A, + const Eigen::PlainObjectBase & B, + Eigen::PlainObjectBase & IA, + Eigen::PlainObjectBase & LOCB) +{ + using namespace Eigen; + using namespace std; + IA.resize(A.rows(),A.cols()); + IA.setConstant(false); + LOCB.resize(A.rows(),A.cols()); + LOCB.setConstant(-1); + // boring base cases + if(A.size() == 0) + { + return; + } + if(B.size() == 0) + { + return; + } + + // Get rid of any duplicates + typedef Matrix VectorA; + typedef Matrix VectorB; + const VectorA vA(Eigen::Map(A.data(), A.cols()*A.rows(),1)); + const VectorB vB(Eigen::Map(B.data(), B.cols()*B.rows(),1)); + VectorA uA; + VectorB uB; + Eigen::Matrix uIA,uIuA,uIB,uIuB; + unique(vA,uA,uIA,uIuA); + unique(vB,uB,uIB,uIuB); + // Sort both + VectorA sA; + VectorB sB; + Eigen::Matrix sIA,sIB; + sort(uA,1,true,sA,sIA); + sort(uB,1,true,sB,sIB); + + Eigen::Matrix uF = + Eigen::Matrix::Zero(sA.size(),1); + Eigen::Matrix uLOCB = + Eigen::Matrix:: + Constant(sA.size(),1,-1); + { + int bi = 0; + // loop over sA + bool past = false; + for(int a = 0;asB(bi)) + { + bi++; + past = bi>=sB.size(); + } + if(!past && sA(a)==sB(bi)) + { + uF(sIA(a)) = true; + uLOCB(sIA(a)) = uIB(sIB(bi)); + } + } + } + + Map< Matrix > + vIA(IA.data(),IA.cols()*IA.rows(),1); + Map< Matrix > + vLOCB(LOCB.data(),LOCB.cols()*LOCB.rows(),1); + for(int a = 0;a, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +#endif diff --git a/include/igl/ismember.h b/include/igl/ismember.h new file mode 100644 index 000000000..7c1889dae --- /dev/null +++ b/include/igl/ismember.h @@ -0,0 +1,41 @@ +// This file is part of libigl, a simple c++ geometry processing library. +// +// Copyright (C) 2016 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/. +#ifndef IGL_ISMEMBER_H +#define IGL_ISMEMBER_H +#include "igl_inline.h" +#include +namespace igl +{ + // Determine if elements of A exist in elements of B + // + // Inputs: + // A ma by na matrix + // B mb by nb matrix + // Outputs: + // IA ma by na matrix of flags whether corresponding element of A exists in + // B + // LOCB ma by na matrix of indices in B locating matching element (-1 if + // not found), indices assume column major ordering + // + template < + typename DerivedA, + typename DerivedB, + typename DerivedIA, + typename DerivedLOCB> + IGL_INLINE void ismember( + const Eigen::PlainObjectBase & A, + const Eigen::PlainObjectBase & B, + Eigen::PlainObjectBase & IA, + Eigen::PlainObjectBase & LOCB); +} + +#ifndef IGL_STATIC_LIBRARY +# include "ismember.cpp" +#endif +#endif + diff --git a/matlab-to-eigen.html b/matlab-to-eigen.html index c8b83f3cb..54e135b1b 100644 --- a/matlab-to-eigen.html +++ b/matlab-to-eigen.html @@ -272,6 +272,12 @@ bool a = A.array().any(); + +
[IA,LOCB] = ismember(A,B)
+
igl::ismember(A,B,IA,LOCB)
+ + +