added a way to define a scope, i.e. a collection of bounds between name of the attributes

and their type, so  that one can add an attribute without knowing its type. It is useful
when working with plugin.
example:
vcg::tri::NameTypeScope myScope;


AddNameTypeBound<int>(myScope,std::string("number");
AddNameTypeBound<float>(myScope,std::string("incoming_light"));

we have crated a scope myScope where "number" is bound a int and incoming_light is a float

In another part of code where I may not know the type of "number", I can still do:

AddPerVertexAttribute(myScope, mesh, "number");

and an int attibute name "number" will be added.
This commit is contained in:
ganovelli 2010-03-15 15:17:20 +00:00
parent 2e739825c8
commit 09b0fb5ef7
1 changed files with 127 additions and 36 deletions

View File

@ -24,7 +24,9 @@
#ifndef __VCGLIB_TRIALLOCATOR #ifndef __VCGLIB_TRIALLOCATOR
#define __VCGLIB_TRIALLOCATOR #define __VCGLIB_TRIALLOCATOR
#include <typeinfo>
#include <vector> #include <vector>
#include <map>
#include <string> #include <string>
#include <set> #include <set>
#include <assert.h> #include <assert.h>
@ -92,10 +94,10 @@ namespace vcg {
typedef typename MeshType::FacePointer FacePointer; typedef typename MeshType::FacePointer FacePointer;
typedef typename MeshType::FaceIterator FaceIterator; typedef typename MeshType::FaceIterator FaceIterator;
typedef typename MeshType::FaceContainer FaceContainer; typedef typename MeshType::FaceContainer FaceContainer;
typedef typename MeshType::PointerToAttribute PtrToAttr; typedef typename MeshType::PointerToAttribute PointerToAttribute;
typedef typename std::set<PtrToAttr>::iterator AttrIterator; typedef typename std::set<PointerToAttribute>::iterator AttrIterator;
typedef typename std::set<PtrToAttr>::const_iterator AttrConstIterator; typedef typename std::set<PointerToAttribute>::const_iterator AttrConstIterator;
typedef typename std::set<PtrToAttr >::iterator PAIte; typedef typename std::set<PointerToAttribute >::iterator PAIte;
/** This class is used when allocating new vertexes and faces to update /** This class is used when allocating new vertexes and faces to update
the pointers that can be changed when resizing the involved vectors of vertex or faces. the pointers that can be changed when resizing the involved vectors of vertex or faces.
@ -146,9 +148,9 @@ namespace vcg {
m.vert.resize(m.vert.size()+n); m.vert.resize(m.vert.size()+n);
m.vn+=n; m.vn+=n;
typename std::set<PtrToAttr>::iterator ai; typename std::set<PointerToAttribute>::iterator ai;
for(ai = m.vert_attr.begin(); ai != m.vert_attr.end(); ++ai) for(ai = m.vert_attr.begin(); ai != m.vert_attr.end(); ++ai)
((PtrToAttr)(*ai)).Resize(m.vert.size()); ((PointerToAttribute)(*ai)).Resize(m.vert.size());
pu.newBase = &*m.vert.begin(); pu.newBase = &*m.vert.begin();
pu.newEnd = &m.vert.back()+1; pu.newEnd = &m.vert.back()+1;
@ -221,9 +223,9 @@ namespace vcg {
m.edge.resize(m.edge.size()+n); m.edge.resize(m.edge.size()+n);
m.en+=n; m.en+=n;
typename std::set<typename MeshType::PtrToAttr>::iterator ai; typename std::set<typename MeshType::PointerToAttribute>::iterator ai;
for(ai = m.edge_attr.begin(); ai != m.edge_attr.end(); ++ai) for(ai = m.edge_attr.begin(); ai != m.edge_attr.end(); ++ai)
((typename MeshType::PtrToAttr)(*ai)).Resize(m.edge.size()); ((typename MeshType::PointerToAttribute)(*ai)).Resize(m.edge.size());
pu.newBase = &*m.edge.begin(); pu.newBase = &*m.edge.begin();
pu.newEnd = &m.edge.back()+1; pu.newEnd = &m.edge.back()+1;
@ -334,9 +336,9 @@ namespace vcg {
m.fn+=n; m.fn+=n;
typename std::set<PtrToAttr>::iterator ai; typename std::set<PointerToAttribute>::iterator ai;
for(ai = m.face_attr.begin(); ai != m.face_attr.end(); ++ai) for(ai = m.face_attr.begin(); ai != m.face_attr.end(); ++ai)
((PtrToAttr)(*ai)).Resize(m.face.size()); ((PointerToAttribute)(*ai)).Resize(m.face.size());
pu.newBase = &*m.face.begin(); pu.newBase = &*m.face.begin();
pu.newEnd = &m.face.back()+1; pu.newEnd = &m.face.back()+1;
@ -616,7 +618,7 @@ public:
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;
PtrToAttr h; PointerToAttribute h;
h._name = name; h._name = name;
if(!name.empty()){ if(!name.empty()){
i = m.vert_attr.find(h); i = m.vert_attr.find(h);
@ -643,13 +645,13 @@ public:
typename MeshType::template PerVertexAttributeHandle<ATTR_TYPE> typename MeshType::template PerVertexAttributeHandle<ATTR_TYPE>
GetPerVertexAttribute( MeshType & m, const std::string & name){ GetPerVertexAttribute( MeshType & m, const std::string & name){
assert(!name.empty()); assert(!name.empty());
PtrToAttr h1; h1._name = name; PointerToAttribute h1; h1._name = name;
typename std::set<PtrToAttr > :: iterator i; typename std::set<PointerToAttribute > :: iterator i;
i =m.vert_attr.find(h1); i =m.vert_attr.find(h1);
if(i!=m.vert_attr.end()){ if(i!=m.vert_attr.end()){
if( (*i)._padding != 0 ){ if( (*i)._padding != 0 ){
PtrToAttr attr = (*i); // copy the PointerToAttribute PointerToAttribute attr = (*i); // copy the PointerToAttribute
m.vert_attr.erase(i); // remove it from the set m.vert_attr.erase(i); // remove it from the set
FixPaddedPerVertexAttribute<ATTR_TYPE>(m,attr); FixPaddedPerVertexAttribute<ATTR_TYPE>(m,attr);
std::pair<AttrIterator,bool> new_i = m.vert_attr.insert(attr); // insert the modified PointerToAttribute std::pair<AttrIterator,bool> new_i = m.vert_attr.insert(attr); // insert the modified PointerToAttribute
@ -669,7 +671,7 @@ public:
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<PtrToAttr > ::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);
@ -681,7 +683,7 @@ public:
static static
void DeletePerVertexAttribute( MeshType & m, std::string name){ void DeletePerVertexAttribute( MeshType & m, std::string name){
AttrIterator i; AttrIterator i;
PtrToAttr h1; h1._name = name; PointerToAttribute h1; h1._name = name;
i = m.vert_attr.find(h1); i = m.vert_attr.find(h1);
assert(i!=m.vert_attr.end()); assert(i!=m.vert_attr.end());
delete ((SimpleTempDataBase<VertContainer>*)(*i)._handle); delete ((SimpleTempDataBase<VertContainer>*)(*i)._handle);
@ -705,7 +707,7 @@ public:
typename MeshType::template PerEdgeAttributeHandle<ATTR_TYPE> typename MeshType::template PerEdgeAttributeHandle<ATTR_TYPE>
AddPerEdgeAttribute( MeshType & m, std::string name){ AddPerEdgeAttribute( MeshType & m, std::string name){
PAIte i; PAIte i;
PtrToAttr h; PointerToAttribute h;
h._name = name; h._name = name;
if(!name.empty()){ if(!name.empty()){
i = m.edge_attr.find(h); i = m.edge_attr.find(h);
@ -730,8 +732,8 @@ public:
typename MeshType::template PerEdgeAttributeHandle<ATTR_TYPE> typename MeshType::template PerEdgeAttributeHandle<ATTR_TYPE>
GetPerEdgeAttribute( const MeshType & m, const std::string & name){ GetPerEdgeAttribute( const MeshType & m, const std::string & name){
assert(!name.empty()); assert(!name.empty());
PtrToAttr h1; h1._name = name; PointerToAttribute h1; h1._name = name;
typename std::set<PtrToAttr > ::const_iterator i; typename std::set<PointerToAttribute > ::const_iterator i;
i =m.edge_attr.find(h1); i =m.edge_attr.find(h1);
if(i!=m.edge_attr.end()) if(i!=m.edge_attr.end())
@ -744,7 +746,7 @@ public:
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<PtrToAttr > ::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);
@ -756,7 +758,7 @@ public:
static static
void DeletePerEdgeAttribute( MeshType & m, std::string name){ void DeletePerEdgeAttribute( MeshType & m, std::string name){
AttrIterator i; AttrIterator i;
PtrToAttr h1; h1._name = name; PointerToAttribute h1; h1._name = name;
i = m.edge_attr.find(h1); i = m.edge_attr.find(h1);
assert(i!=m.edge_attr.end()); assert(i!=m.edge_attr.end());
delete ((SimpleTempDataBase<EdgeContainer>*)(*i)._handle); delete ((SimpleTempDataBase<EdgeContainer>*)(*i)._handle);
@ -778,7 +780,7 @@ public:
typename MeshType::template PerFaceAttributeHandle<ATTR_TYPE> typename MeshType::template PerFaceAttributeHandle<ATTR_TYPE>
AddPerFaceAttribute( MeshType & m, std::string name){ AddPerFaceAttribute( MeshType & m, std::string name){
PAIte i; PAIte i;
PtrToAttr h; PointerToAttribute h;
h._name = name; h._name = name;
if(!name.empty()){ if(!name.empty()){
i = m.face_attr.find(h); i = m.face_attr.find(h);
@ -804,13 +806,13 @@ public:
typename MeshType::template PerFaceAttributeHandle<ATTR_TYPE> typename MeshType::template PerFaceAttributeHandle<ATTR_TYPE>
GetPerFaceAttribute( MeshType & m, const std::string & name){ GetPerFaceAttribute( MeshType & m, const std::string & name){
assert(!name.empty()); assert(!name.empty());
PtrToAttr h1; h1._name = name; PointerToAttribute h1; h1._name = name;
typename std::set<PtrToAttr > ::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)._padding != 0 ){ if( (*i)._padding != 0 ){
PtrToAttr 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
FixPaddedPerFaceAttribute<ATTR_TYPE>(m,attr); FixPaddedPerFaceAttribute<ATTR_TYPE>(m,attr);
std::pair<AttrIterator,bool> new_i = m.face_attr.insert(attr); // insert the modified PointerToAttribute std::pair<AttrIterator,bool> new_i = m.face_attr.insert(attr); // insert the modified PointerToAttribute
@ -827,7 +829,7 @@ public:
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<PtrToAttr > ::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);
@ -839,7 +841,7 @@ public:
static static
void DeletePerFaceAttribute( MeshType & m, std::string name){ void DeletePerFaceAttribute( MeshType & m, std::string name){
AttrIterator i; AttrIterator i;
PtrToAttr h1; h1._name = name; PointerToAttribute h1; h1._name = name;
i = m.face_attr.find(h1); i = m.face_attr.find(h1);
assert(i!=m.face_attr.end()); assert(i!=m.face_attr.end());
delete ((SimpleTempDataBase<FaceContainer>*)(*i)._handle); delete ((SimpleTempDataBase<FaceContainer>*)(*i)._handle);
@ -861,7 +863,7 @@ public:
typename MeshType::template PerMeshAttributeHandle<ATTR_TYPE> typename MeshType::template PerMeshAttributeHandle<ATTR_TYPE>
AddPerMeshAttribute( MeshType & m, std::string name){ AddPerMeshAttribute( MeshType & m, std::string name){
PAIte i; PAIte i;
PtrToAttr h; PointerToAttribute h;
h._name = name; h._name = name;
if(!name.empty()){ if(!name.empty()){
i = m.mesh_attr.find(h); i = m.mesh_attr.find(h);
@ -880,13 +882,13 @@ public:
typename MeshType::template PerMeshAttributeHandle<ATTR_TYPE> typename MeshType::template PerMeshAttributeHandle<ATTR_TYPE>
GetPerMeshAttribute( MeshType & m, const std::string & name){ GetPerMeshAttribute( MeshType & m, const std::string & name){
assert(!name.empty()); assert(!name.empty());
PtrToAttr h1; h1._name = name; PointerToAttribute h1; h1._name = name;
typename std::set<PtrToAttr > ::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)._padding != 0 ){ if( (*i)._padding != 0 ){
PtrToAttr 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
FixPaddedPerMeshAttribute<ATTR_TYPE>(m,attr); FixPaddedPerMeshAttribute<ATTR_TYPE>(m,attr);
std::pair<AttrIterator,bool> new_i = m.mesh_attr.insert(attr); // insert the modified PointerToAttribute std::pair<AttrIterator,bool> new_i = m.mesh_attr.insert(attr); // insert the modified PointerToAttribute
@ -904,7 +906,7 @@ public:
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<PtrToAttr > ::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);
@ -916,7 +918,7 @@ public:
static static
void DeletePerMeshAttribute( MeshType & m, std::string name){ void DeletePerMeshAttribute( MeshType & m, std::string name){
AttrIterator i; AttrIterator i;
PtrToAttr 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 ((AttributeBase *)(*i)._handle); delete ((AttributeBase *)(*i)._handle);
@ -925,7 +927,7 @@ public:
template <class ATTR_TYPE> template <class ATTR_TYPE>
static static
void FixPaddedPerVertexAttribute ( MeshType & m,PtrToAttr & pa){ void FixPaddedPerVertexAttribute ( MeshType & m,PointerToAttribute & pa){
// create the container of the right type // create the container of the right type
SimpleTempData<VertContainer,ATTR_TYPE>* _handle = new SimpleTempData<VertContainer,ATTR_TYPE>(m.vert); SimpleTempData<VertContainer,ATTR_TYPE>* _handle = new SimpleTempData<VertContainer,ATTR_TYPE>(m.vert);
@ -954,7 +956,7 @@ public:
template <class ATTR_TYPE> template <class ATTR_TYPE>
static static
void FixPaddedPerFaceAttribute ( MeshType & m,PtrToAttr & pa){ void FixPaddedPerFaceAttribute ( MeshType & m,PointerToAttribute & pa){
// create the container of the right type // create the container of the right type
SimpleTempData<FaceContainer,ATTR_TYPE>* _handle = new SimpleTempData<FaceContainer,ATTR_TYPE>(m.face); SimpleTempData<FaceContainer,ATTR_TYPE>* _handle = new SimpleTempData<FaceContainer,ATTR_TYPE>(m.face);
@ -984,7 +986,7 @@ public:
template <class ATTR_TYPE> template <class ATTR_TYPE>
static static
void FixPaddedPerMeshAttribute ( MeshType & m,PtrToAttr & 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>();
@ -1006,6 +1008,95 @@ public:
// zero the padding // zero the padding
pa._padding = 0; pa._padding = 0;
} }
/* This section enables the calling of all allocating/deallocating functions by attribute name
*/
// base class of all name type bound
struct NameTypeBound_Base{
virtual std::string Name() = 0;
virtual std::string TypeID() = 0;
};
typedef typename std::map<std::string,NameTypeBound_Base*>::iterator BindersIterator;
typedef std::pair<std::string,NameTypeBound_Base*> TypeBound;
typedef std::map<std::string,NameTypeBound_Base*> NameTypeScope;
template <class TYPE>
struct NameTypeBound: public NameTypeBound_Base{
NameTypeBound(){}
NameTypeBound(std::string name){_name = name ;}
std::string Name() {return _name;}
bool operator ==(const NameTypeBound & o ) const {return Name()==o.Name();}
std::string TypeID(){ return typeid(TYPE).name();}
void AddPerVertexAttribute(MeshType & m){Allocator::AddPerVertexAttribute<TYPE> (m,_name);}
void AddPerFaceAttribute(MeshType & m) {Allocator::AddPerFaceAttribute<TYPE> (m,_name);}
void AddPerEdgeAttribute(MeshType & m) {Allocator::AddPerEdgeAttribute<TYPE> (m,_name);}
private:
std::string _name;
};
// check if a given name has already been bound to a type in the scope passed
bool CheckNameIsBound(NameTypeScope binders,std::string name){ return (binders.find(name)!=binders.end()); }
// add a bound name-type to the passed scope
template <class TYPE>
static void AddNameTypeBound(NameTypeScope binders,std::string name){
assert(!name.empty()); // you cannot bound a type to an empty string
BindersIterator bi = binders.find(name);
if(bi!=binders.end())
assert(typeid(TYPE).name() == ((*bi).second)->TypeID()); // the name was previously bound to a dirrefent type
else{
NameTypeBound<TYPE> * newbound = new NameTypeBound<TYPE>();
binders.insert( TypeBound(name,newbound));
}
}
// remove a previously added name-type bound to the passed scope
void RemoveTypeBind(NameTypeScope binders,std::string name){
BindersIterator bi = binders.find(name);
if(bi!=binders.end()) binders.erase(bi);
}
// add a PerVertexAttribute without knowing its type
void AddPerVertexAttribute(NameTypeScope binders, MeshType & m, std::string name){
BindersIterator bi = binders.find(name);
assert(bi != binders.end() ); // the name MUST have been already bound to a type
(*bi).second->AddPerVertexAttribute(m);
}
// add a PerEdgeAttribute without knowing its type
void AddPerEdgeAttribute(NameTypeScope binders, MeshType & m, std::string name){
BindersIterator bi = binders.find(name);
assert(bi != binders.end() ); // the name MUST have been already bound to a type
(*bi).second->AddPerEdgeAttribute(m);
}
// add a PerFaceAttribute without knowing its type
void AddPerFaceAttribute( NameTypeScope binders,MeshType & m, std::string name){
BindersIterator bi = binders.find(name);
assert(bi != binders.end() ); // the name MUST have been already bound to a type
(*bi).second->AddPerFaceAttribute(m);
}
/* return the name of a previouly bound type */
template <typename TYPE>
std::string NameOf(NameTypeScope binders){
TYPE t;
BindersIterator bi;
for(bi = binders.begin(); bi != binders.end(); ++bi)
if (typdeid(t).name() == ((*bi).second->TypeID()))
return (*bi).second->Name();
return std::string("");
}
}; // end class }; // end class