Lagrange
detect_degenerate_triangles.h
1/*
2 * Copyright 2016 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 <exception>
15#include <iostream>
16
17#include <lagrange/ExactPredicates.h>
18#include <lagrange/Mesh.h>
19#include <lagrange/MeshTrait.h>
20#include <lagrange/common.h>
21#include <lagrange/legacy/inline.h>
22
23namespace lagrange {
24LAGRANGE_LEGACY_INLINE
25namespace legacy {
26
38template <typename MeshType>
39void detect_degenerate_triangles(MeshType& mesh)
40{
41 static_assert(MeshTrait<MeshType>::is_mesh(), "Input type is not Mesh");
42 using Index = typename MeshType::Index;
43 if (mesh.get_vertex_per_facet() != 3) {
44 throw std::runtime_error("Input mesh is not a triangle mesh.");
45 }
46
47 auto predicates = ExactPredicates::create("shewchuk");
48 auto is_degenerate_2D = [&predicates](double p1[2], double p2[2], double p3[3]) -> bool {
49 return predicates->orient2D(p1, p2, p3) == 0;
50 };
51 auto is_degenerate_3D = [&predicates](double p1[3], double p2[3], double p3[3]) -> bool {
52 double p1xy[] = {p1[0], p1[1]};
53 double p1yz[] = {p1[1], p1[2]};
54 double p1zx[] = {p1[2], p1[0]};
55 double p2xy[] = {p2[0], p2[1]};
56 double p2yz[] = {p2[1], p2[2]};
57 double p2zx[] = {p2[2], p2[0]};
58 double p3xy[] = {p3[0], p3[1]};
59 double p3yz[] = {p3[1], p3[2]};
60 double p3zx[] = {p3[2], p3[0]};
61 return predicates->orient2D(p1xy, p2xy, p3xy) == 0 &&
62 predicates->orient2D(p1yz, p2yz, p3yz) == 0 &&
63 predicates->orient2D(p1zx, p2zx, p3zx) == 0;
64 };
65 const Index dim = mesh.get_dim();
66 const Index num_facets = mesh.get_num_facets();
67 typename MeshType::AttributeArray is_degenerate(num_facets, 1);
68 is_degenerate.setConstant(0.0);
69
70 const auto& vertices = mesh.get_vertices();
71 const auto& facets = mesh.get_facets();
72 if (dim == 3) {
73 for (Index i = 0; i < num_facets; i++) {
74 auto f = facets.row(i).eval();
75 double p1[3]{vertices(f[0], 0), vertices(f[0], 1), vertices(f[0], 2)};
76 double p2[3]{vertices(f[1], 0), vertices(f[1], 1), vertices(f[1], 2)};
77 double p3[3]{vertices(f[2], 0), vertices(f[2], 1), vertices(f[2], 2)};
78 is_degenerate(i, 0) = is_degenerate_3D(p1, p2, p3);
79 }
80 } else if (dim == 2) {
81 for (Index i = 0; i < num_facets; i++) {
82 auto f = facets.row(i).eval();
83 double p1[2]{vertices(f[0], 0), vertices(f[0], 1)};
84 double p2[2]{vertices(f[1], 0), vertices(f[1], 1)};
85 double p3[2]{vertices(f[2], 0), vertices(f[2], 1)};
86 is_degenerate(i, 0) = is_degenerate_2D(p1, p2, p3);
87 }
88 }
89
90 mesh.add_facet_attribute("is_degenerate");
91 mesh.import_facet_attribute("is_degenerate", is_degenerate);
92}
93} // namespace legacy
94} // namespace lagrange
static std::unique_ptr< ExactPredicates > create(const std::string &engine)
Factory method to create an exact predicate engine.
Definition: ExactPredicates.cpp:20
Definition: Mesh.h:48
Main namespace for Lagrange.
Definition: AABBIGL.h:30