Visual Computing Library  devel
Loading...
Searching...
No Matches
topology.h
1/*****************************************************************************
2 * VCLib *
3 * Visual Computing Library *
4 * *
5 * Copyright(C) 2021-2025 *
6 * Visual Computing Lab *
7 * ISTI - Italian National Research Council *
8 * *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the Mozilla Public License Version 2.0 as published *
13 * by the Mozilla Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * Mozilla Public License Version 2.0 *
20 * (https://www.mozilla.org/en-US/MPL/2.0/) for more details. *
21 ****************************************************************************/
22
23#ifndef VCL_ALGORITHMS_MESH_UPDATE_TOPOLOGY_H
24#define VCL_ALGORITHMS_MESH_UPDATE_TOPOLOGY_H
25
26#include <vclib/algorithms/mesh/sort.h>
27
28#include <vclib/mesh.h>
29
30namespace vcl {
31
48template<uint ELEM_ID, FaceMeshConcept MeshType>
49void clearPerElementAdjacentFaces(MeshType& mesh)
50{
51 requirePerElementComponent<ELEM_ID, CompId::ADJACENT_FACES>(mesh);
52
53 using AdjacentFacesType = comp::ComponentTypeFromID<
54 CompId::ADJACENT_FACES,
55 typename MeshType::template ElementType<ELEM_ID>::Components>;
56
57 for (auto& e : mesh.template elements<ELEM_ID>()) {
58 if constexpr (comp::IsTiedToVertexNumber<AdjacentFacesType>) {
59 for (uint i = 0; i < e.adjFacesNumber(); ++i) {
60 e.setAdjFace(i, nullptr);
61 }
62 }
63 else {
64 e.clearAdjFaces();
65 }
66 }
67}
68
84template<uint ELEM_ID, EdgeMeshConcept MeshType>
85void clearPerElementAdjacentEdges(MeshType& mesh)
86{
87 requirePerElementComponent<ELEM_ID, CompId::ADJACENT_EDGES>(mesh);
88
89 using AdjacentEdgesType = comp::ComponentTypeFromID<
90 CompId::ADJACENT_EDGES,
91 typename MeshType::template ElementType<ELEM_ID>::Components>;
92
93 for (auto& e : mesh.template elements<ELEM_ID>()) {
94 if constexpr (comp::IsTiedToVertexNumber<AdjacentEdgesType>) {
95 for (uint i = 0; i < e.adjEdgesNumber(); ++i) {
96 e.setAdjEdges(i, nullptr);
97 }
98 }
99 else {
100 e.clearAdjEdges();
101 }
102 }
103}
104
117template<uint ELEM_ID, MeshConcept MeshType>
118void clearPerElementAdjacentVertices(MeshType& mesh)
119{
120 requirePerElementComponent<ELEM_ID, CompId::ADJACENT_VERTICES>(mesh);
121
122 for (auto& e : mesh.template elements<ELEM_ID>()) {
123 e.clearAdjVertices();
124 }
125}
126
138template<FaceMeshConcept MeshType>
139void clearPerVertexAdjacentFaces(MeshType& mesh)
140{
141 clearPerElementAdjacentFaces<ElemId::VERTEX>(mesh);
142}
143
152template<FaceMeshConcept MeshType>
153void updatePerVertexAdjacentFaces(MeshType& mesh)
154{
155 clearPerVertexAdjacentFaces(mesh);
156
157 using VertexType = MeshType::VertexType;
158 using FaceType = MeshType::FaceType;
159
160 for (VertexType& v : mesh.vertices()) {
161 v.clearAdjFaces();
162 }
163
164 for (FaceType& f : mesh.faces()) {
165 for (VertexType* v : f.vertices()) {
166 v->pushAdjFace(&f);
167 }
168 }
169}
170
183template<MeshConcept MeshType>
184void clearPerVertexAdjacentVertices(MeshType& mesh)
185{
186 clearPerElementAdjacentVertices<ElemId::VERTEX>(mesh);
187}
188
200template<MeshConcept MeshType>
201void updatePerVertexAdjacentVertices(
202 MeshType& mesh,
203 bool includeOnlyFaces = false)
204{
205 clearPerVertexAdjacentVertices(mesh);
206
207 using VertexType = MeshType::VertexType;
208
209 if constexpr (FaceMeshConcept<MeshType>) {
210 // vector that contains edges sorted trough unordered vertex pointers
211 // it contains clusters of "same" edges, but each one of them has its
212 // face pointer note that in case on non-manifold mesh, clusters may be
213 // of size
214 // >= 2
215 std::vector<MeshEdgeUtil<MeshType>> vec =
216 fillAndSortMeshEdgeUtilVector(mesh);
217
218 // store the last pair of vertices
219 VertexType* v1 = nullptr;
220 VertexType* v2 = nullptr;
221 for (uint i = 0; i < vec.size(); ++i) {
222 // if this pair is different from the last pair
223 if (vec[i].v[0] != v1 || vec[i].v[1] != v2) {
224 // update last pair
225 v1 = vec[i].v[0];
226 v2 = vec[i].v[1];
227 v1->pushAdjVertex(v2); // set the pair as adjacent
228 v2->pushAdjVertex(v1);
229 }
230 }
231 }
232
233 if (!includeOnlyFaces) {
234 if constexpr (EdgeMeshConcept<MeshType>) {
235 using EdgeType = MeshType::EdgeType;
236
237 for (EdgeType& e : mesh.edges()) {
238 // set the pair as adjacent only if not already present
239 if (!e.vertex(0)->containsAdjVertex(e.vertex(1)))
240 e.vertex(0)->pushAdjVertex(e.vertex(1));
241 if (!e.vertex(1)->containsAdjVertex(e.vertex(0)))
242 e.vertex(1)->pushAdjVertex(e.vertex(0));
243 }
244 }
245 }
246}
247
259template<EdgeMeshConcept MeshType>
260void clearPerVertexAdjacentEdges(MeshType& mesh)
261{
262 clearPerElementAdjacentEdges<ElemId::VERTEX>(mesh);
263}
264
273template<EdgeMeshConcept MeshType>
274void updatePerVertexAdjacentEdges(MeshType& mesh)
275{
276 clearPerVertexAdjacentEdges(mesh);
277
278 using EdgeType = MeshType::EdgeType;
279
280 for (EdgeType& e : mesh.edges()) {
281 e.vertex(0)->pushAdjEdge(&e);
282 e.vertex(1)->pushAdjEdge(&e);
283 }
284}
285
298template<FaceMeshConcept MeshType>
299void clearPerFaceAdjacentFaces(MeshType& mesh)
300{
301 clearPerElementAdjacentFaces<ElemId::FACE>(mesh);
302}
303
345template<FaceMeshConcept MeshType>
346void updatePerFaceAdjacentFaces(MeshType& mesh)
347{
349
350 // vector that contains edges sorted trough unordered vertex pointers
351 // it contains clusters of "same" edges, but each one of them has its face
352 // pointer. note that in case on non-manifold mesh, clusters may be of size
353 // >= 2
354 std::vector<MeshEdgeUtil<MeshType>> vec =
355 fillAndSortMeshEdgeUtilVector(mesh);
356
357 if (vec.size() > 0) {
358 // in this loop, base will point to the first element of a cluster of
359 // edges
360 // increment of clusters into loop
361 for (auto base = vec.begin(); base != vec.end();) {
362 auto first = base; // remember the first to set adj to the last
363
364 // i and j will increment together, and if i == j, i will be adj to
365 // j, but j will not be adj to i (to manage non manifold edges and
366 // make cyclic adj on the same edge)
367 auto i = base;
368 auto j = i + 1;
369 if (j != vec.end()) {
370 // case of cluster composed of one element. adj of i is nullptr
371 if (*i != *j) {
372 i->f->setAdjFace(i->e, nullptr);
373 }
374 else { // at least two edges in the cluster
375 while (j != vec.end() && *i == *j) {
376 i->f->setAdjFace(i->e, j->f);
377 ++i;
378 ++j;
379 }
380 // i now is the last element that was equal to first
381 i->f->setAdjFace(i->e, first->f);
382 }
383 }
384
385 // j is the first different edge from first (or it is vec.end()!)
386 base = j;
387 }
388 }
389}
390
409template<FaceMeshConcept MeshType>
410void clearPerFaceAdjacentEdges(MeshType& mesh)
411 requires EdgeMeshConcept<MeshType>
412{
413 clearPerElementAdjacentEdges<ElemId::FACE>(mesh);
414}
415
435template<FaceMeshConcept MeshType>
436void updatePerFaceAdjacentEdges(MeshType& mesh)
437 requires EdgeMeshConcept<MeshType>
438{
439 using FaceType = MeshType::FaceType;
440
441 using AdjacentEdgesType = comp::ComponentTypeFromID<
442 CompId::ADJACENT_EDGES,
443 typename FaceType::Components>;
444
445 clearPerFaceAdjacentEdges(mesh);
446
447 // vector that contains edges sorted trough unordered vertex pointers
448 std::vector<MeshEdgeUtil<MeshType>> vec =
449 fillAndSortMeshEdgeUtilVector(mesh);
450
451 for (auto& e : mesh.edges()) {
452 MeshEdgeUtil<MeshType> meu(e.vertex(0), e.vertex(1));
453
454 // binary search for the edge in the sorted vector
455 auto it = std::lower_bound(vec.begin(), vec.end(), meu);
456
457 while (it != vec.end() && *it == meu) {
458 auto* f = it->f; // the face adjacent to the edge e
459 if constexpr (comp::IsTiedToVertexNumber<AdjacentEdgesType>) {
460 f->setAdjEdges(it->e, &e);
461 }
462 else {
463 f->pushAdjEdge(&e);
464 }
465 ++it;
466 }
467 }
468}
469
481template<EdgeMeshConcept MeshType>
482void clearPerEdgeAdjacentFaces(MeshType& mesh)
483 requires FaceMeshConcept<MeshType>
484{
485 clearPerElementAdjacentFaces<ElemId::EDGE>(mesh);
486}
487
499template<EdgeMeshConcept MeshType>
500void updatePerEdgeAdjacentFaces(MeshType& mesh)
501 requires FaceMeshConcept<MeshType>
502{
503 clearPerEdgeAdjacentFaces(mesh);
504
505 // vector that contains edges sorted trough unordered vertex pointers
506 std::vector<MeshEdgeUtil<MeshType>> vec =
507 fillAndSortMeshEdgeUtilVector(mesh);
508
509 for (auto& e : mesh.edges()) {
510 MeshEdgeUtil<MeshType> meu(e.vertex(0), e.vertex(1));
511
512 // binary search for the edge in the sorted vector
513 auto it = std::lower_bound(vec.begin(), vec.end(), meu);
514
515 while (it != vec.end() && *it == meu) {
516 auto* f = it->f; // the face adjacent to the edge e
517 e.pushAdjFace(f);
518 ++it;
519 }
520 }
521}
522
534template<EdgeMeshConcept MeshType>
535void clearPerEdgeAdjacentEdges(MeshType& mesh)
536{
537 clearPerElementAdjacentEdges<ElemId::EDGE>(mesh);
538}
539
547template<EdgeMeshConcept MeshType>
548void updatePerEdgeAdjacentEdges(MeshType& mesh)
549{
550 using EdgeType = MeshType::EdgeType;
551
552 // for each vertex, save the edges incident in it
553 std::vector<std::list<EdgeType*>> edgeMap(mesh.vertexContainerSize());
554
555 clearPerEdgeAdjacentEdges(mesh);
556
557 for (EdgeType& e : mesh.edges()) {
558 edgeMap[e.vertex(0)->index()].push_back(&e);
559 edgeMap[e.vertex(1)->index()].push_back(&e);
560 }
561
562 for (const std::list<EdgeType*>& edges : edgeMap) {
563 // all the edges in edges are adjacent to each other
564 for (auto it1 = edges.begin(); it1 != edges.end(); ++it1) {
565 for (auto it2 = std::next(it1); it2 != edges.end(); ++it2) {
566 (*it1)->pushAdjEdge(*it2);
567 (*it2)->pushAdjEdge(*it1);
568 }
569 }
570 }
571}
572
573} // namespace vcl
574
575#endif // VCL_ALGORITHMS_MESH_UPDATE_TOPOLOGY_H
void requirePerFaceAdjacentFaces(const MeshType &m)
This function asserts that a Mesh has a FaceContainer, the Face has a AdjacentFaces Component,...
Definition face_requirements.h:1037
constexpr detail::FacesView faces
A view that allows to iterate overt the Face elements of an object.
Definition face.h:84
constexpr detail::EdgesView edges
A view that allows to iterate overt the Edge elements of an object.
Definition edge.h:84
constexpr detail::VerticesView vertices
A view that allows to iterate over the Vertex elements of an object.
Definition vertex.h:92