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>
24#include <lagrange/utils/warning.h>
28template <
typename Index>
36 EdgeType(Index v1, Index v2)
40 EdgeType(
const EdgeType<Index>& obj)
44 EdgeType(EdgeType<Index>&& obj) noexcept
54 EdgeType(
const std::array<Index, 2>& arr)
59 inline Index v1()
const {
return m_v1; }
60 inline Index v2()
const {
return m_v2; }
63 EdgeType<Index>& operator=(
const EdgeType<Index>& other)
65 this->m_v1 = other.m_v1;
66 this->m_v2 = other.m_v2;
69 EdgeType<Index>& operator=(EdgeType<Index>&& other)
noexcept
71 this->m_v1 = other.m_v1;
72 this->m_v2 = other.m_v2;
76 ~EdgeType()
noexcept =
default;
78 bool operator==(
const EdgeType<Index>& rhs)
const
80 return (m_v1 == rhs.m_v1 && m_v2 == rhs.m_v2) || (m_v1 == rhs.m_v2 && m_v2 == rhs.m_v1);
82 bool operator!=(
const EdgeType<Index>& rhs)
const {
return !(*
this == rhs); }
84 Index operator[](
const Index i)
const
86 if (i == 0)
return m_v1;
87 if (i == 1)
return m_v2;
103 using iterator_category = std::input_iterator_tag;
104 using value_type = EdgeType<Index>;
105 using difference_type = std::ptrdiff_t;
106 using pointer = EdgeType<Index>*;
107 using reference = EdgeType<Index>&;
111 const EdgeType<Index>& m_edge;
114 iterator(
const EdgeType<Index>& edge,
int i)
118 bool operator!=(
const iterator& rhs)
const
120 return m_edge != rhs.m_edge || m_i != rhs.m_i;
122 iterator& operator++()
127 Index operator*()
const {
return m_edge[m_i]; }
130 iterator end()
const {
return iterator(*
this, 2); }
133 bool has_shared_vertex(
const EdgeType<Index>& other)
const
135 return m_v1 == other.m_v1 || m_v1 == other.m_v2 || m_v2 == other.m_v1 || m_v2 == other.m_v2;
137 Index get_shared_vertex(
const EdgeType<Index>& other)
const
139 la_runtime_assert(*
this != other,
"get_shared_vertex() failed due to identical edges");
140 if (m_v1 == other.m_v1)
return m_v1;
141 if (m_v1 == other.m_v2)
return m_v1;
142 if (m_v2 == other.m_v1)
return m_v2;
143 if (m_v2 == other.m_v2)
return m_v2;
146 Index get_other_vertex(Index v)
const
149 if (m_v1 == v)
return m_v2;
154template <
typename Index,
typename T>
155using EdgeMap = std::unordered_map<EdgeType<Index>, T>;
157template <
typename Index>
158using EdgeSet = std::unordered_set<EdgeType<Index>>;
160template <
typename MeshType>
162 std::unordered_map<EdgeType<typename MeshType::Index>, std::vector<typename MeshType::Index>>;
166template <
typename MeshType>
167EdgeFacetMap<MeshType> compute_edge_facet_map_in_active_facets(
168 const MeshType& mesh,
169 const std::unordered_set<typename MeshType::Index>& active_facets)
171 using Index =
typename MeshType::Index;
172 std::unordered_map<EdgeType<Index>, std::vector<Index>> edge_facet_map;
173 const Index num_facets = mesh.get_num_facets();
174 const Index vertex_per_facet = mesh.get_vertex_per_facet();
175 const typename MeshType::FacetArray& facets = mesh.get_facets();
176 edge_facet_map.reserve(active_facets.size() * vertex_per_facet);
177 for (Index i = 0; i < num_facets; ++i) {
178 if (active_facets.find(i) == active_facets.end())
continue;
179 for (Index j = 0; j < vertex_per_facet; ++j) {
180 const Index v1 = facets(i, j);
181 const Index v2 = facets(i, (j + 1) % vertex_per_facet);
183 auto it = edge_facet_map.find(edge);
184 if (it == edge_facet_map.end()) {
188 edge_facet_map[edge] = {i};
189 LA_IGNORE_ARRAY_BOUNDS_END
191 it->second.push_back(i);
195 return edge_facet_map;
200template <
typename MeshType>
201EdgeFacetMap<MeshType> compute_edge_facet_map_in_active_vertices(
202 const MeshType& mesh,
203 const std::unordered_set<typename MeshType::Index>& active_vertices)
205 using Index =
typename MeshType::Index;
207 std::unordered_set<Index> active_facets;
209 if (mesh.is_connectivity_initialized()) {
211 for (Index v : active_vertices) {
212 for (Index f : mesh.get_facets_adjacent_to_vertex(v)) {
213 active_facets.insert(f);
217 const Index num_facets = mesh.get_num_facets();
218 const Index vertex_per_facet = mesh.get_vertex_per_facet();
219 const typename MeshType::FacetArray& facets = mesh.get_facets();
220 for (Index i = 0; i < num_facets; ++i) {
221 if (active_facets.find(i) != active_facets.end())
continue;
222 for (Index j = 0; j < vertex_per_facet; ++j) {
223 if (active_vertices.find(facets(i, j)) != active_vertices.end()) {
224 active_facets.insert(i);
230 return compute_edge_facet_map_in_active_facets(mesh, active_facets);
235template <
typename Index>
#define la_runtime_assert(...)
Runtime assertion check.
Definition assert.h:175
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:51
#define LA_IGNORE_ARRAY_BOUNDS_BEGIN
Ignore warning "out of bounds subscripts or offsets into arrays" This is used to bypass the following...
Definition warning.h:161
Main namespace for Lagrange.