Lagrange
Loading...
Searching...
No Matches
corner_to_edge_mapping.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
15#include <lagrange/legacy/inline.h>
16#include <lagrange/utils/safe_cast.h>
17
18// clang-format off
19#include <lagrange/utils/warnoff.h>
20#include <tbb/parallel_sort.h>
21#include <lagrange/utils/warnon.h>
22// clang-format on
23
24#include <Eigen/Dense>
25
26#include <algorithm>
27#include <utility>
28#include <vector>
30
31namespace lagrange {
32LAGRANGE_LEGACY_INLINE
33namespace legacy {
34
49template <typename DerivedF, typename DerivedC>
50Eigen::Index corner_to_edge_mapping(
51 const Eigen::MatrixBase<DerivedF>& F,
52 Eigen::PlainObjectBase<DerivedC>& C2E)
53{
54 using Index = typename DerivedF::Scalar;
55
56 struct UnorientedEdge
57 {
58 Index v1;
59 Index v2;
60 Index corner;
61
62 UnorientedEdge(Index x, Index y, Index c)
63 : v1(std::min(x, y))
64 , v2(std::max(x, y))
65 , corner(c)
66 {}
67
68 auto key() const { return std::make_pair(v1, v2); }
69
70 bool operator<(const UnorientedEdge& e) const { return key() < e.key(); }
71
72 bool operator!=(const UnorientedEdge& e) const { return key() != e.key(); }
73 };
74
75 Index vert_per_facet = safe_cast<Index>(F.cols());
76
77 // Sort unoriented edges
78 std::vector<UnorientedEdge> edges;
79 edges.reserve(F.rows() * F.cols());
80 for (Index f = 0; f < (Index)F.rows(); ++f) {
81 for (Index lv = 0; lv < (Index)F.cols(); ++lv) {
82 auto v1 = F(f, lv);
83 auto v2 = F(f, (lv + 1) % vert_per_facet);
84 edges.emplace_back(v1, v2, f * vert_per_facet + lv);
85 }
86 }
87 tbb::parallel_sort(edges.begin(), edges.end());
88
89 // Assign unique edge ids
90 C2E.resize(F.rows() * F.cols());
91 Index num_edges = 0;
92 for (auto it_begin = edges.begin(); it_begin != edges.end();) {
93 // First the first edge after it_begin that has a different key
94 auto it_end = std::find_if(it_begin, edges.end(), [&](auto e) { return (e != *it_begin); });
95 for (auto it = it_begin; it != it_end; ++it) {
96 C2E(it->corner) = num_edges;
97 }
98 ++num_edges;
99 it_begin = it_end;
100 }
101
102 return num_edges;
103}
104
105} // namespace legacy
106} // namespace lagrange
constexpr auto safe_cast(SourceType value) -> std::enable_if_t<!std::is_same< SourceType, TargetType >::value, TargetType >
Perform safe cast from SourceType to TargetType, where "safe" means:
Definition safe_cast.h:51
bool operator!=(const shared_ptr< T > &sp1, const shared_ptr< U > &sp2)
Operator != overloading.
Definition shared_ptr.h:364
Main namespace for Lagrange.