Improved adjacency documentation

This commit is contained in:
Paolo Cignoni 2017-02-22 08:51:47 +01:00
parent e8a1c89d1b
commit a19ad21cbb
1 changed files with 37 additions and 23 deletions

View File

@ -1,52 +1,64 @@
/** \page adjacency
Adjacency
=========
VCG Lib does not have a hard-coded way to encode the adjacencies among simplices. It all depends on which attributes are stored with the simplices and how they are used. I the previous examples the definition of face has always included the attribute vcg::face::VertexRef , which stores 3 pointers to MyVertex accessible with the member function V() (the well known Indexed Data Structure). The reason is that almost all of the algorithms currently implemented in VCG Lib assume its presence. So, if your type MyFace does not include the attribute vcg::face::VertexRef, the definition will be correct but almost no algorithm will work..
VCG Lib does not have a unique, hard-coded, way to encode the adjacencies among triangles and edges.
It all depends on which attributes are stored with the simplices and how they are used.
In the previous examples the definition of face has always included the attribute vcg::face::VertexRef,
which stores 3 pointers to MyVertex accessible with the member function V() (implementing a plain Indexed Data Structure).
Almost all of the algorithms currently implemented in vcglib assume that vcg::face::VertexRef is present.
So, if your type MyFace does not include the attribute vcg::face::VertexRef, the definition will be correct,
but almost no algorithm will work.
There are other adjacency relations that can be useful to navigate a mesh, for example to collect the one-ring neighborhood of a vertex. VCG Lib uses two mechanisms which are explained in the following, along with the attributes they use.
There are other adjacency relations that can be useful to navigate a mesh,
for example to collect the one-ring neighborhood of a vertex. vcgib has two main adjacency relations face-face and vertex-face
which are explained in the following, along with the attributes they use.
FF Adjacency
============
The face-to-face adjacency, stored in the attribute for the faces vcg::face::FFAdj ( vcg::face::TTAdj for tetrahedra), encodes the adjacency of faces (tetrahedra) through edges (faces). The image below shows two triangle faces with the convention adopted for indexing vertexes and edges.
The face-to-face adjacency, stored in the attribute for the faces vcg::face::FFAdj ,
encodes the adjacency between faces through edges.
The image below shows two triangle faces with the convention adopted for indexing vertexes and edges.
The vertexes are numbered from 0 to 2 in CCW sense and the edge i = 0..2 is the edge whose extremes are i and (i+1) mod 3 . Therefore the common edge between faces f1 and f2 is the edge 1 of the face f1 and the edge 0 of the face f0.
The vertexes are numbered from 0 to 2 in CCW direction and the edge i = 0..2 is the edge
whose extremes are i and (i+1) mod 3. Therefor, in the below example, the common edge between faces f0 and f1
is the edge 1 of the face f1 and the edge 0 of the face f0.
vcg::face::FFAdj stores, for each edge e of the face f:
vcg::face::FFAdj stores, for the i-th edge of the face f:
FFp(e): a pointer to a face f' sharing e. If e is a border than points to the face f itself
FFi(e):the index of e in the pointed face
- `FFp(i)`: a pointer to the face sharing the i-th edge of f. If that edge is a border than points to the face f itself
- `FFi(i)`: the index of edge that corresponds to i-th edge of f in the pointed face
\image html "FF_Adj.png" "Indexing of vertexes and edges"
So for the above example, assuming that `f0` and `f1` are the two pointers to faces, the following relations hold:
f1->FFp(1) == f0
f1->FFi(1) == 0
f0->FFp(0) == f1
f0->FFi(0) == 1
Note that we specified that FFp(e) point to a adjacent face, not to the adjacent face. The reason is that there could be more than two faces on the same edge, and this is seamlessly supported by VCG Lib. In the picture below is shown an example with 4 faces incident to the same edge
Note that to be precise we should say that `FFp(i)` points to **a** adjacent face, not to **the** adjacent face.
The reason is that, in case of non-manifoldness, there could be more than two faces on the same edge, and this
is seamlessly supported by VCG Lib. In the picture below is shown an example with 4 faces incident to the same edge.
\image html "FF_nonmanifold.png" "Non manifold edge"
In this case the adjacencies are set to form a circular list (not necessarily sorted with the angle around the edge). This is done by the VCG Lib function that update these values (UpdateTopology<MeshType>::FFTopology(MeshType & m)).
In this case the FF adjacencies are arranged to form a circular list (not necessarily sorted with the angle around the edge).
This is done by the VCG Lib function that update these values ( vcg::tri::UpdateTopology::FaceFace (MeshType & m)).
In this way VCG Lib provides a way to check if a mesh is manifold on a specific edge because the FF adjacency relation is mutual, i.e. the face f0 points to the face f1 which points to the face f0, if and only if the mesh is manifold over the corresponding edge.
bool IsManifold(MyFace *f,int e) { return (f0 == f0->FFp(0)->FFp(f0->FFi(0)))}
Referring to the picture:
(f0 == f0->FFp(0)->FFp(f0->FFi(0))} equals
(f0 == f1->FFp(0)} equals
(f0 == f0} Ok! It is manifold
bool IsManifold(MyFace *f,int e) { return (f0 == f0->FFp(0)->FFp(f0->FFi(0)))}
Pos
---
The Pos is the VCG Lib implementation of the Cell-Tuple{ref}. Here we give a as short as possible definition, trading formalisms for space. A Pos in a triangle mesh is a triple made of a vertex: pos = (v,e,f) , such that v is an extreme of e and e belong to the face f . The figure shows few pos in a triangle mesh as small triangles "pointing" to a vertex, "leaning" against an edge and inside a face. For example c0=(v,e0,f).
The Pos is the VCG Lib implementation of the Cell-Tuple{ref}. Here we give a as short as possible definition,
trading formalisms for space. A Pos in a triangle mesh is a triple made of a vertex: pos = (v,e,f) ,
such that v is an extreme of e and e belong to the face f . The figure shows few pos in a triangle mesh as small triangles
"pointing" to a vertex, "leaning" against an edge and inside a face. For example c0=(v,e0,f).
A very nice property is that given a pos c, there is only another neighbor pos c' that can be obtained from c changing only one of the elements of the triple.
@ -132,12 +144,14 @@ VF Adjacency
VCG Lib implements vertex-to-face adjacency, i.e. given a vertex v we can retrieve all the faces incident to v.
Let v_star =(f0,f1,f2,...,fk) be the set faces incident to v arranged in a sequence (with no preferred criteria).
VCG Lib allows to retrieve v_star in optimal time ( O( star_v) ) by using the following attibutes:
VCG Lib allows to retrieve v_star in optimal time ( O( star_v) ) by using the following attributes:
vcg::vertex::VFAdj which is a vertex attribute containing a pointer to f0
vcg::face::VFAdj which is a face attribute containing a pointer to the next face in the list v_star for each of its 3 vertices (4 in the case of tetrahedra)
These two attributes are not only a pointers, they also contain an index referring the index of the vertex in the pointed face in the same style as the vcg::face::FFAdj does. The picture below shows a complete example:
- vcg::vertex::VFAdj which is a vertex attribute containing a pointer to f0
- vcg::face::VFAdj which is a face attribute containing a pointer to the next face in the list v_star for each of its 3 vertices
These two attributes are not only a pointers, they also contain an index referring the index of the vertex in the pointed face
in the same style as the vcg::face::FFAdj does. The picture below shows a practical example:
Similarly to the *Face-Face* adjacency you need to initialize it using vcg::tri::UpdateTopology::VertexFace(MeshType & m).
\image html "VertexStar.png" "Example of vertex-face adjacency"
v.VFp() == f2