bootstrapping tetra as trimesh component

This commit is contained in:
T.Alderighi 2018-05-04 12:08:32 +02:00
parent b0384f68d1
commit b662f747a0
8 changed files with 854 additions and 57 deletions

View File

@ -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,7 +2135,36 @@ 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){

View File

@ -46,19 +46,24 @@ 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;
typedef typename ConstMeshRight::CoordType CoordRight;
typedef typename ConstMeshRight::VertexType VertexRight;
typedef typename ConstMeshRight::EdgeType EdgeRight;
typedef typename ConstMeshRight::HEdgeType HEdgeRight;
typedef typename ConstMeshRight::FaceType FaceRight;
typedef typename ConstMeshRight::ScalarType ScalarRight;
typedef typename ConstMeshRight::CoordType CoordRight;
typedef typename ConstMeshRight::VertexType VertexRight;
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...
@ -275,6 +302,16 @@ static void Mesh(MeshLeft& ml, ConstMeshRight& mr, const bool selected = false,
(*hp).ImportData(*(hi));
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

View File

@ -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 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"); }
/*@}*/

View File

@ -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>

View File

@ -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:

View File

@ -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

View File

@ -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 {};

View File

@ -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 {