Lagrange
bfs_orient.h
1// Source: https://github.com/libigl/libigl/blob/main/include/igl/bfs_orient.cpp
2// SPDX-License-Identifier: MPL-2.0
3//
4// This file is part of libigl, a simple c++ geometry processing library.
5//
6// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
7//
8// This Source Code Form is subject to the terms of the Mozilla Public License
9// v. 2.0. If a copy of the MPL was not distributed with this file, You can
10// obtain one at http://mozilla.org/MPL/2.0/.
11//
12// This file has been modified by Adobe.
13//
14// All modifications are Copyright 2022 Adobe.
15#pragma once
16
17#include <lagrange/internal/orientable_patches.h>
18
19namespace lagrange::internal {
20
21template <typename DerivedF, typename DerivedFF, typename DerivedC>
22void bfs_orient(
23 const Eigen::MatrixBase<DerivedF>& F,
24 Eigen::PlainObjectBase<DerivedFF>& FF,
25 Eigen::PlainObjectBase<DerivedC>& C)
26{
27 Eigen::SparseMatrix<typename DerivedF::Scalar> A;
28 lagrange::internal::orientable_patches(F, C, A);
29
30 // number of faces
31 const int m = static_cast<int>(F.rows());
32 // number of patches
33 const int num_cc = C.maxCoeff() + 1;
34 Eigen::VectorXi seen = Eigen::VectorXi::Zero(m);
35
36 // Edge sets
37 const int ES[3][2] = {{1, 2}, {2, 0}, {0, 1}};
38
39 if (((void*)&FF) != ((void*)&F)) {
40 FF = F;
41 }
42 // loop over patches
43 tbb::parallel_for(0, num_cc, [&](int c) {
44 std::queue<typename DerivedF::Scalar> Q;
45 // find first member of patch c
46 for (int f = 0; f < FF.rows(); f++) {
47 if (C(f) == c) {
48 Q.push(f);
49 break;
50 }
51 }
52 assert(!Q.empty());
53 while (!Q.empty()) {
54 const typename DerivedF::Scalar f = Q.front();
55 Q.pop();
56 if (seen(f) > 0) {
57 continue;
58 }
59 seen(f)++;
60 // loop over neighbors of f
61 for (typename Eigen::SparseMatrix<typename DerivedF::Scalar>::InnerIterator it(A, f);
62 it;
63 ++it) {
64 // might be some lingering zeros, and skip self-adjacency
65 if (it.value() != 0 && it.row() != f) {
66 const int n = static_cast<int>(it.row());
67 assert(n != f);
68 // loop over edges of f
69 for (int efi = 0; efi < 3; efi++) {
70 // efi'th edge of face f
71 Eigen::Vector2i ef(FF(f, ES[efi][0]), FF(f, ES[efi][1]));
72 // loop over edges of n
73 for (int eni = 0; eni < 3; eni++) {
74 // eni'th edge of face n
75 Eigen::Vector2i en(FF(n, ES[eni][0]), FF(n, ES[eni][1]));
76 // Match (half-edges go same direction)
77 if (ef(0) == en(0) && ef(1) == en(1)) {
78 // flip face n
79 FF.row(n) = FF.row(n).reverse().eval();
80 }
81 }
82 }
83 // add neighbor to queue
84 Q.push(n);
85 }
86 }
87 }
88 });
89
90 // make sure flip is OK if &FF = &F
91}
92
93} // namespace lagrange::internal
nullptr_t, size_t, ptrdiff_t basic_ostream bad_weak_ptr extent, remove_extent, is_array,...
Definition: attribute_string_utils.h:21