Visual Computing Library  devel
Loading...
Searching...
No Matches
mesh_pos.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_SPACE_COMPLEX_MESH_POS_H
24#define VCL_SPACE_COMPLEX_MESH_POS_H
25
26#include <vclib/mesh.h>
27
28namespace vcl {
29
46template<face::HasAdjacentFaces FaceType>
48{
49 const FaceType* mFace = nullptr;
50
51 const typename FaceType::VertexType* mVertex = nullptr;
52
53 short mEdge = -1;
54
55public:
56 using VertexType = FaceType::VertexType;
57
61 MeshPos() = default;
62
63 MeshPos(const FaceType* f, short e) : mFace(f), mEdge(e)
64 {
65 if (f != nullptr)
66 mVertex = f->vertex(e);
67 assert(isValid(mFace, mVertex, mEdge));
68 }
69
70 MeshPos(const FaceType* f, const VertexType* v) : mFace(f), mVertex(v)
71 {
72 for (uint i = 0; i < f->vertexNumber(); i++)
73 if (f->vertex(i) == v)
74 mEdge = i;
75 assert(isValid(mFace, mVertex, mEdge));
76 }
77
88 MeshPos(const FaceType* f, const VertexType* v, short e) :
89 mFace(f), mVertex(v), mEdge(e)
90 {
91 assert(isValid(mFace, mVertex, mEdge));
92 }
93
107 static bool isValid(const FaceType* f, const VertexType* v, short e)
108 {
109 if (f == nullptr || v == nullptr || e < 0)
110 return false;
111 if (!comp::isAdjacentFacesAvailableOn(*f))
112 return false;
113 return (ushort) e < f->vertexNumber() &&
114 (v == f->vertex(e) || v == f->vertexMod(e + 1));
115 }
116
117 const FaceType* face() const { return mFace; }
118
119 const VertexType* vertex() const { return mVertex; }
120
121 short edge() const { return mEdge; }
122
123 const FaceType* adjFace() const { return mFace->adjFace(mEdge); }
124
125 const VertexType* adjVertex() const
126 {
127 MeshPos<FaceType> tmpPos = *this;
128 tmpPos.flipVertex();
129 return tmpPos.vertex();
130 }
131
132 short adjEdge() const
133 {
134 MeshPos<FaceType> tmpPos = *this;
135 tmpPos.flipEdge();
136 return tmpPos.edge();
137 }
138
143 bool isValid() const { return isValid(mFace, mVertex, mEdge); }
144
150 bool isNull() const
151 {
152 return mFace == nullptr || mVertex == nullptr || mEdge < 0;
153 }
154
162 bool isEdgeOnBorder() const { return mFace->adjFace(mEdge) == nullptr; }
163
172 bool isCCWOriented() const { return mFace->vertex(mEdge) == mVertex; }
173
185 bool flipFace()
186 {
187 const FaceType* nf = mFace->adjFace(mEdge);
188 if (nf != nullptr) {
189 short oldEdge = mEdge;
190 mEdge = nf->indexOfAdjFace(mFace);
191 if (mEdge < 0) {
192 // non-manifold edge. I need to find the edge that has the
193 // current vertex
194 const auto* v0 = mFace->vertex(oldEdge);
195 const auto* v1 = mFace->vertexMod(oldEdge + 1);
196 mEdge = nf->indexOfEdge(v0, v1);
197 // if this assert fails, it means that the edge was not found.
198 // you probably need to update adjacency information of the mesh
199 assert(mEdge >= 0 && mEdge < nf->vertexNumber());
200 if (mEdge < 0) {
201 *this = MeshPos<FaceType>(); // reset to null
202 return false;
203 }
204 }
205 mFace = nf;
206 return true;
207 }
208 else {
209 return false;
210 }
211 }
212
218 {
219 if (mFace->vertexMod(mEdge) == mVertex) {
220 mVertex = mFace->vertexMod(mEdge + 1);
221 }
222 else {
223 mVertex = mFace->vertexMod(mEdge);
224 }
225 }
226
231 void flipEdge()
232 {
233 if (mFace->vertexMod(mEdge + 1) == mVertex) {
234 mEdge = (mEdge + 1) % (short) mFace->vertexNumber();
235 }
236 else {
237 short n = mFace->vertexNumber();
238 mEdge = ((mEdge - 1) % n + n) %
239 n; // be sure to get the right index of the previous edge
240 }
241 }
242
255 {
256 flipEdge();
257 flipFace();
258 }
259
269 {
271 do {
273 } while (*this != startPos && !isEdgeOnBorder());
274 return (*this != startPos);
275 }
276
286 {
287 bool onBorder = false;
288 uint count = countAdjacentFacesToV(onBorder);
289 // if we visited a border, it means that we visited the all faces
290 // adjacent to v twice to reach the same starting MeshPos.
291 if (onBorder)
292 count /= 2;
293 return count;
294 }
295
296 bool operator==(const MeshPos& op) const
297 {
298 return mFace == op.mFace && mVertex == op.mVertex && mEdge == op.mEdge;
299 }
300
301 bool operator!=(const MeshPos& op) const { return !(*this == op); }
302
303 bool operator<(const MeshPos& op) const
304 {
305 if (mFace == op.mFace) {
306 if (mEdge == op.mEdge)
307 return mVertex < op.mVertex;
308 else
309 return mEdge < op.mEdge;
310 }
311 else {
312 return mFace < op.mFace;
313 }
314 }
315
316private:
317 uint countAdjacentFacesToV(bool& onBorder) const
318 {
319 uint count = 0;
320 onBorder = false;
321 // start from this MeshPos
322 MeshPos<FaceType> mp = *this;
323 do {
324 // go to the next edge in the star of v (if face is on border, will
325 // change just edge)
326 mp.nextEdgeAdjacentToV();
327 ++count;
328 // if we are visiting a border, it means that we will start to
329 // navigate in the opposite sense as we were before.
330 if (mp.isEdgeOnBorder()) // flag that we visited a border
331 onBorder = true;
332 }
333 // we end when we will reach the same pos (same triplet f-v-e) of start
334 while (mp != *this);
335 return count;
336 }
337};
338
339} // namespace vcl
340
341#endif // VCL_SPACE_COMPLEX_MESH_POS_H
A class representing a box in N-dimensional space.
Definition box.h:46
The MeshPos class describes a "Position in a Mesh" that can be identified with a triplet of Face-Vert...
Definition mesh_pos.h:48
uint numberOfAdjacentFacesToV() const
Returns the number of adjacent faces to the current vertex of this MeshPos. This works also for verti...
Definition mesh_pos.h:285
MeshPos()=default
Empty constructor that creates a null (invalid) MeshPos.
bool isEdgeOnBorder() const
Returns true if the current edge of this MeshPos is on a border. To check if is on border,...
Definition mesh_pos.h:162
void flipVertex()
Moves this MeshPos to the vertex adjacent to the current vertex that shares the same face and the sam...
Definition mesh_pos.h:217
bool isCCWOriented() const
Returns true if the current vertex of the MeshPos corresponts to the first vertex of the current edge...
Definition mesh_pos.h:172
MeshPos(const FaceType *f, const VertexType *v, short e)
Constructor that creates a MeshPos with the given facem vertex and edge. The given triplet must descr...
Definition mesh_pos.h:88
static bool isValid(const FaceType *f, const VertexType *v, short e)
Helper function to check if a MeshPos is valid, that is if:
Definition mesh_pos.h:107
bool nextEdgeOnBorderAdjacentToV()
Moves the MeshPos to the next edge on border that is adjacent to the current vertex of the MeshPos....
Definition mesh_pos.h:268
bool flipFace()
Moves this MeshPos to the face adjacent to the current face that shares the same vertex and the same ...
Definition mesh_pos.h:185
bool isNull() const
Returns true if this is null, non initialized, MeshPos. The result of this function is different from...
Definition mesh_pos.h:150
void nextEdgeAdjacentToV()
Moves this MeshPos to the next edge that is adjacent to the current vertex of the MeshPos....
Definition mesh_pos.h:254
void flipEdge()
Moves this MeshPos to the edge adjacent to the current edge that shares the same face and the same ve...
Definition mesh_pos.h:231
bool isValid() const
Returns true if this MeshPos is valid.
Definition mesh_pos.h:143