97 lines
3.0 KiB
C++
97 lines
3.0 KiB
C++
|
// This file is part of libigl, a simple c++ geometry processing library.
|
||
|
//
|
||
|
// Copyright (C) 2018 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 "edge_exists_near.h"
|
||
|
|
||
|
template <
|
||
|
typename DeriveduE,
|
||
|
typename DerivedEMAP,
|
||
|
typename uE2EType,
|
||
|
typename Index>
|
||
|
IGL_INLINE bool igl::edge_exists_near(
|
||
|
const Eigen::MatrixBase<DeriveduE> & uE,
|
||
|
const Eigen::MatrixBase<DerivedEMAP> & EMAP,
|
||
|
const std::vector<std::vector< uE2EType> > & uE2E,
|
||
|
const Index & a,
|
||
|
const Index & b,
|
||
|
const Index & uei)
|
||
|
{
|
||
|
std::vector<Index> face_queue;
|
||
|
face_queue.reserve(32);
|
||
|
std::vector<Index> pushed;
|
||
|
// 32 is faster than 8
|
||
|
pushed.reserve(32);
|
||
|
assert(a!=b);
|
||
|
// starting with the (2) faces incident on e, consider all faces
|
||
|
// incident on edges containing either a or b.
|
||
|
//
|
||
|
// face_queue Queue containing faces incident on exactly one of a/b
|
||
|
// Using a vector seems mildly faster
|
||
|
assert(EMAP.size()%3 == 0);
|
||
|
const Index num_faces = EMAP.size()/3;
|
||
|
const Index f1 = uE2E[uei][0]%num_faces;
|
||
|
const Index f2 = uE2E[uei][1]%num_faces;
|
||
|
// map is faster than unordered_map here, and vector + brute force
|
||
|
// is_member check is even faster
|
||
|
face_queue.push_back(f1);
|
||
|
pushed.push_back(f1);
|
||
|
face_queue.push_back(f2);
|
||
|
pushed.push_back(f2);
|
||
|
while(!face_queue.empty())
|
||
|
{
|
||
|
const Index f = face_queue.back();
|
||
|
face_queue.pop_back();
|
||
|
// consider each edge of this face
|
||
|
for(int c = 0;c<3;c++)
|
||
|
{
|
||
|
// Unique edge id
|
||
|
const Index uec = EMAP(c*num_faces+f);
|
||
|
const Index s = uE(uec,0);
|
||
|
const Index d = uE(uec,1);
|
||
|
const bool ona = s == a || d == a;
|
||
|
const bool onb = s == b || d == b;
|
||
|
// Is this the edge we're looking for?
|
||
|
if(ona && onb)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
// not incident on either?
|
||
|
if(!ona && !onb)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
// loop over all incident half-edges
|
||
|
for(const auto & he : uE2E[uec])
|
||
|
{
|
||
|
// face of this he
|
||
|
const Index fhe = he%num_faces;
|
||
|
bool already_pushed = false;
|
||
|
for(const auto & fp : pushed)
|
||
|
{
|
||
|
if(fp == fhe)
|
||
|
{
|
||
|
already_pushed = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if(!already_pushed)
|
||
|
{
|
||
|
pushed.push_back(fhe);
|
||
|
face_queue.push_back(fhe);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
#ifdef IGL_STATIC_LIBRARY
|
||
|
// Explicit template instantiation
|
||
|
// generated by autoexplicit.sh
|
||
|
template bool igl::edge_exists_near<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, int, int>(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, 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> > > > const&, int const&, int const&, int const&);
|
||
|
#endif
|