18#include <unordered_map>
19#include <unordered_set>
21#include <lagrange/common.h>
22#include <lagrange/utils/assert.h>
23#include <lagrange/utils/safe_cast.h>
27template <
typename Index>
35 EdgeType(Index v1, Index v2)
39 EdgeType(
const EdgeType<Index>& obj)
43 EdgeType(EdgeType<Index>&& obj) noexcept
53 EdgeType(
const std::array<Index, 2>& arr)
58 inline Index v1()
const {
return m_v1; }
59 inline Index v2()
const {
return m_v2; }
62 EdgeType<Index>& operator=(
const EdgeType<Index>& other)
64 this->m_v1 = other.m_v1;
65 this->m_v2 = other.m_v2;
68 EdgeType<Index>& operator=(EdgeType<Index>&& other)
noexcept
70 this->m_v1 = other.m_v1;
71 this->m_v2 = other.m_v2;
75 ~EdgeType()
noexcept =
default;
77 bool operator==(
const EdgeType<Index>& rhs)
const
79 return (m_v1 == rhs.m_v1 && m_v2 == rhs.m_v2) || (m_v1 == rhs.m_v2 && m_v2 == rhs.m_v1);
81 bool operator!=(
const EdgeType<Index>& rhs)
const {
return !(*
this == rhs); }
83 Index operator[](
const Index i)
const
85 if (i == 0)
return m_v1;
86 if (i == 1)
return m_v2;
102 using iterator_category = std::input_iterator_tag;
103 using value_type = EdgeType<Index>;
104 using difference_type = std::ptrdiff_t;
105 using pointer = EdgeType<Index>*;
106 using reference = EdgeType<Index>&;
110 const EdgeType<Index>& m_edge;
113 iterator(
const EdgeType<Index>& edge,
int i)
117 bool operator!=(
const iterator& rhs)
const
119 return m_edge != rhs.m_edge || m_i != rhs.m_i;
121 iterator& operator++()
126 Index operator*()
const {
return m_edge[m_i]; }
129 iterator end()
const {
return iterator(*
this, 2); }
132 bool has_shared_vertex(
const EdgeType<Index>& other)
const
134 return m_v1 == other.m_v1 || m_v1 == other.m_v2 || m_v2 == other.m_v1 || m_v2 == other.m_v2;
136 Index get_shared_vertex(
const EdgeType<Index>& other)
const
138 la_runtime_assert(*
this != other,
"get_shared_vertex() failed due to identical edges");
139 if (m_v1 == other.m_v1)
return m_v1;
140 if (m_v1 == other.m_v2)
return m_v1;
141 if (m_v2 == other.m_v1)
return m_v2;
142 if (m_v2 == other.m_v2)
return m_v2;
145 Index get_other_vertex(Index v)
const
148 if (m_v1 == v)
return m_v2;
153template <
typename Index,
typename T>
154using EdgeMap = std::unordered_map<EdgeType<Index>, T>;
156template <
typename Index>
157using EdgeSet = std::unordered_set<EdgeType<Index>>;
159template <
typename MeshType>
161 std::unordered_map<EdgeType<typename MeshType::Index>, std::vector<typename MeshType::Index>>;
165template <
typename MeshType>
166EdgeFacetMap<MeshType> compute_edge_facet_map_in_active_facets(
167 const MeshType& mesh,
168 const std::unordered_set<typename MeshType::Index>& active_facets)
170 using Index =
typename MeshType::Index;
171 std::unordered_map<EdgeType<Index>, std::vector<Index>> edge_facet_map;
174 const typename MeshType::FacetArray& facets = mesh.get_facets();
175 edge_facet_map.reserve(active_facets.size() * vertex_per_facet);
176 for (Index i = 0; i < num_facets; ++i) {
177 if (active_facets.find(i) == active_facets.end())
continue;
178 for (Index j = 0; j < vertex_per_facet; ++j) {
179 const Index v1 = facets(i, j);
180 const Index v2 = facets(i, (j + 1) % vertex_per_facet);
182 auto it = edge_facet_map.find(edge);
183 if (it == edge_facet_map.end()) {
184 edge_facet_map[edge] = {i};
186 it->second.push_back(i);
190 return edge_facet_map;
195template <
typename MeshType>
196EdgeFacetMap<MeshType> compute_edge_facet_map_in_active_vertices(
197 const MeshType& mesh,
198 const std::unordered_set<typename MeshType::Index>& active_vertices)
200 using Index =
typename MeshType::Index;
202 std::unordered_set<Index> active_facets;
204 if (mesh.is_connectivity_initialized()) {
206 for (Index v : active_vertices) {
207 for (Index f : mesh.get_facets_adjacent_to_vertex(v)) {
208 active_facets.insert(f);
214 const typename MeshType::FacetArray& facets = mesh.get_facets();
215 for (Index i = 0; i < num_facets; ++i) {
216 if (active_facets.find(i) != active_facets.end())
continue;
217 for (Index j = 0; j < vertex_per_facet; ++j) {
218 if (active_vertices.find(facets(i, j)) != active_vertices.end()) {
219 active_facets.insert(i);
225 return compute_edge_facet_map_in_active_facets(mesh, active_facets);
230template <
typename Index>
Index get_num_facets() const
Retrieves the number of facets.
Definition SurfaceMesh.h:678
Index get_vertex_per_facet() const
Retrieves the number of vertex per facet in a regular mesh.
Definition SurfaceMesh.cpp:2130
#define la_runtime_assert(...)
Runtime assertion check.
Definition assert.h:174
constexpr T invalid()
You can use invalid<T>() to get a value that can represent "invalid" values, such as invalid indices ...
Definition invalid.h:40
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:50
Main namespace for Lagrange.