bootstrapping tetra as trimesh component
This commit is contained in:
parent
b0384f68d1
commit
b662f747a0
|
@ -41,6 +41,9 @@ template<class MeshType>
|
|||
size_t Index(MeshType &m, const typename MeshType::EdgeType &e) {return &e-&*m.edge.begin();}
|
||||
template<class MeshType>
|
||||
size_t Index(MeshType &m, const typename MeshType::HEdgeType &h) {return &h-&*m.hedge.begin();}
|
||||
template <class MeshType>
|
||||
size_t Index(MeshType &m, const typename MeshType::TetraType &t) { return &t - &*m.tetra.begin(); }
|
||||
|
||||
|
||||
template<class MeshType>
|
||||
size_t Index(MeshType &m, const typename MeshType::VertexType *vp) {return vp-&*m.vert.begin();}
|
||||
|
@ -50,6 +53,9 @@ template<class MeshType>
|
|||
size_t Index(MeshType &m, const typename MeshType::EdgeType* e) {return e-&*m.edge.begin();}
|
||||
template<class MeshType>
|
||||
size_t Index(MeshType &m, const typename MeshType::HEdgeType* h) {return h-&*m.hedge.begin();}
|
||||
template <class MeshType>
|
||||
size_t Index(MeshType &m, const typename MeshType::TetraType *t) { return t - &*m.tetra.begin(); }
|
||||
|
||||
|
||||
template<class MeshType>
|
||||
bool IsValidPointer( MeshType & m, const typename MeshType::VertexType *vp) { return ( m.vert.size() > 0 && (vp >= &*m.vert.begin()) && (vp <= &m.vert.back()) ); }
|
||||
|
@ -59,6 +65,8 @@ template<class MeshType>
|
|||
bool IsValidPointer(MeshType & m, const typename MeshType::FaceType *fp) { return ( m.face.size() > 0 && (fp >= &*m.face.begin()) && (fp <= &m.face.back())); }
|
||||
template<class MeshType>
|
||||
bool IsValidPointer(MeshType & m, const typename MeshType::HEdgeType *hp) { return ( m.hedge.size() > 0 && (hp >= &*m.hedge.begin()) && (hp <= &m.hedge.back())); }
|
||||
template <class MeshType>
|
||||
bool IsValidPointer(MeshType &m, const typename MeshType::TetraType *tp) { return (m.tetra.size() > 0 && (tp >= &*m.tetra.begin()) && (tp <= &m.tetra.back())); }
|
||||
|
||||
template <class MeshType, class ATTR_CONT>
|
||||
void ReorderAttribute(ATTR_CONT &c, std::vector<size_t> & newVertIndex, MeshType & /* m */){
|
||||
|
@ -106,8 +114,12 @@ public:
|
|||
typedef typename MeshType::HEdgeIterator HEdgeIterator;
|
||||
typedef typename MeshType::HEdgeContainer HEdgeContainer;
|
||||
|
||||
typedef typename MeshType::CoordType CoordType;
|
||||
typedef typename MeshType::TetraType TetraType;
|
||||
typedef typename MeshType::TetraPointer TetraPointer;
|
||||
typedef typename MeshType::TetraIterator TetraIterator;
|
||||
typedef typename MeshType::TetraContainer TetraContainer;
|
||||
|
||||
typedef typename MeshType::CoordType CoordType;
|
||||
|
||||
typedef typename MeshType::PointerToAttribute PointerToAttribute;
|
||||
typedef typename std::set<PointerToAttribute>::iterator AttrIterator;
|
||||
|
@ -174,9 +186,12 @@ public:
|
|||
static VertexIterator AddVertices(MeshType &m, size_t n, PointerUpdater<VertexPointer> &pu)
|
||||
{
|
||||
VertexIterator last;
|
||||
if(n == 0) return m.vert.end();
|
||||
if(n == 0)
|
||||
return m.vert.end();
|
||||
pu.Clear();
|
||||
if(m.vert.empty()) pu.oldBase=0; // if the vector is empty we cannot find the last valid element
|
||||
|
||||
if(m.vert.empty())
|
||||
pu.oldBase=0; // if the vector is empty we cannot find the last valid element
|
||||
else {
|
||||
pu.oldBase=&*m.vert.begin();
|
||||
pu.oldEnd=&m.vert.back()+1;
|
||||
|
@ -201,9 +216,12 @@ public:
|
|||
for (EdgeIterator ei=m.edge.begin(); ei!=m.edge.end(); ++ei)
|
||||
if(!(*ei).IsD())
|
||||
{
|
||||
if(HasEVAdjacency (m)) { pu.Update((*ei).V(0)); pu.Update((*ei).V(1));}
|
||||
// if(HasEVAdjacency (m))
|
||||
pu.Update((*ei).V(0));
|
||||
pu.Update((*ei).V(1));
|
||||
// if(HasEVAdjacency(m)) pu.Update((*ei).EVp());
|
||||
}
|
||||
|
||||
HEdgeIterator hi;
|
||||
for (hi=m.hedge.begin(); hi!=m.hedge.end(); ++hi)
|
||||
if(!(*hi).IsD())
|
||||
|
@ -214,6 +232,12 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
for (TetraIterator ti = m.tetra.begin(); ti != m.tetra.end(); ++ti)
|
||||
if (!(*ti).IsD())
|
||||
for (int i = 0; i < 4; ++i)
|
||||
if ((*ti).cV(i) != 0)
|
||||
pu.Update((*ti).V(i));
|
||||
|
||||
// e poiche' lo spazio e' cambiato si ricalcola anche last da zero
|
||||
}
|
||||
size_t siz=(size_t)(m.vert.size()-n);
|
||||
|
@ -662,6 +686,196 @@ public:
|
|||
return firstNewFace;
|
||||
}
|
||||
|
||||
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
//:::::::::::::::::TETRAS ADDER FUNCTIONS:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
/** \brief Function to add n tetras to the mesh.
|
||||
This is the only full featured function that is able to manage correctly
|
||||
all the official internal pointers of the mesh (like the VT and TT adjacency relations)
|
||||
\warning Calling this function can cause the invalidation of any not-managed TetraPointer
|
||||
just because we resize the face vector.
|
||||
If you have such pointers you need to update them by mean of the PointerUpdater object.
|
||||
\sa PointerUpdater
|
||||
\param m the mesh to be modified
|
||||
\param n the number of elements to be added
|
||||
\param pu a PointerUpdater initialized so that it can be used to update pointers to tetras that could have become invalid after this adding.
|
||||
\retval the iterator to the first element added.
|
||||
*/
|
||||
static TetraIterator AddTetras(MeshType &m, size_t n, PointerUpdater<TetraPointer> &pu)
|
||||
{
|
||||
//nothing to do
|
||||
if (n == 0)
|
||||
return m.tetra.end();
|
||||
|
||||
//prepare the pointerupdater info
|
||||
pu.Clear();
|
||||
if (m.tetra.empty())
|
||||
pu.oldBase = 0;
|
||||
else
|
||||
{
|
||||
pu.oldBase = &*m.tetra.begin();
|
||||
pu.oldEnd = &m.tetra.back() + 1;
|
||||
}
|
||||
|
||||
//resize the tetra list and update tetra count
|
||||
m.tetra.resize(m.tetra.size() + n);
|
||||
m.tn += n;
|
||||
|
||||
//get the old size and advance to the first new tetrahedron position
|
||||
size_t oldSize = (size_t)(m.tetra.size() - n);
|
||||
|
||||
TetraIterator firstNewTetra = m.tetra.begin();
|
||||
advance(firstNewTetra, oldSize);
|
||||
|
||||
//for each attribute make adapt the list size
|
||||
typename std::set<typename MeshType::PointerToAttribute>::iterator ai;
|
||||
for (ai = m.tetra_attr.begin(); ai != m.tetra_attr.end(); ++ai)
|
||||
((typename MeshType::PointerToAttribute)(*ai)).Resize(m.tetra.size());
|
||||
|
||||
//do the update
|
||||
pu.newBase = &*m.tetra.begin();
|
||||
pu.newEnd = &m.tetra.back() + 1;
|
||||
if (pu.NeedUpdate())
|
||||
{
|
||||
if (HasVTAdjacency(m))
|
||||
{
|
||||
for (VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
|
||||
if (!vi->IsD())
|
||||
pu.Update(vi->VTp());
|
||||
|
||||
for (TetraIterator ti = m.tetra.begin(); ti != m.tetra.end(); ++ti)
|
||||
if (!ti->IsD())
|
||||
{
|
||||
pu.Update(ti->VTp(0));
|
||||
pu.Update(ti->VTp(1));
|
||||
pu.Update(ti->VTp(2));
|
||||
pu.Update(ti->VTp(3));
|
||||
}
|
||||
}
|
||||
|
||||
//do edge and face adjacency
|
||||
if (HasTTAdjacency(m))
|
||||
for (TetraIterator ti = m.tetra.begin(); ti != m.tetra.end(); ++ti)
|
||||
if (!ti->IsD())
|
||||
{
|
||||
pu.Update(ti->TTp(0));
|
||||
pu.Update(ti->TTp(1));
|
||||
pu.Update(ti->TTp(2));
|
||||
pu.Update(ti->TTp(3));
|
||||
}
|
||||
}
|
||||
|
||||
return firstNewTetra;
|
||||
}
|
||||
|
||||
//TODO: ADD 4 FACES then add tetra
|
||||
/** Function to add a face to the mesh and initializing it with the three given VertexPointers
|
||||
*/
|
||||
static TetraIterator AddTetra(MeshType &m, VertexPointer v0, VertexPointer v1, VertexPointer v2, VertexPointer v3)
|
||||
{
|
||||
assert(m.vert.size() > 0);
|
||||
assert((v0 != v1) && (v0 != v2) && (v0 != v3) && (v1 != v2) && (v1 != v3) && (v2 != v3));
|
||||
assert(v0 >= &m.vert.front() && v0 <= &m.vert.back());
|
||||
assert(v1 >= &m.vert.front() && v1 <= &m.vert.back());
|
||||
assert(v2 >= &m.vert.front() && v2 <= &m.vert.back());
|
||||
assert(v3 >= &m.vert.front() && v3 <= &m.vert.back());
|
||||
|
||||
AddFace(m, v0, v1, v2);
|
||||
AddFace(m, v0, v3, v1);
|
||||
AddFace(m, v0, v2, v3);
|
||||
AddFace(m, v1, v3, v2);
|
||||
|
||||
PointerUpdater<TetraPointer> pu;
|
||||
TetraIterator ti = AddTetras(m, 1, pu);
|
||||
ti->V(0) = v0;
|
||||
ti->V(1) = v1;
|
||||
ti->V(2) = v2;
|
||||
ti->V(3) = v3;
|
||||
return ti;
|
||||
}
|
||||
|
||||
/** Function to add a face to the mesh and initializing it with three indexes
|
||||
*/
|
||||
static TetraIterator AddTetra(MeshType &m, const size_t v0, const size_t v1, const size_t v2, const size_t v3)
|
||||
{
|
||||
assert(m.vert.size() > 0);
|
||||
assert((v0 != v1) && (v0 != v2) && (v0 != v3) && (v1 != v2) && (v1 != v3) && (v2 != v3));
|
||||
assert(v0 >= 0 && v0 < m.vert.size());
|
||||
assert(v1 >= 0 && v1 < m.vert.size());
|
||||
assert(v2 >= 0 && v2 < m.vert.size());
|
||||
assert(v3 >= 0 && v3 < m.vert.size());
|
||||
|
||||
return AddTetra(m, &(m.vert[v0]), &(m.vert[v1]), &(m.vert[v2]), &(m.vert[v3]));
|
||||
}
|
||||
/** Function to add a face to the mesh and initializing it with the three given coords
|
||||
*/
|
||||
static TetraIterator AddTetra(MeshType &m, const CoordType & p0, const CoordType & p1, const CoordType & p2, const CoordType & p3)
|
||||
{
|
||||
VertexIterator vi = AddVertices(m, 4);
|
||||
|
||||
VertexPointer v0 = &*vi++;
|
||||
VertexPointer v1 = &*vi++;
|
||||
VertexPointer v2 = &*vi++;
|
||||
VertexPointer v3 = &*vi++;
|
||||
|
||||
v0->P() = p0;
|
||||
v1->P() = p1;
|
||||
v2->P() = p2;
|
||||
v3->P() = p3;
|
||||
|
||||
return AddTetra(m, v0, v1, v2, v3);
|
||||
}
|
||||
|
||||
// //requires no duplicate vertices on faces you use
|
||||
// static TetraIterator AddTetra(MeshType &m, const FaceType & f0, const FaceType & f1, const FaceType & f2, const FaceType & f3)
|
||||
// {
|
||||
// assert(m.face.size() > 0);
|
||||
// assert((f0 != f1) && (f0 != f2) && (f0 != f3) && (f1 != f2) && (f1 != f3) && (f2 != f3));
|
||||
// assert(f1 >= 0 && f1 < m.face.size());
|
||||
// assert(f2 >= 0 && f2 < m.face.size());
|
||||
// assert(f3 >= 0 && f3 < m.face.size());
|
||||
// assert(f0 >= 0 && f0 < m.face.size());
|
||||
// //TODO: decide if you want to address this like this
|
||||
// //ERROR: can't use position...so..could force to have no dup verts..and use pointers or avoid this kind of thing
|
||||
// assert(f0.V(0) == f1.V(0) && f0.V(0) == f2.V(0) && //v0
|
||||
// f0.V(1) == f1.V(2) && f0.V(1) == f3.V(0) && //v1
|
||||
// f0.V(2) == f2.V(1) && f0.V(2) == f3.V(2) && //v2
|
||||
// f1.V(1) == f2.V(2) && f1.V(1) == f3.V(1) ) //v3
|
||||
|
||||
// //add a tetra...and set vertices correctly
|
||||
// PointerUpdater<TetraPointer> pu;
|
||||
// TetraIterator ti = AddTetras(m, 1, pu);
|
||||
// ti->V(0) = f0.V(0);
|
||||
// ti->V(1) = f0.V(1);
|
||||
// ti->V(2) = f0.V(2);
|
||||
// ti->V(3) = f1.V(1);
|
||||
|
||||
// return ti;
|
||||
// }
|
||||
|
||||
/** \brief Function to add n faces to the mesh.
|
||||
First wrapper, with no parameters
|
||||
*/
|
||||
static TetraIterator AddTetras(MeshType &m, size_t n)
|
||||
{
|
||||
PointerUpdater<TetraPointer> pu;
|
||||
return AddTetras(m, n, pu);
|
||||
}
|
||||
|
||||
/** \brief Function to add n faces to the mesh.
|
||||
Second Wrapper, with a vector of face pointer to be updated.
|
||||
*/
|
||||
static TetraIterator AddTetras(MeshType &m, size_t n, std::vector<TetraPointer *> &local_vec)
|
||||
{
|
||||
PointerUpdater<TetraPointer> pu;
|
||||
TetraIterator t_ret = AddTetras(m, n, pu);
|
||||
|
||||
typename std::vector<TetraPointer *>::iterator fi;
|
||||
for (ti = local_vec.begin(); ti != local_vec.end(); ++ti)
|
||||
pu.Update(**ti);
|
||||
return t_ret;
|
||||
}
|
||||
|
||||
/* +++++++++++++++ Deleting ++++++++++++++++ */
|
||||
|
||||
/** Function to delete a face from the mesh.
|
||||
|
@ -709,6 +923,17 @@ public:
|
|||
--m.hn;
|
||||
}
|
||||
|
||||
/** Function to delete a tetra from the mesh.
|
||||
NOTE: THIS FUNCTION ALSO UPDATE tn
|
||||
*/
|
||||
static void DeleteTetra(MeshType &m, TetraType &t)
|
||||
{
|
||||
assert(&t >= &m.tetra.front() && &t <= &m.tetra.back());
|
||||
assert(!t.IsD());
|
||||
t.SetD();
|
||||
--m.tn;
|
||||
}
|
||||
|
||||
/*
|
||||
Function to rearrange the vertex vector according to a given index permutation
|
||||
the permutation is vector such that after calling this function
|
||||
|
@ -745,6 +970,15 @@ public:
|
|||
}
|
||||
else m.vert [ pu.remap[i] ].VEClear();
|
||||
}
|
||||
if (HasVTAdjacency(m))
|
||||
{
|
||||
if (m.vert[i].IsVTInitialized())
|
||||
{
|
||||
m.vert[ pu.remap[i] ].VTp() = m.vert[i].cVTp();
|
||||
m.vert[ pu.remap[i] ].VTi() = m.vert[i].cVTi();
|
||||
}
|
||||
else m.vert[ pu.remap[i] ].VTClear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -774,8 +1008,17 @@ public:
|
|||
assert(pu.oldBase <= (*fi).V(i) && oldIndex < pu.remap.size());
|
||||
(*fi).V(i) = pu.newBase+pu.remap[oldIndex];
|
||||
}
|
||||
// Loop on the edges to update the pointers EV relation
|
||||
if(HasEVAdjacency(m))
|
||||
// Loop on the tetras to update the pointers TV relation (vertex refs)
|
||||
for(TetraIterator ti = m.tetra.begin(); ti != m.tetra.end(); ++ti)
|
||||
if(!(*ti).IsD())
|
||||
for(int i = 0; i < 4; ++i)
|
||||
{
|
||||
size_t oldIndex = (*ti).V(i) - pu.oldBase;
|
||||
assert(pu.oldBase <= (*ti).V(i) && oldIndex < pu.remap.size());
|
||||
(*ti).V(i) = pu.newBase+pu.remap[oldIndex];
|
||||
}
|
||||
// Loop on the edges to update the pointers EV relation (vertex refs)
|
||||
// if(HasEVAdjacency(m))
|
||||
for(EdgeIterator ei=m.edge.begin();ei!=m.edge.end();++ei)
|
||||
if(!(*ei).IsD())
|
||||
{
|
||||
|
@ -784,14 +1027,14 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
static void CompactEveryVector( MeshType &m)
|
||||
static void CompactEveryVector(MeshType &m)
|
||||
{
|
||||
CompactVertexVector(m);
|
||||
CompactEdgeVector(m);
|
||||
CompactFaceVector(m);
|
||||
CompactTetraVector(m);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Compact vector of vertices 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)
|
||||
|
@ -885,6 +1128,15 @@ public:
|
|||
m.edge[ pu.remap[i] ].EEp(1) = m.edge[i].cEEp(1);
|
||||
m.edge[ pu.remap[i] ].EEi(1) = m.edge[i].cEEi(1);
|
||||
}
|
||||
if(HasEFAdjacency(m))
|
||||
// if (m.edge[i].cEEp(0)!=0)
|
||||
{
|
||||
m.edge[ pu.remap[i] ].EFp(0) = m.edge[i].cEFp(0);
|
||||
m.edge[ pu.remap[i] ].EFi(0) = m.edge[i].cEFi(0);
|
||||
m.edge[ pu.remap[i] ].EFp(1) = m.edge[i].cEFp(1);
|
||||
m.edge[ pu.remap[i] ].EFi(1) = m.edge[i].cEFi(1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -918,6 +1170,8 @@ public:
|
|||
pu.Update((*ei).VEp(i));
|
||||
if(HasEEAdjacency(m))
|
||||
pu.Update((*ei).EEp(i));
|
||||
if(HasEFAdjacency(m))
|
||||
pu.Update((*ei).EFp(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1046,6 +1300,125 @@ public:
|
|||
CompactFaceVector(m,pu);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Compact tetra vector by 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)
|
||||
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 some TemporaryData is active (but works correctly if attributes are present)
|
||||
*/
|
||||
static void CompactTetraVector(MeshType & m, PointerUpdater<TetraPointer> & pu)
|
||||
{
|
||||
//nothing to do
|
||||
if (size_t(m.tn) == m.tetra.size())
|
||||
return;
|
||||
|
||||
//init the remap
|
||||
pu.remap.resize(m.tetra.size(), std::numeric_limits<size_t>::max());
|
||||
|
||||
//cycle over all the tetras, pos is the last not D() position, I is the index
|
||||
//when pos != i and !tetra[i].IsD() => we need to compact and update adj
|
||||
size_t pos = 0;
|
||||
for (size_t i = 0; i < m.tetra.size(); ++i)
|
||||
{
|
||||
if (!m.tetra.IsD())
|
||||
{
|
||||
if (pos != i)
|
||||
{
|
||||
//import data
|
||||
m.tetra[pos].ImportData(m.tetra[i]);
|
||||
//import vertex refs
|
||||
for (int j = 0; j < 4; ++j)
|
||||
m.tetra[pos].V(j) = m.tetra[i].cV(j);
|
||||
//import VT adj
|
||||
if (HasVTAdjacency(m))
|
||||
for (int j = 0; j < 4; ++j)
|
||||
{
|
||||
if (m.tetra[i].IsVTInitialized(j))
|
||||
{
|
||||
m.tetra[pos].VTp(j) = m.tetra[i].VTp(j);
|
||||
m.tetra[pos].VTi(j) = m.tetra[i].VTi(j);
|
||||
}
|
||||
else
|
||||
m.tetra[pos].VTClear();
|
||||
}
|
||||
//import TT adj
|
||||
if (HasTTAdjacency(m))
|
||||
for (int j = 0; j < 4; ++j)
|
||||
{
|
||||
m.tetra[pos].TTp(j) = m.tetra[i].cTTp(j);
|
||||
m.tetra[pos].TTi(j) = m.tetra[i].cTTi(j);
|
||||
}
|
||||
}
|
||||
//update remapping and advance pos
|
||||
pu.remap[i] = pos;
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
|
||||
assert(size_t(m.tn) == pos);
|
||||
//reorder the optional attributes in m.tetra_attr
|
||||
ReorderAttribute(m.tetra_attr, pu.remap, m);
|
||||
// resize the optional atttributes in m.tetra_attr to reflect the changes
|
||||
ResizeAttribute(m.tetra_attr, m.tn, m);
|
||||
|
||||
// Loop on the tetras to correct VT and TT relations
|
||||
pu.oldBase = &m.tetra[0];
|
||||
pu.oldEnd = &m.tetra.back() + 1;
|
||||
|
||||
m.tetra.resize(m.tn);
|
||||
pu.newBase = (m.tetra.empty()) ? 0 : &m.tetra[0];
|
||||
pu.newEnd = (m.tetra.empty()) ? 0 : &m.tetra.back() + 1;
|
||||
|
||||
TetraPointer tbase = &m.tetra[0];
|
||||
|
||||
//Loop on the vertices to correct VT relation (since we moved things around)
|
||||
if (HasVTAdjacency(m))
|
||||
{
|
||||
for (VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
|
||||
if (!(*vi).IsD())
|
||||
{
|
||||
if ((*vi).IsVTInitialized() && (*vi).VTp() != 0)
|
||||
{
|
||||
size_t oldIndex = (*vi).cVTp() - tbase;
|
||||
assert(tbase <= (*vi).cVTp() && oldIndex < pu.remap.size());
|
||||
(*vi).VTp() = tbase + pu.remap[oldIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Loop on the tetras to correct the VT and TT relations
|
||||
for (TetraIterator ti = m.tetra.begin(); ti != m.tetra.end(); ++ti)
|
||||
if (!(*ti).IsD())
|
||||
{
|
||||
//VT
|
||||
if (HasVTAdjacency(m))
|
||||
for (int i = 0; i < 4; ++i)
|
||||
if ((*ti).IsVTInitialized(i) && (*ti).VTp(i) != 0)
|
||||
{
|
||||
size_t oldIndex = (*ti).VTp(i) - fbase;
|
||||
assert(tbase <= (*ti).VTp(i) && oldIndex < pu.remap.size());
|
||||
(*ti).VTp(i) = tbase + pu.remap[oldIndex];
|
||||
}
|
||||
//TT
|
||||
if (HasTTAdjacency(m))
|
||||
for (int i = 0; i < 4; ++i)
|
||||
if ((*ti).cTTp(i) != 0)
|
||||
{
|
||||
size_t oldIndex = (*ti).TTp(i) - tbase;
|
||||
assert(tbase <= (*ti).TTp(i) && oldIndex < pu.remap.size());
|
||||
(*ti).TTp(i) = tbase + pu.remap[oldIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Wrapper without the PointerUpdater. */
|
||||
static void CompactTetraVector(MeshType &m)
|
||||
{
|
||||
PointerUpdater<TetraPointer> pu;
|
||||
CompactTetraVector(m, pu);
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
@ -1441,6 +1814,136 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
/// Per Tetra Attributes
|
||||
template <class ATTR_TYPE>
|
||||
static bool IsValidHandle(MeshType & m, const typename MeshType::template PerTetraAttributeHandle<ATTR_TYPE> & a)
|
||||
{
|
||||
if (a._handle == NULL)
|
||||
return false;
|
||||
for (AttrIterator i = m.tetra_attr.begin(); i != m.tetra_attr.end(); ++i)
|
||||
if ((*i).n_attr == a.n_attr)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class ATTR_TYPE>
|
||||
static typename MeshType::template PerTetraAttributeHandle<ATTR_TYPE> AddPerTetraAttribute(MeshType & m, std::string name)
|
||||
{
|
||||
PAIte i;
|
||||
PointerToAttribute h;
|
||||
h._name = name;
|
||||
if (!name.empty())
|
||||
{
|
||||
i = m.tetra_attr.find(h);
|
||||
assert(i == m.tetra_attr.end());
|
||||
}
|
||||
|
||||
h._sizeof = sizeof(ATTR_TYPE);
|
||||
h._padding = 0;
|
||||
h._handle = new SimpleTempData<TetraContainer, ATTR_TYPE>(m.tetra);
|
||||
h._type = typeid(ATTR_TYPE);
|
||||
m.attrn++;
|
||||
h.n_attr = m.attrn;
|
||||
std::pair<AttrIterator, bool> res = m.tetra_attr.insert(h);
|
||||
return typename MeshType::template PerTetraAttributeHandle<ATTR_TYPE>(res.first->_handle, res.first->n_attr);
|
||||
}
|
||||
|
||||
template <class ATTR_TYPE>
|
||||
static typename MeshType::template PerTetraAttributeHandle<ATTR_TYPE> AddPerTetraAttribute(MeshType &m)
|
||||
{
|
||||
return AddPerTetraAttribute<ATTR_TYPE>(m, std::string(""));
|
||||
}
|
||||
|
||||
/*! \brief gives a handle to a per-tetra attribute with a given name and ATTR_TYPE
|
||||
\returns a valid handle. If the name is not empty and an attribute with that name and type exists returns a handle to it.
|
||||
Otherwise return a hanlde to a newly created.
|
||||
*/
|
||||
template <class ATTR_TYPE>
|
||||
static typename MeshType::template PerTetraAttributeHandle<ATTR_TYPE> GetPerTetraAttribute(MeshType &m, std::string name = std::string(""))
|
||||
{
|
||||
typename MeshType::template PerTetraAttributeHandle<ATTR_TYPE> h;
|
||||
if (!name.empty())
|
||||
{
|
||||
h = FindPerTetraAttribute<ATTR_TYPE>(m, name);
|
||||
if (IsValidHandle(m, h))
|
||||
return h;
|
||||
}
|
||||
return AddPerTetraAttribute<ATTR_TYPE>(m, name);
|
||||
}
|
||||
|
||||
template <class ATTR_TYPE>
|
||||
static typename MeshType::template PerTetraAttributeHandle<ATTR_TYPE> FindPerTetraAttribute(MeshType &m, const std::string &name)
|
||||
{
|
||||
assert(!name.empty());
|
||||
PointerToAttribute h1;
|
||||
h1._name = name;
|
||||
typename std::set<PointerToAttribute>::iterator i;
|
||||
|
||||
i = m.tetra_attr.find(h1);
|
||||
if (i != m.tetra_attr.end())
|
||||
if ((*i)._sizeof == sizeof(ATTR_TYPE))
|
||||
{
|
||||
if ((*i)._padding != 0)
|
||||
{
|
||||
PointerToAttribute attr = (*i); // copy the PointerToAttribute
|
||||
m.tetra_attr.erase(i); // remove it from the set
|
||||
FixPaddedPerTetraAttribute<ATTR_TYPE>(m, attr);
|
||||
std::pair<AttrIterator, bool> new_i = m.tetra_attr.insert(attr); // insert the modified PointerToAttribute
|
||||
assert(new_i.second);
|
||||
i = new_i.first;
|
||||
}
|
||||
return typename MeshType::template PerTetraAttributeHandle<ATTR_TYPE>((*i)._handle, (*i).n_attr);
|
||||
}
|
||||
return typename MeshType::template PerTetraAttributeHandle<ATTR_TYPE>(NULL, 0);
|
||||
}
|
||||
|
||||
template <class ATTR_TYPE>
|
||||
static void GetAllPerTetraAttribute(MeshType &m, std::vector<std::string> &all)
|
||||
{
|
||||
all.clear();
|
||||
typename std::set<PointerToAttribute>::const_iterator i;
|
||||
for (i = m.tetra_attr.begin(); i != m.tetra_attr.end(); ++i)
|
||||
if (!(*i)._name.empty())
|
||||
{
|
||||
typename MeshType::template PerTetraAttributeHandle<ATTR_TYPE> hh;
|
||||
hh = Allocator<MeshType>::template FindPerTetraAttribute<ATTR_TYPE>(m, (*i)._name);
|
||||
if (IsValidHandle<ATTR_TYPE>(m, hh))
|
||||
all.push_back((*i)._name);
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief If the per-face attribute exists, delete it.
|
||||
*/
|
||||
template <class ATTR_TYPE>
|
||||
static void DeletePerTetraAttribute(MeshType &m, typename MeshType::template PerTetraAttributeHandle<ATTR_TYPE> &h)
|
||||
{
|
||||
typename std::set<PointerToAttribute>::iterator i;
|
||||
for (i = m.tetra_attr.begin(); i != m.tetra_attr.end(); ++i)
|
||||
if ((*i)._handle == h._handle)
|
||||
{
|
||||
delete ((SimpleTempData<TetraContainer, ATTR_TYPE> *)(*i)._handle);
|
||||
m.tetra_attr.erase(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Generic DeleteAttribute.
|
||||
// It must not crash if you try to delete a non existing attribute,
|
||||
// because you do not have a way of asking for a handle of an attribute for which you do not know the type.
|
||||
static bool DeletePerTetraAttribute(MeshType &m, std::string name)
|
||||
{
|
||||
AttrIterator i;
|
||||
PointerToAttribute h1;
|
||||
h1._name = name;
|
||||
i = m.tetra_attr.find(h1);
|
||||
if (i == m.tetra_attr.end())
|
||||
return false;
|
||||
delete ((SimpleTempDataBase *)(*i)._handle);
|
||||
m.tetra_attr.erase(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// Per Mesh Attributes
|
||||
template <class ATTR_TYPE>
|
||||
static
|
||||
|
@ -1632,6 +2135,35 @@ public:
|
|||
pa._padding = 0;
|
||||
}
|
||||
|
||||
template <class ATTR_TYPE>
|
||||
static void FixPaddedPerTetraAttribute(MeshType &m, PointerToAttribute &pa)
|
||||
{
|
||||
|
||||
// create the container of the right type
|
||||
SimpleTempData<TetraContainer, ATTR_TYPE> *_handle = new SimpleTempData<TetraContainer, ATTR_TYPE>(m.tetra);
|
||||
|
||||
// copy the padded container in the new one
|
||||
_handle->Resize(m.tetra.size());
|
||||
for (size_t i = 0; i < m.tetra.size(); ++i)
|
||||
{
|
||||
ATTR_TYPE *dest = &(*_handle)[i];
|
||||
char *ptr = (char *)(((SimpleTempDataBase *)pa._handle)->DataBegin());
|
||||
memcpy((void *)dest,
|
||||
(void *)&(ptr[i * pa._sizeof]), sizeof(ATTR_TYPE));
|
||||
}
|
||||
|
||||
// remove the padded container
|
||||
delete ((SimpleTempDataBase *)pa._handle);
|
||||
|
||||
// update the pointer to data
|
||||
pa._sizeof = sizeof(ATTR_TYPE);
|
||||
|
||||
// update the pointer to data
|
||||
pa._handle = _handle;
|
||||
|
||||
// zero the padding
|
||||
pa._padding = 0;
|
||||
}
|
||||
|
||||
template <class ATTR_TYPE>
|
||||
static void FixPaddedPerMeshAttribute ( MeshType & /* m */,PointerToAttribute & pa){
|
||||
|
|
|
@ -46,11 +46,13 @@ public:
|
|||
typedef typename MeshLeft::EdgeType EdgeLeft;
|
||||
typedef typename MeshLeft::FaceType FaceLeft;
|
||||
typedef typename MeshLeft::HEdgeType HEdgeLeft;
|
||||
typedef typename MeshLeft::TetraType TetraLeft;
|
||||
typedef typename MeshLeft::VertexPointer VertexPointerLeft;
|
||||
typedef typename MeshLeft::VertexIterator VertexIteratorLeft;
|
||||
typedef typename MeshLeft::EdgeIterator EdgeIteratorLeft;
|
||||
typedef typename MeshLeft::HEdgeIterator HEdgeIteratorLeft;
|
||||
typedef typename MeshLeft::FaceIterator FaceIteratorLeft;
|
||||
typedef typename MeshLeft::TetraIterator TetraIteratorLeft;
|
||||
|
||||
|
||||
typedef typename ConstMeshRight::ScalarType ScalarRight;
|
||||
|
@ -59,6 +61,9 @@ public:
|
|||
typedef typename ConstMeshRight::EdgeType EdgeRight;
|
||||
typedef typename ConstMeshRight::HEdgeType HEdgeRight;
|
||||
typedef typename ConstMeshRight::FaceType FaceRight;
|
||||
typedef typename ConstMeshRight::TetraType TetraRight;
|
||||
typedef typename ConstMeshRight::TetraPointer TetraPointerRight;
|
||||
typedef typename ConstMeshRight::TetraIterator TetraIteratorRight;
|
||||
typedef typename ConstMeshRight::VertexPointer VertexPointerRight;
|
||||
typedef typename ConstMeshRight::VertexIterator VertexIteratorRight;
|
||||
typedef typename ConstMeshRight::EdgeIterator EdgeIteratorRight;
|
||||
|
@ -68,7 +73,7 @@ public:
|
|||
|
||||
struct Remap{
|
||||
static size_t InvalidIndex() { return std::numeric_limits<size_t>::max(); }
|
||||
std::vector<size_t> vert,face,edge, hedge;
|
||||
std::vector<size_t> vert, face, edge, hedge, tetra;
|
||||
};
|
||||
|
||||
static void ImportVertexAdj(MeshLeft &ml, ConstMeshRight &mr, VertexLeft &vl, VertexRight &vr, Remap &remap ){
|
||||
|
@ -91,6 +96,13 @@ public:
|
|||
vl.VHp() = &ml.hedge[remap.hedge[Index(mr,vr.cVHp())]];
|
||||
vl.VHi() = vr.VHi();
|
||||
}
|
||||
|
||||
// Vertex to Tetra Adj
|
||||
if(HasVTAdjacency(ml) && HasVTAdjacency(mr) && vr.cVTp() != 0){
|
||||
size_t i = Index(mr, vr.cVTp());
|
||||
vl.VTp() = (i > ml.edge.size()) ? 0 : &ml.tetra[remap.tetra[i]];
|
||||
vl.VTi() = vr.VTi();
|
||||
}
|
||||
}
|
||||
|
||||
static void ImportEdgeAdj(MeshLeft &ml, ConstMeshRight &mr, EdgeLeft &el, const EdgeRight &er, Remap &remap)
|
||||
|
@ -177,6 +189,21 @@ public:
|
|||
hl.HPp() = &ml.hedge[remap.hedge[Index(mr,hr.cHPp())]];
|
||||
}
|
||||
|
||||
static void ImportTetraAdj(MeshLeft &ml, ConstMeshRight &mr, TetraLeft &tl, const TetraRight &tr, Remap &remap )
|
||||
{
|
||||
// Tetra to Tetra Adj
|
||||
if(HasTTAdjacency(ml) && HasTTAdjacency(mr)){
|
||||
assert(tl.TN() == tr.TN());
|
||||
for( int vi = 0; vi < 4; ++vi ){
|
||||
size_t idx = remap.tetra[Index(mr,tr.cTTp(vi))];
|
||||
if(idx != Remap::InvalidIndex()){
|
||||
tl.TTp(vi) = &ml.tetra[idx];
|
||||
tl.TTi(vi) = tr.cTTi(vi);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Append Right Mesh to the Left Mesh
|
||||
// Append::Mesh(ml, mr) is equivalent to ml += mr.
|
||||
// Note MeshRigth could be costant...
|
||||
|
@ -276,6 +303,16 @@ static void Mesh(MeshLeft& ml, ConstMeshRight& mr, const bool selected = false,
|
|||
remap.hedge[ind]=Index(ml,*hp);
|
||||
}
|
||||
|
||||
remap.tetra.resize(mr.tetra.size(), Remap::InvalidIndex());
|
||||
for (TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti)
|
||||
if (!(*ti).IsD() && (!selected || (*ti).IsS())) {
|
||||
size_t idx = Index(mr, *ti);
|
||||
assert (remap.tetra[ind] == Remap::InvalidIndex());
|
||||
TetraIteratorLeft tp = Allocator<MeshLeft>::AddTetras(ml, 1);
|
||||
(*tp).ImportData(*ti);
|
||||
remap.tetra[idx] = Index(ml, *tp);
|
||||
}
|
||||
|
||||
// phase 2.
|
||||
// copy data from ml to its corresponding elements in ml and adjacencies
|
||||
|
||||
|
@ -324,6 +361,21 @@ static void Mesh(MeshLeft& ml, ConstMeshRight& mr, const bool selected = false,
|
|||
if(!(*hi).IsD() && (!selected || (*hi).IsS())){
|
||||
ml.hedge[remap.hedge[Index(mr,*hi)]].ImportData(*hi);
|
||||
ImportHEdgeAdj(ml,mr,ml.hedge[remap.hedge[Index(mr,*hi)]],*hi,remap,selected);
|
||||
}
|
||||
|
||||
//tetra
|
||||
for(TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti)
|
||||
if(!(*ti).IsD() && (!selected || (*ti).IsS()))
|
||||
{
|
||||
TetraLeft &tl = ml.tetra[remap.tetra[Index(mr,*ti)]];
|
||||
|
||||
if(HasFVAdjacency(ml) && HasFVAdjacency(mr)){
|
||||
for(int i = 0; i < 4; ++i)
|
||||
tl.V(i) = &ml.vert[remap.vert[Index(mr,ti->cV(i))]];
|
||||
}
|
||||
tl.ImportData(*ti);
|
||||
if(adjFlag) ImportTetraAdj(ml, mr, ml.tetra[remap.tetra[Index(mr,*ti)]], *ti, remap);
|
||||
|
||||
}
|
||||
|
||||
// phase 3.
|
||||
|
@ -381,6 +433,18 @@ static void Mesh(MeshLeft& ml, ConstMeshRight& mr, const bool selected = false,
|
|||
}
|
||||
}
|
||||
|
||||
// per tetra attributes
|
||||
for(al = ml.tetra_attr.begin(); al != ml.tetra_attr.end(); ++al)
|
||||
if(!(*al)._name.empty()){
|
||||
ar = mr.tetra_attr.find(*al);
|
||||
if(ar!= mr.tetra_attr.end()){
|
||||
id_r = 0;
|
||||
for(TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti, ++id_r)
|
||||
if( !(*ti).IsD() && (!selected || (*ti).IsS()))
|
||||
memcpy((*al)._handle->At(remap.tetra[Index(mr, *ti)]),(*ar)._handle->At(id_r),
|
||||
(*al)._handle->SizeOf());
|
||||
}
|
||||
}
|
||||
// per mesh attributes
|
||||
// if both ml and mr have an attribute with the same name, no action is done
|
||||
// if mr has an attribute that is NOT present in ml, the attribute is added to ml
|
||||
|
|
|
@ -62,6 +62,8 @@ namespace tri {
|
|||
typedef std::vector< typename TYPESPOOL::EdgeType > CONTE;
|
||||
typedef std::vector< typename TYPESPOOL::FaceType > CONTF;
|
||||
typedef std::vector< typename TYPESPOOL::HEdgeType > CONTH;
|
||||
typedef std::vector<typename TYPESPOOL::TetraType> CONTT;
|
||||
|
||||
|
||||
typedef CONTV VertContainer;
|
||||
typedef typename CONTV::value_type VertexType;
|
||||
|
@ -90,6 +92,13 @@ namespace tri {
|
|||
typedef typename CONTH::iterator HEdgeIterator;
|
||||
typedef typename CONTH::const_iterator ConstHEdgeIterator;
|
||||
|
||||
typedef CONTT TetraContainer;
|
||||
typedef typename CONTT::value_type TetraType;
|
||||
typedef typename TYPESPOOL::TetraPointer TetraPointer;
|
||||
typedef const typename TYPESPOOL::TetraPointer ConstTetraPointer;
|
||||
typedef typename CONTT::iterator TetraIterator;
|
||||
typedef typename CONTT::const_iterator ConstTetraIterator;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
@ -137,7 +146,18 @@ namespace tri {
|
|||
typedef typename HEdgeContainer::value_type * HEdgePointer;
|
||||
typedef typename HEdgeContainer::iterator HEdgeIterator;
|
||||
typedef typename HEdgeContainer::const_iterator ConstHEdgeIterator;
|
||||
};
|
||||
};
|
||||
|
||||
template <typename T, class CONT>
|
||||
struct MeshTypeHolder<T, CONT, AllTypes::ATetraType> : public T
|
||||
{
|
||||
typedef CONT TetraContainer;
|
||||
typedef typename TetraContainer::value_type TetraType;
|
||||
typedef TetraType *TetraPointer;
|
||||
typedef const TetraType *ConstTetraPointer;
|
||||
typedef typename TetraContainer::iterator TetraIterator;
|
||||
typedef typename TetraContainer::const_iterator ConstTetraIterator;
|
||||
};
|
||||
|
||||
template <typename T, typename CONT> struct Der: public MeshTypeHolder<T,CONT, typename CONT::value_type::IAm>{};
|
||||
struct DummyContainer{struct value_type{ typedef int IAm;}; };
|
||||
|
@ -146,15 +166,16 @@ struct DummyContainer{struct value_type{ typedef int IAm;}; };
|
|||
As explained in \ref basic_concepts, this class is templated over a list of container of simplexes (like vertex, face, edges)
|
||||
*/
|
||||
|
||||
template < class Container0 = DummyContainer, class Container1 = DummyContainer, class Container2 = DummyContainer, class Container3 = DummyContainer >
|
||||
template < class Container0 = DummyContainer, class Container1 = DummyContainer, class Container2 = DummyContainer, class Container3 = DummyContainer, class Container4 = DummyContainer >
|
||||
class TriMesh
|
||||
: public MArity4< BaseMeshTypeHolder<typename Container0::value_type::TypesPool>, Container0, Der ,Container1, Der, Container2, Der, Container3, Der>{
|
||||
: public MArity5< BaseMeshTypeHolder<typename Container0::value_type::TypesPool>, Container0, Der ,Container1, Der, Container2, Der, Container3, Der, Container4, Der >{
|
||||
public:
|
||||
|
||||
typedef typename TriMesh::ScalarType ScalarType;
|
||||
typedef typename TriMesh::VertContainer VertContainer;
|
||||
typedef typename TriMesh::EdgeContainer EdgeContainer;
|
||||
typedef typename TriMesh::FaceContainer FaceContainer;
|
||||
typedef typename TriMesh::TetraContainer TetraContainer;
|
||||
|
||||
// types for vertex
|
||||
typedef typename TriMesh::VertexType VertexType;
|
||||
|
@ -184,9 +205,16 @@ class TriMesh
|
|||
typedef typename TriMesh::HEdgeContainer HEdgeContainer;
|
||||
typedef typename TriMesh::ConstHEdgeIterator ConstHEdgeIterator;
|
||||
|
||||
// types for tetra
|
||||
typedef typename TriMesh::TetraType TetraType;
|
||||
typedef typename TriMesh::TetraPointer TetraPointer;
|
||||
typedef typename TriMesh::TetraIterator TetraIterator;
|
||||
typedef typename TriMesh::TetraContainer TetraContainer;
|
||||
typedef typename TriMesh::ConstTetraIterator ConstTetraIterator;
|
||||
|
||||
typedef vcg::PointerToAttribute PointerToAttribute;
|
||||
|
||||
typedef TriMesh<Container0, Container1,Container2,Container3> MeshType;
|
||||
typedef TriMesh<Container0, Container1, Container2, Container3, Container4> MeshType;
|
||||
|
||||
typedef Box3<ScalarType> BoxType;
|
||||
|
||||
|
@ -218,6 +246,13 @@ class TriMesh
|
|||
/// Current number of halfedges;
|
||||
inline int HN() const { return hn; }
|
||||
|
||||
/// Container of tetras, usually a vector.
|
||||
TetraContainer tetra;
|
||||
/// Current number of tetras; this member is for internal use only. You should always use the TN() member
|
||||
int tn;
|
||||
/// Current number of tetras;
|
||||
inline int TN() const { return tn; }
|
||||
|
||||
/// Bounding box of the mesh
|
||||
Box3<typename TriMesh::VertexType::CoordType::ScalarType> bbox;
|
||||
|
||||
|
@ -234,7 +269,7 @@ class TriMesh
|
|||
std::set< PointerToAttribute > edge_attr;
|
||||
std::set< PointerToAttribute > face_attr;
|
||||
std::set< PointerToAttribute > mesh_attr;
|
||||
|
||||
std::set< PointerToAttribute > tetra_attr;
|
||||
|
||||
|
||||
template <class ATTR_TYPE, class CONT>
|
||||
|
@ -282,6 +317,14 @@ class TriMesh
|
|||
PerEdgeAttributeHandle( void *ah,const int & n):AttributeHandle<ATTR_TYPE,EdgeContainer>(ah,n){}
|
||||
};
|
||||
|
||||
template <class ATTR_TYPE>
|
||||
class PerTetraAttributeHandle : public AttributeHandle<ATTR_TYPE, TetraContainer>
|
||||
{
|
||||
public:
|
||||
PerTetraAttributeHandle() : AttributeHandle<ATTR_TYPE, TetraContainer>() {}
|
||||
PerTetraAttributeHandle(void *ah, const int &n) : AttributeHandle<ATTR_TYPE, TetraContainer>(ah, n) {}
|
||||
};
|
||||
|
||||
template <class ATTR_TYPE>
|
||||
class PerMeshAttributeHandle{
|
||||
public:
|
||||
|
@ -309,6 +352,11 @@ class TriMesh
|
|||
typedef typename MeshType::template PerFaceAttributeHandle<bool> PerFaceBoolHandle;
|
||||
typedef typename MeshType::template PerFaceAttributeHandle<CoordType> PerFaceCoordHandle;
|
||||
|
||||
typedef typename MeshType::template PerTetraAttributeHandle<ScalarType> PerTetraScalarHandle;
|
||||
typedef typename MeshType::template PerTetraAttributeHandle<int> PerTetraIntHandle;
|
||||
typedef typename MeshType::template PerTetraAttributeHandle<bool> PerTetraBoolHandle;
|
||||
typedef typename MeshType::template PerTetraAttributeHandle<CoordType> PerTetraCoordHandle;
|
||||
|
||||
|
||||
// the camera member (that should keep the intrinsics) is no more needed since 2006, when intrisncs moved into the Shot structure
|
||||
//Camera<ScalarType> camera; // intrinsic
|
||||
|
@ -346,12 +394,14 @@ public:
|
|||
size += ((SimpleTempDataBase*)(*i)._handle)->SizeOf()*en;
|
||||
for( i = face_attr.begin(); i != face_attr.end(); ++i)
|
||||
size += ((SimpleTempDataBase*)(*i)._handle)->SizeOf()*nf;
|
||||
for (i = tetra_attr.begin(); i != tetra_attr.end(); ++i)
|
||||
size += ((SimpleTempDataBase *)(*i)._handle)->SizeOf() * nt;
|
||||
for( i = mesh_attr.begin(); i != mesh_attr.end(); ++i)
|
||||
size += ((SimpleTempDataBase*)(*i)._handle)->SizeOf();
|
||||
|
||||
return size;
|
||||
}
|
||||
int MemUsed() const {return Mem(vert.size(),face.size());}
|
||||
int MemUsed() const {return Mem(vert.size(),face.size(), tetra.size());}
|
||||
inline int MemNeeded() const {return Mem(vn,fn);}
|
||||
|
||||
|
||||
|
@ -370,6 +420,7 @@ public:
|
|||
en = 0;
|
||||
fn = 0;
|
||||
hn = 0;
|
||||
tn = 0;
|
||||
imark = 0;
|
||||
C()=Color4b::Gray;
|
||||
}
|
||||
|
@ -391,6 +442,10 @@ public:
|
|||
delete ((SimpleTempDataBase*)(*i)._handle);
|
||||
face_attr.clear();
|
||||
|
||||
for (i = tetra_attr.begin(); i != tetra_attr.end(); ++i)
|
||||
delete ((SimpleTempDataBase *)(*i)._handle);
|
||||
tetra_attr.clear();
|
||||
|
||||
for (i = mesh_attr.begin(); i != mesh_attr.end(); ++i)
|
||||
delete ((SimpleTempDataBase*)(*i)._handle);
|
||||
mesh_attr.clear();
|
||||
|
@ -399,7 +454,7 @@ public:
|
|||
|
||||
bool IsEmpty() const
|
||||
{
|
||||
return vert.empty() && edge.empty() && face.empty();
|
||||
return vert.empty() && edge.empty() && face.empty() && tetra.empty();
|
||||
}
|
||||
|
||||
int & SimplexNumber(){ return fn;}
|
||||
|
@ -434,6 +489,18 @@ template <class MeshType> inline void InitVertexIMark(MeshType & m)
|
|||
if( !(*vi).IsD() && (*vi).IsRW() )
|
||||
(*vi).InitIMark();
|
||||
}
|
||||
|
||||
///initialize the imark-sysyem of the tetras
|
||||
template <class MeshType>
|
||||
inline void InitTetraIMark(MeshType &m)
|
||||
{
|
||||
typename MeshType::TetraIterator ti;
|
||||
|
||||
for (ti = m.tetra.begin(); ti != m.tetra.end(); ++ti)
|
||||
if (!(*ti).IsD() && (*ti).IsRW())
|
||||
(*ti).InitIMark();
|
||||
}
|
||||
|
||||
/** \brief Access function to the incremental mark.
|
||||
You should not use this member directly. In most of the case just use IsMarked() and Mark()
|
||||
*/
|
||||
|
@ -449,6 +516,12 @@ template <class MeshType> inline bool IsMarked(MeshType & m, typename MeshType::
|
|||
@param f Face pointer */
|
||||
template <class MeshType> inline bool IsMarked( MeshType & m,typename MeshType::ConstFacePointer f ) { return f->cIMark() == m.imark; }
|
||||
|
||||
/** \brief Check if the tetra incremental mark matches the one of the mesh.
|
||||
@param m the mesh containing the element
|
||||
@param t tetra pointer */
|
||||
template <class MeshType>
|
||||
inline bool IsMarked(MeshType &m, typename MeshType::ConstTetraPointer t) { return t->cIMark() == m.imark; }
|
||||
|
||||
/** \brief Set the vertex incremental mark of the vertex to the one of the mesh.
|
||||
@param m the mesh containing the element
|
||||
@param v Vertex pointer */
|
||||
|
@ -459,6 +532,12 @@ template <class MeshType> inline void Mark(MeshType & m, typename MeshType::Vert
|
|||
@param f Vertex pointer */
|
||||
template <class MeshType> inline void Mark(MeshType & m, typename MeshType::FacePointer f ) { f->IMark() = m.imark; }
|
||||
|
||||
/** \brief Set the tetra incremental mark to the one of the mesh.
|
||||
@param m the mesh containing the element
|
||||
@param t tetra pointer */
|
||||
template <class MeshType>
|
||||
inline void Mark(MeshType &m, typename MeshType::TetraPointer t) { t->IMark() = m.imark; }
|
||||
|
||||
|
||||
/** \brief Unmark, in constant time, all the elements (face and vertices) of a mesh.
|
||||
@param m the mesh containing the element
|
||||
|
@ -479,13 +558,17 @@ template <class MeshType> inline void UnMarkAll(MeshType & m)
|
|||
|
||||
template < class VertexType> bool VertexVectorHasVFAdjacency (const std::vector<VertexType> &) { return VertexType::HasVFAdjacency(); }
|
||||
template < class VertexType> bool VertexVectorHasVEAdjacency (const std::vector<VertexType> &) { return VertexType::HasVEAdjacency(); }
|
||||
template < class VertexType> bool VertexVectorHasVTAdjacency (const std::vector<VertexType> &) { return VertexType::HasVTAdjacency(); }
|
||||
template < class EdgeType > bool EdgeVectorHasVEAdjacency (const std::vector<EdgeType > &) { return EdgeType::HasVEAdjacency(); }
|
||||
template < class EdgeType > bool EdgeVectorHasEEAdjacency (const std::vector<EdgeType> &) { return EdgeType::HasEEAdjacency(); }
|
||||
template < class EdgeType > bool EdgeVectorHasEFAdjacency (const std::vector<EdgeType> &) { return EdgeType::HasEFAdjacency(); }
|
||||
template < class FaceType > bool FaceVectorHasVFAdjacency (const std::vector<FaceType > &) { return FaceType::HasVFAdjacency(); }
|
||||
|
||||
template < class TriMeshType> bool HasPerVertexVFAdjacency (const TriMeshType &m) { return tri::VertexVectorHasVFAdjacency(m.vert); }
|
||||
template < class TriMeshType> bool HasPerVertexVEAdjacency (const TriMeshType &m) { return tri::VertexVectorHasVEAdjacency(m.vert); }
|
||||
template < class TriMeshType> bool HasPerVertexVTAdjacency (const TriMeshType &m) { return tetra::VertexVectorHasVTAdjacency(m.vert); }
|
||||
template < class TriMeshType> bool HasPerEdgeVEAdjacency (const TriMeshType &m) { return tri::EdgeVectorHasVEAdjacency (m.edge); }
|
||||
template < class TriMeshType> bool HasPerEdgeEFAdjacency (const TriMeshType &m) { return tri::EdgeVectorHasEFAdjacency (m.edge); }
|
||||
template < class TriMeshType> bool HasPerFaceVFAdjacency (const TriMeshType &m) { return tri::FaceVectorHasVFAdjacency (m.face); }
|
||||
|
||||
|
||||
|
@ -549,14 +632,30 @@ template < class TriMeshType> bool HasPerFaceColor (const TriMeshType &m)
|
|||
template < class TriMeshType> bool HasPerFaceMark (const TriMeshType &m) { return tri::FaceVectorHasPerFaceMark (m.face); }
|
||||
template < class TriMeshType> bool HasPerFaceQuality (const TriMeshType &m) { return tri::FaceVectorHasPerFaceQuality (m.face); }
|
||||
template < class TriMeshType> bool HasPerFaceCurvatureDir(const TriMeshType &m) { return tri::FaceVectorHasPerFaceCurvatureDir(m.face); }
|
||||
|
||||
|
||||
template < class TetraType> bool TetraVectorHasPerTetraFlags (const std::vector<TetraType> &) { return TetraType::HasFlags (); }
|
||||
template < class TetraType> bool TetraVectorHasPerTetraColor (const std::vector<TetraType> &) { return TetraType::HasColor (); }
|
||||
template < class TetraType> bool TetraVectorHasPerTetraMark (const std::vector<TetraType> &) { return TetraType::HasMark (); }
|
||||
template < class TetraType> bool TetraVectorHasPerTetraQuality(const std::vector<TetraType> &) { return TetraType::HasQuality(); }
|
||||
template < class TetraType> bool TetraVectorHasVTAdjacency (const std::vector<TetraType> &) { return TetraType::HasVTAdjacency(); }
|
||||
template < class TetraType> bool TetraVectorHasTTAdjacency (const std::vector<TetraType> &) { return TetraType::HasTTAdjacency(); }
|
||||
|
||||
template < class TriMeshType> bool HasPerTetraFlags (const TriMeshType &m) { return tri::FaceVectorHasPerTetraFlags (m.face); }
|
||||
template < class TriMeshType> bool HasPerTetraColor (const TriMeshType &m) { return tri::FaceVectorHasPerTetraColor (m.face); }
|
||||
template < class TriMeshType> bool HasPerTetraMark (const TriMeshType &m) { return tri::FaceVectorHasPerTetraMark (m.face); }
|
||||
template < class TriMeshType> bool HasPerTetraQuality (const TriMeshType &m) { return tri::FaceVectorHasPerTetraQuality (m.face); }
|
||||
|
||||
template < class TriMeshType> bool HasFFAdjacency (const TriMeshType &m) { return tri::FaceVectorHasFFAdjacency (m.face); }
|
||||
template < class TriMeshType> bool HasEEAdjacency (const TriMeshType &m) { return tri::EdgeVectorHasEEAdjacency (m.edge); }
|
||||
template < class TriMeshType> bool HasFEAdjacency (const TriMeshType &m) { return tri::FaceVectorHasFEAdjacency (m.face); }
|
||||
template < class TriMeshType> bool HasEFAdjacency (const TriMeshType &m) { return tri::FaceVectorHasFEAdjacency(m.face) && tri::EdgeVectorHasEFAdjacency(m.edge); }
|
||||
template < class TriMeshType> bool HasFVAdjacency (const TriMeshType &m) { return tri::FaceVectorHasFVAdjacency (m.face); }
|
||||
|
||||
template < class TriMeshType> bool HasVFAdjacency (const TriMeshType &m) { return tri::FaceVectorHasVFAdjacency (m.face) && tri::VertexVectorHasVFAdjacency(m.vert); }
|
||||
template < class TriMeshType> bool HasVEAdjacency (const TriMeshType &m) { return tri::EdgeVectorHasVEAdjacency (m.edge) && tri::VertexVectorHasVEAdjacency(m.vert); }
|
||||
|
||||
template < class TriMeshType> bool HasTVAdjacency (const TriMeshType &m) { return tri::TetraVectorHasVTAdjacency(m.tetra); }
|
||||
template < class TriMeshType> bool HasVTAdjacency (const TriMeshType &m) { return tri::VertexVectorHasVTAdjacency(m.vert) && tri::TetraVectorHasVTAdjacency(m.tetra); }
|
||||
template < class TriMeshType> bool HasTTAdjacency (const TriMeshType &m) { return tri::TetraVectorHasTTAdjacency(m.tetra); }
|
||||
|
||||
|
||||
//template < class CType0, class CType1, class CType2 , class CType3>
|
||||
|
@ -630,6 +729,16 @@ bool HasPerFaceAttribute(const MeshType &m, std::string name){
|
|||
return (ai!= m.face_attr.end() ) ;
|
||||
}
|
||||
|
||||
template <class MeshType>
|
||||
bool HasPerTetraAttribute(const MeshType &m, std::string name)
|
||||
{
|
||||
typename std::set<typename MeshType::PointerToAttribute>::const_iterator ai;
|
||||
typename MeshType::PointerToAttribute h;
|
||||
h._name = name;
|
||||
ai = m.tetra_attr.find(h);
|
||||
return (ai != m.tetra_attr.end());
|
||||
}
|
||||
|
||||
template <class MeshType>
|
||||
bool HasPerMeshAttribute(const MeshType &m, std::string name){
|
||||
typename std::set< typename MeshType::PointerToAttribute>::const_iterator ai;
|
||||
|
@ -648,13 +757,20 @@ template <class MeshType> void RequireFaceCompactness (MeshType &m) {
|
|||
template <class MeshType> void RequireEdgeCompactness (MeshType &m) {
|
||||
if(m.edge.size()!=size_t(m.en)) throw vcg::MissingCompactnessException("Edge Vector Contains deleted elements");
|
||||
}
|
||||
|
||||
template <class MeshType> void RequireCompactness (MeshType &m) {
|
||||
RequireVertexCompactness<MeshType>(m);
|
||||
RequireFaceCompactness<MeshType> (m);
|
||||
RequireEdgeCompactness<MeshType> (m);
|
||||
template <class MeshType> void RequireTetraCompactness(MeshType &m) {
|
||||
if (m.tetra.size() != size_t(m.tn)) throw vcg::MissingCompactnessException("Tetra Vector Contains deleted elements");
|
||||
}
|
||||
|
||||
template <class MeshType>
|
||||
void RequireCompactness(MeshType &m)
|
||||
{
|
||||
RequireVertexCompactness<MeshType>(m);
|
||||
RequireFaceCompactness<MeshType>(m);
|
||||
RequireEdgeCompactness<MeshType>(m);
|
||||
RequireTetraCompactness<MeshType>(m);
|
||||
}
|
||||
|
||||
//todo require tetramesh
|
||||
template <class MeshType> void RequireTriangularMesh (MeshType &m ) { if( tri::HasPolyInfo( m ) ) throw vcg::MissingTriangularRequirementException("");}
|
||||
template <class MeshType> void RequirePolygonalMesh (MeshType &m ) { if(!tri::HasPolyInfo( m ) ) throw vcg::MissingPolygonalRequirementException("");}
|
||||
|
||||
|
@ -664,6 +780,8 @@ template <class MeshType> void RequireFFAdjacency (MeshType &m) { if(!tri::Ha
|
|||
template <class MeshType> void RequireEEAdjacency (MeshType &m) { if(!tri::HasEEAdjacency (m)) throw vcg::MissingComponentException("EEAdjacency"); }
|
||||
template <class MeshType> void RequireFEAdjacency (MeshType &m) { if(!tri::HasFEAdjacency (m)) throw vcg::MissingComponentException("FEAdjacency"); }
|
||||
template <class MeshType> void RequireFHAdjacency (MeshType &m) { if(!tri::HasFHAdjacency (m)) throw vcg::MissingComponentException("FHAdjacency"); }
|
||||
template <class MeshType> void RequireVTAdjacency (MeshType &m) { if(!tri::HasVTAdjacency (m)) throw vcg::MissingComponentException("VTAdjacency"); }
|
||||
template <class MeshType> void RequireTTAdjacency (MeshType &m) { if(!tri::HasTTAdjacency (m)) throw vcg::MissingComponentException("TTAdjacency"); }
|
||||
|
||||
template <class MeshType> void RequirePerVertexQuality (MeshType &m) { if(!tri::HasPerVertexQuality (m)) throw vcg::MissingComponentException("PerVertexQuality "); }
|
||||
template <class MeshType> void RequirePerVertexNormal (MeshType &m) { if(!tri::HasPerVertexNormal (m)) throw vcg::MissingComponentException("PerVertexNormal "); }
|
||||
|
@ -692,9 +810,15 @@ template <class MeshType> void RequirePerFaceWedgeColor (MeshType &m) { if(!tr
|
|||
template <class MeshType> void RequirePerFaceWedgeNormal (MeshType &m) { if(!tri::HasPerWedgeNormal (m)) throw vcg::MissingComponentException("PerFaceWedgeNormal "); }
|
||||
template <class MeshType> void RequirePerFaceWedgeTexCoord(MeshType &m) { if(!tri::HasPerWedgeTexCoord(m)) throw vcg::MissingComponentException("PerFaceWedgeTexCoord"); }
|
||||
|
||||
template <class MeshType> void RequirePerTetraFlags (MeshType &m) { if(!tri::HasPerTetraFlags (m)) throw vcg::MissingComponentException("PerTetraFlags "); }
|
||||
template <class MeshType> void RequirePerTetraColor (MeshType &m) { if(!tri::HasPerTetraColor (m)) throw vcg::MissingComponentException("PerTetraColor "); }
|
||||
template <class MeshType> void RequirePerTetraMark (MeshType &m) { if(!tri::HasPerTetraMark (m)) throw vcg::MissingComponentException("PerTetraMark "); }
|
||||
template <class MeshType> void RequirePerTetraQuality (MeshType &m) { if(!tri::HasPerTetraQuality (m)) throw vcg::MissingComponentException("PerTetraQuality "); }
|
||||
|
||||
template <class MeshType> void RequirePerVertexAttribute(MeshType &m, const char *name) { if(!HasPerVertexAttribute(m,name)) throw vcg::MissingComponentException("PerVertex attribute"); }
|
||||
template <class MeshType> void RequirePerEdgeAttribute(MeshType &m, const char *name) { if(!HasPerEdgeAttribute(m,name)) throw vcg::MissingComponentException("PerEdge attribute"); }
|
||||
template <class MeshType> void RequirePerFaceAttribute(MeshType &m, const char *name) { if(!HasPerFaceAttribute(m,name)) throw vcg::MissingComponentException("PerFace attribute"); }
|
||||
template <class MeshType> void RequirePerTetraAttribute(MeshType &m, const char *name) { if(!HasPerTetraAttribute(m,name)) throw vcg::MissingComponentException("PerTetra attribute"); }
|
||||
template <class MeshType> void RequirePerMeshAttribute(MeshType &m, const char *name) { if(!HasPerMeshAttribute(m,name)) throw vcg::MissingComponentException("PerMesh attribute"); }
|
||||
|
||||
/*@}*/
|
||||
|
|
|
@ -50,6 +50,8 @@
|
|||
#include <vcg/simplex/face/topology.h>
|
||||
#include <vcg/simplex/edge/pos.h>
|
||||
#include <vcg/simplex/edge/topology.h>
|
||||
#include <vcg/simplex/tetrahedron/pos.h>
|
||||
// #include <vcg/simplex/tetrahedron/topology.h>
|
||||
#include <vcg/complex/foreach.h>
|
||||
#include <vcg/complex/algorithms/update/flag.h>
|
||||
#include <vcg/complex/algorithms/update/selection.h>
|
||||
|
|
|
@ -83,6 +83,21 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class MissingTetrahedralRequirementException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
MissingTetrahedralRequirementException(const std::string &err):std::runtime_error(err)
|
||||
{
|
||||
std::cout << "Mesh has to be composed by tetrahedras -" << err << "- \n";
|
||||
}
|
||||
|
||||
virtual const char *what() const throw ()
|
||||
{
|
||||
static char buf[128]="Mesh has to be composed by tetrahedras";
|
||||
return buf;
|
||||
}
|
||||
};
|
||||
|
||||
class MissingPreconditionException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -156,7 +156,53 @@ inline void ForEachEdge(MeshType &m, std::function<void (typename MeshType::Edge
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ForEachTetra Helper
|
||||
* to traverse all the tetras of a mesh you can simply write something like:
|
||||
*
|
||||
* ForEachTetra(m, [&](const TetraType &t){
|
||||
* MakeSomethingWithTetra(t);
|
||||
* });
|
||||
*
|
||||
*/
|
||||
|
||||
template <class MeshType>
|
||||
inline void ForEachTetra(const MeshType &m, std::function<void (const typename MeshType::TetraType &)> action)
|
||||
{
|
||||
if(m.tn == (int) m.tetra.size())
|
||||
{
|
||||
for(auto ti = m.tetra.begin(); ti! = m.tetra.end(); ++ti) {
|
||||
action(*ti);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(auto ti = m.tetra.begin(); ti != m.tetra.end(); ++ti)
|
||||
if(!(*ti).IsD())
|
||||
{
|
||||
action(*ti);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class MeshType>
|
||||
inline void ForEachTetra(MeshType &m, std::function<void (typename MeshType::TetraType &)> action)
|
||||
{
|
||||
if(m.tn == (int) m.tetra.size())
|
||||
{
|
||||
for(auto ti = m.tetra.begin(); ti! = m.tetra.end(); ++ti) {
|
||||
action(*ti);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(auto ti = m.tetra.begin(); ti != m.tetra.end(); ++ti)
|
||||
if(!(*ti).IsD())
|
||||
{
|
||||
action(*ti);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */ // end doxygen group trimesh
|
||||
} // end namespace tri
|
||||
|
|
|
@ -173,6 +173,20 @@ template <
|
|||
template <typename,typename> class D>
|
||||
class MArity4: public D<MArity3<Base, TA,A,TB, B, TC,C>,TD > {};
|
||||
|
||||
template <
|
||||
class Base,
|
||||
class TA,
|
||||
template <typename,typename> class A,
|
||||
class TB,
|
||||
template <typename,typename> class B,
|
||||
class TC,
|
||||
template <typename,typename> class C,
|
||||
class TD,
|
||||
template <typename,typename> class D,
|
||||
class TE,
|
||||
template <typename,typename> class E>
|
||||
class MArity5: public E<MArity4<Base, TA,A,TB, B, TC,C, TD, D>, TE> {};
|
||||
|
||||
|
||||
|
||||
class DumClass {};
|
||||
|
|
|
@ -55,13 +55,13 @@ public:
|
|||
static bool HasVertexRef() { return false; }
|
||||
static bool HasTVAdjacency() { return false; }
|
||||
|
||||
//Empty normals
|
||||
typedef typename T::VertexType::NormalType NormalType;
|
||||
NormalType &N(const int & ){ static NormalType dummynormal(0, 0, 0); assert(0); return dummynormal; }
|
||||
const NormalType cN(const int & ) const { static NormalType dummynormal(0, 0, 0); assert(0); return dummynormal; }
|
||||
// //Empty normals
|
||||
// typedef typename T::VertexType::NormalType NormalType;
|
||||
// NormalType &N(const int & ){ static NormalType dummynormal(0, 0, 0); assert(0); return dummynormal; }
|
||||
// const NormalType cN(const int & ) const { static NormalType dummynormal(0, 0, 0); assert(0); return dummynormal; }
|
||||
|
||||
static bool HasFaceNormal() { return false; }
|
||||
static bool HasFaceNormalOcc() { return false; }
|
||||
// static bool HasFaceNormal() { return false; }
|
||||
// static bool HasFaceNormalOcc() { return false; }
|
||||
|
||||
//Empty color
|
||||
typedef vcg::Color4b ColorType;
|
||||
|
@ -223,33 +223,33 @@ public:
|
|||
|
||||
// };
|
||||
|
||||
template <class A, class T> class FaceNormal: public T {
|
||||
public:
|
||||
typedef A NormalType;
|
||||
// template <class A, class T> class FaceNormal: public T {
|
||||
// public:
|
||||
// typedef A NormalType;
|
||||
|
||||
inline NormalType N(const int & i){ assert((i>=0)&&(i < 4)); return _facenormals[i]; }
|
||||
inline NormalType cN(const int & i) const { assert((i>=0)&&(i < 4)); return _facenormals[i]; }
|
||||
static bool HasFaceNormals() { return true; }
|
||||
static bool HasFaceNormalOcc() { return false; }
|
||||
// inline NormalType N(const int & i){ assert((i>=0)&&(i < 4)); return _facenormals[i]; }
|
||||
// inline NormalType cN(const int & i) const { assert((i>=0)&&(i < 4)); return _facenormals[i]; }
|
||||
// static bool HasFaceNormals() { return true; }
|
||||
// static bool HasFaceNormalOcc() { return false; }
|
||||
|
||||
template <class RightValueType>
|
||||
void ImportData(const RightValueType & rightT)
|
||||
{
|
||||
if(rightT.IsNormalEnabled()) N().Import(rightT.cN());
|
||||
T::ImportData(rightT);
|
||||
}
|
||||
// template <class RightValueType>
|
||||
// void ImportData(const RightValueType & rightT)
|
||||
// {
|
||||
// if(rightT.IsNormalEnabled()) N().Import(rightT.cN());
|
||||
// T::ImportData(rightT);
|
||||
// }
|
||||
|
||||
static void Name(std::vector<std::string> & name){name.push_back(std::string("FaceNormal"));T::Name(name);}
|
||||
// static void Name(std::vector<std::string> & name){name.push_back(std::string("FaceNormal"));T::Name(name);}
|
||||
|
||||
private:
|
||||
NormalType _facenormals[4];
|
||||
};
|
||||
// private:
|
||||
// NormalType _facenormals[4];
|
||||
// };
|
||||
|
||||
template <class T> class FaceNormal3f: public FaceNormal<vcg::Point3f, T>{
|
||||
public:static void Name(std::vector<std::string> & name){name.push_back(std::string("FaceNormal3f"));T::Name(name);} };
|
||||
//template <class T> class FaceNormal3f: public FaceNormal<vcg::Point3f, T>{
|
||||
//public:static void Name(std::vector<std::string> & name){name.push_back(std::string("FaceNormal3f"));T::Name(name);} };
|
||||
|
||||
template <class T> class FaceNormal3d: public FaceNormal<vcg::Point3d, T>{
|
||||
public:static void Name(std::vector<std::string> & name){name.push_back(std::string("FaceNormal3d"));T::Name(name);} };
|
||||
//template <class T> class FaceNormal3d: public FaceNormal<vcg::Point3d, T>{
|
||||
//public:static void Name(std::vector<std::string> & name){name.push_back(std::string("FaceNormal3d"));T::Name(name);} };
|
||||
|
||||
/*------------------------- FLAGS -----------------------------------------*/
|
||||
// template <class T> class EmptyBitFlags: public T {
|
||||
|
|
Loading…
Reference in New Issue