Wildmeshing Toolkit
Loading...
Searching...
No Matches
EdgeMesh.cpp
Go to the documentation of this file.
1#include "EdgeMesh.hpp"
2
3
5#include <numeric>
7namespace wmtk {
8EdgeMesh::~EdgeMesh() = default;
10 : MeshCRTP<EdgeMesh>(1)
11 , m_ve_handle(register_attribute_typed<int64_t>("m_ve", PrimitiveType::Vertex, 1, false, -1))
12 , m_ev_handle(register_attribute_typed<int64_t>("m_ev", PrimitiveType::Edge, 2, false, -1))
13 , m_ee_handle(register_attribute_typed<int64_t>("m_ee", PrimitiveType::Edge, 2, false, -1))
14{}
15
16
17bool EdgeMesh::is_boundary(PrimitiveType pt, const Tuple& tuple) const
18{
19 switch (pt) {
20 case PrimitiveType::Vertex: return is_boundary_vertex(tuple);
24 default: break;
25 }
26 assert(
27 false); // "tried to compute the boundary of an edge mesh for an invalid simplex dimension"
28 return false;
29}
30
31bool EdgeMesh::is_boundary_vertex(const Tuple& tuple) const
32{
33 assert(is_valid(tuple));
34 const attribute::Accessor<int64_t> ee_accessor = create_const_accessor<int64_t>(m_ee_handle);
35 return ee_accessor.const_vector_attribute<2>(tuple)(tuple.local_vid()) < 0;
36}
37
39{
40 assert(is_valid(tuple));
41 bool ccw = is_ccw(tuple);
42
43 switch (type) {
45 return Tuple(
46 1 - tuple.local_vid(),
47 tuple.local_eid(),
48 tuple.local_fid(),
49 tuple.global_cid());
51 const int64_t gvid = id(tuple, PrimitiveType::Vertex);
52
53 const attribute::Accessor<int64_t> ee_accessor =
54 create_const_accessor<int64_t>(m_ee_handle);
55 auto ee = ee_accessor.const_vector_attribute<2>(tuple);
56
57 int64_t gcid_new = ee(tuple.local_vid());
58
59 // This is for special case self-loop, just to make sure the local vid of the returned
60 // tuple is the same as the input. (When doing double-switch this is needed)
61 if (gcid_new == tuple.global_cid()) {
62 return tuple;
63 }
64
65 int64_t lvid_new = -1;
66
67 const attribute::Accessor<int64_t> ev_accessor =
68 create_const_accessor<int64_t>(m_ev_handle);
69 auto ev = ev_accessor.index_access().const_vector_attribute<2>(gcid_new);
70
71 for (int64_t i = 0; i < 2; ++i) {
72 if (ev(i) == gvid) {
73 lvid_new = i;
74 // break;
75 }
76 }
77 assert(lvid_new != -1);
78
79
80 const Tuple res(lvid_new, tuple.local_eid(), tuple.local_fid(), gcid_new);
81 assert(is_valid(res));
82 return res;
83 }
86 default: assert(false); // "Tuple switch: Invalid primitive type"
87 }
88
89 return Tuple();
90}
91
92bool EdgeMesh::is_ccw(const Tuple& tuple) const
93{
94 assert(is_valid(tuple));
95 return tuple.local_vid() == 0;
96}
97
99 Eigen::Ref<const RowVectors2l> EV,
100 Eigen::Ref<const RowVectors2l> EE,
101 Eigen::Ref<const VectorXl> VE)
102{
103 // reserve memory for attributes
104
105 std::vector<int64_t> cap{static_cast<int64_t>(VE.rows()), static_cast<int64_t>(EE.rows())};
106
107 set_capacities(cap);
108
109 // get accessors for topology
110 attribute::Accessor<int64_t> ev_accessor = create_accessor<int64_t>(m_ev_handle);
111 attribute::Accessor<int64_t> ee_accessor = create_accessor<int64_t>(m_ee_handle);
112 attribute::Accessor<int64_t> ve_accessor = create_accessor<int64_t>(m_ve_handle);
113
116
117 // iterate over the matrices and fill attributes
118
119 for (int64_t i = 0; i < capacity(PrimitiveType::Edge); ++i) {
120 ev_accessor.index_access().vector_attribute<2>(i) = EV.row(i).transpose();
121 ee_accessor.index_access().vector_attribute<2>(i) = EE.row(i).transpose();
122
123 e_flag_accessor.index_access().activate(i);
124 }
125 // m_ve
126 for (int64_t i = 0; i < capacity(PrimitiveType::Vertex); ++i) {
127 ve_accessor.index_access().scalar_attribute(i) = VE(i);
128 v_flag_accessor.index_access().activate(i);
129 }
130}
131
132void EdgeMesh::initialize(Eigen::Ref<const RowVectors2l> E, bool is_free)
133{
134 this->m_is_free = is_free;
135 auto [EE, VE] = edgemesh_topology_initialization(E);
136 if (is_free) {
137 EE.setConstant(-1);
138 }
139 initialize(E, EE, VE);
140}
141void EdgeMesh::initialize_free(int64_t count)
142{
143 RowVectors2l S(count, 2);
144 std::iota(S.data(), S.data() + S.size(), int64_t(0));
145 initialize(S, true);
146}
147
148Tuple EdgeMesh::tuple_from_id(const PrimitiveType type, const int64_t gid) const
149{
150 switch (type) {
152 return vertex_tuple_from_id(gid);
153 }
154 case PrimitiveType::Edge: {
155 return edge_tuple_from_id(gid);
156 }
158 throw std::runtime_error("no tet tuple supported for edgemesh");
159 break;
160 }
162 throw std::runtime_error("no tet tuple supported for edgemesh");
163 break;
164 }
165 default: assert(false); //"Invalid primitive type"
166 }
167
168 return Tuple();
169}
170
172{
173 const attribute::Accessor<int64_t> ve_accessor = create_const_accessor<int64_t>(m_ve_handle);
174 auto e = ve_accessor.index_access().const_scalar_attribute(id);
175 const attribute::Accessor<int64_t> ev_accessor = create_const_accessor<int64_t>(m_ev_handle);
176 auto ev = ev_accessor.index_access().const_vector_attribute<2>(e);
177 for (int64_t i = 0; i < 2; ++i) {
178 if (ev(i) == id) {
179 Tuple v_tuple = Tuple(i, -1, -1, e);
180 return v_tuple;
181 }
182 }
183 assert(false); // "vertex_tuple_from_id failed"
184
185 return Tuple();
186}
187
189{
190 Tuple e_tuple = Tuple(0, -1, -1, id);
191
192 assert(is_valid(e_tuple));
193 return e_tuple;
194}
195
196Tuple EdgeMesh::tuple_from_global_ids(int64_t eid, int64_t vid) const
197{
198 const attribute::Accessor<int64_t> ev_accessor = create_const_accessor<int64_t>(m_ev_handle);
199 auto ev = ev_accessor.index_access().const_vector_attribute<2>(eid);
200
201 int64_t lvid = -1;
202
203 for (int j = 0; j < 2; ++j) {
204 if (ev(j) == vid) {
205 lvid = j;
206 }
207 }
208 assert(lvid != -1);
209
210 return Tuple(lvid, -1, -1, eid);
211}
212
213
214bool EdgeMesh::is_valid(const Tuple& tuple) const
215{
216 if (!Mesh::is_valid(tuple)) {
217 return false;
218 }
219
220 const bool is_connectivity_valid = tuple.local_vid() >= 0 && tuple.global_cid() >= 0;
222#if !defined(NDEBUG)
223 logger().debug(
224 "tuple.local_vid()={} >= 0"
225 " tuple.global_cid()={} >= 0",
226 tuple.local_vid(),
227 tuple.global_cid());
228 assert(tuple.local_vid() >= 0);
229 assert(tuple.global_cid() >= 0);
230#endif
231 return false;
232 }
233 return true;
234}
235
237{
238 // get accessors for topology
239 const attribute::Accessor<int64_t> ev_accessor = create_const_accessor<int64_t>(m_ev_handle);
240 const attribute::Accessor<int64_t> ee_accessor = create_const_accessor<int64_t>(m_ee_handle);
241 const attribute::Accessor<int64_t> ve_accessor = create_const_accessor<int64_t>(m_ve_handle);
242 const attribute::FlagAccessor<EdgeMesh> v_flag_accessor =
244 const attribute::FlagAccessor<EdgeMesh> e_flag_accessor =
246
247 // VE and EV
248 for (int64_t i = 0; i < capacity(PrimitiveType::Vertex); ++i) {
249 if (!v_flag_accessor.index_access().is_active(i)) {
250 continue;
251 }
252 int cnt = 0;
253 for (int64_t j = 0; j < 2; ++j) {
254 if (ev_accessor.index_access().const_vector_attribute<2>(
255 ve_accessor.index_access().const_scalar_attribute(i))(j) == i) {
256 cnt++;
257 }
258 }
259 if (cnt == 0) {
260 int64_t idx = ve_accessor.index_access().const_scalar_attribute(i);
261 wmtk::logger().error(
262 "EV[VE[{}]={},:]] ({}) = doesn't contain {}",
263 i,
264 idx,
265 fmt::join(ev_accessor.index_access().const_vector_attribute<2>(idx), ","),
266 i);
267 return false;
268 }
269 }
270
271 // EV and EE
272 for (int64_t i = 0; i < capacity(PrimitiveType::Edge); ++i) {
273 if (!e_flag_accessor.index_access().is_active(i)) {
274 continue;
275 }
276 // TODO: need to handle cornor case (self-loop)
277 }
278
279 return true;
280}
281
282std::vector<std::vector<TypedAttributeHandle<int64_t>>> EdgeMesh::connectivity_attributes() const
283{
284 std::vector<std::vector<TypedAttributeHandle<int64_t>>> handles(2);
285
286 handles[1].push_back(m_ve_handle);
287 handles[1].push_back(m_ee_handle);
288 handles[0].push_back(m_ev_handle);
289
290 return handles;
291}
292
293std::vector<Tuple> EdgeMesh::orient_vertices(const Tuple& tuple) const
294{
295 int64_t cid = tuple.global_cid();
296 return {Tuple(0, -1, -1, cid), Tuple(1, -1, -1, cid)};
297}
298
299
300} // namespace wmtk
attribute::TypedAttributeHandle< int64_t > m_ee_handle
Definition EdgeMesh.hpp:81
Tuple tuple_from_global_ids(int64_t eid, int64_t vid) const
Definition EdgeMesh.cpp:196
bool is_boundary(PrimitiveType, const Tuple &tuple) const override
check if a simplex (encoded as a tuple/primitive pair) lies on a boundary or not
Definition EdgeMesh.cpp:17
int64_t id(const Tuple &tuple, PrimitiveType type) const
Definition EdgeMesh.hpp:98
bool is_connectivity_valid() const override
Definition EdgeMesh.cpp:236
Tuple switch_tuple(const Tuple &tuple, PrimitiveType type) const override
switch the orientation of the Tuple of the given dimension
Definition EdgeMesh.cpp:38
bool is_boundary_vertex(const Tuple &tuple) const
Definition EdgeMesh.cpp:31
void initialize_free(int64_t count)
Definition EdgeMesh.cpp:141
Tuple tuple_from_id(const PrimitiveType type, const int64_t gid) const override
internal function that returns the tuple of requested type, and has the global index cid
Definition EdgeMesh.cpp:148
Tuple edge_tuple_from_id(int64_t id) const
Definition EdgeMesh.cpp:188
std::vector< Tuple > orient_vertices(const Tuple &tuple) const override
Definition EdgeMesh.cpp:293
attribute::TypedAttributeHandle< int64_t > m_ev_handle
Definition EdgeMesh.hpp:80
Tuple vertex_tuple_from_id(int64_t id) const
Definition EdgeMesh.cpp:171
bool is_ccw(const Tuple &tuple) const override
TODO this needs dimension?
Definition EdgeMesh.cpp:92
attribute::TypedAttributeHandle< int64_t > m_ve_handle
Definition EdgeMesh.hpp:78
~EdgeMesh() override
void initialize(Eigen::Ref< const RowVectors2l > E, bool is_free=false)
Definition EdgeMesh.cpp:132
bool is_valid(const Tuple &tuple) const final override
check validity of tuple including its hash
Definition EdgeMesh.cpp:214
std::vector< std::vector< TypedAttributeHandle< int64_t > > > connectivity_attributes() const override
Returns a vector of vectors of attribute handles.
Definition EdgeMesh.cpp:282
A Curiously Recurring Template Pattern shim to enable generic specialization of functions.
Definition MeshCRTP.hpp:24
bool m_is_free
Definition Mesh.hpp:832
void set_capacities(std::vector< int64_t > capacities)
int64_t capacity(PrimitiveType type) const
read in the m_capacities return the upper bound for the number of entities of the given dimension
bool is_free() const
Definition Mesh.hpp:973
virtual bool is_valid(const Tuple &tuple) const
check validity of tuple including its hash
Definition Mesh.cpp:113
const attribute::FlagAccessor< Mesh > get_flag_accessor(PrimitiveType type) const
Definition Mesh.cpp:159
The Tuple is the basic navigation tool in our mesh data structure.
Definition Tuple.hpp:19
int8_t local_vid() const
Definition Tuple.hxx:52
int8_t local_fid() const
Definition Tuple.hxx:62
int8_t local_eid() const
Definition Tuple.hxx:57
int64_t global_cid() const
Definition Tuple.hxx:47
A CachingAccessor that uses tuples for accessing attributes instead of indices.
Definition Accessor.hpp:28
CachingBaseType & index_access()
Definition Accessor.hpp:97
ConstMapResult< D > const_vector_attribute(const ArgType &t) const
T const_scalar_attribute(const int64_t index) const
T & scalar_attribute(const int64_t index)
ConstMapResult< D > const_vector_attribute(const int64_t index) const
MapResult< D > vector_attribute(const int64_t index)
const IndexBaseType & index_access() const
spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:58
RowVectors< int64_t, 2 > RowVectors2l
Definition Types.hpp:46
std::tuple< RowVectors2l, VectorXl > edgemesh_topology_initialization(Eigen::Ref< const RowVectors2l > E)