Lagrange
corner_to_edge_mapping.impl.h
1/*
2 * Copyright 2020 Adobe. All rights reserved.
3 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License. You may obtain a copy
5 * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 *
7 * Unless required by applicable law or agreed to in writing, software distributed under
8 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 * OF ANY KIND, either express or implied. See the License for the specific language
10 * governing permissions and limitations under the License.
11 */
13#pragma once
14#include <lagrange/corner_to_edge_mapping.h>
15
16#include <lagrange/Logger.h>
17#include <lagrange/utils/assert.h>
18#include <lagrange/utils/safe_cast.h>
19
20// clang-format off
21#include <lagrange/utils/warnoff.h>
22#include <tbb/parallel_sort.h>
23#include <lagrange/utils/warnon.h>
24// clang-format on
25
26#include <Eigen/Dense>
27
28#include <algorithm>
29#include <utility>
30#include <vector>
32
33namespace lagrange {
34
35template <typename DerivedF, typename DerivedC>
37 const Eigen::MatrixBase<DerivedF>& F,
38 Eigen::PlainObjectBase<DerivedC>& C2E)
39{
40 using Index = typename DerivedF::Scalar;
41
42 struct UnorientedEdge
43 {
44 Index v1;
45 Index v2;
46 Index corner;
47
48 UnorientedEdge(Index x, Index y, Index c)
49 : v1(std::min(x, y))
50 , v2(std::max(x, y))
51 , corner(c)
52 {}
53
54 auto key() const { return std::make_pair(v1, v2); }
55
56 bool operator<(const UnorientedEdge& e) const { return key() < e.key(); }
57
58 bool operator!=(const UnorientedEdge& e) const { return key() != e.key(); }
59 };
60
61 Index vert_per_facet = safe_cast<Index>(F.cols());
62
63 // Sort unoriented edges
64 std::vector<UnorientedEdge> edges;
65 edges.reserve(F.rows() * F.cols());
66 for (Index f = 0; f < (Index) F.rows(); ++f) {
67 for (Index lv = 0; lv < (Index) F.cols(); ++lv) {
68 auto v1 = F(f, lv);
69 auto v2 = F(f, (lv + 1) % vert_per_facet);
70 edges.emplace_back(v1, v2, f * vert_per_facet + lv);
71 }
72 }
73 tbb::parallel_sort(edges.begin(), edges.end());
74
75 // Assign unique edge ids
76 C2E.resize(F.rows() * F.cols());
77 Index num_edges = 0;
78 for (auto it_begin = edges.begin(); it_begin != edges.end();) {
79 // First the first edge after it_begin that has a different key
80 auto it_end = std::find_if(it_begin, edges.end(), [&](auto e) { return (e != *it_begin); });
81 for (auto it = it_begin; it != it_end; ++it) {
82 C2E(it->corner) = num_edges;
83 }
84 ++num_edges;
85 it_begin = it_end;
86 }
87
88 return num_edges;
89}
90
91} // namespace lagrange
Main namespace for Lagrange.
Definition: AABBIGL.h:30
Eigen::Index corner_to_edge_mapping(const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedC > &C2E)
Computes a mapping from mesh corners (k*f+i) to unique edge ids.
Definition: corner_to_edge_mapping.impl.h:36