Corrected the behavoiour of the allocate::Compact when managing uninitialized and null element in adjacency

This commit is contained in:
Paolo Cignoni 2013-03-13 14:33:09 +00:00
parent 4665f36e40
commit f62e07ee66
1 changed files with 341 additions and 338 deletions

View File

@ -74,8 +74,8 @@ namespace tri {
It also provide an accessory class vcg::tri::PointerUpdater for updating pointers to mesh elements that are kept by the user. It also provide an accessory class vcg::tri::PointerUpdater for updating pointers to mesh elements that are kept by the user.
*/ */
template <class MeshType> template <class MeshType>
class Allocator class Allocator
{ {
public: public:
typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexType VertexType;
@ -118,31 +118,31 @@ namespace tri {
{ {
public: public:
PointerUpdater(void) : newBase(0), oldBase(0), newEnd(0), oldEnd(0), preventUpdateFlag(false) { ; } PointerUpdater(void) : newBase(0), oldBase(0), newEnd(0), oldEnd(0), preventUpdateFlag(false) { ; }
void Clear(){newBase=oldBase=newEnd=oldEnd=0;} void Clear(){newBase=oldBase=newEnd=oldEnd=0;}
/*! \brief Update a pointer to an element of a mesh after a reallocation /*! \brief Update a pointer to an element of a mesh after a reallocation
The updating is correctly done only if this PointerUpdater have been passed to the corresponing allocation call. \sa \ref allocation The updating is correctly done only if this PointerUpdater have been passed to the corresponing allocation call. \sa \ref allocation
*/ */
void Update(SimplexPointerType &vp) void Update(SimplexPointerType &vp)
{ {
//if(vp>=newBase && vp<newEnd) return; //if(vp>=newBase && vp<newEnd) return;
if(vp<oldBase || vp>oldEnd) return; if(vp<oldBase || vp>oldEnd) return;
assert(vp>=oldBase); assert(vp>=oldBase);
assert(vp<oldEnd); assert(vp<oldEnd);
vp=newBase+(vp-oldBase); vp=newBase+(vp-oldBase);
if(!remap.empty()) if(!remap.empty())
vp = newBase + remap[vp-newBase]; vp = newBase + remap[vp-newBase];
} }
/*! /*!
\brief return true if the allocation operation that initialized this PointerUpdater has caused a reallocation \brief return true if the allocation operation that initialized this PointerUpdater has caused a reallocation
*/ */
bool NeedUpdate() {if((oldBase && newBase!=oldBase && !preventUpdateFlag) || !remap.empty()) return true; else return false;} bool NeedUpdate() {if((oldBase && newBase!=oldBase && !preventUpdateFlag) || !remap.empty()) return true; else return false;}
SimplexPointerType newBase; SimplexPointerType newBase;
SimplexPointerType oldBase; SimplexPointerType oldBase;
SimplexPointerType newEnd; SimplexPointerType newEnd;
SimplexPointerType oldEnd; SimplexPointerType oldEnd;
std::vector<size_t> remap; std::vector<size_t> remap; // this vector keep the new position of an element. Uninitialized elements have max_int value to denote an element that has not to be remapped.
bool preventUpdateFlag; /// when true no update is considered necessary. bool preventUpdateFlag; /// when true no update is considered necessary.
}; };
@ -225,11 +225,11 @@ namespace tri {
PointerUpdater<VertexPointer> pu; PointerUpdater<VertexPointer> pu;
VertexIterator v_ret = AddVertices(m, n,pu); VertexIterator v_ret = AddVertices(m, n,pu);
typename std::vector<VertexPointer *>::iterator vi; typename std::vector<VertexPointer *>::iterator vi;
for(vi=local_vec.begin();vi!=local_vec.end();++vi) for(vi=local_vec.begin();vi!=local_vec.end();++vi)
pu.Update(**vi); pu.Update(**vi);
return v_ret; return v_ret;
} }
/* ++++++++++ edges +++++++++++++ */ /* ++++++++++ edges +++++++++++++ */
/** \brief Add n edges to the mesh. /** \brief Add n edges to the mesh.
@ -242,15 +242,15 @@ namespace tri {
\retval the iterator to the first element added. \retval the iterator to the first element added.
*/ */
static EdgeIterator AddEdges(MeshType &m,int n, PointerUpdater<EdgePointer> &pu) static EdgeIterator AddEdges(MeshType &m,int n, PointerUpdater<EdgePointer> &pu)
{ {
EdgeIterator last; EdgeIterator last;
if(n == 0) return m.edge.end(); if(n == 0) return m.edge.end();
pu.Clear(); pu.Clear();
if(m.edge.empty()) pu.oldBase=0; // if the vector is empty we cannot find the last valid element if(m.edge.empty()) pu.oldBase=0; // if the vector is empty we cannot find the last valid element
else { else {
pu.oldBase=&*m.edge.begin(); pu.oldBase=&*m.edge.begin();
pu.oldEnd=&m.edge.back()+1; pu.oldEnd=&m.edge.back()+1;
} }
m.edge.resize(m.edge.size()+n); m.edge.resize(m.edge.size()+n);
m.en+=n; m.en+=n;
@ -261,21 +261,21 @@ namespace tri {
pu.newBase = &*m.edge.begin(); pu.newBase = &*m.edge.begin();
pu.newEnd = &m.edge.back()+1; pu.newEnd = &m.edge.back()+1;
if(pu.NeedUpdate()) if(pu.NeedUpdate())
{ {
FaceIterator fi; FaceIterator fi;
for (fi=m.face.begin(); fi!=m.face.end(); ++fi){ for (fi=m.face.begin(); fi!=m.face.end(); ++fi){
//if(HasFHEAdjacency(m)) //if(HasFHEAdjacency(m))
// pu.Update((*fi).FHEp()); // pu.Update((*fi).FHEp());
if(!(*fi).IsD()) if(!(*fi).IsD())
for(int i=0; i < (*fi).VN(); ++i) for(int i=0; i < (*fi).VN(); ++i)
if ((*fi).cFEp(i)!=0) pu.Update((*fi).FEp(i)); if ((*fi).cFEp(i)!=0) pu.Update((*fi).FEp(i));
} }
VertexIterator vi; VertexIterator vi;
if(HasVEAdjacency(m)) if(HasVEAdjacency(m))
for (vi=m.vert.begin(); vi!=m.vert.end(); ++vi) for (vi=m.vert.begin(); vi!=m.vert.end(); ++vi)
if(!(*vi).IsD()) if(!(*vi).IsD())
if ((*vi).cVEp()!=0) pu.Update((*vi).VEp()); if ((*vi).cVEp()!=0) pu.Update((*vi).VEp());
HEdgeIterator hi; HEdgeIterator hi;
@ -312,33 +312,33 @@ namespace tri {
PointerUpdater<EdgePointer> pu; PointerUpdater<EdgePointer> pu;
EdgeIterator v_ret = AddEdges(m, n,pu); EdgeIterator v_ret = AddEdges(m, n,pu);
typename std::vector<EdgePointer *>::iterator ei; typename std::vector<EdgePointer *>::iterator ei;
for(ei=local_vec.begin();ei!=local_vec.end();++ei) for(ei=local_vec.begin();ei!=local_vec.end();++ei)
pu.Update(**ei); pu.Update(**ei);
return v_ret; return v_ret;
} }
/* ++++++++++ hedges +++++++++++++ */ /* ++++++++++ hedges +++++++++++++ */
/** Function to add n halfedges to the mesh. The second parameter hold a vector of /** Function to add n halfedges to the mesh. The second parameter hold a vector of
pointers to pointer to elements of the mesh that should be updated after a pointers to pointer to elements of the mesh that should be updated after a
possible vector realloc. possible vector realloc.
\sa PointerUpdater \sa PointerUpdater
\param m the mesh to be modified \param m the mesh to be modified
\param n the number of elements to be added \param n the number of elements to be added
\param pu a PointerUpdater initialized so that it can be used to update pointers to edges that could have become invalid after this adding. \param pu a PointerUpdater initialized so that it can be used to update pointers to edges that could have become invalid after this adding.
\retval the iterator to the first element added. \retval the iterator to the first element added.
*/ */
static HEdgeIterator AddHEdges(MeshType &m,int n, PointerUpdater<HEdgePointer> &pu) static HEdgeIterator AddHEdges(MeshType &m,int n, PointerUpdater<HEdgePointer> &pu)
{ {
HEdgeIterator last; HEdgeIterator last;
if(n == 0) return m.hedge.end(); if(n == 0) return m.hedge.end();
pu.Clear(); pu.Clear();
if(m.hedge.empty()) pu.oldBase=0; // if the vector is empty we cannot find the last valid element if(m.hedge.empty()) pu.oldBase=0; // if the vector is empty we cannot find the last valid element
else { else {
pu.oldBase=&*m.hedge.begin(); pu.oldBase=&*m.hedge.begin();
pu.oldEnd=&m.hedge.back()+1; pu.oldEnd=&m.hedge.back()+1;
} }
m.hedge.resize(m.hedge.size()+n); m.hedge.resize(m.hedge.size()+n);
m.hn+=n; m.hn+=n;
@ -354,7 +354,7 @@ namespace tri {
{ {
if(HasFHAdjacency(m)) if(HasFHAdjacency(m))
if(!(*fi).IsD() && (*fi).FHp()) if(!(*fi).IsD() && (*fi).FHp())
pu.Update((*fi).FHp()); pu.Update((*fi).FHp());
} }
{ {
@ -390,7 +390,7 @@ namespace tri {
++hi; ++hi;
} }
} }
} }
unsigned int siz = (unsigned int)m.hedge.size()-n; unsigned int siz = (unsigned int)m.hedge.size()-n;
last = m.hedge.begin(); last = m.hedge.begin();
@ -432,7 +432,7 @@ namespace tri {
return AddFaces(m,n,pu); return AddFaces(m,n,pu);
} }
/** Function to add n faces to the mesh. /** Function to add n faces to the mesh.
Second Wrapper, with a vector of face pointer to be updated. Second Wrapper, with a vector of face pointer to be updated.
*/ */
static FaceIterator AddFaces(MeshType &m, int n,std::vector<FacePointer *> &local_vec) static FaceIterator AddFaces(MeshType &m, int n,std::vector<FacePointer *> &local_vec)
@ -440,28 +440,28 @@ namespace tri {
PointerUpdater<FacePointer> pu; PointerUpdater<FacePointer> pu;
FaceIterator f_ret= AddFaces(m,n,pu); FaceIterator f_ret= AddFaces(m,n,pu);
typename std::vector<FacePointer *>::iterator fi; typename std::vector<FacePointer *>::iterator fi;
for(fi=local_vec.begin();fi!=local_vec.end();++fi) for(fi=local_vec.begin();fi!=local_vec.end();++fi)
pu.Update(**fi); pu.Update(**fi);
return f_ret; return f_ret;
} }
/** Function to add n faces to the mesh. /** Function to add n faces to the mesh.
This is the only full featured function that is able to manage correctly all the internal pointers of the mesh (ff and vf relations). This is the only full featured function that is able to manage correctly all the internal pointers of the mesh (ff and vf relations).
NOTE: THIS FUNCTION ALSO UPDATE FN NOTE: THIS FUNCTION ALSO UPDATE FN
*/ */
static FaceIterator AddFaces(MeshType &m, int n, PointerUpdater<FacePointer> &pu) static FaceIterator AddFaces(MeshType &m, int n, PointerUpdater<FacePointer> &pu)
{ {
FaceIterator last, fi; FaceIterator last, fi;
if(n == 0) return m.face.end(); if(n == 0) return m.face.end();
pu.Clear(); pu.Clear();
if(m.face.empty()) { if(m.face.empty()) {
pu.oldBase=0; // if the vector is empty we cannot find the last valid element pu.oldBase=0; // if the vector is empty we cannot find the last valid element
} else { } else {
pu.oldBase=&*m.face.begin(); pu.oldBase=&*m.face.begin();
pu.oldEnd=&m.face.back()+1; pu.oldEnd=&m.face.back()+1;
last=m.face.end(); last=m.face.end();
} }
m.face.resize(m.face.size()+n); m.face.resize(m.face.size()+n);
m.fn+=n; m.fn+=n;
@ -543,7 +543,7 @@ namespace tri {
*/ */
static void DeleteFace(MeshType &m, FaceType &f) static void DeleteFace(MeshType &m, FaceType &f)
{ {
assert(&f >= &m.face.front() && &f <= &m.face.back()); assert(&f >= &m.face.front() && &f <= &m.face.back());
assert(!f.IsD()); assert(!f.IsD());
f.SetD(); f.SetD();
--m.fn; --m.fn;
@ -554,7 +554,7 @@ namespace tri {
*/ */
static void DeleteVertex(MeshType &m, VertexType &v) static void DeleteVertex(MeshType &m, VertexType &v)
{ {
assert(&v >= &m.vert.front() && &v <= &m.vert.back()); assert(&v >= &m.vert.front() && &v <= &m.vert.back());
assert(!v.IsD()); assert(!v.IsD());
v.SetD(); v.SetD();
--m.vn; --m.vn;
@ -574,10 +574,10 @@ namespace tri {
/** Function to delete a hedge from the mesh. /** Function to delete a hedge from the mesh.
NOTE: THIS FUNCTION ALSO UPDATE en NOTE: THIS FUNCTION ALSO UPDATE en
*/ */
static void DeleteHEdge(MeshType &m, HEdgeType &h) static void DeleteHEdge(MeshType &m, HEdgeType &h)
{ {
assert(!h.IsD()); assert(!h.IsD());
h.SetD(); h.SetD();
--m.hn; --m.hn;
} }
@ -590,60 +590,61 @@ namespace tri {
e.g. newVertIndex[i] is the new index of the vertex i e.g. newVertIndex[i] is the new index of the vertex i
*/ */
static void PermutateVertexVector(MeshType &m, PointerUpdater<VertexPointer> &pu) static void PermutateVertexVector(MeshType &m, PointerUpdater<VertexPointer> &pu)
{ {
if(m.vert.empty()) return; if(m.vert.empty()) return;
for(unsigned int i=0;i<m.vert.size();++i) for(unsigned int i=0;i<m.vert.size();++i)
{ {
if(pu.remap[i]<size_t(m.vn)) if(pu.remap[i]<size_t(m.vn))
{
assert(!m.vert[i].IsD());
m.vert[ pu.remap [i] ].ImportData(m.vert[i]);
if(HasPerVertexVFAdjacency(m) &&HasPerFaceVFAdjacency(m) )
if (m.vert[i].cVFp()!=0)
{
m.vert[ pu.remap[i] ].VFp() = m.vert[i].cVFp();
m.vert[ pu.remap[i] ].VFi() = m.vert[i].cVFi();
}
}
}
// reorder the optional atttributes in m.vert_attr to reflect the changes
ReorderAttribute(m.vert_attr,pu.remap,m);
// setup the pointer updater
pu.oldBase = &m.vert[0];
pu.oldEnd = &m.vert.back()+1;
// resize
m.vert.resize(m.vn);
// setup the pointer updater
pu.newBase = (m.vert.empty())?0:&m.vert[0];
pu.newEnd = (m.vert.empty())?0:&m.vert.back()+1;
// resize the optional atttributes in m.vert_attr to reflect the changes
ResizeAttribute(m.vert_attr,m.vn,m);
// Loop on the face to update the pointers FV relation (vertex refs)
for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
if(!(*fi).IsD())
for(unsigned int i=0;i<3;++i)
{ {
assert(!m.vert[i].IsD());
m.vert[ pu.remap [i] ].ImportData(m.vert[i]);
if(HasVFAdjacency(m))
if (m.vert[i].IsVFInitialized())
{
m.vert[ pu.remap[i] ].VFp() = m.vert[i].cVFp();
m.vert[ pu.remap[i] ].VFi() = m.vert[i].cVFi();
}
else m.vert [ pu.remap[i] ].VFClear();
}
}
// reorder the optional atttributes in m.vert_attr to reflect the changes
ReorderAttribute(m.vert_attr,pu.remap,m);
// setup the pointer updater
pu.oldBase = &m.vert[0];
pu.oldEnd = &m.vert.back()+1;
// resize
m.vert.resize(m.vn);
// setup the pointer updater
pu.newBase = (m.vert.empty())?0:&m.vert[0];
pu.newEnd = (m.vert.empty())?0:&m.vert.back()+1;
// resize the optional atttributes in m.vert_attr to reflect the changes
ResizeAttribute(m.vert_attr,m.vn,m);
// Loop on the face to update the pointers FV relation (vertex refs)
for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
if(!(*fi).IsD())
for(unsigned int i=0;i<3;++i)
{
size_t oldIndex = (*fi).V(i) - pu.oldBase; size_t oldIndex = (*fi).V(i) - pu.oldBase;
assert(pu.oldBase <= (*fi).V(i) && oldIndex < pu.remap.size()); assert(pu.oldBase <= (*fi).V(i) && oldIndex < pu.remap.size());
(*fi).V(i) = pu.newBase+pu.remap[oldIndex]; (*fi).V(i) = pu.newBase+pu.remap[oldIndex];
} }
// Loop on the edges to update the pointers EV relation // Loop on the edges to update the pointers EV relation
if(HasEVAdjacency(m)) if(HasEVAdjacency(m))
for(EdgeIterator ei=m.edge.begin();ei!=m.edge.end();++ei) for(EdgeIterator ei=m.edge.begin();ei!=m.edge.end();++ei)
if(!(*ei).IsD()) if(!(*ei).IsD())
for(unsigned int i=0;i<2;++i) for(unsigned int i=0;i<2;++i)
{ {
pu.Update((*ei).V(i)); pu.Update((*ei).V(i));
} }
} }
static void CompactEveryVector( MeshType &m) static void CompactEveryVector( MeshType &m)
{ {
@ -700,9 +701,9 @@ namespace tri {
\warning It should not be called when TemporaryData is active (but works correctly if attributes are present) \warning It should not be called when TemporaryData is active (but works correctly if attributes are present)
*/ */
static void CompactEdgeVector( MeshType &m, PointerUpdater<EdgePointer> &pu ) static void CompactEdgeVector( MeshType &m, PointerUpdater<EdgePointer> &pu )
{ {
// If already compacted fast return please! // If already compacted fast return please!
if(m.en==(int)m.edge.size()) return; if(m.en==(int)m.edge.size()) return;
// remap [ <old_edge_position> ] gives you the new position of the edge in the vector; // remap [ <old_edge_position> ] gives you the new position of the edge in the vector;
pu.remap.resize( m.edge.size(),std::numeric_limits<size_t>::max() ); pu.remap.resize( m.edge.size(),std::numeric_limits<size_t>::max() );
@ -793,7 +794,7 @@ namespace tri {
\brief Compact vector of faces removing deleted elements. \brief Compact vector of faces removing deleted elements.
Deleted elements are put to the end of the vector and the vector is resized. Order between elements is preserved but not their position (hence the PointerUpdater) Deleted elements are put to the end of the vector and the vector is resized. Order between elements is preserved but not their position (hence the PointerUpdater)
After calling this function the \c IsD() test in the scanning a vector, is no more necessary. Immediately after calling this function the \c IsD() test during the scanning a vector, is no more necessary.
\warning It should not be called when TemporaryData is active (but works correctly if attributes are present) \warning It should not be called when TemporaryData is active (but works correctly if attributes are present)
*/ */
static void CompactFaceVector( MeshType &m, PointerUpdater<FacePointer> &pu ) static void CompactFaceVector( MeshType &m, PointerUpdater<FacePointer> &pu )
@ -805,31 +806,32 @@ namespace tri {
pu.remap.resize( m.face.size(),std::numeric_limits<size_t>::max() ); pu.remap.resize( m.face.size(),std::numeric_limits<size_t>::max() );
size_t pos=0; size_t pos=0;
size_t i=0; for(size_t i=0;i<m.face.size();++i)
for(i=0;i<m.face.size();++i)
{ {
if(!m.face[i].IsD()) if(!m.face[i].IsD())
{ {
if(pos!=i) if(pos!=i)
{ {
m.face[pos].ImportData(m.face[i]); m.face[pos].ImportData(m.face[i]);
m.face[pos].V(0) = m.face[i].V(0); m.face[pos].V(0) = m.face[i].V(0);
m.face[pos].V(1) = m.face[i].V(1); m.face[pos].V(1) = m.face[i].V(1);
m.face[pos].V(2) = m.face[i].V(2); m.face[pos].V(2) = m.face[i].V(2);
if(HasPerVertexVFAdjacency(m) && HasPerFaceVFAdjacency(m)) if(HasVFAdjacency(m))
for(int j=0;j<3;++j) for(int j=0;j<3;++j)
if (m.face[i].cVFp(j)!=0) { {
m.face[pos].VFp(j) = m.face[i].cVFp(j); if (m.face[i].IsVFInitialized(j)) {
m.face[pos].VFi(j) = m.face[i].cVFi(j); m.face[pos].VFp(j) = m.face[i].cVFp(j);
} m.face[pos].VFi(j) = m.face[i].cVFi(j);
if(HasFFAdjacency(m)) }
for(int j=0;j<3;++j) else m.face[pos].VFClear(j);
if (m.face[i].cFFp(j)!=0) { }
m.face[pos].FFp(j) = m.face[i].cFFp(j); if(HasFFAdjacency(m))
m.face[pos].FFi(j) = m.face[i].cFFi(j); for(int j=0;j<3;++j)
} if (m.face[i].cFFp(j)!=0) {
} m.face[pos].FFp(j) = m.face[i].cFFp(j);
m.face[pos].FFi(j) = m.face[i].cFFi(j);
}
}
pu.remap[i]=pos; pu.remap[i]=pos;
++pos; ++pos;
} }
@ -839,21 +841,22 @@ namespace tri {
// reorder the optional atttributes in m.face_attr to reflect the changes // reorder the optional atttributes in m.face_attr to reflect the changes
ReorderAttribute(m.face_attr,pu.remap,m); ReorderAttribute(m.face_attr,pu.remap,m);
// Loop on the vertices to correct VF relation
VertexIterator vi;
FacePointer fbase=&m.face[0]; FacePointer fbase=&m.face[0];
for (vi=m.vert.begin(); vi!=m.vert.end(); ++vi)
if(!(*vi).IsD())
{
if(HasPerVertexVFAdjacency(m) &&HasPerFaceVFAdjacency(m) )
if ((*vi).cVFp()!=0)
{
size_t oldIndex = (*vi).cVFp() - fbase;
assert(fbase <= (*vi).cVFp() && oldIndex < pu.remap.size());
(*vi).VFp() = fbase+pu.remap[oldIndex];
}
}
// Loop on the vertices to correct VF relation
if(HasVFAdjacency(m))
{
for (VertexIterator vi=m.vert.begin(); vi!=m.vert.end(); ++vi)
if(!(*vi).IsD())
{
if ((*vi).IsVFInitialized() && (*vi).VFp()!=0 )
{
size_t oldIndex = (*vi).cVFp() - fbase;
assert(fbase <= (*vi).cVFp() && oldIndex < pu.remap.size());
(*vi).VFp() = fbase+pu.remap[oldIndex];
}
}
}
// Loop on the faces to correct VF and FF relations // Loop on the faces to correct VF and FF relations
pu.oldBase = &m.face[0]; pu.oldBase = &m.face[0];
@ -866,27 +869,27 @@ namespace tri {
// resize the optional atttributes in m.face_attr to reflect the changes // resize the optional atttributes in m.face_attr to reflect the changes
ResizeAttribute(m.face_attr,m.fn,m); ResizeAttribute(m.face_attr,m.fn,m);
FaceIterator fi; // now we update the various (not null) face pointers (inside VF and FF relations)
for(fi=m.face.begin();fi!=m.face.end();++fi) for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
if(!(*fi).IsD()) if(!(*fi).IsD())
{ {
if(HasPerVertexVFAdjacency(m) &&HasPerFaceVFAdjacency(m) ) if(HasVFAdjacency(m))
for(i=0;i<3;++i) for(int i=0;i<3;++i)
if ((*fi).cVFp(i)!=0) if ((*fi).IsVFInitialized(i) && (*fi).VFp(i)!=0 )
{ {
size_t oldIndex = (*fi).VFp(i) - fbase; size_t oldIndex = (*fi).VFp(i) - fbase;
assert(fbase <= (*fi).VFp(i) && oldIndex < pu.remap.size()); assert(fbase <= (*fi).VFp(i) && oldIndex < pu.remap.size());
(*fi).VFp(i) = fbase+pu.remap[oldIndex]; (*fi).VFp(i) = fbase+pu.remap[oldIndex];
} }
if(HasFFAdjacency(m)) if(HasFFAdjacency(m))
for(i=0;i<3;++i) for(int i=0;i<3;++i)
if ((*fi).cFFp(i)!=0) if ((*fi).cFFp(i)!=0)
{ {
size_t oldIndex = (*fi).FFp(i) - fbase; size_t oldIndex = (*fi).FFp(i) - fbase;
assert(fbase <= (*fi).FFp(i) && oldIndex < pu.remap.size()); assert(fbase <= (*fi).FFp(i) && oldIndex < pu.remap.size());
(*fi).FFp(i) = fbase+pu.remap[oldIndex]; (*fi).FFp(i) = fbase+pu.remap[oldIndex];
} }
} }
@ -920,7 +923,7 @@ public:
template <class ATTR_TYPE> template <class ATTR_TYPE>
static static
typename MeshType::template PerVertexAttributeHandle<ATTR_TYPE> typename MeshType::template PerVertexAttributeHandle<ATTR_TYPE>
AddPerVertexAttribute( MeshType & m, std::string name){ AddPerVertexAttribute( MeshType & m, std::string name){
PAIte i; PAIte i;
PointerToAttribute h; PointerToAttribute h;
h._name = name; h._name = name;
@ -966,7 +969,7 @@ public:
*/ */
template <class ATTR_TYPE> template <class ATTR_TYPE>
static typename MeshType::template PerVertexAttributeHandle<ATTR_TYPE> static typename MeshType::template PerVertexAttributeHandle<ATTR_TYPE>
FindPerVertexAttribute( MeshType & m, const std::string & name) FindPerVertexAttribute( MeshType & m, const std::string & name)
{ {
assert(!name.empty()); assert(!name.empty());
PointerToAttribute h1; h1._name = name; PointerToAttribute h1; h1._name = name;
@ -991,11 +994,11 @@ public:
/*! \brief query the mesh for all the attributes per vertex /*! \brief query the mesh for all the attributes per vertex
\returns the name of all attributes with a non-empy name. \returns the name of all attributes with a non-empy name.
*/ */
template <class ATTR_TYPE> template <class ATTR_TYPE>
static void GetAllPerVertexAttribute(MeshType & m, std::vector<std::string> &all){ static void GetAllPerVertexAttribute(MeshType & m, std::vector<std::string> &all){
all.clear(); all.clear();
typename std::set<PointerToAttribute > ::const_iterator i; typename std::set<PointerToAttribute > ::const_iterator i;
for(i = m.vert_attr.begin(); i != m.vert_attr.end(); ++i ) for(i = m.vert_attr.begin(); i != m.vert_attr.end(); ++i )
if(!(*i)._name.empty()) if(!(*i)._name.empty())
{ {
typename MeshType:: template PerVertexAttributeHandle<ATTR_TYPE> hh; typename MeshType:: template PerVertexAttributeHandle<ATTR_TYPE> hh;
@ -1003,7 +1006,7 @@ public:
if(IsValidHandle<ATTR_TYPE>(m,hh)) if(IsValidHandle<ATTR_TYPE>(m,hh))
all.push_back((*i)._name); all.push_back((*i)._name);
} }
} }
template <class ATTR_TYPE> template <class ATTR_TYPE>
static static
@ -1021,14 +1024,14 @@ public:
/*! \brief If the per-vertex attribute exists, delete it. /*! \brief If the per-vertex attribute exists, delete it.
*/ */
template <class ATTR_TYPE> template <class ATTR_TYPE>
static static
void void
DeletePerVertexAttribute( MeshType & m,typename MeshType::template PerVertexAttributeHandle<ATTR_TYPE> & h){ DeletePerVertexAttribute( MeshType & m,typename MeshType::template PerVertexAttributeHandle<ATTR_TYPE> & h){
typename std::set<PointerToAttribute > ::iterator i; typename std::set<PointerToAttribute > ::iterator i;
for( i = m.vert_attr.begin(); i != m.vert_attr.end(); ++i) for( i = m.vert_attr.begin(); i != m.vert_attr.end(); ++i)
if( (*i)._handle == h._handle ){ if( (*i)._handle == h._handle ){
delete ((SimpleTempData<VertContainer,ATTR_TYPE>*)(*i)._handle); delete ((SimpleTempData<VertContainer,ATTR_TYPE>*)(*i)._handle);
m.vert_attr.erase(i); m.vert_attr.erase(i);
return;} return;}
} }
@ -1073,11 +1076,11 @@ public:
h._padding = 0; h._padding = 0;
// h._typename = typeid(ATTR_TYPE).name(); // h._typename = typeid(ATTR_TYPE).name();
h._handle = new SimpleTempData<EdgeContainer,ATTR_TYPE>(m.edge); h._handle = new SimpleTempData<EdgeContainer,ATTR_TYPE>(m.edge);
m.attrn++; m.attrn++;
h.n_attr = m.attrn; h.n_attr = m.attrn;
std::pair < AttrIterator , bool> res = m.edge_attr.insert(h); std::pair < AttrIterator , bool> res = m.edge_attr.insert(h);
return typename MeshType::template PerEdgeAttributeHandle<ATTR_TYPE>(res.first->_handle,res.first->n_attr); return typename MeshType::template PerEdgeAttributeHandle<ATTR_TYPE>(res.first->_handle,res.first->n_attr);
} }
template <class ATTR_TYPE> template <class ATTR_TYPE>
static static
@ -1107,7 +1110,7 @@ public:
template <class ATTR_TYPE> template <class ATTR_TYPE>
static static
typename MeshType::template PerEdgeAttributeHandle<ATTR_TYPE> typename MeshType::template PerEdgeAttributeHandle<ATTR_TYPE>
FindPerEdgeAttribute( MeshType & m, const std::string & name){ FindPerEdgeAttribute( MeshType & m, const std::string & name){
assert(!name.empty()); assert(!name.empty());
PointerToAttribute h1; h1._name = name; PointerToAttribute h1; h1._name = name;
typename std::set<PointerToAttribute > ::const_iterator i; typename std::set<PointerToAttribute > ::const_iterator i;
@ -1131,31 +1134,31 @@ public:
template <class ATTR_TYPE> template <class ATTR_TYPE>
static void GetAllPerEdgeAttribute(const MeshType & m, std::vector<std::string> &all){ static void GetAllPerEdgeAttribute(const MeshType & m, std::vector<std::string> &all){
all.clear(); all.clear();
typename std::set<PointerToAttribute > :: const_iterator i; typename std::set<PointerToAttribute > :: const_iterator i;
for(i = m.edge_attr.begin(); i != m.edge_attr.end(); ++i ) for(i = m.edge_attr.begin(); i != m.edge_attr.end(); ++i )
if(!(*i)._name.empty()) if(!(*i)._name.empty())
{ {
typename MeshType:: template PerEdgeAttributeHandle<ATTR_TYPE> hh; typename MeshType:: template PerEdgeAttributeHandle<ATTR_TYPE> hh;
hh = Allocator<MeshType>:: template FindPerEdgeAttribute <ATTR_TYPE>(m,(*i)._name); hh = Allocator<MeshType>:: template FindPerEdgeAttribute <ATTR_TYPE>(m,(*i)._name);
if(IsValidHandle<ATTR_TYPE>(m,hh)) if(IsValidHandle<ATTR_TYPE>(m,hh))
all.push_back((*i)._name); all.push_back((*i)._name);
} }
} }
/*! \brief If the per-edge attribute exists, delete it. /*! \brief If the per-edge attribute exists, delete it.
*/ */
template <class ATTR_TYPE> template <class ATTR_TYPE>
static static
void void
DeletePerEdgeAttribute( MeshType & m,typename MeshType::template PerEdgeAttributeHandle<ATTR_TYPE> & h){ DeletePerEdgeAttribute( MeshType & m,typename MeshType::template PerEdgeAttributeHandle<ATTR_TYPE> & h){
typename std::set<PointerToAttribute > ::iterator i; typename std::set<PointerToAttribute > ::iterator i;
for( i = m.edge_attr.begin(); i != m.edge_attr.end(); ++i) for( i = m.edge_attr.begin(); i != m.edge_attr.end(); ++i)
if( (*i)._handle == h._handle ){ if( (*i)._handle == h._handle ){
delete ((SimpleTempData<FaceContainer,ATTR_TYPE>*)(*i)._handle); delete ((SimpleTempData<FaceContainer,ATTR_TYPE>*)(*i)._handle);
m.edge_attr.erase(i); m.edge_attr.erase(i);
return;} return;}
} }
// Generic DeleteAttribute. // Generic DeleteAttribute.
// It must not crash if you try to delete a non existing attribute, // It must not crash if you try to delete a non existing attribute,
@ -1193,14 +1196,14 @@ public:
assert(i ==m.face_attr.end() );// an attribute with this name exists assert(i ==m.face_attr.end() );// an attribute with this name exists
} }
h._sizeof = sizeof(ATTR_TYPE); h._sizeof = sizeof(ATTR_TYPE);
h._padding = 0; h._padding = 0;
h._handle = new SimpleTempData<FaceContainer,ATTR_TYPE>(m.face); h._handle = new SimpleTempData<FaceContainer,ATTR_TYPE>(m.face);
m.attrn++; m.attrn++;
h.n_attr = m.attrn; h.n_attr = m.attrn;
std::pair < AttrIterator , bool> res = m.face_attr.insert(h); std::pair < AttrIterator , bool> res = m.face_attr.insert(h);
return typename MeshType::template PerFaceAttributeHandle<ATTR_TYPE>(res.first->_handle,res.first->n_attr); return typename MeshType::template PerFaceAttributeHandle<ATTR_TYPE>(res.first->_handle,res.first->n_attr);
} }
template <class ATTR_TYPE> template <class ATTR_TYPE>
static static
@ -1229,14 +1232,14 @@ public:
template <class ATTR_TYPE> template <class ATTR_TYPE>
static static
typename MeshType::template PerFaceAttributeHandle<ATTR_TYPE> typename MeshType::template PerFaceAttributeHandle<ATTR_TYPE>
FindPerFaceAttribute( MeshType & m, const std::string & name){ FindPerFaceAttribute( MeshType & m, const std::string & name){
assert(!name.empty()); assert(!name.empty());
PointerToAttribute h1; h1._name = name; PointerToAttribute h1; h1._name = name;
typename std::set<PointerToAttribute > ::iterator i; typename std::set<PointerToAttribute > ::iterator i;
i =m.face_attr.find(h1); i =m.face_attr.find(h1);
if(i!=m.face_attr.end()) if(i!=m.face_attr.end())
if((*i)._sizeof == sizeof(ATTR_TYPE) ){ if((*i)._sizeof == sizeof(ATTR_TYPE) ){
if( (*i)._padding != 0 ){ if( (*i)._padding != 0 ){
PointerToAttribute attr = (*i); // copy the PointerToAttribute PointerToAttribute attr = (*i); // copy the PointerToAttribute
m.face_attr.erase(i); // remove it from the set m.face_attr.erase(i); // remove it from the set
@ -1250,11 +1253,11 @@ public:
return typename MeshType:: template PerFaceAttributeHandle<ATTR_TYPE>(NULL,0); return typename MeshType:: template PerFaceAttributeHandle<ATTR_TYPE>(NULL,0);
} }
template <class ATTR_TYPE> template <class ATTR_TYPE>
static void GetAllPerFaceAttribute(MeshType & m, std::vector<std::string> &all){ static void GetAllPerFaceAttribute(MeshType & m, std::vector<std::string> &all){
all.clear(); all.clear();
typename std::set<PointerToAttribute > :: const_iterator i; typename std::set<PointerToAttribute > :: const_iterator i;
for(i = m.face_attr.begin(); i != m.face_attr.end(); ++i ) for(i = m.face_attr.begin(); i != m.face_attr.end(); ++i )
if(!(*i)._name.empty()) if(!(*i)._name.empty())
{ {
typename MeshType:: template PerFaceAttributeHandle<ATTR_TYPE> hh; typename MeshType:: template PerFaceAttributeHandle<ATTR_TYPE> hh;
@ -1262,22 +1265,22 @@ public:
if(IsValidHandle<ATTR_TYPE>(m,hh)) if(IsValidHandle<ATTR_TYPE>(m,hh))
all.push_back((*i)._name); all.push_back((*i)._name);
} }
} }
/*! \brief If the per-face attribute exists, delete it. /*! \brief If the per-face attribute exists, delete it.
*/ */
template <class ATTR_TYPE> template <class ATTR_TYPE>
static static
void void
DeletePerFaceAttribute( MeshType & m,typename MeshType::template PerFaceAttributeHandle<ATTR_TYPE> & h){ DeletePerFaceAttribute( MeshType & m,typename MeshType::template PerFaceAttributeHandle<ATTR_TYPE> & h){
typename std::set<PointerToAttribute > ::iterator i; typename std::set<PointerToAttribute > ::iterator i;
for( i = m.face_attr.begin(); i != m.face_attr.end(); ++i) for( i = m.face_attr.begin(); i != m.face_attr.end(); ++i)
if( (*i)._handle == h._handle ){ if( (*i)._handle == h._handle ){
delete ((SimpleTempData<FaceContainer,ATTR_TYPE>*)(*i)._handle); delete ((SimpleTempData<FaceContainer,ATTR_TYPE>*)(*i)._handle);
m.face_attr.erase(i); m.face_attr.erase(i);
return;} return;}
} }
// Generic DeleteAttribute. // Generic DeleteAttribute.
// It must not crash if you try to delete a non existing attribute, // It must not crash if you try to delete a non existing attribute,
@ -1315,7 +1318,7 @@ public:
assert(i ==m.mesh_attr.end() );// an attribute with this name exists assert(i ==m.mesh_attr.end() );// an attribute with this name exists
} }
h._sizeof = sizeof(ATTR_TYPE); h._sizeof = sizeof(ATTR_TYPE);
h._padding = 0; h._padding = 0;
h._handle = new Attribute<ATTR_TYPE>(); h._handle = new Attribute<ATTR_TYPE>();
m.attrn++; m.attrn++;
h.n_attr = m.attrn; h.n_attr = m.attrn;
@ -1343,14 +1346,14 @@ public:
template <class ATTR_TYPE> template <class ATTR_TYPE>
static static
typename MeshType::template PerMeshAttributeHandle<ATTR_TYPE> typename MeshType::template PerMeshAttributeHandle<ATTR_TYPE>
FindPerMeshAttribute( MeshType & m, const std::string & name){ FindPerMeshAttribute( MeshType & m, const std::string & name){
assert(!name.empty()); assert(!name.empty());
PointerToAttribute h1; h1._name = name; PointerToAttribute h1; h1._name = name;
typename std::set<PointerToAttribute > ::iterator i; typename std::set<PointerToAttribute > ::iterator i;
i =m.mesh_attr.find(h1); i =m.mesh_attr.find(h1);
if(i!=m.mesh_attr.end()) if(i!=m.mesh_attr.end())
if((*i)._sizeof == sizeof(ATTR_TYPE) ){ if((*i)._sizeof == sizeof(ATTR_TYPE) ){
if( (*i)._padding != 0 ){ if( (*i)._padding != 0 ){
PointerToAttribute attr = (*i); // copy the PointerToAttribute PointerToAttribute attr = (*i); // copy the PointerToAttribute
m.mesh_attr.erase(i); // remove it from the set m.mesh_attr.erase(i); // remove it from the set
@ -1370,23 +1373,23 @@ public:
static void GetAllPerMeshAttribute(const MeshType & m, std::vector<std::string> &all){ static void GetAllPerMeshAttribute(const MeshType & m, std::vector<std::string> &all){
typename std::set<PointerToAttribute > :: iterator i; typename std::set<PointerToAttribute > :: iterator i;
for(i = m.mesh_attr.begin(); i != m.mesh_attr.end(); ++i ) for(i = m.mesh_attr.begin(); i != m.mesh_attr.end(); ++i )
if((*i)._sizeof == sizeof(ATTR_TYPE)) if((*i)._sizeof == sizeof(ATTR_TYPE))
all.push_back((*i)._name); all.push_back((*i)._name);
} }
/*! \brief If the per-mesh attribute exists, delete it. /*! \brief If the per-mesh attribute exists, delete it.
*/ */
template <class ATTR_TYPE> template <class ATTR_TYPE>
static static
void void
DeletePerMeshAttribute( MeshType & m,typename MeshType::template PerMeshAttributeHandle<ATTR_TYPE> & h){ DeletePerMeshAttribute( MeshType & m,typename MeshType::template PerMeshAttributeHandle<ATTR_TYPE> & h){
typename std::set<PointerToAttribute > ::iterator i; typename std::set<PointerToAttribute > ::iterator i;
for( i = m.mesh_attr.begin(); i != m.mesh_attr.end(); ++i) for( i = m.mesh_attr.begin(); i != m.mesh_attr.end(); ++i)
if( (*i)._handle == h._handle ){ if( (*i)._handle == h._handle ){
delete (( Attribute<ATTR_TYPE> *)(*i)._handle); delete (( Attribute<ATTR_TYPE> *)(*i)._handle);
m.mesh_attr.erase(i); m.mesh_attr.erase(i);
return;} return;}
} }
static static
void DeletePerMeshAttribute( MeshType & m, std::string name){ void DeletePerMeshAttribute( MeshType & m, std::string name){
@ -1394,7 +1397,7 @@ public:
PointerToAttribute h1; h1._name = name; PointerToAttribute h1; h1._name = name;
i = m.mesh_attr.find(h1); i = m.mesh_attr.find(h1);
assert(i!=m.mesh_attr.end()); assert(i!=m.mesh_attr.end());
delete ((SimpleTempDataBase *)(*i)._handle); delete ((SimpleTempDataBase *)(*i)._handle);
m.mesh_attr.erase(i); m.mesh_attr.erase(i);
} }
@ -1466,12 +1469,12 @@ public:
_handle->Resize(m.face.size()); _handle->Resize(m.face.size());
for(unsigned int i = 0; i < m.face.size(); ++i){ for(unsigned int i = 0; i < m.face.size(); ++i){
ATTR_TYPE * dest = &(*_handle)[i]; ATTR_TYPE * dest = &(*_handle)[i];
char * ptr = (char*)( ((SimpleTempDataBase *)pa._handle)->DataBegin()); char * ptr = (char*)( ((SimpleTempDataBase *)pa._handle)->DataBegin());
memcpy((void*)dest , memcpy((void*)dest ,
(void*) &(ptr[i * pa._sizeof ]) ,sizeof(ATTR_TYPE)); (void*) &(ptr[i * pa._sizeof ]) ,sizeof(ATTR_TYPE));
} }
// remove the padded container // remove the padded container
delete ((SimpleTempDataBase*) pa._handle); delete ((SimpleTempDataBase*) pa._handle);
// update the pointer to data // update the pointer to data
@ -1487,14 +1490,14 @@ public:
template <class ATTR_TYPE> template <class ATTR_TYPE>
static static
void FixPaddedPerMeshAttribute ( MeshType & /* m */,PointerToAttribute & pa){ void FixPaddedPerMeshAttribute ( MeshType & /* m */,PointerToAttribute & pa){
// create the container of the right type // create the container of the right type
Attribute<ATTR_TYPE> * _handle = new Attribute<ATTR_TYPE>(); Attribute<ATTR_TYPE> * _handle = new Attribute<ATTR_TYPE>();
// copy the padded container in the new one // copy the padded container in the new one
char * ptr = (char*)( ((Attribute<ATTR_TYPE> *)pa._handle)->DataBegin()); char * ptr = (char*)( ((Attribute<ATTR_TYPE> *)pa._handle)->DataBegin());
memcpy((void*)_handle->attribute ,(void*) &(ptr[0]) ,sizeof(ATTR_TYPE)); memcpy((void*)_handle->attribute ,(void*) &(ptr[0]) ,sizeof(ATTR_TYPE));
// remove the padded container // remove the padded container
delete ( (Attribute<ATTR_TYPE> *) pa._handle); delete ( (Attribute<ATTR_TYPE> *) pa._handle);