Lagrange
unify_corner_indices.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 */
12#pragma once
13
14#include <algorithm>
15
16#include <tbb/parallel_for.h>
17#include <tbb/parallel_sort.h>
18
19#include <lagrange/Logger.h>
20#include <lagrange/Mesh.h>
21#include <lagrange/common.h>
22#include <lagrange/create_mesh.h>
23#include <lagrange/legacy/inline.h>
24
25namespace lagrange {
26LAGRANGE_LEGACY_INLINE
27namespace legacy {
28
33template <typename MeshType>
34auto unify_corner_indices(
35 MeshType& mesh,
36 const std::vector<std::string>& indexed_attribute_names,
37 std::vector<typename MeshType::Index>& corner_to_unified_index) -> typename MeshType::Index
38{
39 using AttributeArray = typename MeshType::AttributeArray;
40 using Index = typename MeshType::Index;
41 using IndexArray = typename MeshType::IndexArray;
42
43 const Index num_attrs = safe_cast<Index>(indexed_attribute_names.size());
44 std::vector<std::tuple<const AttributeArray&, const IndexArray&>> attrs;
45 attrs.reserve(num_attrs);
46 for (const auto& attr_name : indexed_attribute_names) {
47 attrs.emplace_back(mesh.get_indexed_attribute(attr_name));
48 }
49
50 const Index num_vertices = mesh.get_num_vertices();
51 const Index num_facets = mesh.get_num_facets();
52 const Index vertex_per_facet = mesh.get_vertex_per_facet();
53 const auto& facets = mesh.get_facets();
54 const Index num_corners = num_facets * vertex_per_facet;
55 std::vector<Index> corner_indices(num_corners);
56 std::iota(corner_indices.begin(), corner_indices.end(), 0);
57
58 // Lexicographical comparison of corner indices.
59 auto corner_index_comp = [&](Index i, Index j) -> bool {
60 const Index fi = i / vertex_per_facet;
61 const Index ci = i % vertex_per_facet;
62 const Index fj = j / vertex_per_facet;
63 const Index cj = j % vertex_per_facet;
64
65 if (facets(fi, ci) == facets(fj, cj)) {
66 for (auto k : range(num_attrs)) {
67 const auto& indices = std::get<1>(attrs[k]);
68 if (indices(fi, ci) != indices(fj, cj)) {
69 return indices(fi, ci) < indices(fj, cj);
70 }
71 }
72 } else {
73 return facets(fi, ci) < facets(fj, cj);
74 }
75 return false;
76 };
77
78 auto corner_index_eq = [&](Index i, Index j) -> bool {
79 const Index fi = i / vertex_per_facet;
80 const Index ci = i % vertex_per_facet;
81 const Index fj = j / vertex_per_facet;
82 const Index cj = j % vertex_per_facet;
83
84 if (facets(fi, ci) == facets(fj, cj)) {
85 for (auto k : range(num_attrs)) {
86 const auto& indices = std::get<1>(attrs[k]);
87 if (indices(fi, ci) != indices(fj, cj)) {
88 return false;
89 }
90 }
91 } else {
92 return false;
93 }
94 return true;
95 };
96
97 tbb::parallel_sort(corner_indices.begin(), corner_indices.end(), corner_index_comp);
98
99 std::vector<bool> visited(num_vertices, false);
100 Index num_unified_vertices = num_vertices;
101 corner_to_unified_index.resize(num_corners);
102
103 for (Index i = 0; i < num_corners;) {
104 const Index fi = corner_indices[i] / vertex_per_facet;
105 const Index ci = corner_indices[i] % vertex_per_facet;
106
107 Index vi = facets(fi, ci);
108 if (!visited[vi]) {
109 visited[vi] = true;
110 } else {
111 vi = num_unified_vertices++;
112 }
113
114 Index j = i;
115 while (j < num_corners && corner_index_eq(corner_indices[i], corner_indices[j])) {
116 corner_to_unified_index[corner_indices[j]] = vi;
117 ++j;
118 }
119 i = j;
120 }
121
122 return num_unified_vertices;
123}
124
125} // namespace legacy
126} // namespace lagrange
Definition: Mesh.h:48
internal::Range< Index > range(Index end)
Returns an iterable object representing the range [0, end).
Definition: range.h:176
Main namespace for Lagrange.
Definition: AABBIGL.h:30