dust3d/third_party/libigl/include/igl/adjacency_list.cpp

181 lines
5.5 KiB
C++
Raw Normal View History

// 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 "adjacency_list.h"
#include "verbose.h"
#include <algorithm>
template <typename Index, typename IndexVector>
IGL_INLINE void igl::adjacency_list(
const Eigen::MatrixBase<Index> & F,
std::vector<std::vector<IndexVector> >& A,
bool sorted)
{
A.clear();
A.resize(F.maxCoeff()+1);
// Loop over faces
for(int i = 0;i<F.rows();i++)
{
// Loop over this face
for(int j = 0;j<F.cols();j++)
{
// Get indices of edge: s --> 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<std::vector<std::vector<int> > > SR;
SR.resize(A.size());
for(int i = 0;i<F.rows();i++)
{
// Loop over this face
for(int j = 0;j<F.cols();j++)
{
// Get indices of edge: s --> 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<int> e(2);
e[0] = d;
e[1] = v;
SR[s].push_back(e);
}
}
for(int v=0; v<(int)SR.size();++v)
{
std::vector<IndexVector>& vv = A.at(v);
std::vector<std::vector<int> >& sr = SR[v];
std::vector<std::vector<int> > 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 <typename Index>
IGL_INLINE void igl::adjacency_list(
const std::vector<std::vector<Index> > & F,
std::vector<std::vector<Index> >& 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<F.size();i++)
{
// Loop over this face
for(int j = 0;j<F[i].size();j++)
{
// Get indices of edge: s --> 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<Eigen::Matrix<int, -1, 2, 0, -1, 2>, int>(Eigen::MatrixBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, bool);
// generated by autoexplicit.sh
template void igl::adjacency_list<Eigen::Matrix<int, -1, -1, 0, -1, -1>, int>(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, bool);
template void igl::adjacency_list<Eigen::Matrix<int, -1, 3, 0, -1, 3>, int>(Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, bool);
template void igl::adjacency_list<class Eigen::Matrix<int, -1, -1, 0, -1, -1>, unsigned int>(class Eigen::MatrixBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1> > const &, class std::vector<class std::vector<unsigned int, class std::allocator<unsigned int> >, class std::allocator<class std::vector<unsigned int, class std::allocator<unsigned int> > > > &, bool);
template void igl::adjacency_list<int>(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&);
#endif