Lagrange
remove_duplicate_facets.h
1/*
2 * Copyright 2018 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 <lagrange/MeshTrait.h>
15#include <lagrange/attributes/map_attributes.h>
16#include <lagrange/common.h>
17#include <lagrange/create_mesh.h>
18#include <lagrange/legacy/inline.h>
19
20#include <array>
21#include <cassert>
22#include <list>
23#include <unordered_map>
24
25namespace lagrange {
26LAGRANGE_LEGACY_INLINE
27namespace legacy {
28
43template <typename MeshType>
44std::unique_ptr<MeshType> remove_duplicate_facets(const MeshType& mesh)
45{
46 static_assert(MeshTrait<MeshType>::is_mesh(), "Input type is not Mesh");
47 using Index = typename MeshType::FacetArray::Scalar;
48 using Facet = std::array<Index, 3>;
49
50 const Index num_facets = mesh.get_num_facets();
51 const auto& facets = mesh.get_facets();
52
53 auto facet_hash = [](const Facet& f) { return f[0] + f[1] + f[2]; };
54 auto facet_eq = [](const Facet& f1, const Facet& f2) {
55 return f1[0] == f2[0] && f1[1] == f2[1] && f1[2] == f2[2];
56 };
57
58 std::unordered_map<Facet, std::list<Index>, decltype(facet_hash), decltype(facet_eq)> facet_map(
59 num_facets,
60 facet_hash,
61 facet_eq);
62 for (Index i = 0; i < num_facets; i++) {
63 Facet f{facets(i, 0), facets(i, 1), facets(i, 2)};
64 std::sort(f.begin(), f.end());
65 auto itr = facet_map.find(f);
66 if (itr == facet_map.end()) {
67 facet_map.insert({f, {i}});
68 } else {
69 itr->second.push_back(i);
70 }
71 }
72
73 const auto num_unique_facets = facet_map.size();
74 typename MeshType::FacetArray unique_facets(num_unique_facets, 3);
75 std::vector<Index> ori_facet_indices(num_unique_facets);
76 Index count = 0;
77 for (const auto& entry : facet_map) {
78 const auto& fs = entry.second;
79 assert(fs.size() > 0);
80 auto fid = fs.front();
81 if (fs.size() > 1) {
82 // Orientation votes. Use the orientation with most votes.
83 int orientation = 0;
84 Index inverted_fid = fid;
85 for (const auto fj : fs) {
86 if ((facets(fj, 0) == facets(fid, 0) && facets(fj, 1) == facets(fid, 1) &&
87 facets(fj, 2) == facets(fid, 2)) ||
88 (facets(fj, 0) == facets(fid, 1) && facets(fj, 1) == facets(fid, 2) &&
89 facets(fj, 2) == facets(fid, 0)) ||
90 (facets(fj, 0) == facets(fid, 2) && facets(fj, 1) == facets(fid, 0) &&
91 facets(fj, 2) == facets(fid, 1))) {
92 orientation += 1;
93 } else {
94 orientation -= 1;
95 inverted_fid = fid;
96 }
97 }
98 if (orientation < 0) {
99 fid = inverted_fid;
100 }
101 }
102 unique_facets.row(count) = facets.row(fid);
103 ori_facet_indices[count] = fid;
104 count++;
105 }
106
107 const auto vertices = mesh.get_vertices();
108 auto out_mesh = create_mesh(std::move(vertices), std::move(unique_facets));
109
110 map_attributes(mesh, *out_mesh, {}, ori_facet_indices);
111
112 return out_mesh;
113}
114} // namespace legacy
115} // namespace lagrange
Definition: Mesh.h:48
@ Facet
Per-facet mesh attributes.
Definition: AttributeFwd.h:31
void map_attributes(const SurfaceMesh< Scalar, Index > &source_mesh, SurfaceMesh< Scalar, Index > &target_mesh, span< const Index > mapping_data, span< const Index > mapping_offsets={}, const MapAttributesOptions &options={})
Map attributes from the source mesh to the target mesh.
Definition: map_attributes.cpp:26
Main namespace for Lagrange.
Definition: AABBIGL.h:30
auto create_mesh(const Eigen::MatrixBase< DerivedV > &vertices, const Eigen::MatrixBase< DerivedF > &facets)
This function create a new mesh given the vertex and facet arrays by copying data into the Mesh objec...
Definition: create_mesh.h:39
void remove_duplicate_facets(SurfaceMesh< Scalar, Index > &mesh, const RemoveDuplicateFacetOptions &opts={})
Remove duplicate facets in the mesh.
Definition: remove_duplicate_facets.cpp:235