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();}
|
size_t Index(MeshType &m, const typename MeshType::EdgeType &e) {return &e-&*m.edge.begin();}
|
||||||
template<class MeshType>
|
template<class MeshType>
|
||||||
size_t Index(MeshType &m, const typename MeshType::HEdgeType &h) {return &h-&*m.hedge.begin();}
|
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>
|
template<class MeshType>
|
||||||
size_t Index(MeshType &m, const typename MeshType::VertexType *vp) {return vp-&*m.vert.begin();}
|
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();}
|
size_t Index(MeshType &m, const typename MeshType::EdgeType* e) {return e-&*m.edge.begin();}
|
||||||
template<class MeshType>
|
template<class MeshType>
|
||||||
size_t Index(MeshType &m, const typename MeshType::HEdgeType* h) {return h-&*m.hedge.begin();}
|
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>
|
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()) ); }
|
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())); }
|
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>
|
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())); }
|
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>
|
template <class MeshType, class ATTR_CONT>
|
||||||
void ReorderAttribute(ATTR_CONT &c, std::vector<size_t> & newVertIndex, MeshType & /* m */){
|
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::HEdgeIterator HEdgeIterator;
|
||||||
typedef typename MeshType::HEdgeContainer HEdgeContainer;
|
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 MeshType::PointerToAttribute PointerToAttribute;
|
||||||
typedef typename std::set<PointerToAttribute>::iterator AttrIterator;
|
typedef typename std::set<PointerToAttribute>::iterator AttrIterator;
|
||||||
|
@ -174,9 +186,12 @@ public:
|
||||||
static VertexIterator AddVertices(MeshType &m, size_t n, PointerUpdater<VertexPointer> &pu)
|
static VertexIterator AddVertices(MeshType &m, size_t n, PointerUpdater<VertexPointer> &pu)
|
||||||
{
|
{
|
||||||
VertexIterator last;
|
VertexIterator last;
|
||||||
if(n == 0) return m.vert.end();
|
if(n == 0)
|
||||||
|
return m.vert.end();
|
||||||
pu.Clear();
|
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 {
|
else {
|
||||||
pu.oldBase=&*m.vert.begin();
|
pu.oldBase=&*m.vert.begin();
|
||||||
pu.oldEnd=&m.vert.back()+1;
|
pu.oldEnd=&m.vert.back()+1;
|
||||||
|
@ -201,9 +216,12 @@ public:
|
||||||
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())
|
||||||
{
|
{
|
||||||
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());
|
// if(HasEVAdjacency(m)) pu.Update((*ei).EVp());
|
||||||
}
|
}
|
||||||
|
|
||||||
HEdgeIterator hi;
|
HEdgeIterator hi;
|
||||||
for (hi=m.hedge.begin(); hi!=m.hedge.end(); ++hi)
|
for (hi=m.hedge.begin(); hi!=m.hedge.end(); ++hi)
|
||||||
if(!(*hi).IsD())
|
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
|
// e poiche' lo spazio e' cambiato si ricalcola anche last da zero
|
||||||
}
|
}
|
||||||
size_t siz=(size_t)(m.vert.size()-n);
|
size_t siz=(size_t)(m.vert.size()-n);
|
||||||
|
@ -662,6 +686,196 @@ public:
|
||||||
return firstNewFace;
|
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 ++++++++++++++++ */
|
/* +++++++++++++++ Deleting ++++++++++++++++ */
|
||||||
|
|
||||||
/** Function to delete a face from the mesh.
|
/** Function to delete a face from the mesh.
|
||||||
|
@ -709,6 +923,17 @@ public:
|
||||||
--m.hn;
|
--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
|
Function to rearrange the vertex vector according to a given index permutation
|
||||||
the permutation is vector such that after calling this function
|
the permutation is vector such that after calling this function
|
||||||
|
@ -745,6 +970,15 @@ public:
|
||||||
}
|
}
|
||||||
else m.vert [ pu.remap[i] ].VEClear();
|
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());
|
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 tetras to update the pointers TV relation (vertex refs)
|
||||||
if(HasEVAdjacency(m))
|
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)
|
for(EdgeIterator ei=m.edge.begin();ei!=m.edge.end();++ei)
|
||||||
if(!(*ei).IsD())
|
if(!(*ei).IsD())
|
||||||
{
|
{
|
||||||
|
@ -784,14 +1027,14 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CompactEveryVector( MeshType &m)
|
static void CompactEveryVector(MeshType &m)
|
||||||
{
|
{
|
||||||
CompactVertexVector(m);
|
CompactVertexVector(m);
|
||||||
CompactEdgeVector(m);
|
CompactEdgeVector(m);
|
||||||
CompactFaceVector(m);
|
CompactFaceVector(m);
|
||||||
|
CompactTetraVector(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Compact vector of vertices removing deleted elements.
|
\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)
|
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] ].EEp(1) = m.edge[i].cEEp(1);
|
||||||
m.edge[ pu.remap[i] ].EEi(1) = m.edge[i].cEEi(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));
|
pu.Update((*ei).VEp(i));
|
||||||
if(HasEEAdjacency(m))
|
if(HasEEAdjacency(m))
|
||||||
pu.Update((*ei).EEp(i));
|
pu.Update((*ei).EEp(i));
|
||||||
|
if(HasEFAdjacency(m))
|
||||||
|
pu.Update((*ei).EFp(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1046,6 +1300,125 @@ public:
|
||||||
CompactFaceVector(m,pu);
|
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:
|
public:
|
||||||
|
@ -1441,6 +1814,136 @@ public:
|
||||||
return true;
|
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
|
/// Per Mesh Attributes
|
||||||
template <class ATTR_TYPE>
|
template <class ATTR_TYPE>
|
||||||
static
|
static
|
||||||
|
@ -1632,6 +2135,35 @@ public:
|
||||||
pa._padding = 0;
|
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>
|
template <class ATTR_TYPE>
|
||||||
static void FixPaddedPerMeshAttribute ( MeshType & /* m */,PointerToAttribute & pa){
|
static void FixPaddedPerMeshAttribute ( MeshType & /* m */,PointerToAttribute & pa){
|
||||||
|
|
|
@ -46,11 +46,13 @@ public:
|
||||||
typedef typename MeshLeft::EdgeType EdgeLeft;
|
typedef typename MeshLeft::EdgeType EdgeLeft;
|
||||||
typedef typename MeshLeft::FaceType FaceLeft;
|
typedef typename MeshLeft::FaceType FaceLeft;
|
||||||
typedef typename MeshLeft::HEdgeType HEdgeLeft;
|
typedef typename MeshLeft::HEdgeType HEdgeLeft;
|
||||||
|
typedef typename MeshLeft::TetraType TetraLeft;
|
||||||
typedef typename MeshLeft::VertexPointer VertexPointerLeft;
|
typedef typename MeshLeft::VertexPointer VertexPointerLeft;
|
||||||
typedef typename MeshLeft::VertexIterator VertexIteratorLeft;
|
typedef typename MeshLeft::VertexIterator VertexIteratorLeft;
|
||||||
typedef typename MeshLeft::EdgeIterator EdgeIteratorLeft;
|
typedef typename MeshLeft::EdgeIterator EdgeIteratorLeft;
|
||||||
typedef typename MeshLeft::HEdgeIterator HEdgeIteratorLeft;
|
typedef typename MeshLeft::HEdgeIterator HEdgeIteratorLeft;
|
||||||
typedef typename MeshLeft::FaceIterator FaceIteratorLeft;
|
typedef typename MeshLeft::FaceIterator FaceIteratorLeft;
|
||||||
|
typedef typename MeshLeft::TetraIterator TetraIteratorLeft;
|
||||||
|
|
||||||
|
|
||||||
typedef typename ConstMeshRight::ScalarType ScalarRight;
|
typedef typename ConstMeshRight::ScalarType ScalarRight;
|
||||||
|
@ -59,6 +61,9 @@ public:
|
||||||
typedef typename ConstMeshRight::EdgeType EdgeRight;
|
typedef typename ConstMeshRight::EdgeType EdgeRight;
|
||||||
typedef typename ConstMeshRight::HEdgeType HEdgeRight;
|
typedef typename ConstMeshRight::HEdgeType HEdgeRight;
|
||||||
typedef typename ConstMeshRight::FaceType FaceRight;
|
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::VertexPointer VertexPointerRight;
|
||||||
typedef typename ConstMeshRight::VertexIterator VertexIteratorRight;
|
typedef typename ConstMeshRight::VertexIterator VertexIteratorRight;
|
||||||
typedef typename ConstMeshRight::EdgeIterator EdgeIteratorRight;
|
typedef typename ConstMeshRight::EdgeIterator EdgeIteratorRight;
|
||||||
|
@ -68,7 +73,7 @@ public:
|
||||||
|
|
||||||
struct Remap{
|
struct Remap{
|
||||||
static size_t InvalidIndex() { return std::numeric_limits<size_t>::max(); }
|
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 ){
|
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.VHp() = &ml.hedge[remap.hedge[Index(mr,vr.cVHp())]];
|
||||||
vl.VHi() = vr.VHi();
|
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)
|
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())]];
|
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 Right Mesh to the Left Mesh
|
||||||
// Append::Mesh(ml, mr) is equivalent to ml += mr.
|
// Append::Mesh(ml, mr) is equivalent to ml += mr.
|
||||||
// Note MeshRigth could be costant...
|
// 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.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.
|
// phase 2.
|
||||||
// copy data from ml to its corresponding elements in ml and adjacencies
|
// 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())){
|
if(!(*hi).IsD() && (!selected || (*hi).IsS())){
|
||||||
ml.hedge[remap.hedge[Index(mr,*hi)]].ImportData(*hi);
|
ml.hedge[remap.hedge[Index(mr,*hi)]].ImportData(*hi);
|
||||||
ImportHEdgeAdj(ml,mr,ml.hedge[remap.hedge[Index(mr,*hi)]],*hi,remap,selected);
|
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.
|
// 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
|
// per mesh attributes
|
||||||
// if both ml and mr have an attribute with the same name, no action is done
|
// 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
|
// 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::EdgeType > CONTE;
|
||||||
typedef std::vector< typename TYPESPOOL::FaceType > CONTF;
|
typedef std::vector< typename TYPESPOOL::FaceType > CONTF;
|
||||||
typedef std::vector< typename TYPESPOOL::HEdgeType > CONTH;
|
typedef std::vector< typename TYPESPOOL::HEdgeType > CONTH;
|
||||||
|
typedef std::vector<typename TYPESPOOL::TetraType> CONTT;
|
||||||
|
|
||||||
|
|
||||||
typedef CONTV VertContainer;
|
typedef CONTV VertContainer;
|
||||||
typedef typename CONTV::value_type VertexType;
|
typedef typename CONTV::value_type VertexType;
|
||||||
|
@ -90,6 +92,13 @@ namespace tri {
|
||||||
typedef typename CONTH::iterator HEdgeIterator;
|
typedef typename CONTH::iterator HEdgeIterator;
|
||||||
typedef typename CONTH::const_iterator ConstHEdgeIterator;
|
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::value_type * HEdgePointer;
|
||||||
typedef typename HEdgeContainer::iterator HEdgeIterator;
|
typedef typename HEdgeContainer::iterator HEdgeIterator;
|
||||||
typedef typename HEdgeContainer::const_iterator ConstHEdgeIterator;
|
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>{};
|
template <typename T, typename CONT> struct Der: public MeshTypeHolder<T,CONT, typename CONT::value_type::IAm>{};
|
||||||
struct DummyContainer{struct value_type{ typedef int 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)
|
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
|
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:
|
public:
|
||||||
|
|
||||||
typedef typename TriMesh::ScalarType ScalarType;
|
typedef typename TriMesh::ScalarType ScalarType;
|
||||||
typedef typename TriMesh::VertContainer VertContainer;
|
typedef typename TriMesh::VertContainer VertContainer;
|
||||||
typedef typename TriMesh::EdgeContainer EdgeContainer;
|
typedef typename TriMesh::EdgeContainer EdgeContainer;
|
||||||
typedef typename TriMesh::FaceContainer FaceContainer;
|
typedef typename TriMesh::FaceContainer FaceContainer;
|
||||||
|
typedef typename TriMesh::TetraContainer TetraContainer;
|
||||||
|
|
||||||
// types for vertex
|
// types for vertex
|
||||||
typedef typename TriMesh::VertexType VertexType;
|
typedef typename TriMesh::VertexType VertexType;
|
||||||
|
@ -184,9 +205,16 @@ class TriMesh
|
||||||
typedef typename TriMesh::HEdgeContainer HEdgeContainer;
|
typedef typename TriMesh::HEdgeContainer HEdgeContainer;
|
||||||
typedef typename TriMesh::ConstHEdgeIterator ConstHEdgeIterator;
|
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 vcg::PointerToAttribute PointerToAttribute;
|
||||||
|
|
||||||
typedef TriMesh<Container0, Container1,Container2,Container3> MeshType;
|
typedef TriMesh<Container0, Container1, Container2, Container3, Container4> MeshType;
|
||||||
|
|
||||||
typedef Box3<ScalarType> BoxType;
|
typedef Box3<ScalarType> BoxType;
|
||||||
|
|
||||||
|
@ -218,6 +246,13 @@ class TriMesh
|
||||||
/// Current number of halfedges;
|
/// Current number of halfedges;
|
||||||
inline int HN() const { return hn; }
|
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
|
/// Bounding box of the mesh
|
||||||
Box3<typename TriMesh::VertexType::CoordType::ScalarType> bbox;
|
Box3<typename TriMesh::VertexType::CoordType::ScalarType> bbox;
|
||||||
|
|
||||||
|
@ -234,7 +269,7 @@ class TriMesh
|
||||||
std::set< PointerToAttribute > edge_attr;
|
std::set< PointerToAttribute > edge_attr;
|
||||||
std::set< PointerToAttribute > face_attr;
|
std::set< PointerToAttribute > face_attr;
|
||||||
std::set< PointerToAttribute > mesh_attr;
|
std::set< PointerToAttribute > mesh_attr;
|
||||||
|
std::set< PointerToAttribute > tetra_attr;
|
||||||
|
|
||||||
|
|
||||||
template <class ATTR_TYPE, class CONT>
|
template <class ATTR_TYPE, class CONT>
|
||||||
|
@ -282,6 +317,14 @@ class TriMesh
|
||||||
PerEdgeAttributeHandle( void *ah,const int & n):AttributeHandle<ATTR_TYPE,EdgeContainer>(ah,n){}
|
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>
|
template <class ATTR_TYPE>
|
||||||
class PerMeshAttributeHandle{
|
class PerMeshAttributeHandle{
|
||||||
public:
|
public:
|
||||||
|
@ -309,6 +352,11 @@ class TriMesh
|
||||||
typedef typename MeshType::template PerFaceAttributeHandle<bool> PerFaceBoolHandle;
|
typedef typename MeshType::template PerFaceAttributeHandle<bool> PerFaceBoolHandle;
|
||||||
typedef typename MeshType::template PerFaceAttributeHandle<CoordType> PerFaceCoordHandle;
|
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
|
// 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
|
//Camera<ScalarType> camera; // intrinsic
|
||||||
|
@ -346,12 +394,14 @@ public:
|
||||||
size += ((SimpleTempDataBase*)(*i)._handle)->SizeOf()*en;
|
size += ((SimpleTempDataBase*)(*i)._handle)->SizeOf()*en;
|
||||||
for( i = face_attr.begin(); i != face_attr.end(); ++i)
|
for( i = face_attr.begin(); i != face_attr.end(); ++i)
|
||||||
size += ((SimpleTempDataBase*)(*i)._handle)->SizeOf()*nf;
|
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)
|
for( i = mesh_attr.begin(); i != mesh_attr.end(); ++i)
|
||||||
size += ((SimpleTempDataBase*)(*i)._handle)->SizeOf();
|
size += ((SimpleTempDataBase*)(*i)._handle)->SizeOf();
|
||||||
|
|
||||||
return size;
|
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);}
|
inline int MemNeeded() const {return Mem(vn,fn);}
|
||||||
|
|
||||||
|
|
||||||
|
@ -370,6 +420,7 @@ public:
|
||||||
en = 0;
|
en = 0;
|
||||||
fn = 0;
|
fn = 0;
|
||||||
hn = 0;
|
hn = 0;
|
||||||
|
tn = 0;
|
||||||
imark = 0;
|
imark = 0;
|
||||||
C()=Color4b::Gray;
|
C()=Color4b::Gray;
|
||||||
}
|
}
|
||||||
|
@ -391,6 +442,10 @@ public:
|
||||||
delete ((SimpleTempDataBase*)(*i)._handle);
|
delete ((SimpleTempDataBase*)(*i)._handle);
|
||||||
face_attr.clear();
|
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)
|
for (i = mesh_attr.begin(); i != mesh_attr.end(); ++i)
|
||||||
delete ((SimpleTempDataBase*)(*i)._handle);
|
delete ((SimpleTempDataBase*)(*i)._handle);
|
||||||
mesh_attr.clear();
|
mesh_attr.clear();
|
||||||
|
@ -399,7 +454,7 @@ public:
|
||||||
|
|
||||||
bool IsEmpty() const
|
bool IsEmpty() const
|
||||||
{
|
{
|
||||||
return vert.empty() && edge.empty() && face.empty();
|
return vert.empty() && edge.empty() && face.empty() && tetra.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
int & SimplexNumber(){ return fn;}
|
int & SimplexNumber(){ return fn;}
|
||||||
|
@ -434,6 +489,18 @@ template <class MeshType> inline void InitVertexIMark(MeshType & m)
|
||||||
if( !(*vi).IsD() && (*vi).IsRW() )
|
if( !(*vi).IsD() && (*vi).IsRW() )
|
||||||
(*vi).InitIMark();
|
(*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.
|
/** \brief Access function to the incremental mark.
|
||||||
You should not use this member directly. In most of the case just use IsMarked() and 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 */
|
@param f Face pointer */
|
||||||
template <class MeshType> inline bool IsMarked( MeshType & m,typename MeshType::ConstFacePointer f ) { return f->cIMark() == m.imark; }
|
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.
|
/** \brief Set the vertex incremental mark of the vertex to the one of the mesh.
|
||||||
@param m the mesh containing the element
|
@param m the mesh containing the element
|
||||||
@param v Vertex pointer */
|
@param v Vertex pointer */
|
||||||
|
@ -459,6 +532,12 @@ template <class MeshType> inline void Mark(MeshType & m, typename MeshType::Vert
|
||||||
@param f Vertex pointer */
|
@param f Vertex pointer */
|
||||||
template <class MeshType> inline void Mark(MeshType & m, typename MeshType::FacePointer f ) { f->IMark() = m.imark; }
|
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.
|
/** \brief Unmark, in constant time, all the elements (face and vertices) of a mesh.
|
||||||
@param m the mesh containing the element
|
@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 VertexVectorHasVFAdjacency (const std::vector<VertexType> &) { return VertexType::HasVFAdjacency(); }
|
||||||
template < class VertexType> bool VertexVectorHasVEAdjacency (const std::vector<VertexType> &) { return VertexType::HasVEAdjacency(); }
|
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 EdgeVectorHasVEAdjacency (const std::vector<EdgeType > &) { return EdgeType::HasVEAdjacency(); }
|
||||||
template < class EdgeType > bool EdgeVectorHasEEAdjacency (const std::vector<EdgeType> &) { return EdgeType::HasEEAdjacency(); }
|
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 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 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 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 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); }
|
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 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 HasPerFaceQuality (const TriMeshType &m) { return tri::FaceVectorHasPerFaceQuality (m.face); }
|
||||||
template < class TriMeshType> bool HasPerFaceCurvatureDir(const TriMeshType &m) { return tri::FaceVectorHasPerFaceCurvatureDir(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 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 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 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 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 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 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>
|
//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() ) ;
|
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>
|
template <class MeshType>
|
||||||
bool HasPerMeshAttribute(const MeshType &m, std::string name){
|
bool HasPerMeshAttribute(const MeshType &m, std::string name){
|
||||||
typename std::set< typename MeshType::PointerToAttribute>::const_iterator ai;
|
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) {
|
template <class MeshType> void RequireEdgeCompactness (MeshType &m) {
|
||||||
if(m.edge.size()!=size_t(m.en)) throw vcg::MissingCompactnessException("Edge Vector Contains deleted elements");
|
if(m.edge.size()!=size_t(m.en)) throw vcg::MissingCompactnessException("Edge Vector Contains deleted elements");
|
||||||
}
|
}
|
||||||
|
template <class MeshType> void RequireTetraCompactness(MeshType &m) {
|
||||||
template <class MeshType> void RequireCompactness (MeshType &m) {
|
if (m.tetra.size() != size_t(m.tn)) throw vcg::MissingCompactnessException("Tetra Vector Contains deleted elements");
|
||||||
RequireVertexCompactness<MeshType>(m);
|
|
||||||
RequireFaceCompactness<MeshType> (m);
|
|
||||||
RequireEdgeCompactness<MeshType> (m);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 RequireTriangularMesh (MeshType &m ) { if( tri::HasPolyInfo( m ) ) throw vcg::MissingTriangularRequirementException("");}
|
||||||
template <class MeshType> void RequirePolygonalMesh (MeshType &m ) { if(!tri::HasPolyInfo( m ) ) throw vcg::MissingPolygonalRequirementException("");}
|
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 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 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 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 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 "); }
|
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 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 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 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 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 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"); }
|
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/face/topology.h>
|
||||||
#include <vcg/simplex/edge/pos.h>
|
#include <vcg/simplex/edge/pos.h>
|
||||||
#include <vcg/simplex/edge/topology.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/foreach.h>
|
||||||
#include <vcg/complex/algorithms/update/flag.h>
|
#include <vcg/complex/algorithms/update/flag.h>
|
||||||
#include <vcg/complex/algorithms/update/selection.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
|
class MissingPreconditionException : public std::runtime_error
|
||||||
{
|
{
|
||||||
public:
|
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 doxygen group trimesh
|
||||||
} // end namespace tri
|
} // end namespace tri
|
||||||
|
|
|
@ -173,6 +173,20 @@ template <
|
||||||
template <typename,typename> class D>
|
template <typename,typename> class D>
|
||||||
class MArity4: public D<MArity3<Base, TA,A,TB, B, TC,C>,TD > {};
|
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 {};
|
class DumClass {};
|
||||||
|
|
|
@ -55,13 +55,13 @@ public:
|
||||||
static bool HasVertexRef() { return false; }
|
static bool HasVertexRef() { return false; }
|
||||||
static bool HasTVAdjacency() { return false; }
|
static bool HasTVAdjacency() { return false; }
|
||||||
|
|
||||||
//Empty normals
|
// //Empty normals
|
||||||
typedef typename T::VertexType::NormalType NormalType;
|
// typedef typename T::VertexType::NormalType NormalType;
|
||||||
NormalType &N(const int & ){ static NormalType dummynormal(0, 0, 0); assert(0); return dummynormal; }
|
// 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; }
|
// const NormalType cN(const int & ) const { static NormalType dummynormal(0, 0, 0); assert(0); return dummynormal; }
|
||||||
|
|
||||||
static bool HasFaceNormal() { return false; }
|
// static bool HasFaceNormal() { return false; }
|
||||||
static bool HasFaceNormalOcc() { return false; }
|
// static bool HasFaceNormalOcc() { return false; }
|
||||||
|
|
||||||
//Empty color
|
//Empty color
|
||||||
typedef vcg::Color4b ColorType;
|
typedef vcg::Color4b ColorType;
|
||||||
|
@ -223,33 +223,33 @@ public:
|
||||||
|
|
||||||
// };
|
// };
|
||||||
|
|
||||||
template <class A, class T> class FaceNormal: public T {
|
// template <class A, class T> class FaceNormal: public T {
|
||||||
public:
|
// public:
|
||||||
typedef A NormalType;
|
// typedef A NormalType;
|
||||||
|
|
||||||
inline NormalType N(const int & i){ assert((i>=0)&&(i < 4)); return _facenormals[i]; }
|
// 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]; }
|
// inline NormalType cN(const int & i) const { assert((i>=0)&&(i < 4)); return _facenormals[i]; }
|
||||||
static bool HasFaceNormals() { return true; }
|
// static bool HasFaceNormals() { return true; }
|
||||||
static bool HasFaceNormalOcc() { return false; }
|
// static bool HasFaceNormalOcc() { return false; }
|
||||||
|
|
||||||
template <class RightValueType>
|
// template <class RightValueType>
|
||||||
void ImportData(const RightValueType & rightT)
|
// void ImportData(const RightValueType & rightT)
|
||||||
{
|
// {
|
||||||
if(rightT.IsNormalEnabled()) N().Import(rightT.cN());
|
// if(rightT.IsNormalEnabled()) N().Import(rightT.cN());
|
||||||
T::ImportData(rightT);
|
// 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:
|
// private:
|
||||||
NormalType _facenormals[4];
|
// NormalType _facenormals[4];
|
||||||
};
|
// };
|
||||||
|
|
||||||
template <class T> class FaceNormal3f: public FaceNormal<vcg::Point3f, T>{
|
//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);} };
|
//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>{
|
//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);} };
|
//public:static void Name(std::vector<std::string> & name){name.push_back(std::string("FaceNormal3d"));T::Name(name);} };
|
||||||
|
|
||||||
/*------------------------- FLAGS -----------------------------------------*/
|
/*------------------------- FLAGS -----------------------------------------*/
|
||||||
// template <class T> class EmptyBitFlags: public T {
|
// template <class T> class EmptyBitFlags: public T {
|
||||||
|
|
Loading…
Reference in New Issue