the mesh is stored in a object m of type MyMesh
Accessing the coords of all the vertexes
MyMesh::VertexIterator vi; for(vi = m.vert.begin(); vi!=m.vert.end(); ++vi ) { DoSomething((*vi).P()); }
Accessing all the faces and computing their barycenter
MyMesh::FaceIterator vi; for(fi = m.face.begin(); vi!=m.face.end(); ++fi ) { MyMesh::CoordType b = ((*fi).V(0)->P() + (*fi).V(1)->P() + (*fi).V(2)->P() ) / 3.0; }
or using a common shorthand for accessing to the coord of a face vertex:
MyMesh::FaceIterator vi; for(fi = m.face.begin(); vi!=m.face.end(); ++fi ) { MyMesh::CoordType b = ((*fi).P(0) + (*fi).P(1) + (*fi).P(2) ) / 3.0; }
Or even in a shorter way:
MyMesh::FaceIterator vi; for(fi = m.face.begin(); vi!=m.face.end(); ++fi ) { MyMesh::CoordType b = vcg::Barycenter(*fi); }
Creating the simplest single triangle mesh.
m.Clear(); Allocator<MyMesh>::AddVertices(m,3); Allocator<MyMesh>::AddFaces(m,1); MyMesh::VertexPointer ivp[3]; VertexIterator vi=in.vert.begin(); ivp[0]=&*vi;(*vi).P()=CoordType ( 1.0, 1.0, 1.0); ++vi; ivp[1]=&*vi;(*vi).P()=CoordType (-1.0, 1.0,-1.0); ++vi; ivp[2]=&*vi;(*vi).P()=CoordType (-1.0,-1.0, 1.0); ++vi; FaceIterator fi=in.face.begin(); (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[2];
look to complex/trimesh/create/platonic.hplatonic.h for more examples.
Destroying Elements
Lazy deletion strategy.
Note that the two basic deletion strategies are very low level functions. They simply mark as deleted the corresponding entries without affecting the rest of the structures. So for example if you delete a vertex with these structures without checking that all the faces incident on it have been removed you create a non consistent situation...
Similarly, but less dangerously, when you delete a face its vertices are left around so at the end you can have unreferenced floating vertices.
Allocator<MyMesh>::DeleteVertex(m,v); Allocator<MyMesh>::DeleteFace(m,v);
If your algorithm performs deletion the size of a container could be different from the number of valid element of your meshes (e.g.:
m.vert.size() != m.vn m.face.size() != m.fn
Therefore when you scan the containers of vertices and faces you could encounter deleted elements so you should take care with a simple !IsD() check:
MyMesh::FaceIterator vi; for(fi = m.face.begin(); vi!=m.face.end(); ++fi ) if(!(*fi).IsD()) // <---- Check added { MyMesh::CoordType b = vcg::Barycenter(*fi); }
In some situations, particularly when you have to loop many many times over the element of the mesh without deleting/creating anything, it can be practical and convenient to get rid of deleted elements by explicitly calling the two garbage collecting functions:
Allocator<MyMesh>::CompactVertexVector(m); Allocator<MyMesh>::CompactFaceVector(m);
After calling these function it is safe to not check the IsD() state of every element and always holds that:
m.vert.size() == m.vn m.face.size() == m.fn
Note that if there are no deleted elements in your mesh, the compactor functions returns immediately.
Adjacency relations
VCG meshes DO NOT store edges, only vertex and triangles. Even the basic adjacdncy relations has to be explicitly computed. We always try to do not store per-edge information and keep them only more or less implicitly. This is simply there are many algorithms that do not require it and the cost of updating/storing should be avoided when possible. In many cases algorithms that seems based on some kind
Counting border edges (without topology)
Typical example are border flags. Each face keep a bit for each of its sides saying if that face has a boundary on that side or not. This information can be accessed by mean of the IsB(i) function. To compute the border flags there are various algorithm according to the available topological informations.
Allocator<MyMesh>::CompactFaceVector(m); UpdateFlags<MyMesh>::FaceBorderFromNone(m); int BorderEdgeCounter=0; MyMesh::FaceIterator fi; for(fi = m.face.begin(); fi!=m.face.end(); ++fi ) { for(int i=0;i<3;++i) if((*fi).IsB(i)) BorderEdgeCounter++; }
Counting border edge (using FF adjacency)
When your mesh as Face-Face adjacency the FFp(i) member store the pointer of the face that is adjacent to the current face along the i-th edg
int BorderEdgeCounter=0; MyMesh::FaceIterator fi; for(fi = m.face.begin(); fi!=m.face.end(); ++fi ) { for(int i=0;i<3;++i) if((*fi).FFp(i) == &*fi) BorderEdgeCounter++; }
or alternatively using the same flag based approach as above
UpdateFlags<MyMesh>::FaceBorderFromFFAdjacency(m); int BorderEdgeCounter=0; MyMesh::FaceIterator fi; for(fi = m.face.begin(); fi!=m.face.end(); ++fi ) { for(int i=0;i<3;++i) if((*fi).IsB(i)) BorderEdgeCounter++; }
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
Ref.
http://meshlab.sourceforge.net/wiki/index.php/Accessing_the_mesh
No comments:
Post a Comment