| 76 | } |
| 77 | |
| 78 | size_t DegeneratedTriangleRemoval::remove_line_faces() { |
| 79 | init_edge_map(); |
| 80 | // loop through faces, check if a face is a colinear. |
| 81 | // If so, flip the longest edge. |
| 82 | |
| 83 | auto comp = [&](const Duplet& e1, const Duplet& e2) -> bool{ |
| 84 | // Return true if e1 is longer than e2. |
| 85 | auto v1 = m_vertices.row(e1.get_ori_data()[0]); |
| 86 | auto v2 = m_vertices.row(e1.get_ori_data()[1]); |
| 87 | auto v3 = m_vertices.row(e2.get_ori_data()[0]); |
| 88 | auto v4 = m_vertices.row(e2.get_ori_data()[1]); |
| 89 | return (v1-v2).squaredNorm() > (v3-v4).squaredNorm(); |
| 90 | }; |
| 91 | |
| 92 | const size_t num_faces = m_faces.rows(); |
| 93 | std::set<Duplet, decltype(comp)> edges_to_remove(comp); |
| 94 | std::vector<size_t> longest_edges(num_faces, INVALID); |
| 95 | for (size_t fi=0; fi<num_faces; fi++) { |
| 96 | if (!is_degenerated(fi)) continue; |
| 97 | const auto& face = m_faces.row(fi); |
| 98 | const auto fi_opp_v = find_longest_edge(fi); |
| 99 | const auto vi_0 = face[(fi_opp_v+1)%3]; |
| 100 | const auto vi_1 = face[(fi_opp_v+2)%3]; |
| 101 | edges_to_remove.insert(Duplet{vi_0, vi_1}); |
| 102 | longest_edges[fi] = fi_opp_v; |
| 103 | } |
| 104 | |
| 105 | std::vector<VectorI> new_faces; |
| 106 | std::vector<VectorI::Scalar> new_ori_face_indices; |
| 107 | std::vector<bool> is_valid(num_faces, true); |
| 108 | size_t count = 0; |
| 109 | |
| 110 | for (auto& edge : edges_to_remove) { |
| 111 | auto& neighboring_faces = m_edge_map[edge]; |
| 112 | bool all_valid = true; |
| 113 | for (auto fj : neighboring_faces) { all_valid &= is_valid[fj]; } |
| 114 | if (!all_valid) continue; |
| 115 | |
| 116 | const size_t vi_0 = edge.get_ori_data()[0]; |
| 117 | const size_t vi_1 = edge.get_ori_data()[1]; |
| 118 | size_t vi_opp = INVALID; |
| 119 | size_t fi = INVALID; |
| 120 | for (auto fj : neighboring_faces) { |
| 121 | if (longest_edges[fj] == INVALID) continue; |
| 122 | const auto neighbor_face = m_faces.row(fj); |
| 123 | const size_t vj_opp = neighbor_face[longest_edges[fj]]; |
| 124 | if (vj_opp != vi_0 && vj_opp != vi_1) { |
| 125 | fi = fj; |
| 126 | vi_opp = vj_opp; |
| 127 | break; |
| 128 | } |
| 129 | } |
| 130 | assert(vi_opp != INVALID); |
| 131 | assert(fi != INVALID); |
| 132 | |
| 133 | for (auto fj : neighboring_faces) { |
| 134 | is_valid[fj] = false; |
| 135 | if (fj == fi) continue; |