You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
88 lines
2.7 KiB
88 lines
2.7 KiB
// This file is part of libigl, a simple c++ geometry processing library.
|
|
//
|
|
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
|
//
|
|
// 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 "slice_sorted.h"
|
|
|
|
#include <vector>
|
|
|
|
// TODO: Write a version that works for row-major sparse matrices as well.
|
|
template <typename TX, typename TY, typename DerivedR, typename DerivedC>
|
|
IGL_INLINE void igl::slice_sorted(const Eigen::SparseMatrix<TX> &X,
|
|
const Eigen::DenseBase<DerivedR> &R,
|
|
const Eigen::DenseBase<DerivedC> &C,
|
|
Eigen::SparseMatrix<TY> &Y)
|
|
{
|
|
int xm = X.rows();
|
|
int xn = X.cols();
|
|
int ym = R.size();
|
|
int yn = C.size();
|
|
|
|
// Special case when R or C is empty
|
|
if (ym == 0 || yn == 0)
|
|
{
|
|
Y.resize(ym, yn);
|
|
return;
|
|
}
|
|
|
|
assert(R.minCoeff() >= 0);
|
|
assert(R.maxCoeff() < xm);
|
|
assert(C.minCoeff() >= 0);
|
|
assert(C.maxCoeff() < xn);
|
|
|
|
// Multiplicity count for each row/col
|
|
using RowIndexType = typename DerivedR::Scalar;
|
|
using ColIndexType = typename DerivedC::Scalar;
|
|
std::vector<RowIndexType> slicedRowStart(xm);
|
|
std::vector<RowIndexType> rowRepeat(xm, 0);
|
|
for (int i = 0; i < ym; ++i)
|
|
{
|
|
if (rowRepeat[R(i)] == 0)
|
|
{
|
|
slicedRowStart[R(i)] = i;
|
|
}
|
|
rowRepeat[R(i)]++;
|
|
}
|
|
std::vector<ColIndexType> columnRepeat(xn, 0);
|
|
for (int i = 0; i < yn; i++)
|
|
{
|
|
columnRepeat[C(i)]++;
|
|
}
|
|
// Count number of nnz per outer row/col
|
|
Eigen::VectorXi nnz(yn);
|
|
for (int k = 0, c = 0; k < X.outerSize(); ++k)
|
|
{
|
|
int cnt = 0;
|
|
for (typename Eigen::SparseMatrix<TX>::InnerIterator it(X, k); it; ++it)
|
|
{
|
|
cnt += rowRepeat[it.row()];
|
|
}
|
|
for (int i = 0; i < columnRepeat[k]; ++i, ++c)
|
|
{
|
|
nnz(c) = cnt;
|
|
}
|
|
}
|
|
Y.resize(ym, yn);
|
|
Y.reserve(nnz);
|
|
// Insert values
|
|
for (int k = 0, c = 0; k < X.outerSize(); ++k)
|
|
{
|
|
for (int i = 0; i < columnRepeat[k]; ++i, ++c)
|
|
{
|
|
for (typename Eigen::SparseMatrix<TX>::InnerIterator it(X, k); it; ++it)
|
|
{
|
|
for (int j = 0, r = slicedRowStart[it.row()]; j < rowRepeat[it.row()]; ++j, ++r)
|
|
{
|
|
Y.insert(r, c) = it.value();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef IGL_STATIC_LIBRARY
|
|
template void igl::slice_sorted<double, double, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::SparseMatrix<double, 0, int> const&, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::SparseMatrix<double, 0, int>&);
|
|
#endif
|
|
|