Lagrange
Mesh.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 <lagrange/ActingMeshGeometry.h>
15#include <lagrange/Attributes.h>
16#include <lagrange/Components.h>
17#include <lagrange/Connectivity.h>
18#include <lagrange/Edge.h>
19#include <lagrange/GenuineMeshGeometry.h>
20#include <lagrange/MeshGeometry.h>
21#include <lagrange/MeshNavigation.h>
22#include <lagrange/MeshTopology.h>
23#include <lagrange/common.h>
24#include <lagrange/corner_to_edge_mapping.h>
25#include <lagrange/experimental/AttributeManager.h>
26#include <lagrange/experimental/IndexedAttributeManager.h>
27#include <lagrange/utils/assert.h>
28#include <lagrange/utils/safe_cast.h>
29#include <lagrange/utils/invalid.h>
30
31#include <Eigen/Core>
32#include <map>
33#include <memory>
34#include <string>
35#include <vector>
36
37namespace lagrange {
38
39// TODO: Extend base class with non-templated methods for access to vertex/facet/attribute generic arrays!
41{
42public:
43 virtual ~MeshBase() = default;
44};
45
46template <typename _VertexArray, typename _FacetArray>
47class Mesh : public MeshBase
48{
49public:
50 using VertexArray = _VertexArray;
51 using FacetArray = _FacetArray;
52 using VertexType =
53 Eigen::Matrix<typename VertexArray::Scalar, 1, VertexArray::ColsAtCompileTime>;
55
56 using Scalar = typename VertexArray::Scalar;
57 using Index = typename FacetArray::Scalar;
58
59 using AttributeArray = Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
60 using IndexArray = FacetArray;
63
64 using AdjacencyList = typename Connectivity<Geometry>::AdjacencyList;
65 using IndexList = typename Connectivity<Geometry>::IndexList;
66
67 using Edge = EdgeType<Index>;
68
69 using UVArray = AttributeArray;
70 using UVIndices = IndexArray;
71 using UVType = Eigen::Matrix<Scalar, 1, 2>;
72
73public:
81 {
82 m_connectivity = std::make_unique<Connectivity<Geometry>>();
83 m_components = std::make_unique<Components<Geometry>>();
84 m_topology = std::make_unique<MeshTopology<MeshType>>();
85 }
86
87 Mesh(std::shared_ptr<Geometry> geom)
88 : m_geometry(geom)
89 {
90 init_attributes();
91 m_connectivity = std::make_unique<Connectivity<Geometry>>();
92 m_components = std::make_unique<Components<Geometry>>();
93 m_topology = std::make_unique<MeshTopology<MeshType>>();
94 }
95 Mesh(const Mesh& other) = delete;
96 void operator=(const Mesh& other) = delete;
97 virtual ~Mesh() = default;
98
99public:
100 void initialize(const VertexArray& vertices, const FacetArray& facets)
101 {
102 m_geometry =
103 std::make_shared<GenuineMeshGeometry<VertexArray, FacetArray>>(vertices, facets);
104 init_attributes();
105 }
106
107 bool is_initialized() const
108 {
109 return m_geometry && m_vertex_attributes && m_facet_attributes && m_corner_attributes &&
110 m_edge_attributes && m_indexed_attributes;
111 }
112
113 Index get_dim() const
114 {
115 la_runtime_assert(is_initialized());
116 return m_geometry->get_dim();
117 }
118 Index get_num_vertices() const
119 {
120 la_runtime_assert(is_initialized());
121 return m_geometry->get_num_vertices();
122 }
123 Index get_num_facets() const
124 {
125 la_runtime_assert(is_initialized());
126 return m_geometry->get_num_facets();
127 }
128 Index get_vertex_per_facet() const
129 {
130 la_runtime_assert(is_initialized());
131 return m_geometry->get_vertex_per_facet();
132 }
133
134 const VertexArray& get_vertices() const
135 {
136 la_runtime_assert(is_initialized());
137 return m_geometry->get_vertices();
138 }
139 const FacetArray& get_facets() const
140 {
141 la_runtime_assert(is_initialized());
142 return m_geometry->get_facets();
143 }
144
145 VertexArray& ref_vertices()
146 {
147 la_runtime_assert(is_initialized());
148 return m_geometry->get_vertices_ref();
149 }
150 FacetArray& ref_facets()
151 {
152 la_runtime_assert(is_initialized());
153 return m_geometry->get_facets_ref();
154 }
155
156 std::vector<std::string> get_vertex_attribute_names() const
157 {
158 la_runtime_assert(is_initialized());
159 return m_vertex_attributes->get_names();
160 }
161
162 std::vector<std::string> get_facet_attribute_names() const
163 {
164 la_runtime_assert(is_initialized());
165 return m_facet_attributes->get_names();
166 }
167
168 std::vector<std::string> get_corner_attribute_names() const
169 {
170 la_runtime_assert(is_initialized());
171 return m_corner_attributes->get_names();
172 }
173
174 std::vector<std::string> get_edge_attribute_names() const
175 {
176 la_runtime_assert(is_initialized());
177 return m_edge_attributes->get_names();
178 }
179
180 std::vector<std::string> get_indexed_attribute_names() const
181 {
182 la_runtime_assert(is_initialized());
183 return m_indexed_attributes->get_names();
184 }
185
186 bool has_vertex_attribute(const std::string& name) const
187 {
188 la_runtime_assert(is_initialized());
189 return m_vertex_attributes->has(name);
190 }
191
192 bool has_facet_attribute(const std::string& name) const
193 {
194 la_runtime_assert(is_initialized());
195 return m_facet_attributes->has(name);
196 }
197
198 bool has_corner_attribute(const std::string& name) const
199 {
200 la_runtime_assert(is_initialized());
201 return m_corner_attributes->has(name);
202 }
203
204 bool has_edge_attribute(const std::string& name) const
205 {
206 la_runtime_assert(is_initialized());
207 return m_edge_attributes->has(name);
208 }
209
210 bool has_indexed_attribute(const std::string& name) const
211 {
212 la_runtime_assert(is_initialized());
213 return m_indexed_attributes->has(name);
214 }
215
216 void add_vertex_attribute(const std::string& name) const
217 {
218 la_runtime_assert(is_initialized());
219 m_vertex_attributes->add(name);
220 }
221
222 void add_facet_attribute(const std::string& name) const
223 {
224 la_runtime_assert(is_initialized());
225 m_facet_attributes->add(name);
226 }
227
228 void add_corner_attribute(const std::string& name) const
229 {
230 la_runtime_assert(is_initialized());
231 m_corner_attributes->add(name);
232 }
233
234 void add_edge_attribute(const std::string& name) const
235 {
236 la_runtime_assert(is_initialized() && is_edge_data_initialized());
237 m_edge_attributes->add(name);
238 }
239
240 void add_indexed_attribute(const std::string& name) const
241 {
242 la_runtime_assert(is_initialized());
243 m_indexed_attributes->add(name);
244 }
245
246 const AttributeArray& get_vertex_attribute(const std::string& name) const
247 {
248 la_runtime_assert(is_initialized());
249 const auto* attr = m_vertex_attributes->get(name);
250 la_runtime_assert(attr != nullptr, "Attribute " + name + " is not initialized.");
251 return attr->get()->template get<AttributeArray>();
252 }
253
254 decltype(auto) get_vertex_attribute_array(const std::string& name) const
255 {
256 la_runtime_assert(is_initialized());
257 const auto* attr = m_vertex_attributes->get(name);
258 la_runtime_assert(attr != nullptr, "Attribute " + name + " is not initialized.");
259 return attr->get();
260 }
261
262 decltype(auto) get_vertex_attribute_array(const std::string& name)
263 {
264 la_runtime_assert(is_initialized());
265 auto* attr = m_vertex_attributes->get(name);
266 la_runtime_assert(attr != nullptr, "Attribute " + name + " is not initialized.");
267 return attr->get();
268 }
269
270
271 const AttributeArray& get_facet_attribute(const std::string& name) const
272 {
273 la_runtime_assert(is_initialized());
274 const auto* attr = m_facet_attributes->get(name);
275 la_runtime_assert(attr != nullptr, "Attribute " + name + " is not initialized.");
276 return attr->get()->template get<AttributeArray>();
277 }
278
279 decltype(auto) get_facet_attribute_array(const std::string& name) const
280 {
281 la_runtime_assert(is_initialized());
282 const auto* attr = m_facet_attributes->get(name);
283 la_runtime_assert(attr != nullptr, "Attribute " + name + " is not initialized.");
284 return attr->get();
285 }
286
287 decltype(auto) get_facet_attribute_array(const std::string& name)
288 {
289 la_runtime_assert(is_initialized());
290 auto* attr = m_facet_attributes->get(name);
291 la_runtime_assert(attr != nullptr, "Attribute " + name + " is not initialized.");
292 return attr->get();
293 }
294
295 const AttributeArray& get_corner_attribute(const std::string& name) const
296 {
297 la_runtime_assert(is_initialized());
298 const auto* attr = m_corner_attributes->get(name);
299 la_runtime_assert(attr != nullptr, "Attribute " + name + " is not initialized.");
300 return attr->get()->template get<AttributeArray>();
301 }
302
303 decltype(auto) get_corner_attribute_array(const std::string& name) const
304 {
305 la_runtime_assert(is_initialized());
306 const auto* attr = m_corner_attributes->get(name);
307 la_runtime_assert(attr != nullptr, "Attribute " + name + " is not initialized.");
308 return attr->get();
309 }
310
311 decltype(auto) get_corner_attribute_array(const std::string& name)
312 {
313 la_runtime_assert(is_initialized());
314 auto* attr = m_corner_attributes->get(name);
315 la_runtime_assert(attr != nullptr, "Attribute " + name + " is not initialized.");
316 return attr->get();
317 }
318
319 const AttributeArray& get_edge_attribute(const std::string& name) const
320 {
321 la_runtime_assert(is_initialized() && is_edge_data_initialized());
322 const auto* attr = m_edge_attributes->get(name);
323 la_runtime_assert(attr != nullptr);
324 return attr->get()->template get<AttributeArray>();
325 }
326
327 decltype(auto) get_edge_attribute_array(const std::string& name) const
328 {
329 la_runtime_assert(is_initialized() && is_edge_data_initialized());
330 auto* attr = m_edge_attributes->get(name);
331 la_runtime_assert(attr != nullptr, "Attribute " + name + " is not initialized.");
332 return attr->get();
333 }
334
335 decltype(auto) get_edge_attribute_array(const std::string& name)
336 {
337 la_runtime_assert(is_initialized() && is_edge_data_initialized());
338 auto* attr = m_edge_attributes->get(name);
339 la_runtime_assert(attr != nullptr, "Attribute " + name + " is not initialized.");
340 return attr->get();
341 }
342
343 auto get_indexed_attribute(const std::string& name) const
344 {
345 la_runtime_assert(is_initialized());
346 const auto data = m_indexed_attributes->get(name);
347 la_runtime_assert(data != nullptr);
348 return std::forward_as_tuple(
349 data->template get_values<AttributeArray>(),
350 data->template get_indices<IndexArray>());
351 }
352
353 auto get_indexed_attribute_array(const std::string& name) const
354 {
355 la_runtime_assert(is_initialized());
356 const auto data = m_indexed_attributes->get(name);
357 la_runtime_assert(data != nullptr);
358 return std::make_tuple(data->get_values(), data->get_indices());
359 }
360
361 auto get_indexed_attribute_array(const std::string& name)
362 {
363 la_runtime_assert(is_initialized());
364 const auto data = m_indexed_attributes->get(name);
365 la_runtime_assert(data != nullptr);
366 return std::make_tuple(data->get_values(), data->get_indices());
367 }
368
369 void set_vertex_attribute(const std::string& name, const AttributeArray& attr)
370 {
371 la_runtime_assert(is_initialized());
372 m_vertex_attributes->set(name, attr);
373 }
374
375 void set_facet_attribute(const std::string& name, const AttributeArray& attr)
376 {
377 la_runtime_assert(is_initialized());
378 m_facet_attributes->set(name, attr);
379 }
380
381 void set_corner_attribute(const std::string& name, const AttributeArray& attr)
382 {
383 la_runtime_assert(is_initialized());
384 m_corner_attributes->set(name, attr);
385 }
386
387 void set_edge_attribute(const std::string& name, const AttributeArray& attr)
388 {
389 la_runtime_assert(is_initialized() && is_edge_data_initialized());
390 m_edge_attributes->set(name, attr);
391 }
392
393 template <typename Derived>
394 void set_vertex_attribute_array(const std::string& name, Derived&& attr)
395 {
396 la_runtime_assert(is_initialized());
397 m_vertex_attributes->set(name, std::forward<Derived>(attr));
398 }
399
400 template <typename Derived>
401 void set_facet_attribute_array(const std::string& name, Derived&& attr)
402 {
403 la_runtime_assert(is_initialized());
404 m_facet_attributes->set(name, std::forward<Derived>(attr));
405 }
406
407 template <typename Derived>
408 void set_corner_attribute_array(const std::string& name, Derived&& attr)
409 {
410 la_runtime_assert(is_initialized());
411 m_corner_attributes->set(name, std::forward<Derived>(attr));
412 }
413
414 template <typename Derived>
415 void set_edge_attribute_array(const std::string& name, Derived&& attr)
416 {
417 la_runtime_assert(is_initialized() && is_edge_data_initialized());
418 m_edge_attributes->set(name, std::forward<Derived>(attr));
419 }
420
421 void set_indexed_attribute(
422 const std::string& name,
423 const AttributeArray& values,
424 const IndexArray& indices)
425 {
426 la_runtime_assert(is_initialized());
427 auto attr = m_indexed_attributes->get(name);
428 attr->set_values(values);
429 attr->set_indices(indices);
430 }
431
432 void remove_vertex_attribute(const std::string& name)
433 {
434 la_runtime_assert(is_initialized());
435 m_vertex_attributes->remove(name);
436 }
437
438 void remove_facet_attribute(const std::string& name)
439 {
440 la_runtime_assert(is_initialized());
441 m_facet_attributes->remove(name);
442 }
443
444 void remove_corner_attribute(const std::string& name)
445 {
446 la_runtime_assert(is_initialized());
447 m_corner_attributes->remove(name);
448 }
449
450 void remove_edge_attribute(const std::string& name)
451 {
452 la_runtime_assert(is_initialized() && is_edge_data_initialized());
453 m_edge_attributes->remove(name);
454 }
455
456 void remove_indexed_attribute(const std::string& name)
457 {
458 la_runtime_assert(is_initialized());
459 m_indexed_attributes->remove(name);
460 }
461
462public:
463 //========================
464 // Import/export functions
465 //========================
466 //
467 // Data are moved from source varibles to target varaibles.
468 // Once the data is moved out, the source variable is resized to have 0
469 // rows.
470
471 template <typename Derived>
472 void import_vertices(Eigen::PlainObjectBase<Derived>& vertices)
473 {
474 la_runtime_assert(is_initialized());
475 m_geometry->import_vertices(vertices);
476 }
477
478 template <typename Derived>
479 void import_facets(Eigen::PlainObjectBase<Derived>& facets)
480 {
481 la_runtime_assert(is_initialized());
482 m_geometry->import_facets(facets);
483 }
484
485 template <typename AttributeDerived>
486 void import_vertex_attribute(const std::string& name, AttributeDerived&& attr) const
487 {
488 la_runtime_assert(is_initialized());
489 m_vertex_attributes->import_data(name, std::forward<AttributeDerived>(attr));
490 }
491
492 template <typename AttributeDerived>
493 void import_facet_attribute(const std::string& name, AttributeDerived&& attr) const
494 {
495 la_runtime_assert(is_initialized());
496 m_facet_attributes->import_data(name, std::forward<AttributeDerived>(attr));
497 }
498
499 template <typename AttributeDerived>
500 void import_corner_attribute(const std::string& name, AttributeDerived&& attr) const
501 {
502 la_runtime_assert(is_initialized());
503 m_corner_attributes->import_data(name, std::forward<AttributeDerived>(attr));
504 }
505
506 template <typename AttributeDerived>
507 void import_edge_attribute(const std::string& name, AttributeDerived&& attr) const
508 {
509 la_runtime_assert(is_initialized() && is_edge_data_initialized());
510 m_edge_attributes->import_data(name, std::forward<AttributeDerived>(attr));
511 }
512
513 template <typename ValueDerived, typename IndexDerived>
514 void
515 import_indexed_attribute(const std::string& name, ValueDerived&& values, IndexDerived&& indices)
516 {
517 la_runtime_assert(is_initialized());
518 m_indexed_attributes->import_data(
519 name,
520 std::forward<ValueDerived>(values),
521 std::forward<IndexDerived>(indices));
522 }
523
524 template <typename Derived>
525 void export_vertices(Eigen::PlainObjectBase<Derived>& vertices)
526 {
527 la_runtime_assert(is_initialized());
528 m_geometry->export_vertices(vertices);
529 }
530
531 template <typename Derived>
532 void export_facets(Eigen::PlainObjectBase<Derived>& facets)
533 {
534 la_runtime_assert(is_initialized());
535 m_geometry->export_facets(facets);
536 }
537
538 template <typename Derived>
539 void export_vertex_attribute(const std::string& name, Eigen::PlainObjectBase<Derived>& attr)
540 {
541 la_runtime_assert(is_initialized());
542 m_vertex_attributes->export_data(name, attr);
543 }
544
545 template <typename Derived>
546 void export_facet_attribute(const std::string& name, Eigen::PlainObjectBase<Derived>& attr)
547 {
548 la_runtime_assert(is_initialized());
549 m_facet_attributes->export_data(name, attr);
550 }
551
552 template <typename Derived>
553 void export_corner_attribute(const std::string& name, Eigen::PlainObjectBase<Derived>& attr)
554 {
555 la_runtime_assert(is_initialized());
556 m_corner_attributes->export_data(name, attr);
557 }
558
559 template <typename Derived>
560 void export_edge_attribute(const std::string& name, Eigen::PlainObjectBase<Derived>& attr)
561 {
562 la_runtime_assert(is_initialized() && is_edge_data_initialized());
563 m_edge_attributes->export_data(name, attr);
564 }
565
566 template <typename ValueDerived, typename IndexDerived>
567 void export_indexed_attribute(
568 const std::string& name,
569 Eigen::PlainObjectBase<ValueDerived>& values,
570 Eigen::PlainObjectBase<IndexDerived>& indices)
571 {
572 m_indexed_attributes->export_data(name, values, indices);
573 }
574
575public:
576 //========================
577 // Connecitivity functions
578 //========================
579
580 void initialize_connectivity()
581 {
582 la_runtime_assert(m_connectivity);
583 m_connectivity->initialize(*m_geometry);
584 }
585
586 bool is_connectivity_initialized() const
587 {
588 return (m_connectivity && m_connectivity->is_initialized());
589 }
590
591 const AdjacencyList& get_vertex_vertex_adjacency() const
592 {
593 la_runtime_assert(is_connectivity_initialized());
594 return m_connectivity->get_vertex_vertex_adjacency();
595 }
596
597 const AdjacencyList& get_vertex_facet_adjacency() const
598 {
599 la_runtime_assert(is_connectivity_initialized());
600 return m_connectivity->get_vertex_facet_adjacency();
601 }
602
603 const AdjacencyList& get_facet_facet_adjacency() const
604 {
605 la_runtime_assert(is_connectivity_initialized());
606 return m_connectivity->get_facet_facet_adjacency();
607 }
608
609 const IndexList& get_vertices_adjacent_to_vertex(Index vi) const
610 {
611 la_runtime_assert(is_connectivity_initialized());
612 return m_connectivity->get_vertices_adjacent_to_vertex(vi);
613 }
614
615 const IndexList& get_facets_adjacent_to_vertex(Index vi) const
616 {
617 la_runtime_assert(is_connectivity_initialized());
618 return m_connectivity->get_facets_adjacent_to_vertex(vi);
619 }
620
621 const IndexList& get_facets_adjacent_to_facet(Index fi) const
622 {
623 la_runtime_assert(is_connectivity_initialized());
624 return m_connectivity->get_facets_adjacent_to_facet(fi);
625 }
626
627public:
628 // ========================
629 // Edge-facet map functions.
630 // ========================
631
634 {
635 if (m_navigation) return;
636 m_navigation = std::make_unique<MeshNavigation<MeshType>>(std::ref(*this));
637 }
638
640 void clear_edge_data() { m_navigation = nullptr; }
641
643 bool is_edge_data_initialized() const { return m_navigation != nullptr; }
644
650 Index get_num_edges() const
651 {
652 la_runtime_assert(is_edge_data_initialized(), "Edge data not initialized");
653 return m_navigation->get_num_edges();
654 }
655
664 Index get_edge(Index f, Index lv) const
665 {
666 la_runtime_assert(is_edge_data_initialized(), "Edge data not initialized");
667 return m_navigation->get_edge(f, lv);
668 }
669
677 Index get_edge_from_corner(Index c) const
678 {
679 la_runtime_assert(is_edge_data_initialized(), "Edge data not initialized");
680 return m_navigation->get_edge_from_corner(c);
681 }
682
694 Index find_edge_from_vertices(Index v0, Index v1) const
695 {
696 la_runtime_assert(is_edge_data_initialized(), "Edge data not initialized");
697 Index edge_id = invalid<Index>();
698
699 const Index vertex_per_facet = get_vertex_per_facet();
700 foreach_corners_around_vertex(v0, [&](Index c) {
701 const Index fid = c / vertex_per_facet;
702 const Index lv = c % vertex_per_facet;
703 if (get_facets()(fid, (lv + 1) % vertex_per_facet) == v1) {
704 edge_id = get_edge(fid, lv);
705 }
706 });
707 if (edge_id != invalid<Index>()) return edge_id;
708
709 // It is possible that (v0, v1) is a boundary edge, in which case
710 // the above code will only find the edge_id if (v0, v1) is oriented
711 // correctly (i.e. counterclockwise). Thus, we need to check the
712 // opposite orientation if the above code failed.
713 foreach_corners_around_vertex(v1, [&](Index c) {
714 const Index fid = c / vertex_per_facet;
715 const Index lv = c % vertex_per_facet;
716 if (get_facets()(fid, (lv + 1) % vertex_per_facet) == v0) {
717 edge_id = get_edge(fid, lv);
718 }
719 });
720 return edge_id;
721 }
722
730 std::array<Index, 2> get_edge_vertices(Index e) const
731 {
732 la_runtime_assert(is_edge_data_initialized(), "Edge data not initialized");
733 return m_navigation->get_edge_vertices(get_facets(), e);
734 }
735
745 Index get_vertex_opposite_edge(Index e) const
746 {
747 la_runtime_assert(is_edge_data_initialized(), "Edge data not initialized");
748 return m_navigation->get_vertex_opposite_edge(get_facets(), e);
749 }
750
757 Index get_num_facets_around_vertex(Index v) const
758 {
759 la_runtime_assert(is_edge_data_initialized(), "Edge data not initialized");
760 return m_navigation->get_num_facets_around_vertex(v);
761 }
762
769 Index get_num_facets_around_edge(Index e) const
770 {
771 la_runtime_assert(is_edge_data_initialized(), "Edge data not initialized");
772 return m_navigation->get_num_facets_around_edge(e);
773 }
774
782 Index get_one_facet_around_edge(Index e) const
783 {
784 la_runtime_assert(is_edge_data_initialized(), "Edge data not initialized");
785 return m_navigation->get_one_facet_around_edge(e);
786 }
787
795 Index get_one_corner_around_edge(Index e) const
796 {
797 la_runtime_assert(is_edge_data_initialized(), "Edge data not initialized");
798 return m_navigation->get_one_corner_around_edge(e);
799 }
800
808 Index get_one_corner_around_vertex(Index v) const
809 {
810 la_runtime_assert(is_edge_data_initialized(), "Edge data not initialized");
811 return m_navigation->get_one_corner_around_vertex(v);
812 }
813
821 bool is_boundary_edge(Index e) const
822 {
823 la_runtime_assert(is_edge_data_initialized(), "Edge data not initialized");
824 return m_navigation->is_boundary_edge(e);
825 }
826
834 bool is_boundary_vertex(Index v) const
835 {
836 la_runtime_assert(is_edge_data_initialized(), "Edge data not initialized");
837 return m_navigation->is_boundary_vertex(v);
838 }
839
840 // ==== edge data utility functions ====
841
850 template <typename Func>
851 void foreach_facets_around_vertex(Index v, Func func) const
852 {
853 la_runtime_assert(is_edge_data_initialized(), "Edge data not initialized");
854 m_navigation->foreach_facets_around_vertex(v, func);
855 }
856
865 template <typename Func>
866 void foreach_facets_around_edge(Index e, Func func) const
867 {
868 la_runtime_assert(is_edge_data_initialized(), "Edge data not initialized");
869 m_navigation->foreach_facets_around_edge(e, func);
870 }
871
880 template <typename Func>
881 void foreach_corners_around_vertex(Index v, Func func) const
882 {
883 la_runtime_assert(is_edge_data_initialized(), "Edge data not initialized");
884 m_navigation->foreach_corners_around_vertex(v, func);
885 }
886
895 template <typename Func>
896 void foreach_corners_around_edge(Index e, Func func) const
897 {
898 la_runtime_assert(is_edge_data_initialized(), "Edge data not initialized");
899 m_navigation->foreach_corners_around_edge(e, func);
900 }
901
902public:
903 //========================
904 // Topology functions
905 //========================
906
907 void initialize_topology()
908 {
909 la_runtime_assert(m_topology);
910 m_topology->initialize(*this);
911 }
912
913 bool is_topology_initialized() const { return m_topology->is_initialized(); }
914
915 bool is_edge_manifold() const
916 {
917 la_runtime_assert(m_topology->is_initialized(), "Mesh topology not initialized");
918 return m_topology->is_edge_manifold();
919 }
920
921 bool is_vertex_manifold() const
922 {
923 la_runtime_assert(m_topology->is_initialized(), "Mesh topology not initialized");
924 return m_topology->is_vertex_manifold();
925 }
926
927 const MeshTopology<MeshType>& get_topology() const { return *m_topology; }
928
929public:
930 //=====================
931 // Components functions
932 //=====================
933 void initialize_components()
934 {
935 la_runtime_assert(m_components);
936 la_runtime_assert(m_connectivity);
937 if (!m_connectivity->is_initialized()) {
938 initialize_connectivity();
939 }
940 m_components->initialize(*m_geometry, m_connectivity.get());
941 }
942
943 bool is_components_initialized() const
944 {
945 return (m_components && (get_num_facets() == 0 || m_components->get_num_components() > 0));
946 }
947
948 Index get_num_components() const
949 {
950 la_runtime_assert(is_components_initialized());
951 return m_components->get_num_components();
952 }
953
954 const std::vector<IndexList>& get_components() const
955 {
956 la_runtime_assert(is_components_initialized());
957 return m_components->get_components();
958 }
959
960 const IndexList& get_per_facet_component_ids() const
961 {
962 la_runtime_assert(is_components_initialized());
963 return m_components->get_per_facet_component_ids();
964 }
965
966public:
967 //========================
968 // UV coordinates.
969 //========================
970
971 bool is_uv_initialized() const { return m_indexed_attributes->has("uv"); }
972
973 void initialize_uv(const UVArray& uv, const UVIndices& uv_indices)
974 {
975 if (!m_indexed_attributes->has("uv")) {
976 m_indexed_attributes->add("uv");
977 }
978 auto uv_attr = m_indexed_attributes->get("uv");
979
980 uv_attr->set_values(uv);
981 uv_attr->set_indices(uv_indices);
982 }
983
984 void import_uv(UVArray&& uv, UVIndices&& uv_indices)
985 {
986 if (!m_indexed_attributes->has("uv")) {
987 m_indexed_attributes->add("uv");
988 }
989 this->import_indexed_attribute("uv", uv, uv_indices);
990 }
991
992 decltype(auto) get_uv() const
993 {
994 la_runtime_assert(is_uv_initialized());
995 return m_indexed_attributes->get_values<UVArray>("uv");
996 }
997
998 decltype(auto) get_uv_indices() const
999 {
1000 la_runtime_assert(is_uv_initialized());
1001 return m_indexed_attributes->get_indices<UVIndices>("uv");
1002 }
1003
1004 decltype(auto) get_uv_mesh() const
1005 {
1006 const auto attr = m_indexed_attributes->get("uv");
1007 auto geometry = std::make_unique<GenuineMeshGeometry<UVArray, UVIndices>>(
1008 attr->get_values()->template get<UVArray>(),
1009 attr->get_indices()->template get<UVIndices>());
1010 return std::make_unique<Mesh<UVArray, UVIndices>>(std::move(geometry));
1011 }
1012
1013 void clear_uv() const { m_indexed_attributes->remove("uv"); }
1014
1015public:
1016 //========================
1017 // Serialization.
1018 //========================
1019
1020 template <typename Archive>
1021 void serialize_impl(Archive& ar)
1022 {
1024 const std::array<int32_t, 3> current_version = {{0, 1, 0}};
1025 std::array<int32_t, 3> version = current_version;
1026 if (ar.is_input()) {
1027 init_attributes();
1028 }
1029 enum {
1030 VERSION = 0,
1031 GEOMETRY = 1,
1032 VERTEX_ATTR = 2,
1033 FACET_ATTR = 3,
1034 CORNER_ATTR = 4,
1035 EDGE_ATTR = 5,
1036 INDEXED_ATTR = 6,
1037 DEPRECATED_EDGE_ATTR = 7, // Not used anymore, but we keep the slot occupied
1038 };
1039 ar.object([&](auto& ar) {
1040 ar("version", VERSION) & version;
1041 ar("geometry", GEOMETRY) & m_geometry;
1042 ar("vertex_attributes", VERTEX_ATTR) & m_vertex_attributes;
1043 ar("facet_attributes", FACET_ATTR) & m_facet_attributes;
1044 ar("corner_attributes", CORNER_ATTR) & m_corner_attributes;
1045 ar("edge_attributes", EDGE_ATTR) & m_edge_attributes;
1046 ar("indexed_attributes", INDEXED_ATTR) & m_indexed_attributes;
1047 });
1048 la_runtime_assert(version == current_version, "Incompatible version number");
1049 LA_IGNORE_SHADOW_WARNING_END
1050
1051 // If mesh has edge attributes, we need to initialize edge data too
1052 if (ar.is_input()) {
1053 if (m_edge_attributes->get_size() > 0) {
1055 }
1056 }
1057
1058 // Hack/workaround until we have a stable API for mesh attributes. Currently `IndexArray`
1059 // can have a fixed num of columns at compile-time, but array serialization always save/load
1060 // arrays with Eigen::Dynamic as the number of rows/cols (as it should).
1061 if (ar.is_input()) {
1062 const auto names = m_indexed_attributes->get_names();
1063 for (const auto& name : names) {
1064 AttributeArray values = m_indexed_attributes->view_values<AttributeArray>(name);
1065 IndexArray indices = m_indexed_attributes->view_indices<IndexArray>(name);
1066 m_indexed_attributes->remove(name);
1067 m_indexed_attributes->add(name, std::move(values), std::move(indices));
1068 }
1069 }
1070 }
1071
1072protected:
1073 void init_attributes()
1074 {
1075 m_vertex_attributes = std::make_unique<experimental::AttributeManager>();
1076 m_facet_attributes = std::make_unique<experimental::AttributeManager>();
1077 m_corner_attributes = std::make_unique<experimental::AttributeManager>();
1078 m_edge_attributes = std::make_unique<experimental::AttributeManager>();
1079 m_indexed_attributes = std::make_unique<experimental::IndexedAttributeManager>();
1080 }
1081
1082protected:
1083 std::shared_ptr<Geometry> m_geometry;
1084 std::unique_ptr<MeshTopology<MeshType>> m_topology;
1085 std::unique_ptr<MeshNavigation<MeshType>> m_navigation;
1086
1087 std::unique_ptr<Connectivity<Geometry>> m_connectivity;
1088 std::unique_ptr<Components<Geometry>> m_components;
1089 std::unique_ptr<experimental::AttributeManager> m_vertex_attributes;
1090 std::unique_ptr<experimental::AttributeManager> m_facet_attributes;
1091 std::unique_ptr<experimental::AttributeManager> m_corner_attributes;
1092 std::unique_ptr<experimental::AttributeManager> m_edge_attributes;
1093 std::unique_ptr<experimental::IndexedAttributeManager> m_indexed_attributes;
1094};
1095
1096template <typename _VertexArray, typename _FacetArray, typename Archive>
1097void serialize(Mesh<_VertexArray, _FacetArray>& mesh, Archive& ar)
1098{
1099 mesh.serialize_impl(ar);
1100}
1101
1102extern template class Mesh<Vertices3D, Triangles>;
1103extern template class Mesh<Vertices2D, Triangles>;
1104extern template class Mesh<Vertices3Df, Triangles>;
1105extern template class Mesh<Vertices2Df, Triangles>;
1106extern template class Mesh<Vertices3D, Quads>;
1107extern template class Mesh<Vertices2D, Quads>;
1108extern template class Mesh<Vertices3Df, Quads>;
1109extern template class Mesh<Vertices2Df, Quads>;
1110
1111} // namespace lagrange
Definition: Edge.h:29
Definition: Mesh.h:41
Definition: MeshGeometry.h:25
Definition: Mesh.h:48
Index find_edge_from_vertices(Index v0, Index v1) const
Retrieve the edge id from end vertices (v0, v1).
Definition: Mesh.h:694
bool is_boundary_edge(Index e) const
Determines whether the specified edge e is a boundary edge.
Definition: Mesh.h:821
bool is_boundary_vertex(Index v) const
Determines whether the specified vertex v is a boundary vertex.
Definition: Mesh.h:834
Index get_vertex_opposite_edge(Index e) const
Returns a vertex id opposite the edge.
Definition: Mesh.h:745
Index get_num_facets_around_vertex(Index v) const
Count the number of facets incident to a given vertex.
Definition: Mesh.h:757
Index get_one_corner_around_edge(Index e) const
Get the index of one corner around a given edge.
Definition: Mesh.h:795
Mesh()
The default constructor only build a frame of the data structure with null geometry and attributes.
Definition: Mesh.h:80
bool is_edge_data_initialized() const
Edge data accessors (const)
Definition: Mesh.h:643
Index get_edge(Index f, Index lv) const
Gets the edge index corresponding to (f, lv) – (f, lv+1).
Definition: Mesh.h:664
std::array< Index, 2 > get_edge_vertices(Index e) const
Retrieve edge endpoints.
Definition: Mesh.h:730
void initialize_edge_data()
Edge data initialization.
Definition: Mesh.h:633
Index get_num_facets_around_edge(Index e) const
Count the number of facets incident to a given edge.
Definition: Mesh.h:769
void foreach_facets_around_edge(Index e, Func func) const
Applies a function to each facet around a prescribed edge.
Definition: Mesh.h:866
void foreach_corners_around_edge(Index e, Func func) const
Applies a function to each corner around a prescribed edge.
Definition: Mesh.h:896
Index get_one_facet_around_edge(Index e) const
Get the index of one facet around a given edge.
Definition: Mesh.h:782
Index get_one_corner_around_vertex(Index v) const
Get the index of one corner around a given vertex.
Definition: Mesh.h:808
Index get_num_edges() const
Gets the number of edges.
Definition: Mesh.h:650
void foreach_facets_around_vertex(Index v, Func func) const
Applies a function to each facet around a prescribed vertex.
Definition: Mesh.h:851
void foreach_corners_around_vertex(Index v, Func func) const
Applies a function to each corner around a prescribed vertex.
Definition: Mesh.h:881
Index get_edge_from_corner(Index c) const
Gets the edge index corresponding to a corner index.
Definition: Mesh.h:677
void clear_edge_data()
Clear edge data.
Definition: Mesh.h:640
#define la_runtime_assert(...)
Runtime assertion check.
Definition: assert.h:169
#define LA_IGNORE_SHADOW_WARNING_BEGIN
Ignore shadow warnings.
Definition: warning.h:68
Main namespace for Lagrange.
Definition: AABBIGL.h:30