$darkmode
VCG Library
Allocating and Deleting mesh elements

Creating elements

To create a simple single triangle mesh or to add elements to an existing mesh you should use the AddVertices and AddFaces functions, elements are added at the end of the mesh. These functions returns a pointer to the first allocated element.

Adding element to a vector can cause reallocation, and therefore invalidation of any pointer that points to the mesh elements. These fucntion manage safely re-allocation and updating of pointers for all the pointers stored internally in the mesh (e.g. if you add some vertices and that causes a reallocation of the vertex vector, the pointers from faces to vertices will be automatically updated by the Allocator functions. You should never directly reallocate or resize the vertex or face vectors.

class MyMesh : public vcg::tri::TriMesh< std::vector<MyVertex>, std::vector<MyFace> > {};
int main()
{
MyMesh m;
MyMesh::VertexIterator vi = vcg::tri::Allocator<MyMesh>::AddVertices(m,3);
MyMesh::FaceIterator fi = vcg::tri::Allocator<MyMesh>::AddFaces(m,1);
MyMesh::VertexPointer ivp[4];
ivp[0]=&*vi; vi->P()=MyMesh::CoordType ( 0.0, 0.0, 0.0); ++vi;
ivp[1]=&*vi; vi->P()=MyMesh::CoordType ( 1.0, 0.0, 0.0); ++vi;
ivp[2]=&*vi; vi->P()=MyMesh::CoordType ( 0.0, 1.0, 0.0); ++vi;
fi->V(0)=ivp[0];
fi->V(1)=ivp[1];
fi->V(2)=ivp[2];
static VertexIterator AddVertices(MeshType &m, size_t n, PointerUpdater< VertexPointer > &pu)
Add n vertices to the mesh. Function to add n vertices to the mesh. The elements are added always to ...
Definition: allocate.h:189
static FaceIterator AddFaces(MeshType &m, size_t n)
Function to add n faces to the mesh. First wrapper, with no parameters.
Definition: allocate.h:615

look to platonic.h for more examples.

Alternatively you can add single vertex and faces in a more compact way as follows:

// Alternative, more compact, method for adding a single face (once you have the vertex pointers)
vcg::tri::Allocator<MyMesh>::AddFace(m, ivp[1],ivp[0],ivp[2]);
static FaceIterator AddFace(MeshType &m, VertexPointer v0, VertexPointer v1, VertexPointer v2)
Definition: allocate.h:539

If you keep internally some pointers to the mesh elements adding elements can invalidate them. In that case you should pass to the vcg::tri::Allocator functions a PointerUpdater to be used to update your private pointers.

// a potentially dangerous pointer to a mesh element
MyMesh::FacePointer fp = &m.face[0];
// now the fp pointer could be no more valid due to eventual re-allocation of the m.face vector.
// check if an update of the pointer is needed and do it.
if(pu.NeedUpdate()) pu.Update(fp);
Accessory class to update pointers after eventual reallocation caused by adding elements.
Definition: allocate.h:145

Destroying Elements

The library adopts a Lazy Deletion Strategy i.e. the elements in the vector that are deleted are only flagged as deleted, but they are still there.

Note that the basic deletion functions are very low level ones. 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 could 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. Again you should never, ever try to delete vertexes by yourself by directly flagging deleted, but you must call the Allocator utility function. The following snippet of code shows how to delete a few faces from an icosahedron.

// Now fill the mesh with an Icosahedron and then delete some faces
vcg::tri::Icosahedron(m);
static void DeleteFace(MeshType &m, FaceType &f)
Definition: allocate.h:923

After such a deletion the vector of the faces still contains 20 elements (number of faces of an icosahedron) but the m.FN() function correctly reports 18 faces. Therefore if your algorithm performs deletions it happens that the size of a container could be different from the number of valid element of your meshes:

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:

// If you loop in a mesh with deleted elements you have to skip them!
MyMesh::CoordType b(0,0,0);
for(fi = m.face.begin(); fi!=m.face.end(); ++fi )
{
if(!fi->IsD()) // <---- Check added
{
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:

static void CompactFaceVector(MeshType &m, PointerUpdater< FacePointer > &pu)
Compact face vector by removing deleted elements.
Definition: allocate.h:1231
static void CompactVertexVector(MeshType &m, PointerUpdater< VertexPointer > &pu)
Compact vector of vertices removing deleted elements. Deleted elements are put to the end of the vect...
Definition: allocate.h:1084

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
If there are no deleted elements in your mesh, the compactor functions returns immediately (it just test that the container size match the number of the elements) so it is safe to call it before lenghty operations.
If you are messing around with deleted elements it is rather dangerous to loop over mesh elements using FN() or VN() as end guards in the for; the following code snipped is WRONG:
// WRONG WAY of iterating: if there are deleted elements FN() != m.face.size()
// so in that case you will not scan the whole vector.
for(int i=0;i<m.FN();++i)
{
if(!m.face[i].IsD())
{
b += vcg::Barycenter(m.face[i]);
}
}

How to copy a mesh

Given the intricate nature of the mesh itself it is severely forbidden any attempt of copying meshes as simple object. To copy a mesh you have to use the Append utility class:

MyMesh m2;
static void MeshCopy(MeshLeft &ml, ConstMeshRight &mr, bool selected=false, const bool adjFlag=false)
Copy the second mesh over the first one. The first mesh is destroyed. If requested only the selected ...
Definition: append.h:601

In the vcg::tri::Append utility class there are also functions for copying only a subset of the second mesh (the selected one) or to append the second mesh to the first one.