removed
This commit is contained in:
parent
256a767f37
commit
60be67113d
|
@ -1,257 +0,0 @@
|
|||
/****************************************************************************
|
||||
* VCGLib o o *
|
||||
* Visual and Computer Graphics Library o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2004 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
/****************************************************************************
|
||||
History
|
||||
|
||||
$Log: not supported by cvs2svn $
|
||||
Revision 1.4 2004/06/01 17:12:46 ganovelli
|
||||
addVertices corrected (two copies instead of specializing te call)
|
||||
and put static (also addTetra) * g++ compliant *
|
||||
|
||||
Revision 1.3 2004/05/31 16:01:56 pietroni
|
||||
added function addtetra
|
||||
|
||||
Revision 1.2 2004/05/14 15:14:34 turini
|
||||
Added $Log: not supported by cvs2svn $
|
||||
Added Revision 1.4 2004/06/01 17:12:46 ganovelli
|
||||
Added addVertices corrected (two copies instead of specializing te call)
|
||||
Added and put static (also addTetra) * g++ compliant *
|
||||
Added
|
||||
Added Revision 1.3 2004/05/31 16:01:56 pietroni
|
||||
Added added function addtetra
|
||||
Added for CVS History Log
|
||||
|
||||
Revision 1.1 2004/19/04 13:05 pietroni
|
||||
Initial commit
|
||||
|
||||
|
||||
****************************************************************************/
|
||||
#ifndef __VCG_TETRA_ALLOCATE
|
||||
#define __VCG_TETRA_ALLOCATE
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
namespace vcg {
|
||||
namespace tetra {
|
||||
/** \addtogroup tetramesh */
|
||||
/*@{*/
|
||||
|
||||
/** Class Allocate.
|
||||
This is class for Allocate new vertices or tetrahedron on the mesh.
|
||||
@param TM_TYPE (Template Parameter) Specifies the type of the tetrahedral mesh.
|
||||
*/
|
||||
|
||||
template < class TM_TYPE >
|
||||
class Allocator
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/// The tetramesh type
|
||||
typedef TM_TYPE TetraMeshType;
|
||||
|
||||
|
||||
/// The vertex type
|
||||
typedef typename TM_TYPE::VertexType VertexType;
|
||||
|
||||
/// The tetrahedron type
|
||||
typedef typename TM_TYPE::TetraType TetraType;
|
||||
|
||||
/// The type of vertex iterator
|
||||
typedef typename TM_TYPE::VertexIterator VertexIterator;
|
||||
|
||||
/// The type of tetra iterator
|
||||
typedef typename TM_TYPE::TetraIterator TetraIterator;
|
||||
|
||||
/// The type of constant vertex iterator
|
||||
typedef typename TM_TYPE::const_VertexIterator const_VertexIterator;
|
||||
|
||||
/// The type of constant face iterator
|
||||
typedef typename TM_TYPE::const_TetraIterator const_TetraIterator;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/** Function to add n vertices to the mesh. The second parameter hold a vector of
|
||||
pointers to pointer to elements of the mesh that should be updated after a
|
||||
possible vector realloc.
|
||||
@param n Il numero di vertici che si vuole aggiungere alla mesh.
|
||||
@param local_var Vettore di variabili locali che rappresentano puntatori a vertici.
|
||||
restituisce l'iteratore al primo elemento aggiunto.
|
||||
*/
|
||||
|
||||
static VertexIterator AddVertices(TetraMeshType &m,int n, vector<VertexType **> &local_var)
|
||||
{
|
||||
VertexIterator oldbegin, newbegin;
|
||||
oldbegin = m.vert.begin();
|
||||
VertexIterator last=m.vert.end();
|
||||
if(m.vert.empty()) last=(VertexIterator)0; // if the vector is empty we cannot find the last valid element
|
||||
else --last;
|
||||
unsigned int siz=0;
|
||||
#ifdef __STL_CONFIG_H
|
||||
if(last!=(VertexIterator)0) distance(m.vert.begin(),last,siz);
|
||||
#else
|
||||
if(last!=(VertexIterator)0) siz=distance(m.vert.begin(),last);
|
||||
#endif
|
||||
for(unsigned int i=0; i<n; ++i)
|
||||
{
|
||||
m.vert.push_back(VertexType());
|
||||
m.vert.back().ClearFlags();
|
||||
}
|
||||
m.vn+=n;
|
||||
newbegin = m.vert.begin();
|
||||
if(newbegin != oldbegin)
|
||||
{
|
||||
TetraIterator f;
|
||||
for (f=m.tetra.begin(); f!=m.tetra.end(); ++f)
|
||||
if(!(*f).IsD())
|
||||
for(unsigned int k=0; k<4; ++k)
|
||||
(*f).V(k)= (*f).V(k)-&*oldbegin+&*newbegin;
|
||||
for(unsigned int j=0; j<local_var.size(); ++j)
|
||||
if((*local_var[j]) !=0 ) *local_var[j] = *local_var[j]-&*oldbegin+&*newbegin;
|
||||
|
||||
// deve restituire l'iteratore alla prima faccia aggiunta;
|
||||
// e poiche' lo spazio e' cambiato si ricalcola last da zero
|
||||
if(last!=(VertexIterator)0)
|
||||
{
|
||||
last = m.vert.begin();
|
||||
advance(last,siz+1);
|
||||
}
|
||||
else last=m.vert.begin();
|
||||
}
|
||||
else
|
||||
{
|
||||
// se non e'cambiato lo spazio (vector abbastanza grande o lista)
|
||||
if(last==(VertexIterator)0) last = m.vert.begin(); // se il vettore era vuoto si restituisce begin
|
||||
else advance(last,1); // altrimenti il primo dopo quello che era in precedenza l'ultimo valido.
|
||||
}
|
||||
return last;
|
||||
}
|
||||
|
||||
/** Function to add n vertices to the mesh.
|
||||
@param n Il numero di vertici che si vuole aggiungere alla mesh.
|
||||
*/
|
||||
static VertexIterator AddVertices(TetraMeshType &m,int n)
|
||||
{
|
||||
vector<VertexType **> empty_var;
|
||||
return AddVertices(m,n,empty_var);
|
||||
}
|
||||
|
||||
struct InsertedVT{
|
||||
InsertedVT(VertexType *_v,
|
||||
TetraType *_t,
|
||||
int _z):v(_v),t(_t),z(_z){}
|
||||
|
||||
VertexType *v;
|
||||
TetraType *t;
|
||||
int z;
|
||||
|
||||
const bool operator <(const InsertedVT & o){
|
||||
return (v<o.v);
|
||||
}
|
||||
const bool operator ==(const InsertedVT & o){
|
||||
return (v==o.v);
|
||||
}
|
||||
const bool operator !=(const InsertedVT & o){
|
||||
return (v!=o.v);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** Function to add n tetrafedron to the mesh.
|
||||
@param n number of vertices we want to add.
|
||||
*/
|
||||
static TetraIterator AddTetra(TetraMeshType &m,int n)
|
||||
{
|
||||
unsigned int sz = m.tetra.size();
|
||||
m.tetra.resize(sz+n);
|
||||
|
||||
TetraIterator ti =m.tetra.begin();
|
||||
advance(ti,sz);
|
||||
|
||||
m.tn+=n;
|
||||
return ti;
|
||||
}
|
||||
|
||||
/** Crate a copy of the mesh with tetrahedron that are into the templated container
|
||||
@param ST_CONT (Template Parameter) Specifies the type of the container of tetrahedron.
|
||||
@param subSet Container of tetrahedron.
|
||||
@param m destination mesh.
|
||||
*/
|
||||
template <class STL_CONT >
|
||||
static void SubSetT(STL_CONT & subSet, TetraMeshType & m)
|
||||
{
|
||||
vector< InsertedVT > newVertices;
|
||||
typename STL_CONT :: iterator pfi;
|
||||
newVertices.clear();
|
||||
|
||||
for(pfi = subSet.begin(); pfi != subSet.end(); ++pfi)
|
||||
m.tetra.push_back((*pfi));
|
||||
|
||||
TetraIterator fi;
|
||||
for(fi = m.tetra.begin(); fi != m.tetra.end(); ++fi)
|
||||
{
|
||||
newVertices.push_back(InsertedVT( (*fi).V(0),&(*fi),0));
|
||||
newVertices.push_back(InsertedVT( (*fi).V(1),&(*fi),1));
|
||||
newVertices.push_back(InsertedVT( (*fi).V(2),&(*fi),2));
|
||||
newVertices.push_back(InsertedVT( (*fi).V(3),&(*fi),3));
|
||||
}
|
||||
|
||||
sort(newVertices.begin(),newVertices.end());
|
||||
|
||||
typename std::vector< InsertedVT >::iterator curr,next;
|
||||
int pos = 0;
|
||||
curr = next = newVertices.begin();
|
||||
while( next != newVertices.end())
|
||||
{
|
||||
if((*curr)!=(*next))
|
||||
pos++;
|
||||
(*next).t->V( (*next).z) = (VertexType *)pos;
|
||||
curr = next;
|
||||
next++;
|
||||
}
|
||||
|
||||
typename std::vector<InsertedVT >::iterator newE = unique(newVertices.begin(),newVertices.end());
|
||||
|
||||
for(curr = newVertices.begin();curr!= newE;++curr)
|
||||
m.vert.push_back(*((*curr).v));
|
||||
|
||||
for(fi = m.tetra.begin(); fi != m.tetra.end(); ++fi)
|
||||
{
|
||||
(*fi).V(0) = &(m.vert[(int)(*fi).V(0)]);
|
||||
(*fi).V(1) = &(m.vert[(int)(*fi).V(1)]);
|
||||
(*fi).V(2) = &(m.vert[(int)(*fi).V(2)]);
|
||||
(*fi).V(3) = &(m.vert[(int)(*fi).V(3)]);
|
||||
}
|
||||
m.vn = m.vert.size();
|
||||
m.tn = m.tetra.size();
|
||||
}
|
||||
|
||||
}; // end class
|
||||
|
||||
|
||||
/*@}*/
|
||||
} // End namespace
|
||||
} // End namespace
|
||||
|
||||
|
||||
#endif
|
|
@ -1,273 +0,0 @@
|
|||
/****************************************************************************
|
||||
* VCGLib o o *
|
||||
* Visual and Computer Graphics Library o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2004 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
/****************************************************************************
|
||||
History
|
||||
|
||||
$Log: not supported by cvs2svn $
|
||||
Revision 1.13 2007/03/12 15:38:03 tarini
|
||||
Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD.
|
||||
|
||||
Revision 1.12 2005/12/12 11:10:35 ganovelli
|
||||
modifications to compile with gcc
|
||||
|
||||
Revision 1.11 2005/01/12 11:06:54 ganovelli
|
||||
added InitVertexIMark
|
||||
|
||||
Revision 1.10 2004/10/11 17:44:07 ganovelli
|
||||
added include of color4
|
||||
|
||||
Revision 1.9 2004/07/15 00:16:37 cignoni
|
||||
Better doxigen documentation
|
||||
|
||||
Revision 1.8 2004/07/09 10:18:49 ganovelli
|
||||
added access functions to vn and tn
|
||||
|
||||
Revision 1.7 2004/06/25 11:27:21 pietroni
|
||||
added function to access temporary mark for decimation
|
||||
|
||||
Revision 1.6 2004/06/01 17:17:29 ganovelli
|
||||
pragma once removed ,
|
||||
load ts removed to be put in io_tetramesh
|
||||
CLear() added
|
||||
|
||||
Revision 1.5 2004/05/13 12:16:12 pietroni
|
||||
first version... add vertex to mesh
|
||||
|
||||
Revision 1.4 2004/05/13 07:41:47 turini
|
||||
Chenged #include <space\\box3.h> in #include <vcg\\space\\box3.h>
|
||||
|
||||
Revision 1.3 2004/05/06 10:57:49 pietroni
|
||||
changed names to topology functions
|
||||
|
||||
Revision 1.2 2004/04/28 11:37:14 pietroni
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2004/04/20 12:41:39 pietroni
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2004/04/15 08:54:20 pietroni
|
||||
*** empty log message ***
|
||||
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef __VCG_TETRAMESH
|
||||
#define __VCG_TETRAMESH
|
||||
#include <vcg/space/box3.h>
|
||||
#include <vcg/space/color4.h>
|
||||
|
||||
|
||||
namespace vcg {
|
||||
namespace tetra {
|
||||
/** \addtogroup tetramesh */
|
||||
/*@{*/
|
||||
|
||||
/** Class TetraMesh.
|
||||
This is class for definition of a mesh.
|
||||
@param STL_VERT_CONT (Template Parameter) Specifies the type of the vertices container any the vertex type.
|
||||
@param STL_FACE_CONT (Template Parameter) Specifies the type of the faces container any the face type.
|
||||
*/
|
||||
|
||||
|
||||
template < class STL_VERT_CONT ,class STL_TETRA_CONT >
|
||||
class Tetramesh{
|
||||
public:
|
||||
|
||||
/***********************************************/
|
||||
/** @name Tetramesh Type Definitions **/
|
||||
//@{
|
||||
|
||||
/// The mesh type
|
||||
typedef Tetramesh<STL_VERT_CONT,STL_TETRA_CONT> TetraMeshType;
|
||||
|
||||
/// The vertex container
|
||||
typedef STL_VERT_CONT VertexContainer;
|
||||
|
||||
/// The tethaedhron container
|
||||
typedef STL_TETRA_CONT TetraContainer;
|
||||
|
||||
/// The vertex type
|
||||
typedef typename STL_VERT_CONT::value_type VertexType;
|
||||
|
||||
/// The tetrahedron type
|
||||
typedef typename STL_TETRA_CONT::value_type TetraType;
|
||||
|
||||
/// The type of vertex iterator
|
||||
typedef typename STL_VERT_CONT::iterator VertexIterator;
|
||||
|
||||
/// The type of tetra iterator
|
||||
typedef typename STL_TETRA_CONT::iterator TetraIterator;
|
||||
|
||||
/// The type of constant vertex iterator
|
||||
typedef typename STL_VERT_CONT::const_iterator const_VertexIterator;
|
||||
|
||||
/// The type of constant face iterator
|
||||
typedef typename STL_TETRA_CONT::const_iterator const_TetraIterator;
|
||||
|
||||
/// The vertex pointer type
|
||||
typedef VertexType * VertexPointer;
|
||||
|
||||
/// The tetra pointer type
|
||||
typedef TetraType * TetraPointer;
|
||||
|
||||
/// The type of the constant vertex pointer
|
||||
typedef const VertexType * const_VertexPointer;
|
||||
|
||||
/// The type of the constant tetrahedron pointer
|
||||
typedef const VertexType * const_TetraPointer;
|
||||
|
||||
typedef typename VertexType::ScalarType ScalarType;
|
||||
//@}
|
||||
|
||||
/***********************************************/
|
||||
/** @Common Attributes of a tetrahedral mesh **/
|
||||
//@{
|
||||
|
||||
///temporary mark for decimation
|
||||
int IMark;
|
||||
|
||||
/// Set of vertices
|
||||
STL_VERT_CONT vert;
|
||||
|
||||
/// Real number of vertices
|
||||
int vn;
|
||||
|
||||
/// Set of tetrahedron
|
||||
STL_TETRA_CONT tetra;
|
||||
|
||||
/// Real number of tetrahedron
|
||||
int tn;
|
||||
|
||||
/// Real number of edges
|
||||
int en;
|
||||
|
||||
///Boundingbox della mesh
|
||||
Box3<ScalarType> bbox;
|
||||
//@}
|
||||
|
||||
/***********************************************/
|
||||
/** @Default Functions **/
|
||||
//@{
|
||||
|
||||
/// Default constructor
|
||||
Tetramesh()
|
||||
{
|
||||
tn = vn = en = 0;
|
||||
}
|
||||
|
||||
Tetramesh(VertexContainer v,TetraContainer t)
|
||||
{
|
||||
this->vert=v;
|
||||
this->tetra=t;
|
||||
vn=v.size();
|
||||
tn=t.size();
|
||||
}
|
||||
|
||||
inline int MemUsed() const
|
||||
{
|
||||
return sizeof(Tetramesh)+sizeof(VertexType)*vert.size()+sizeof(TetraType)*tetra.size();
|
||||
}
|
||||
|
||||
void Clear(){
|
||||
vert.clear();
|
||||
tetra.clear();
|
||||
tn = 0;
|
||||
vn = 0;
|
||||
}
|
||||
|
||||
/// Initialize the imark-system of the vertices
|
||||
void InitVertexIMark()
|
||||
{
|
||||
VertexIterator vi;
|
||||
|
||||
for(vi=vert.begin();vi!=vert.end();++vi)
|
||||
if( !(*vi).IsD() && (*vi).IsRW() )
|
||||
(*vi).InitIMark();
|
||||
}
|
||||
//@}
|
||||
|
||||
/***********************************************/
|
||||
/** @Functions used to retrieve informations**/
|
||||
//@{
|
||||
/// Reflection functions that speak about vertex and face properties.
|
||||
static bool HasPerVertexNormal() { return VertexType::HasNormal() ; }
|
||||
static bool HasPerVertexColor() { return VertexType::HasColor() ; }
|
||||
static bool HasPerVertexMark() { return VertexType::HasMark() ; }
|
||||
static bool HasPerVertexQuality() { return VertexType::HasQuality(); }
|
||||
static bool HasPerVertexTexCoord(){ return VertexType::HasTexCoord(); }
|
||||
|
||||
static bool HasPerTetraNormal() { return TetraType::HasTetraNormal() ; }
|
||||
static bool HasPerTetraMark() { return TetraType::HasTetraMark() ; }
|
||||
static bool HasPerTetraQuality() { return TetraType::HasTetraQuality(); }
|
||||
|
||||
static bool HasTTTopology() { return TetraType::HasTTAdjacency(); }
|
||||
static bool HasVTTopology() { return TetraType::HasVTAdjacency(); }
|
||||
static bool HasTopology() { return HasTTTopology() || HasVTTopology(); }
|
||||
|
||||
int & SimplexNumber(){ return tn;}
|
||||
int & VertexNumber(){ return vn;}
|
||||
/***********************************************/
|
||||
|
||||
/** @Functions used for handle the temporany mark of a tetrahedron used in decimation**/
|
||||
//@{
|
||||
|
||||
///Increase the current mark.
|
||||
void UnMarkAll()
|
||||
{
|
||||
++IMark;
|
||||
}
|
||||
|
||||
///Mark the vertex with current value
|
||||
void Mark(VertexType *v)
|
||||
{
|
||||
v->IMark()=IMark;
|
||||
}
|
||||
|
||||
///return the current mark
|
||||
int GetMark()
|
||||
{
|
||||
return (IMark);
|
||||
}
|
||||
|
||||
///Initialize the mark of all vertices
|
||||
void InitIMark()
|
||||
{
|
||||
VertexIterator vi;
|
||||
IMark=0;
|
||||
for(vi=vert.begin();vi!=vert.end();vi++)
|
||||
{
|
||||
(*vi).InitIMark();
|
||||
}
|
||||
}
|
||||
|
||||
//@}
|
||||
};//End class
|
||||
|
||||
/*@}*/
|
||||
|
||||
|
||||
};//end namespace
|
||||
};//end namespace
|
||||
#endif
|
||||
|
|
@ -1,973 +0,0 @@
|
|||
/****************************************************************************
|
||||
* VCGLib o o *
|
||||
* Visual and Computer Graphics Library o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2004 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
/****************************************************************************
|
||||
History
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __VCG_TETRA_EDGE_COLLAPSE
|
||||
#define __VCG_TETRA_EDGE_COLLAPSE
|
||||
|
||||
#include <vcg/space/tetra3.h>
|
||||
#include <vcg/complex/tetramesh/update/topology.h>
|
||||
#include <vcg/complex/tetramesh/update/normal.h>
|
||||
|
||||
|
||||
|
||||
namespace vcg{
|
||||
namespace tetra{
|
||||
|
||||
/** \addtogroup tetramesh */
|
||||
/*@{*/
|
||||
/// This Class is used for the edge collapse
|
||||
template <class TETRA_MESH_TYPE>
|
||||
class EdgeCollapse
|
||||
{
|
||||
public:
|
||||
/// The tetrahedral mesh type
|
||||
typedef TETRA_MESH_TYPE TetraMeshType;
|
||||
/// The tetrahedron type
|
||||
typedef typename TetraMeshType::TetraType TetraType;
|
||||
/// The vertex type
|
||||
typedef typename TetraType::VertexType VertexType;
|
||||
/// The vertex iterator type
|
||||
typedef typename TetraMeshType::VertexIterator VertexIterator;
|
||||
/// The tetra iterator type
|
||||
typedef typename TetraMeshType::TetraIterator TetraIterator;
|
||||
/// The coordinate type
|
||||
typedef typename TetraType::VertexType::CoordType CoordType;
|
||||
/// The scalar type
|
||||
typedef typename TetraMeshType::VertexType::ScalarType ScalarType;
|
||||
///the container of tetrahedron type
|
||||
typedef typename TetraMeshType::TetraContainer TetraContainer;
|
||||
///the container of vertex type
|
||||
typedef typename TetraMeshType::VertexContainer VertexContainer;
|
||||
/// The HEdgePos type
|
||||
typedef Pos<TetraType> PosType;
|
||||
/// The HEdgePos Loop type
|
||||
typedef PosLoop<TetraType> PosLType;
|
||||
/// The topology updater type
|
||||
typedef typename vcg::tetra::UpdateTetraTopology<VertexContainer,TetraContainer> Topology;
|
||||
///the normal updater type
|
||||
typedef typename vcg::tetra::UpdateNormals<TetraMeshType> UpdateNormals;
|
||||
|
||||
|
||||
/// Default Constructor
|
||||
EdgeCollapse()
|
||||
{
|
||||
};
|
||||
|
||||
~EdgeCollapse()
|
||||
{
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
typedef pair <int,int> FacePair;
|
||||
struct Face
|
||||
{
|
||||
VertexType* v[3];
|
||||
|
||||
Face( VertexType* a, VertexType* b,VertexType* c)
|
||||
{
|
||||
assert((a!=b)&&(b!=c)&&(a!=c));
|
||||
v[0]=a;
|
||||
v[1]=b;
|
||||
v[2]=c;
|
||||
sort(v,v+3);
|
||||
}
|
||||
|
||||
const bool operator <(const Face & f) const
|
||||
{
|
||||
return ((v[0]==f.v[0])?((v[1]==f.v[1])?(v[2]<f.v[2]):(v[1]<f.v[1])):(v[0]<f.v[0]));
|
||||
}
|
||||
|
||||
const bool operator ==(const Face & f) const {
|
||||
return ((v[0]==f.v[0])&&(v[1]==f.v[1])&&(v[2]==f.v[2]));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct Edge{
|
||||
VertexType* v0;
|
||||
VertexType* v1;
|
||||
Edge( VertexType* a, VertexType* b){
|
||||
assert(a!=b);
|
||||
if(a<b)
|
||||
{v0=a;v1=b;}
|
||||
else
|
||||
{v1=a;v0=b;}
|
||||
}
|
||||
|
||||
const bool operator <(const Edge & e) const {
|
||||
return (v0==e.v0)?(v1<e.v1):(v0<e.v0);
|
||||
}
|
||||
|
||||
const bool operator ==(const Edge & e) const {
|
||||
return (v0==e.v0)&&(v1==e.v1);
|
||||
}
|
||||
|
||||
};
|
||||
struct TetraSets
|
||||
{
|
||||
std::vector <TetraType*> v0;
|
||||
std::vector <TetraType*> v1;
|
||||
std::vector <TetraType*> v0_U_v1;
|
||||
std::vector <TetraType*> no_E;
|
||||
std::vector <TetraType*> E;
|
||||
std::vector <char> indexE;
|
||||
std::vector <char> indexv0;
|
||||
std::vector <char> indexv1;
|
||||
|
||||
void clear()
|
||||
{
|
||||
v0.clear();
|
||||
v1.clear();
|
||||
v0_U_v1.clear();
|
||||
no_E.clear();
|
||||
E.clear();
|
||||
indexE.clear();
|
||||
indexv0.clear();
|
||||
indexv1.clear();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static map<Edge,char> & _EdgeMark(){
|
||||
static map<Edge,char> em;
|
||||
return em;
|
||||
};
|
||||
|
||||
static map<Face,char> & _FaceMark(){
|
||||
static map<Face,char> fm;
|
||||
return fm;
|
||||
}
|
||||
|
||||
static VertexType &_DummyV(){
|
||||
static VertexType _dv;
|
||||
return _dv;
|
||||
}
|
||||
|
||||
static TetraSets &_Sets(){
|
||||
static TetraSets _s;
|
||||
return _s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///select the 2 faces that does not share the edge
|
||||
static FacePair _FindNoEdgeFace(TetraType *t,int edge)
|
||||
{
|
||||
//as first I find the 2 faces on the opposite sides of the egde
|
||||
int fa0=Tetra::FofE(edge,0);
|
||||
int fa1=Tetra::FofE(edge,1);
|
||||
|
||||
//then find the faces that remain
|
||||
int fa2=(fa0+1)%4;
|
||||
while ((fa2==fa0)||(fa2==fa1))
|
||||
{
|
||||
fa2=(fa2+1)%4;
|
||||
}
|
||||
int fa3=(fa2+1)%4;
|
||||
while ((fa3==fa0)||(fa3==fa1)||(fa3==fa2))
|
||||
{
|
||||
fa3=(fa3+1)%4;
|
||||
}
|
||||
return FacePair(fa2,fa3);
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
static void _AssertingVolume(TetraType *t)
|
||||
{
|
||||
//assert(t->ComputeVolume() >0);
|
||||
assert(vcg::ComputeVolume<TetraType>(*t)>0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
///collpse de edge specified by pos (the first vertex on edge remain)
|
||||
static int _Collapse(PosType p,CoordType NewP)
|
||||
{
|
||||
int n_deleted=0;
|
||||
vector<TetraType*> To_Del;
|
||||
VertexType *Vrem=(p.T()->V(Tetra::VofE(p.E(),0)));
|
||||
VertexType *Vdel=(p.T()->V(Tetra::VofE(p.E(),1)));
|
||||
//Vrem->P()=(Vrem->P()*alfa)+(Vdel->P()*(1.f-alfa));
|
||||
Vrem->P()=NewP;
|
||||
PosLType pos(p.T(),p.F(),p.E(),p.V());
|
||||
pos.Reset();
|
||||
To_Del.reserve(40);
|
||||
To_Del.clear();
|
||||
while (!pos.LoopEnd())
|
||||
{
|
||||
//get the two faces that doesn't share the edge
|
||||
FacePair fp=_FindNoEdgeFace(pos.T(),pos.E());
|
||||
int fa0=fp.first;
|
||||
int fa1=fp.second;
|
||||
|
||||
//now set the T-T topology on that faces
|
||||
TetraType *tleft=pos.T()->TTp(fa0);
|
||||
TetraType *tright=pos.T()->TTp(fa1);
|
||||
int ileft=pos.T()->TTi(fa0);
|
||||
int iright=pos.T()->TTi(fa1);
|
||||
|
||||
//in this case I cannot do the collapse
|
||||
assert (!((pos.T()==tleft)&&(pos.T()==tright)));
|
||||
|
||||
//case no one is extern face
|
||||
if ((!pos.T()->IsBorderF(fa0))&&(!pos.T()->IsBorderF(fa1)))
|
||||
//connect the 2 tetrahedrons
|
||||
Topology::_AttachTTTopology(tleft,ileft,tright,iright);
|
||||
else
|
||||
//case f2 is an extern face
|
||||
if (pos.T()->IsBorderF(fa0))
|
||||
{
|
||||
tright->TTp(iright)=tright;
|
||||
tright->TTi(iright)=iright;
|
||||
}
|
||||
|
||||
else //case fa1 is an extern face
|
||||
//if ((pos.T()->IsBorderF(fa3))
|
||||
{
|
||||
tleft->TTp(ileft)=tleft;
|
||||
tleft->TTi(ileft)=ileft;
|
||||
}
|
||||
|
||||
//end setting T-T topology
|
||||
|
||||
//setting the V-T topology
|
||||
|
||||
//i remove the tetrahedrons that have the edge
|
||||
// to collapse
|
||||
Topology::DetachVTTopology(pos.T());
|
||||
|
||||
//end setting the V-T topology
|
||||
To_Del.push_back(pos.T());
|
||||
pos.NextT();
|
||||
n_deleted++;
|
||||
// tm.tn--;
|
||||
}
|
||||
|
||||
//delting old tetrahedrons
|
||||
typename vector<TetraType*>::iterator ti;
|
||||
for (ti=To_Del.begin();ti<To_Del.end();ti++)
|
||||
(*ti)->SetD();
|
||||
|
||||
//now I cycle on the tetrahedron that had the old vertex
|
||||
//reassegning the new one.
|
||||
|
||||
VTIterator<TetraType> VTi(Vdel->VTb(),Vdel->VTi());
|
||||
while (!VTi.End())
|
||||
{
|
||||
TetraType *T_Change=VTi.Vt();
|
||||
int index=VTi.Vi();
|
||||
//VTi++;
|
||||
//assegning the vertex that remain
|
||||
T_Change->V(index)=Vrem;
|
||||
Topology::DetachVTTopology(Vdel,T_Change);
|
||||
Topology::InsertVTTopology(Vrem,index,T_Change);
|
||||
//that's cause i restart everytime in the chain
|
||||
//from the vertex
|
||||
VTi.Vt()=Vdel->VTb();
|
||||
VTi.Vi()=Vdel->VTi();
|
||||
#ifdef _DEBUG
|
||||
_AssertingVolume(T_Change);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
if (Vdel->IsB())
|
||||
Vrem->SetB();
|
||||
//set as deleted the vertex
|
||||
Vdel->SetD();
|
||||
return n_deleted;
|
||||
}
|
||||
|
||||
|
||||
static void orMarkE(Edge E,char M)
|
||||
{
|
||||
typename map<Edge,char>::iterator EI;
|
||||
EI=_EdgeMark().find(E);
|
||||
if (EI==_EdgeMark().end())
|
||||
_EdgeMark().insert (pair<Edge,char>(E,M));
|
||||
else
|
||||
(*EI).second|=M;
|
||||
}
|
||||
|
||||
static bool isMarkedE(Edge E,char M)
|
||||
{
|
||||
typename map<Edge,char>::iterator EI;
|
||||
EI=_EdgeMark().find(E);
|
||||
if (EI==_EdgeMark().end())
|
||||
return false;
|
||||
else return (((*EI).second & M)!=0);
|
||||
}
|
||||
|
||||
static void orMarkF(Face F,char M)
|
||||
{
|
||||
typename map< Face,char>::iterator FI;
|
||||
FI=_FaceMark().find(F);
|
||||
if (FI==_FaceMark().end())
|
||||
_FaceMark().insert (pair<Face,char>(F,M));
|
||||
else
|
||||
(*FI).second|=M;
|
||||
}
|
||||
|
||||
static bool isMarkedF(Face F,char M)
|
||||
{
|
||||
typename map<Face,char>::iterator FI;
|
||||
FI=_FaceMark().find(F);
|
||||
if (FI==_FaceMark().end())
|
||||
return false;
|
||||
else return (((*FI).second & M)!=0);
|
||||
}
|
||||
|
||||
|
||||
///verify the link conditions on faces
|
||||
static bool _LinkConditionsF(PosType pos)
|
||||
{
|
||||
const int LINK_V0 = 0x00000001;
|
||||
const int LINK_EE = 0x00000002;
|
||||
|
||||
_EdgeMark().clear();
|
||||
|
||||
// Mark edges of ve0
|
||||
typename vector< TetraType *>::iterator ti=_Sets().v0.begin();
|
||||
typename vector< char >::iterator en=_Sets().indexv0.begin();
|
||||
VertexType *v0=(*ti)->V(*en);
|
||||
while (ti!=_Sets().v0.end())
|
||||
{
|
||||
assert(v0==(*ti)->V(*en));
|
||||
//put dummy face
|
||||
for (int f=0;f<3;f++)
|
||||
{
|
||||
int f_test=Tetra::FofV((*en),f);
|
||||
if ((*ti)->IsBorderF(f_test))
|
||||
{
|
||||
orMarkF(Face((*ti)->V(Tetra::VofF(f_test,0)),(*ti)->V(Tetra::VofF(f_test,1)),&_DummyV()),LINK_V0);
|
||||
orMarkF(Face((*ti)->V(Tetra::VofF(f_test,1)),(*ti)->V(Tetra::VofF(f_test,2)),&_DummyV()),LINK_V0);
|
||||
orMarkF(Face((*ti)->V(Tetra::VofF(f_test,2)),(*ti)->V(Tetra::VofF(f_test,0)),&_DummyV()),LINK_V0);
|
||||
}
|
||||
}
|
||||
ti++;
|
||||
en++;
|
||||
}
|
||||
|
||||
ti=_Sets().E.begin();
|
||||
en=_Sets().indexE.begin();
|
||||
//mark them as intersection
|
||||
while (ti!=_Sets().E.end())
|
||||
{
|
||||
//faces on the edge
|
||||
int f0=Tetra::FofE((*en),0);
|
||||
int f1=Tetra::FofE((*en),1);
|
||||
|
||||
if ((*ti)->IsBorderF(f0))
|
||||
{
|
||||
orMarkF(Face((*ti)->V(Tetra::VofF(f0,0)),(*ti)->V(Tetra::VofF(f0,1)),&_DummyV()),LINK_EE);
|
||||
orMarkF(Face((*ti)->V(Tetra::VofF(f0,1)),(*ti)->V(Tetra::VofF(f0,2)),&_DummyV()),LINK_EE);
|
||||
orMarkF(Face((*ti)->V(Tetra::VofF(f0,2)),(*ti)->V(Tetra::VofF(f0,0)),&_DummyV()),LINK_EE);
|
||||
}
|
||||
|
||||
if ((*ti)->IsBorderF(f1))
|
||||
{
|
||||
orMarkF(Face((*ti)->V(Tetra::VofF(f1,0)),(*ti)->V(Tetra::VofF(f1,1)),&_DummyV()),LINK_EE);
|
||||
orMarkF(Face((*ti)->V(Tetra::VofF(f1,1)),(*ti)->V(Tetra::VofF(f1,2)),&_DummyV()),LINK_EE);
|
||||
orMarkF(Face((*ti)->V(Tetra::VofF(f1,2)),(*ti)->V(Tetra::VofF(f1,0)),&_DummyV()),LINK_EE);
|
||||
}
|
||||
|
||||
ti++;
|
||||
en++;
|
||||
}
|
||||
|
||||
//and at the end I verify if the intersection is equal to the star of the edge
|
||||
ti=_Sets().v1.begin();
|
||||
en=_Sets().indexv1.begin();
|
||||
VertexType *v1=(*ti)->V(*en);
|
||||
while (ti!=_Sets().v1.end())
|
||||
{
|
||||
assert(v1==(*ti)->V(*en));
|
||||
//dummy edges control
|
||||
for (int f=0;f<3;f++)
|
||||
{
|
||||
int f_test=Tetra::FofV((*en),f);
|
||||
if ((*ti)->IsBorderF(f_test))
|
||||
{
|
||||
//control all the 3 edges
|
||||
Face f_test0=Face((*ti)->V(Tetra::VofF(f_test,0)),(*ti)->V(Tetra::VofF(f_test,1)),&_DummyV());
|
||||
Face f_test1=Face((*ti)->V(Tetra::VofF(f_test,1)),(*ti)->V(Tetra::VofF(f_test,2)),&_DummyV());
|
||||
Face f_test2=Face((*ti)->V(Tetra::VofF(f_test,2)),(*ti)->V(Tetra::VofF(f_test,0)),&_DummyV());
|
||||
if (((isMarkedF(f_test0,LINK_V0))&&(!isMarkedF(f_test0,LINK_EE)))||
|
||||
((isMarkedF(f_test1,LINK_V0))&&(!isMarkedF(f_test1,LINK_EE)))||
|
||||
((isMarkedF(f_test2,LINK_V0))&&(!isMarkedF(f_test2,LINK_EE))))
|
||||
{
|
||||
// FAIL::LKF();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
ti++;
|
||||
en++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
///verify the link conditions on edges
|
||||
static bool _LinkConditionsE(PosType pos)
|
||||
{
|
||||
const int LINK_V0 = 0x00000001;
|
||||
const int LINK_EE = 0x00000002;
|
||||
|
||||
_FaceMark().clear();
|
||||
|
||||
// Mark edges of ve0
|
||||
typename vector< TetraType *>::iterator ti=_Sets().v0.begin();
|
||||
typename vector< char >::iterator en=_Sets().indexv0.begin();
|
||||
while (ti!=_Sets().v0.end())
|
||||
{
|
||||
//put dummy edge
|
||||
for (int f=0;f<3;f++)
|
||||
{
|
||||
int f_test=Tetra::FofV((*en),f);
|
||||
if ((*ti)->IsBorderF(f_test))
|
||||
{
|
||||
orMarkE(Edge((*ti)->V(Tetra::VofF(f_test,0)),&_DummyV()),LINK_V0);
|
||||
orMarkE(Edge((*ti)->V(Tetra::VofF(f_test,1)),&_DummyV()),LINK_V0);
|
||||
orMarkE(Edge((*ti)->V(Tetra::VofF(f_test,2)),&_DummyV()),LINK_V0);
|
||||
}
|
||||
}
|
||||
ti++;
|
||||
en++;
|
||||
}
|
||||
|
||||
ti=_Sets().E.begin();
|
||||
en=_Sets().indexE.begin();
|
||||
//mark them as intersection
|
||||
while (ti!=_Sets().E.end())
|
||||
{
|
||||
//faces on the edge
|
||||
int f0=Tetra::FofE((*en),0);
|
||||
int f1=Tetra::FofE((*en),1);
|
||||
|
||||
if ((*ti)->IsBorderF(f0))
|
||||
{
|
||||
orMarkE(Edge((*ti)->V(Tetra::VofF(f0,0)),&_DummyV()),LINK_EE);
|
||||
orMarkE(Edge((*ti)->V(Tetra::VofF(f0,1)),&_DummyV()),LINK_EE);
|
||||
orMarkE(Edge((*ti)->V(Tetra::VofF(f0,2)),&_DummyV()),LINK_EE);
|
||||
}
|
||||
|
||||
if ((*ti)->IsBorderF(f1))
|
||||
{
|
||||
orMarkE(Edge((*ti)->V(Tetra::VofF(f1,0)),&_DummyV()),LINK_EE);
|
||||
orMarkE(Edge((*ti)->V(Tetra::VofF(f1,1)),&_DummyV()),LINK_EE);
|
||||
orMarkE(Edge((*ti)->V(Tetra::VofF(f1,2)),&_DummyV()),LINK_EE);
|
||||
}
|
||||
|
||||
ti++;
|
||||
en++;
|
||||
}
|
||||
|
||||
//and at the end I verify if the intersection is equal to the star of the edge
|
||||
ti=_Sets().v1.begin();
|
||||
en=_Sets().indexv1.begin();
|
||||
while (ti!=_Sets().v1.end())
|
||||
{
|
||||
|
||||
//dummy edges control
|
||||
for (int f=0;f<3;f++)
|
||||
{
|
||||
int f_test=Tetra::FofV((*en),f);
|
||||
if ((*ti)->IsBorderF(f_test))
|
||||
{
|
||||
//control all the 3 edges
|
||||
Edge e_test0=Edge((*ti)->V(Tetra::VofF(f_test,0)),&_DummyV());
|
||||
Edge e_test1=Edge((*ti)->V(Tetra::VofF(f_test,1)),&_DummyV());
|
||||
Edge e_test2=Edge((*ti)->V(Tetra::VofF(f_test,2)),&_DummyV());
|
||||
if (((isMarkedE(e_test0,LINK_V0))&&(!isMarkedE(e_test0,LINK_EE)))||
|
||||
((isMarkedE(e_test1,LINK_V0))&&(!isMarkedE(e_test1,LINK_EE)))||
|
||||
((isMarkedE(e_test2,LINK_V0))&&(!isMarkedE(e_test2,LINK_EE))))
|
||||
{
|
||||
// FAIL::LKE();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
ti++;
|
||||
en++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _QuickConditions(PosType pos)
|
||||
{
|
||||
VertexType *v0=pos.T()->V(Tetra::VofE(pos.E(),0));
|
||||
VertexType *v1=pos.T()->V(Tetra::VofE(pos.E(),1));
|
||||
|
||||
//if the two vertices are of border and the edge is not a border edge
|
||||
//we can do it.
|
||||
|
||||
bool border0=v0->IsB();
|
||||
bool border1=v1->IsB();
|
||||
bool bordere=Topology::IsExternEdge(pos.T(),pos.E());
|
||||
|
||||
//first case vertex external and edge internal
|
||||
if ((border0 && border1)&&(!bordere))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else /// look if the 2 other faces that don't share the vertex are external on not
|
||||
{
|
||||
|
||||
typename vector< TetraType *>::iterator ti=_Sets().E.begin();
|
||||
typename vector< char >::iterator en=_Sets().indexE.begin();
|
||||
//mark them as intersection
|
||||
while (ti!=_Sets().E.end())
|
||||
{
|
||||
//get the two faces that doesn't share the edge
|
||||
FacePair fp=_FindNoEdgeFace(pos.T(),pos.E());
|
||||
int fa0=fp.first;
|
||||
int fa1=fp.second;
|
||||
|
||||
//now set the T-T topology on that faces
|
||||
TetraType *tleft=pos.T()->TTp(fa0);
|
||||
TetraType *tright=pos.T()->TTp(fa1);
|
||||
int ileft=pos.T()->TTi(fa0);
|
||||
int iright=pos.T()->TTi(fa1);
|
||||
|
||||
//in this case I cannot do the collapse
|
||||
if (((pos.T()==tleft)&&(pos.T()==tright)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
ti++;
|
||||
en++;
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
///verify the link conditions on vertices
|
||||
static bool _LinkConditionsV()
|
||||
{
|
||||
const int LINK_V0 = VertexType::NewBitFlag();
|
||||
const int LINK_V1 = VertexType::NewBitFlag();
|
||||
const int LINK_EE = VertexType::NewBitFlag();
|
||||
|
||||
const int NOT_LINKED = ~(LINK_V0 | LINK_V1 | LINK_EE);
|
||||
_DummyV().Flags() &= NOT_LINKED;
|
||||
|
||||
VertexType *vt0;
|
||||
VertexType *vt1;
|
||||
VertexType *vt2;
|
||||
VertexType *vt3;
|
||||
|
||||
|
||||
typename vector< TetraType *>::iterator ti=_Sets().v0_U_v1.begin();
|
||||
|
||||
//reset all link flags
|
||||
while (ti!=_Sets().v0_U_v1.end())
|
||||
{
|
||||
for(int i=0;i<4;i++)
|
||||
(*ti)->V(i)->Flags() &= NOT_LINKED;
|
||||
ti++;
|
||||
}
|
||||
|
||||
|
||||
//also in the ones that appartain to the edge
|
||||
typename vector< char >::iterator en;
|
||||
ti=_Sets().E.begin();
|
||||
en=_Sets().indexE.begin();
|
||||
//reset all link flags for intersection and in the same
|
||||
//time mark them as intersection
|
||||
while (ti!=_Sets().E.end())
|
||||
{
|
||||
for(int i=0;i<4;i++)
|
||||
{
|
||||
(*ti)->V(i)->Flags() &= NOT_LINKED;
|
||||
(*ti)->V(i)->Flags() |= LINK_EE;
|
||||
}
|
||||
|
||||
//dummy vertex
|
||||
|
||||
//faces on the edge
|
||||
int f0=Tetra::FofE((*en),0);
|
||||
int f1=Tetra::FofE((*en),1);
|
||||
|
||||
if (((*ti)->IsBorderF(f0))||((*ti)->IsBorderF(f1)))
|
||||
_DummyV().Flags() |= LINK_EE;
|
||||
|
||||
ti++;
|
||||
en++;
|
||||
}
|
||||
|
||||
|
||||
// Mark vertices of ve0
|
||||
ti=_Sets().v0.begin();
|
||||
en=_Sets().indexv0.begin();
|
||||
|
||||
while (ti!=_Sets().v0.end())
|
||||
{
|
||||
for(int i=0;i<4;i++)
|
||||
(*ti)->V(i)->Flags() |= LINK_V0;
|
||||
|
||||
//dummy faces on the vertex
|
||||
int f0=Tetra::FofV((*en),0);
|
||||
int f1=Tetra::FofV((*en),1);
|
||||
int f2=Tetra::FofV((*en),2);
|
||||
|
||||
if (((*ti)->IsBorderF(f0))||((*ti)->IsBorderF(f1))||((*ti)->IsBorderF(f2)))
|
||||
_DummyV().Flags() |= LINK_V0;
|
||||
|
||||
ti++;
|
||||
en++;
|
||||
}
|
||||
|
||||
//and at the end I verify if the intersection is equal to the star of the edge
|
||||
bool correct=true;
|
||||
ti=_Sets().v1.begin();
|
||||
en=_Sets().indexv1.begin();
|
||||
|
||||
while (ti!=_Sets().v1.end())
|
||||
{
|
||||
vt0=(*ti)->V(0);
|
||||
vt1=(*ti)->V(1);
|
||||
vt2=(*ti)->V(2);
|
||||
vt3=(*ti)->V(3);
|
||||
|
||||
if ((vt0->Flags()& LINK_V0)&&(!(vt0->Flags()& LINK_EE)))
|
||||
correct=false;
|
||||
else
|
||||
if ((vt1->Flags()& LINK_V0)&&(!(vt1->Flags()& LINK_EE)))
|
||||
correct=false;
|
||||
else
|
||||
if ((vt2->Flags()& LINK_V0)&&(!(vt2->Flags()& LINK_EE)))
|
||||
correct=false;
|
||||
else
|
||||
if ((vt3->Flags()& LINK_V0)&&(!(vt3->Flags()& LINK_EE)))
|
||||
correct=false;
|
||||
|
||||
//dummy vertex control
|
||||
int f0=Tetra::FofV((*en),0);
|
||||
int f1=Tetra::FofV((*en),1);
|
||||
int f2=Tetra::FofV((*en),2);
|
||||
|
||||
if (((*ti)->IsBorderF(f0))||((*ti)->IsBorderF(f1))||((*ti)->IsBorderF(f2)))
|
||||
if ((_DummyV().Flags()& LINK_V0)&&(!(_DummyV().Flags()& LINK_EE)))
|
||||
correct=false;
|
||||
|
||||
if (!correct)
|
||||
{
|
||||
VertexType::DeleteBitFlag(LINK_EE);
|
||||
VertexType::DeleteBitFlag(LINK_V1);
|
||||
VertexType::DeleteBitFlag(LINK_V0);
|
||||
// FAIL::LKV();
|
||||
return (false);
|
||||
}
|
||||
en++;
|
||||
ti++;
|
||||
}
|
||||
VertexType::DeleteBitFlag(LINK_EE);
|
||||
VertexType::DeleteBitFlag(LINK_V1);
|
||||
VertexType::DeleteBitFlag(LINK_V0);
|
||||
return true;
|
||||
}
|
||||
|
||||
///verify the flip condition
|
||||
static bool _FlipCondition(PosType pos,CoordType NewP)
|
||||
{
|
||||
int edge=pos.E();
|
||||
VertexType *ve0=pos.T()->V(Tetra::VofE(edge,0));
|
||||
VertexType *ve1=pos.T()->V(Tetra::VofE(edge,1));
|
||||
CoordType oldpos0;
|
||||
CoordType oldpos1;
|
||||
|
||||
typename vector< TetraType *>::iterator ti=_Sets().no_E.begin();
|
||||
|
||||
//saving old position
|
||||
oldpos0 = ve0->P();
|
||||
oldpos1 = ve1->P();
|
||||
|
||||
//assegning new position
|
||||
ve0->P() =NewP;
|
||||
ve1->P() =NewP;
|
||||
|
||||
while (ti!=_Sets().no_E.end())
|
||||
{
|
||||
assert(!(*ti)->IsD());
|
||||
assert((((*ti)->V(0)==ve0)||((*ti)->V(1)==ve0)||((*ti)->V(2)==ve0)||((*ti)->V(3)==ve0))^
|
||||
(((*ti)->V(0)==ve1)||((*ti)->V(1)==ve1)||((*ti)->V(2)==ve1)||((*ti)->V(3)==ve1)));
|
||||
if (vcg::ComputeVolume<TetraType>(**ti)<=0)
|
||||
{
|
||||
// FAIL::VOL();
|
||||
ve0->P()=oldpos0;
|
||||
ve1->P()=oldpos1;
|
||||
return false;
|
||||
}
|
||||
ti++;
|
||||
}
|
||||
|
||||
//reset initial value
|
||||
ve0->P()=oldpos0;
|
||||
ve1->P()=oldpos1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///update the normal of the modified tetrahedrons ond the normal of the vertex that remain after collapse
|
||||
static void _InitTetrahedronValues(VertexType* v)
|
||||
{
|
||||
|
||||
VTIterator<TetraType> VTi= VTIterator<TetraType>(v->VTb(),v->VTi());
|
||||
while (!VTi.End())
|
||||
{
|
||||
if (TetraType::HasTetraQuality())
|
||||
{
|
||||
VTi.Vt()->ComputeAspectRatio();
|
||||
}
|
||||
|
||||
if (TetraType::HasTetraNormal())
|
||||
{
|
||||
VTi.Vt()->ComputeNormal();
|
||||
}
|
||||
|
||||
++VTi;
|
||||
}
|
||||
|
||||
VTi.Vt()=v->VTb();
|
||||
VTi.Vi()=v->VTi();
|
||||
while (!VTi.End())
|
||||
{
|
||||
for (int i=0;i<4;i++)
|
||||
{
|
||||
if (VTi.Vt()->V(i)->IsB())
|
||||
{
|
||||
if (VertexType::HasNormal())
|
||||
UpdateNormals::PerVertex(VTi.Vt()->V(i));
|
||||
}
|
||||
|
||||
}
|
||||
++VTi;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// clean everything
|
||||
static void Reset(){
|
||||
_EdgeMark().clear();
|
||||
_FaceMark().clear();
|
||||
_Sets().clear();
|
||||
_DummyV().ClearFlags();
|
||||
}
|
||||
///Return the aspect Ratio media of the tetrahedrons
|
||||
///that share the adge to collapse
|
||||
static ScalarType AspectRatioCollapsed(PosType p)
|
||||
{
|
||||
//PosL pos=PosL(p.T(),p.F(),p.E(),p.V());
|
||||
PosLoop<TetraType> pos=PosLoop<TetraType>(p.T(),p.F(),p.E(),p.V());
|
||||
pos.Reset();
|
||||
int num=0;
|
||||
ScalarType ratio_media=0.f;
|
||||
while(!pos.end())
|
||||
{
|
||||
ratio_media+=pos.T()->AspectRatio();
|
||||
pos.NextT();
|
||||
num++;
|
||||
}
|
||||
ratio_media=ratio_media/num;
|
||||
return (ratio_media);
|
||||
}
|
||||
|
||||
|
||||
///check the topologycal preserving conditions for the collapse indicated by pos
|
||||
static bool CheckPreconditions(PosType pos,CoordType NewP)
|
||||
{
|
||||
VertexType *v0=pos.T()->V(Tetra::VofE(pos.E(),0));
|
||||
VertexType *v1=pos.T()->V(Tetra::VofE(pos.E(),1));
|
||||
//if the two vertices are of border and the edge is not a border edge
|
||||
//we can do it.
|
||||
bool border0=v0->IsB();
|
||||
bool border1=v1->IsB();
|
||||
bool bordere=Topology::IsExternEdge(pos.T(),pos.E());
|
||||
if (!_QuickConditions(pos))
|
||||
{
|
||||
//FAIL::BOR();
|
||||
return false;
|
||||
}
|
||||
// //first case vertex external and edge internal
|
||||
//if ((border0 && border1)&&(!bordere))
|
||||
//{
|
||||
// //FAIL::BOR();
|
||||
// return false;
|
||||
//}
|
||||
else
|
||||
//if both vertex are internal so is enougth to verify flip conditions
|
||||
if ((!border0) && (!border1))
|
||||
return (_FlipCondition(pos,NewP));
|
||||
else
|
||||
//if the edge is internal is enougth to verify link condition on vertex
|
||||
if (!bordere)
|
||||
return((_FlipCondition(pos,NewP))&&(_LinkConditionsV()));
|
||||
else
|
||||
//at the end if trh edge is on the border we must verify also with the complete test
|
||||
return ((_FlipCondition(pos,NewP))&&(_LinkConditionsV())&&(_LinkConditionsE(pos))&&(_LinkConditionsF(pos)));
|
||||
//return false;
|
||||
}
|
||||
|
||||
///return the sum of volumes of the union of stars on vertices (the original volume of tetrahedrons)
|
||||
static ScalarType VolumeOriginal()
|
||||
{
|
||||
typename vector< TetraType *>::iterator ti=_Sets().v0_U_v1.begin();
|
||||
ScalarType vol=0;
|
||||
while (ti!=_Sets().v0_U_v1.end())
|
||||
{
|
||||
vol+=(*ti)->Volume();
|
||||
ti++;
|
||||
}
|
||||
return vol;
|
||||
}
|
||||
|
||||
///Calculate the volume on the vertex resulting after collapse...
|
||||
static ScalarType VolumeSimulateCollapse(PosType Pos,CoordType &newP)
|
||||
{
|
||||
VertexType *Vrem=(Pos.T()->V(Tetra::VofE(Pos.E(),0)));
|
||||
VertexType *Vdel=(Pos.T()->V(Tetra::VofE(Pos.E(),1)));
|
||||
|
||||
if (Vrem!=Pos.T()->V(Pos.V()))
|
||||
swap<VertexType*>(Vdel,Vrem);
|
||||
|
||||
ScalarType vol=0;
|
||||
CoordType oldpos = Vrem->P();
|
||||
|
||||
//move vertex that remain in the new position
|
||||
Vrem->P() = newP;
|
||||
|
||||
typename vector< TetraType *>::iterator ti=_Sets().no_E.begin();
|
||||
|
||||
while (ti!=_Sets().no_E.end())
|
||||
{
|
||||
/* Tetra3<ScalarType> T=Tetra3<ScalarType>();
|
||||
T.P0(0)=(*ti)->V(0)->cP();
|
||||
T.P1(0)=(*ti)->V(1)->cP();
|
||||
T.P2(0)=(*ti)->V(2)->cP();
|
||||
T.P3(0)=(*ti)->V(3)->cP();
|
||||
|
||||
vol+=T.ComputeVolume(); */
|
||||
// vol+= vcg::ComputeVolume<TetraType>(*((Tetra3<ScalarType>*)&*ti));
|
||||
|
||||
vol+= vcg::ComputeVolume(**ti);
|
||||
ti++;
|
||||
}
|
||||
Vrem->P()=oldpos;
|
||||
return vol;
|
||||
}
|
||||
|
||||
///finds sets used for all test in edge collapse
|
||||
static void FindSets(vcg::tetra::Pos<TetraType> pos)
|
||||
{
|
||||
|
||||
_Sets().clear();
|
||||
int size=40;
|
||||
_Sets().v0.reserve(size);
|
||||
_Sets().indexv0.reserve(size);
|
||||
_Sets().v1.reserve(size);
|
||||
_Sets().indexv1.reserve(size);
|
||||
_Sets().v0_U_v1.reserve(size*2);
|
||||
_Sets().no_E.reserve(size*2);
|
||||
_Sets().E.reserve(size);
|
||||
_Sets().indexE.reserve(size);
|
||||
|
||||
int edge =pos.E();
|
||||
|
||||
VertexType *ve0=pos.T()->V(Tetra::VofE(edge,0));
|
||||
VertexType *ve1=pos.T()->V(Tetra::VofE(edge,1));
|
||||
|
||||
// put all tetrahedrons in the first one vector and in the union
|
||||
VTIterator<TetraType> vf0(ve0->VTb(),ve0->VTi());
|
||||
while (!vf0.End())
|
||||
{
|
||||
//set of ve0
|
||||
_Sets().v0.push_back(vf0.Vt());
|
||||
_Sets().indexv0.push_back(vf0.Vi());
|
||||
//set of union
|
||||
_Sets().v0_U_v1.push_back(vf0.Vt());
|
||||
//set of union minus intersection
|
||||
if ((vf0.Vt()->V(0)!=ve1)&&(vf0.Vt()->V(1)!=ve1)&&(vf0.Vt()->V(2)!=ve1)&&(vf0.Vt()->V(3)!=ve1))
|
||||
_Sets().no_E.push_back(vf0.Vt());
|
||||
++vf0;
|
||||
}
|
||||
|
||||
//second vertex iteration
|
||||
vf0.Vt()=ve1->VTb();
|
||||
vf0.Vi()=ve1->VTi();
|
||||
|
||||
while (!vf0.End())
|
||||
{
|
||||
//set of ve1
|
||||
_Sets().v1.push_back(vf0.Vt());
|
||||
_Sets().indexv1.push_back(vf0.Vi());
|
||||
//set of union
|
||||
_Sets().v0_U_v1.push_back(vf0.Vt());
|
||||
//set of union minus intersection
|
||||
if ((vf0.Vt()->V(0)!=ve0)&&(vf0.Vt()->V(1)!=ve0)&&(vf0.Vt()->V(2)!=ve0)&&(vf0.Vt()->V(3)!=ve0))
|
||||
_Sets().no_E.push_back(vf0.Vt());
|
||||
++vf0;
|
||||
}
|
||||
|
||||
//erase duplicated tetrahedrons from the union set
|
||||
sort(_Sets().v0_U_v1.begin(),_Sets().v0_U_v1.end());
|
||||
unique(_Sets().v0_U_v1.begin(),_Sets().v0_U_v1.end());
|
||||
|
||||
//now compute the intersection
|
||||
PosLType PL(pos.T(),pos.F(),pos.E(),pos.V());
|
||||
|
||||
//mark the vertex on the edge
|
||||
while (!PL.LoopEnd())
|
||||
{
|
||||
_Sets().E.push_back(PL.T());
|
||||
_Sets().indexE.push_back(PL.E());
|
||||
PL.NextT();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
///do the collapse on the edge in postype p
|
||||
static int DoCollapse(PosType p,CoordType newP)
|
||||
{
|
||||
VertexType *v=p.T()->V(p.V());
|
||||
assert(p.T()->HasVTAdjacency());
|
||||
int n_del=_Collapse(p,newP);
|
||||
_InitTetrahedronValues(v);
|
||||
return n_del;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
}//end namespace
|
||||
}//end namespace
|
||||
#endif
|
|
@ -1,478 +0,0 @@
|
|||
/****************************************************************************
|
||||
* VCGLib o o *
|
||||
* Visual and Computer Graphics Library o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2004 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
/****************************************************************************
|
||||
History
|
||||
|
||||
****************************************************************************/
|
||||
#ifndef __VCG_TETRA_EDGE_SPLIT
|
||||
#define __VCG_TETRA_EDGE_SPLIT
|
||||
|
||||
#include <vcg/simplex/tetrahedron/pos.h>
|
||||
#include <vcg/complex/tetramesh/allocate.h>
|
||||
#include <vcg/complex/tetramesh/update/topology.h>
|
||||
#include <vcg/space/tetra.h>
|
||||
namespace vcg{
|
||||
namespace tetra{
|
||||
|
||||
/** \addtogroup tetramesh */
|
||||
/*@{*/
|
||||
/// This Class is used for split the edges
|
||||
|
||||
template <class TETRA_MESH_TYPE>
|
||||
class EdgeSplit
|
||||
{
|
||||
public:
|
||||
/// The tetrahedral mesh type
|
||||
typedef typename TETRA_MESH_TYPE TetraMeshType;
|
||||
/// The tetrahedron type
|
||||
typedef typename TetraMeshType::TetraType TetraType;
|
||||
/// The vertex type
|
||||
typedef typename TetraType::VertexType VertexType;
|
||||
/// The vertex iterator type
|
||||
typedef typename TetraMeshType::VertexIterator VertexIterator;
|
||||
/// The tetra iterator type
|
||||
typedef typename TetraMeshType::TetraIterator TetraIterator;
|
||||
/// The coordinate type
|
||||
typedef typename TetraType::VertexType::CoordType CoordType;
|
||||
///the container of tetrahedron type
|
||||
typedef typename TetraMeshType::TetraContainer TetraContainer;
|
||||
///the container of vertex type
|
||||
typedef typename TetraMeshType::VertexContainer VertexContainer;
|
||||
/// The HEdgePos type
|
||||
typedef PosLoop<TetraType> PosType;
|
||||
/// The topology updater type
|
||||
typedef vcg::tetra::UpdateTetraTopology<VertexContainer,TetraContainer> Topology;
|
||||
/// The allocator type
|
||||
typedef vcg::tetra::Allocator<TetraMeshType> TetraAllocator;
|
||||
/// Default Constructor
|
||||
EdgeSplit()
|
||||
{
|
||||
};
|
||||
|
||||
~EdgeSplit()
|
||||
{
|
||||
};
|
||||
|
||||
private:
|
||||
///the tetrahedron that must mark as Deleted after substitution
|
||||
TetraType* _toDel[30];
|
||||
///The number of tetrahedrons that are substituted
|
||||
int _nT;
|
||||
|
||||
Topology _Topo;
|
||||
|
||||
///add a vertex into the edge at distance alfa ( 0<alfa<1) to the first vertex of the edge
|
||||
|
||||
VertexType* _AddVertexEdge(TetraMeshType &tm,const TetraType &t,const int &edge,const double &alfa)
|
||||
{
|
||||
VertexType *v0=(VertexType*)t.V(Tetra::VofE(edge,0));
|
||||
VertexType *v1=(VertexType*)t.V(Tetra::VofE(edge,1));
|
||||
Allocator<TetraMeshType> All= Allocator<TetraMeshType>();
|
||||
VertexIterator vn=All.AddVertices(tm,1);
|
||||
vn->Flags()=0;
|
||||
vn->VTb()=NULL;
|
||||
vn->VTi()=-1;
|
||||
vn->P()=(v0->P()*alfa)+(v1->P()*(1.0f-alfa));
|
||||
return (&(*vn));
|
||||
}
|
||||
|
||||
///set the default v-t topology
|
||||
void _SetDefultVTTopology(TetraType *t)
|
||||
{
|
||||
unsigned int j;
|
||||
for (j=0;j<4;j++)
|
||||
{
|
||||
t->TVp(j) = NULL;
|
||||
t->TVi(j) = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/// Transform the vertex index according to rotation of the tetraedron
|
||||
/// that trasform it in the basic case
|
||||
static int _GetMapVertEdgeRot(const int &indexE,const int &indexV)
|
||||
{
|
||||
static int mapvertedgerot[12][4]={
|
||||
{0,3,1,2},
|
||||
{0,1,2,3},
|
||||
{0,2,3,1},
|
||||
{1,3,2,0},
|
||||
{1,0,3,2},
|
||||
{2,1,3,0},
|
||||
|
||||
{1,2,0,3},
|
||||
{2,3,0,1},
|
||||
{3,1,0,2},
|
||||
{2,0,1,3},
|
||||
{3,2,1,0},
|
||||
{3,0,2,1},
|
||||
};
|
||||
assert ((indexE<12)&&(indexV<4));
|
||||
return mapvertedgerot[indexE][indexV];
|
||||
}
|
||||
|
||||
/// Transform the face index according to rotation of the tetraedron
|
||||
/// that trasform it in the basic case
|
||||
static int _GetMapFaceEdgeRot(const int &indexE,const int &indexF)
|
||||
{
|
||||
static int mapfaceedgerot[12][4]={
|
||||
{1,2,0,3},
|
||||
{0,1,2,3},
|
||||
{2,0,1,3},
|
||||
{3,1,0,2},
|
||||
{1,0,3,2},
|
||||
{3,0,2,1},
|
||||
|
||||
{0,3,1,2},
|
||||
{2,3,0,1},
|
||||
{1,3,2,0},
|
||||
{0,2,3,1},
|
||||
{3,2,1,0},
|
||||
{2,1,3,0},
|
||||
};
|
||||
assert ((indexE<12)&&(indexF<4));
|
||||
return mapfaceedgerot[indexE][indexF];
|
||||
}
|
||||
|
||||
/// Returns the rotation sense during the loop on the edge to divide
|
||||
/// according to rotation of the tetraedron that trasform it in the basic case
|
||||
static int _GetDirRot(int indexE,int indexF)
|
||||
{
|
||||
static int mapfaceedgerot[12][4]={
|
||||
{2,0,-1,-1},
|
||||
{0,-1,2,-1},
|
||||
{-1,2,0,-1},
|
||||
{2,-1,-1,0},
|
||||
{-1,0,-1,2},
|
||||
{-1,-1,2,0},
|
||||
|
||||
{0,2,-1,-1},
|
||||
{2,-1,0,-1},
|
||||
{-1,0,2,-1},
|
||||
{0,-1,-1,2},
|
||||
{-1,2,-1,0},
|
||||
{-1,-1,0,2},
|
||||
};
|
||||
|
||||
assert ((indexE<12)&&(indexF<4));
|
||||
return mapfaceedgerot[indexE][indexF];
|
||||
}
|
||||
|
||||
///Built an Half edge on tetrahedron t using edge edge
|
||||
PosType _FindPos(TetraType *t,int edge)
|
||||
{
|
||||
int face0=Tetra::FofE(edge,0);
|
||||
int ve0=Tetra::VofE(edge,0);
|
||||
PosType pos(t,face0,edge,ve0);
|
||||
return pos;
|
||||
}
|
||||
|
||||
///Assert the right order of vertex that compose the tetrahedron
|
||||
void _AssertOrder(TetraType *t,VertexType *v0,VertexType *v1,VertexType *v2,VertexType *v3)
|
||||
{
|
||||
assert(t->V(0)==v0);
|
||||
assert(t->V(1)==v1);
|
||||
assert(t->V(2)==v2);
|
||||
assert(t->V(3)==v3);
|
||||
}
|
||||
|
||||
///Connect trought Tetrahedron-Tetrahedron Topology t0 and t1 with faces i0 and i1
|
||||
void _ConnectTTTopology(TetraType *t0,int i0,TetraType *t1,int i1)
|
||||
{
|
||||
assert((i0>=0)&&(i0<4));
|
||||
assert((i1>=0)&&(i1<4));
|
||||
assert((!t0->IsD())&&(!t1->IsD()));
|
||||
t0->TTp(i0)=t1;
|
||||
t0->TTi(i0)=i1;
|
||||
t1->TTp(i1)=t0;
|
||||
t1->TTi(i1)=i0;
|
||||
assert( (((t0->TTp(i0))->TTp(t0->TTi(i0)))==t0));
|
||||
assert( (((t1->TTp(i1))->TTp(t1->TTi(i1)))==t1));
|
||||
}
|
||||
|
||||
///Divide the tetrahadron in pos in two tetrahedrons using the new vertex vnew
|
||||
void _Divide(PosType pos,VertexType *vnew,TetraType *newtp0,TetraType *newtp1,bool invert)
|
||||
{
|
||||
int curredge=pos.E();
|
||||
|
||||
//control if the edge vertices arein the right order for the table
|
||||
if (invert)
|
||||
curredge+=6;
|
||||
|
||||
//find the new position to vertex according
|
||||
int ie0=_GetMapVertEdgeRot(curredge,0);
|
||||
int ie1=_GetMapVertEdgeRot(curredge,2);
|
||||
int in0=_GetMapVertEdgeRot(curredge,1);
|
||||
int in1=_GetMapVertEdgeRot(curredge,3);
|
||||
|
||||
//as first the ones that appartain to the selected curredge
|
||||
VertexType *ve0=pos.T()->V(ie0);
|
||||
VertexType *ve1=pos.T()->V(ie1);
|
||||
|
||||
//and after the others that will be in the cutting plane
|
||||
VertexType *vn0=pos.T()->V(in0);
|
||||
VertexType *vn1=pos.T()->V(in1);
|
||||
|
||||
newtp0->V(0)=ve0;
|
||||
newtp0->V(1)=vn0;
|
||||
newtp0->V(2)=vnew;
|
||||
newtp0->V(3)=vn1;
|
||||
|
||||
newtp1->V(0)=vnew;
|
||||
newtp1->V(1)=vn0;
|
||||
newtp1->V(2)=ve1;
|
||||
newtp1->V(3)=vn1;
|
||||
|
||||
//right order of the vertices
|
||||
#ifdef _DEBUG
|
||||
_AssertOrder(newtp0,ve0,vn0,vnew,vn1);
|
||||
_AssertOrder(newtp1,vnew,vn0,ve1,vn1);
|
||||
//end asserts
|
||||
#endif
|
||||
}
|
||||
|
||||
bool _InvertRotation(PosType pos)
|
||||
{
|
||||
return (pos.V()!=Tetra::VofE(pos.E(),0));
|
||||
}
|
||||
|
||||
///substitute the told tetrahedon on VT topology with newtp0 and newtp1 as created
|
||||
void _SubstituteVTTopology(TetraType *told,TetraType *newtp0,TetraType *newtp1)
|
||||
{
|
||||
_SetDefultVTTopology(newtp0);
|
||||
_SetDefultVTTopology(newtp1);
|
||||
|
||||
//detach the old tetrahedron from VTtopology
|
||||
_Topo.DetachVTTopology(told);
|
||||
//tetrahedron 0
|
||||
_Topo.InsertVTTopology(newtp0);
|
||||
//tetrahedron 1
|
||||
_Topo.InsertVTTopology(newtp1);
|
||||
}
|
||||
|
||||
///control if the connections between tetrahedron created have the right shared vertices
|
||||
void _ControlConnection(TetraType *oldtp0,TetraType *newtp0)
|
||||
{
|
||||
VertexType *v00=oldtp0->V(0);
|
||||
VertexType *v01=oldtp0->V(1);
|
||||
VertexType *v02=oldtp0->V(2);
|
||||
VertexType *v03=oldtp0->V(3);
|
||||
|
||||
VertexType *v10=newtp0->V(0);
|
||||
VertexType *v11=newtp0->V(1);
|
||||
VertexType *v12=newtp0->V(2);
|
||||
VertexType *v13=newtp0->V(3);
|
||||
|
||||
assert(((v00==v10)&&(v02==v12))||((v00==v12)&&(v02==v10)));
|
||||
assert(((v01==v13)&&(v03!=v11))||((v01!=v13)&&(v03==v11)));
|
||||
}
|
||||
|
||||
///set as extern the 4 faces of the tetrahedron
|
||||
void _SetDefaultTTExtern(TetraType *t)
|
||||
{
|
||||
for (int y=0;y<4;y++)
|
||||
{
|
||||
t->TTp(y)=t;
|
||||
t->TTi(y)=y;
|
||||
}
|
||||
}
|
||||
|
||||
///substitute in Tetra Tetra Topology the tetrahedron old_t with new_t in according
|
||||
///to face and edge
|
||||
|
||||
void _SubstituteTTTopology(TetraType *old_t,TetraType *new_t,int edgerot,int face)
|
||||
{
|
||||
int indexface=_GetMapFaceEdgeRot(edgerot,face);
|
||||
|
||||
if (old_t->IsBorderF(indexface))
|
||||
{
|
||||
new_t->TTp(face)=new_t;
|
||||
new_t->TTi(face)=face;
|
||||
}
|
||||
else
|
||||
{
|
||||
TetraType *tetrad=old_t->TTp(indexface);
|
||||
int fad=old_t->TTi(indexface);
|
||||
_ConnectTTTopology(new_t,face,tetrad,fad);
|
||||
assert (!tetrad->IsD());
|
||||
}
|
||||
}
|
||||
|
||||
/// sobstitute the old tetrahedrons that share the edge in pos with new ones
|
||||
/// that share the vertex vnew that divide the old edge
|
||||
|
||||
void _AddNewTetrahedrons(TetraMeshType &tm,PosType pos,VertexType *vnew)
|
||||
{
|
||||
|
||||
TetraType *oldtp0=NULL;
|
||||
TetraType *oldtp1=NULL;
|
||||
|
||||
TetraType *newtp0;
|
||||
TetraType *newtp1;
|
||||
|
||||
TetraType *firsttp0=NULL;
|
||||
TetraType *firsttp1=NULL;
|
||||
|
||||
|
||||
int curredge;
|
||||
int direction=-1;
|
||||
bool invert=false;
|
||||
|
||||
TetraAllocator All=TetraAllocator();
|
||||
pos.Reset();
|
||||
_nT=0;
|
||||
|
||||
while (!pos.LoopEnd())
|
||||
{
|
||||
assert(!pos.T()->IsD());
|
||||
|
||||
invert=_InvertRotation(pos);
|
||||
|
||||
//CREATE THE NEW TETRAHEDRONS
|
||||
|
||||
//create the new ones putting the veritices in the right order
|
||||
TetraIterator ti=All.AddTetra(tm,2);
|
||||
newtp0 = &(*ti);
|
||||
ti++;
|
||||
newtp1 = &(*ti);
|
||||
|
||||
|
||||
_Divide(pos,vnew,newtp0,newtp1,invert);
|
||||
|
||||
#ifdef _DEBUG
|
||||
if ((oldtp0!=NULL)&&(!pos.Jump()))
|
||||
_ControlConnection(oldtp0,newtp0);
|
||||
if ((oldtp1!=NULL)&&(!pos.Jump()))
|
||||
_ControlConnection(oldtp1,newtp1);
|
||||
#endif
|
||||
|
||||
// SUBSTITUTE NEW TETRAHEDRONS ON VT TOPOLOGY
|
||||
if (tm.HasVTTopology())
|
||||
_SubstituteVTTopology(pos.T(),newtp0,newtp1);
|
||||
|
||||
|
||||
//THEN SET THE T-T TOPOLOGY
|
||||
|
||||
_SetDefaultTTExtern(newtp0);
|
||||
_SetDefaultTTExtern(newtp1);
|
||||
|
||||
curredge=pos.E();
|
||||
if (invert)
|
||||
curredge+=6;
|
||||
|
||||
//face3
|
||||
_SubstituteTTTopology(pos.T(),newtp1,curredge,3);
|
||||
|
||||
//face1
|
||||
_SubstituteTTTopology(pos.T(),newtp0,curredge,1);
|
||||
|
||||
//now I set t-t topology between themselfes
|
||||
|
||||
_ConnectTTTopology(newtp0,3,newtp1,1);
|
||||
|
||||
if (pos.Jump())
|
||||
{
|
||||
vnew->SetB();
|
||||
oldtp0=NULL;
|
||||
oldtp1=NULL;
|
||||
}
|
||||
|
||||
direction=_GetDirRot(curredge,pos.F());
|
||||
assert(direction!=-1);
|
||||
//control the direction of moving
|
||||
if ((oldtp0!=NULL)&&(oldtp1!=NULL))
|
||||
{
|
||||
//direction=_GetDirRot(oldtp0,newtp0);
|
||||
|
||||
//find direction of moving
|
||||
if (direction==0)
|
||||
{
|
||||
_ConnectTTTopology(oldtp0,0,newtp0,2);
|
||||
_ConnectTTTopology(oldtp1,0,newtp1,2);
|
||||
}
|
||||
else
|
||||
if (direction==2)
|
||||
{
|
||||
_ConnectTTTopology(oldtp0,2,newtp0,0);
|
||||
_ConnectTTTopology(oldtp1,2,newtp1,0);
|
||||
}
|
||||
}
|
||||
//assign if it is the first one
|
||||
if (firsttp0==NULL)
|
||||
firsttp0=newtp0;
|
||||
if (firsttp1==NULL)
|
||||
firsttp1=newtp1;
|
||||
|
||||
oldtp0=newtp0;
|
||||
oldtp1=newtp1;
|
||||
|
||||
_toDel[_nT]=pos.T();
|
||||
_nT++;
|
||||
pos.NextT();
|
||||
}
|
||||
|
||||
//at the end I finish the connections
|
||||
if (!(pos.Jump())&&(direction==0)&&(firsttp0!=NULL)&&(firsttp1!=NULL)&&(oldtp0!=NULL)&&(oldtp1!=NULL))
|
||||
{
|
||||
_ConnectTTTopology(oldtp0,0,firsttp0,2);
|
||||
_ConnectTTTopology(oldtp1,0,firsttp1,2);
|
||||
}
|
||||
else if (!(pos.Jump())&&(direction==2)&&(firsttp0!=NULL)&&(firsttp1!=NULL)&&(oldtp0!=NULL)&&(oldtp1!=NULL))
|
||||
{
|
||||
_ConnectTTTopology(oldtp0,2,firsttp0,0);
|
||||
_ConnectTTTopology(oldtp1,2,firsttp1,0);
|
||||
}
|
||||
else if (pos.Jump())
|
||||
vnew->SetB();
|
||||
|
||||
}
|
||||
|
||||
///Mark as deleted the tetrahedron that must be substituted
|
||||
void _DeleteOldTetra()
|
||||
{
|
||||
for (int i=0;i<_nT;i++)
|
||||
_toDel[i]->SetD();
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
|
||||
public:
|
||||
|
||||
/// Split the edge with local remeshing
|
||||
/// Tetrahedron-Tetrahedron topology is required
|
||||
VertexType* DoSplit(TetraMeshType &tm,TetraType *t,int edge,double alfa)
|
||||
{
|
||||
assert(!t->IsD());
|
||||
assert(tm.HasTTTopology());
|
||||
assert((alfa>0)&&(alfa<1));
|
||||
assert((edge>=0)&&(edge<6));
|
||||
VertexType *vnew=_AddVertexEdge(tm,*t,edge,alfa);
|
||||
_AddNewTetrahedrons(tm,_FindPos(t,edge),vnew);
|
||||
_DeleteOldTetra();
|
||||
return(vnew);
|
||||
}
|
||||
|
||||
};//end class
|
||||
|
||||
}//end namespace tetra
|
||||
}//end namespace vcg
|
||||
#endif
|
|
@ -1,150 +0,0 @@
|
|||
|
||||
|
||||
/****************************************************************************
|
||||
* VCGLib o o *
|
||||
* Visual and Computer Graphics Library o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2004 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
/****************************************************************************
|
||||
History
|
||||
|
||||
$Log: not supported by cvs2svn $
|
||||
Revision 1.4 2005/02/08 14:36:20 turini
|
||||
Warnings Correction
|
||||
|
||||
Revision 1.3 2004/05/17 08:22:45 turini
|
||||
Minor Changes and Now Use STLContainer of Tetrahedron Pointers.
|
||||
|
||||
Revision 1.2 2004/05/14 15:51:47 turini
|
||||
Adjusted VCG Style
|
||||
|
||||
Revision 1.1 2004/05/14 15:43:41 turini
|
||||
Initial Commit
|
||||
|
||||
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __VCGLIB_TETRASUBSET
|
||||
#define __VCGLIB_TETRASUBSET
|
||||
|
||||
|
||||
namespace vcg {
|
||||
namespace tetra {
|
||||
|
||||
/** \addtogroup tetramesh */
|
||||
/*@{*/
|
||||
|
||||
|
||||
template <class I_TETRAMESH_TYPE>
|
||||
struct InsertedVT
|
||||
{
|
||||
typedef I_TETRAMESH_TYPE ITetraMeshType;
|
||||
typedef typename ITetraMeshType::VertexPointer VertexPointer;
|
||||
typedef typename ITetraMeshType::TetraPointer TetraPointer;
|
||||
|
||||
InsertedVT(VertexPointer _v, TetraPointer _t, int _z)
|
||||
: v(_v), t(_t), z(_z)
|
||||
{}
|
||||
|
||||
VertexPointer v;
|
||||
TetraPointer t;
|
||||
int z;
|
||||
|
||||
const bool operator <(const InsertedVT & o)
|
||||
{
|
||||
return (v<o.v);
|
||||
}
|
||||
|
||||
const bool operator ==(const InsertedVT & o)
|
||||
{
|
||||
return (v==o.v);
|
||||
}
|
||||
|
||||
const bool operator !=(const InsertedVT & o)
|
||||
{
|
||||
return (v!=o.v);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** Create a copy of the mesh with tetrahedron that are into the templated container
|
||||
@param ST_CONT (Template Parameter) Specifies the type of the container of tetrahedron.
|
||||
@param subSet Container of tetrahedron pointers !!!
|
||||
@param m destination mesh.
|
||||
*/
|
||||
template <class S_TETRAMESH_TYPE, class STL_CONT >
|
||||
void SubSet(S_TETRAMESH_TYPE & m, STL_CONT & subSet)
|
||||
{
|
||||
std::vector< InsertedVT<S_TETRAMESH_TYPE> > newVertices;
|
||||
typename STL_CONT::iterator pfi;
|
||||
newVertices.clear();
|
||||
|
||||
for(pfi=subSet.begin(); pfi!=subSet.end(); ++pfi)
|
||||
m.tetra.push_back(*(*pfi));
|
||||
|
||||
typename S_TETRAMESH_TYPE::TetraIterator fi;
|
||||
for(fi=m.tetra.begin(); fi!=m.tetra.end(); ++fi)
|
||||
{
|
||||
newVertices.push_back(InsertedVT<S_TETRAMESH_TYPE>((*fi).V(0), &(*fi), 0));
|
||||
newVertices.push_back(InsertedVT<S_TETRAMESH_TYPE>((*fi).V(1), &(*fi), 1));
|
||||
newVertices.push_back(InsertedVT<S_TETRAMESH_TYPE>((*fi).V(2), &(*fi), 2));
|
||||
newVertices.push_back(InsertedVT<S_TETRAMESH_TYPE>((*fi).V(3), &(*fi), 3));
|
||||
}
|
||||
|
||||
std::sort(newVertices.begin(), newVertices.end());
|
||||
|
||||
typename std::vector< InsertedVT<S_TETRAMESH_TYPE> >::iterator curr,next;
|
||||
int pos=0;
|
||||
curr=next=newVertices.begin();
|
||||
while(next!=newVertices.end())
|
||||
{
|
||||
if((*curr)!=(*next))
|
||||
pos++;
|
||||
(*next).t->V((*next).z)=(typename S_TETRAMESH_TYPE::VertexPointer)pos;
|
||||
curr=next;
|
||||
next++;
|
||||
}
|
||||
|
||||
typename std::vector< InsertedVT<S_TETRAMESH_TYPE> >::iterator newE=std::unique(newVertices.begin(), newVertices.end());
|
||||
|
||||
for(curr=newVertices.begin(); curr!=newE; ++curr)
|
||||
m.vert.push_back(*((*curr).v));
|
||||
|
||||
for(fi=m.tetra.begin(); fi!=m.tetra.end(); ++fi)
|
||||
{
|
||||
(*fi).V(0)=&(m.vert[(int)(*fi).V(0)]);
|
||||
(*fi).V(1)=&(m.vert[(int)(*fi).V(1)]);
|
||||
(*fi).V(2)=&(m.vert[(int)(*fi).V(2)]);
|
||||
(*fi).V(3)=&(m.vert[(int)(*fi).V(3)]);
|
||||
}
|
||||
m.vn=(int)m.vert.size();
|
||||
m.tn=(int)m.tetra.size();
|
||||
}
|
||||
|
||||
|
||||
/*@}*/
|
||||
} // End namespace
|
||||
} // End namespace
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
/****************************************************************************
|
||||
* VCGLib o o *
|
||||
* Visual and Computer Graphics Library o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2004 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
/****************************************************************************
|
||||
History
|
||||
|
||||
$Log: not supported by cvs2svn $
|
||||
Revision 1.1 2004/05/04 11:15:13 pietroni
|
||||
First working version!
|
||||
|
||||
|
||||
****************************************************************************/
|
||||
#ifndef __VCG_TETRA_UPDATE_BOUNDING
|
||||
#define __VCG_TETRA_UPDATE_BOUNDING
|
||||
|
||||
namespace vcg {
|
||||
namespace tetra {
|
||||
|
||||
/** \addtogroup tetramesh */
|
||||
/*@{*/
|
||||
|
||||
/// Management, updating and computation of bonding box on a tetrahedral mesh
|
||||
|
||||
template <class ComputeMeshType>
|
||||
class UpdateBounding
|
||||
{
|
||||
|
||||
public:
|
||||
typedef ComputeMeshType MeshType;
|
||||
typedef typename MeshType::VertexType VertexType;
|
||||
typedef typename MeshType::VertexPointer VertexPointer;
|
||||
typedef typename MeshType::VertexIterator VertexIterator;
|
||||
typedef typename MeshType::TetraType TetraType;
|
||||
typedef typename MeshType::TetraPointer TetraPointer;
|
||||
typedef typename MeshType::TetraIterator TetraIterator;
|
||||
|
||||
/// Calculates the limits of bounding box of tetrahedral mesh
|
||||
static void Box(ComputeMeshType &m)
|
||||
{
|
||||
m.bbox.SetNull();
|
||||
VertexIterator vi;
|
||||
for(vi=m.vert.begin();vi!=m.vert.end();++vi)
|
||||
if( !(*vi).IsD() ) m.bbox.Add((*vi).P());
|
||||
|
||||
}
|
||||
|
||||
|
||||
}; // end class
|
||||
|
||||
} // End namespace
|
||||
} // End namespace
|
||||
|
||||
|
||||
#endif
|
|
@ -1,179 +0,0 @@
|
|||
/****************************************************************************
|
||||
* VCGLib o o *
|
||||
* Visual and Computer Graphics Library o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2004 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
/****************************************************************************
|
||||
History
|
||||
|
||||
$Log: not supported by cvs2svn $
|
||||
Revision 1.8 2004/10/28 00:54:34 cignoni
|
||||
Better Doxygen documentation
|
||||
|
||||
Revision 1.7 2004/09/01 12:17:25 pietroni
|
||||
minor changes to comply gcc compiler (typename's )
|
||||
|
||||
Revision 1.6 2004/06/25 11:25:07 pietroni
|
||||
changrd update for a vertex normal functions void PerVertex(VertexType *v)
|
||||
|
||||
Revision 1.5 2004/06/15 16:01:26 pietroni
|
||||
added functions to update local vertices normal
|
||||
|
||||
Revision 1.4 2004/05/26 11:59:09 turini
|
||||
Changed : Use Of vector In Use Of std::vector.
|
||||
|
||||
Revision 1.3 2004/05/26 11:53:17 pietroni
|
||||
modified face declaration
|
||||
|
||||
Revision 1.2 2004/05/26 11:48:53 turini
|
||||
Changed : include Path.
|
||||
|
||||
Revision 1.1 2004/05/12 13:52:11 pietroni
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.2 2004/03/12 15:22:19 pietroni
|
||||
Written some documentation and added to the trimes doxygen module
|
||||
|
||||
|
||||
****************************************************************************/
|
||||
#ifndef __VCG_TETRA_UPDATE_NORMALS
|
||||
#define __VCG_TETRA_UPDATE_NORMALS
|
||||
|
||||
#include<vcg\complex\tetramesh\update\triconvert.h>
|
||||
#include<vcg\simplex\face\face.h>
|
||||
#include<vcg\complex\trimesh\base.h>
|
||||
#include<vcg\complex\trimesh\update\normal.h>
|
||||
#include<vcg\simplex\tetrahedron\pos.h>
|
||||
#include<vector>
|
||||
|
||||
namespace vcg {
|
||||
namespace tetra {
|
||||
|
||||
/** \addtogroup tetramesh */
|
||||
/*@{*/
|
||||
|
||||
/// Management, updating and computation of per-vertex and per-face normals.
|
||||
/// This class is used to compute or update the normals that can be stored in the vertex or face component of a mesh.
|
||||
template <class ComputeMeshType>
|
||||
class UpdateNormals
|
||||
{
|
||||
|
||||
public:
|
||||
typedef ComputeMeshType TetraMeshType;
|
||||
typedef typename TetraMeshType::VertexType VertexType;
|
||||
typedef typename TetraMeshType::VertexPointer VertexPointer;
|
||||
typedef typename TetraMeshType::VertexIterator VertexIterator;
|
||||
typedef typename TetraMeshType::TetraType TetraType;
|
||||
typedef typename TetraMeshType::TetraPointer TetraPointer;
|
||||
typedef typename TetraMeshType::TetraIterator TetraIterator;
|
||||
typedef typename VertexType::NormalType NormalType;
|
||||
|
||||
typedef vcg::Face<VertexType,vcg::DUMMYEDGETYPE,vcg::DUMMYFACETYPE> FaceTemp;
|
||||
typedef vcg::tri::TriMesh< std::vector<VertexType>,std::vector<FaceTemp> > TriMeshTemp;
|
||||
|
||||
/// Calculates the vertex normal (if stored in the current face type)
|
||||
static void PerTetraFace(TetraMeshType &m)
|
||||
{
|
||||
if( !m.HasPerTetraNormal()) return;
|
||||
TetraIterator t;
|
||||
for(t=m.tetra.begin();t!=m.tetra.end();++t)
|
||||
if( !(*t).IsD() ) (*t).ComputeNormal();
|
||||
}
|
||||
|
||||
/// Calculates the vertex normal of a vertex.
|
||||
static void PerVertex(VertexType *v)
|
||||
{
|
||||
|
||||
if( !VertexType::HasNormal()) return;
|
||||
|
||||
VTIterator<TetraType> VTi=VTIterator<TetraType>(v->VTb(),v->VTi());
|
||||
NormalType Norm=NormalType(0,0,0);
|
||||
int iter=0;
|
||||
while (!VTi.End())
|
||||
{
|
||||
//take the tree faces on the vertex's tetrahedron
|
||||
for (int j=0;j<3;j++)
|
||||
{
|
||||
int f=Tetra::FofV(VTi.Vi(),j);
|
||||
if (VTi.Vt()->IsBorderF(f))
|
||||
{
|
||||
iter++;
|
||||
Norm+=VTi.Vt()->N(f);
|
||||
}
|
||||
}
|
||||
++VTi;
|
||||
}
|
||||
Norm/=(float)iter;
|
||||
v->N()=Norm.Normalize();
|
||||
}
|
||||
|
||||
/// Calculates the vertex normal. Without exploiting or touching face normals
|
||||
/// The normal of a vertex v is the weigthed average of the normals of the faces incident on v.
|
||||
static void PerVertex(TetraMeshType &m)
|
||||
{
|
||||
|
||||
if( !HasPerVertexNormal(m)) return;
|
||||
_ClearNormal(m);
|
||||
TriMeshTemp tri_mesh=TriMeshTemp();
|
||||
TriConverter <TetraMeshType,TriMeshTemp>tric=TriConverter<TetraMeshType,TriMeshTemp>();
|
||||
tric.Convert(m.tetra,tri_mesh);
|
||||
vcg::tri::UpdateNormals<TriMeshTemp> UNT=vcg::tri::UpdateNormals<TriMeshTemp>();
|
||||
UNT.PerVertexNormalized(tri_mesh);
|
||||
}
|
||||
private:
|
||||
static void _ClearNormal(TetraMeshType &m)
|
||||
{
|
||||
if( !HasPerVertexNormal(m)) return;
|
||||
VertexIterator vi;
|
||||
for(vi=m.vert.begin();vi!=m.vert.end();++vi)
|
||||
if( !(*vi).IsD() && (*vi).IsRW() )
|
||||
(*vi).N() = VertexType::NormalType(0,0,0);
|
||||
}
|
||||
|
||||
///// Calculates both vertex and face normals.
|
||||
///// The normal of a vertex v is the weigthed average of the normals of the faces incident on v.
|
||||
//static void PerVertexPerFace(ComputeTetraMeshType &m)
|
||||
//{
|
||||
// if( !HasPerVertexNormal(m) || !HasPerFaceNormal(m)) return;
|
||||
//
|
||||
//
|
||||
//}
|
||||
//
|
||||
//
|
||||
//static void PerFaceNormalized(ComputeTetraMeshType &m)
|
||||
//{
|
||||
//
|
||||
//}
|
||||
//
|
||||
//
|
||||
///// Calculates the vertex normal
|
||||
//static void PerVertexNormalized(ComputeTetraMeshType &m)
|
||||
//{
|
||||
//
|
||||
//}
|
||||
|
||||
|
||||
}; // end class
|
||||
|
||||
} // End namespace
|
||||
} // End namespace
|
||||
|
||||
|
||||
#endif
|
|
@ -1,710 +0,0 @@
|
|||
/****************************************************************************
|
||||
* VCGLib o o *
|
||||
* Visual and Computer Graphics Library o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2004 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
/****************************************************************************
|
||||
History
|
||||
|
||||
$Log: not supported by cvs2svn $
|
||||
Revision 1.17 2006/12/03 14:56:30 ganovelli
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.16 2006/06/29 13:07:33 ganovelli
|
||||
Aggiunta superclasse UpdateTopology templated sui container e con funzioni sui container
|
||||
|
||||
|
||||
Revision 1.1 2004/16/04 14:32 pietroni
|
||||
Initial commit
|
||||
|
||||
|
||||
****************************************************************************/
|
||||
#ifndef __VCG_TETRA_UPDATE_TOPOLOGY
|
||||
#define __VCG_TETRA_UPDATE_TOPOLOGY
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <vcg\simplex\tetrahedron\pos.h>
|
||||
using namespace std;
|
||||
namespace vcg {
|
||||
namespace tetra {
|
||||
/** Class Facet.
|
||||
This is class for definition of a face of tethahedron
|
||||
@param STL_VERT_CONT (Template Parameter) Specifies the type of the vertices container any the vertex type.
|
||||
*/
|
||||
|
||||
|
||||
template < class VERT_TYPE , class TETRA_TYPE>
|
||||
class Facet{
|
||||
|
||||
public:
|
||||
|
||||
/// The vertex type
|
||||
typedef VERT_TYPE MVTYPE;
|
||||
typedef TETRA_TYPE MTTYPE;
|
||||
|
||||
|
||||
private:
|
||||
MTTYPE *Tr;
|
||||
int numface;
|
||||
MVTYPE * vertex[3];
|
||||
|
||||
public:
|
||||
|
||||
Facet(MVTYPE *v0,MVTYPE *v1,MVTYPE *v2,TETRA_TYPE * t,int index)
|
||||
{
|
||||
vertex[0]=v0;
|
||||
vertex[1]=v1;
|
||||
vertex[2]=v2;
|
||||
if(vertex[0] > vertex[1]) std::swap(vertex[0], vertex[1]);
|
||||
if(vertex[1] > vertex[2])
|
||||
{
|
||||
std::swap(vertex[1], vertex[2]);
|
||||
if(vertex[0] > vertex[1])
|
||||
{
|
||||
std::swap(vertex[0], vertex[1]);
|
||||
}
|
||||
}
|
||||
Tr = t;
|
||||
numface = index;
|
||||
}
|
||||
|
||||
inline const MVTYPE * V(int index) const
|
||||
{
|
||||
return vertex[index];
|
||||
}
|
||||
|
||||
TETRA_TYPE *getTetrahedron()
|
||||
{
|
||||
return Tr;
|
||||
}
|
||||
|
||||
void setTetrahedron(TETRA_TYPE * t)
|
||||
{
|
||||
Tr=t;
|
||||
}
|
||||
|
||||
inline bool operator == ( Facet const & f) const
|
||||
{
|
||||
return ((vertex[0]==f.V(0))&&(vertex[1]==f.V(1))&&(vertex[2]==f.V(2)));
|
||||
}
|
||||
|
||||
inline bool operator != ( Facet const & f) const
|
||||
{
|
||||
return !((*this) == f);
|
||||
}
|
||||
|
||||
inline bool operator > ( Facet const & f) const
|
||||
{
|
||||
|
||||
if (vertex[0]!=f.V(0))
|
||||
{
|
||||
if (vertex[0]>f.V(0))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
if (vertex[1]!=f.V(1))
|
||||
{
|
||||
if (vertex[1]>f.V(1))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
if (vertex[2]!=f.V(2))
|
||||
{
|
||||
if (vertex[2]>f.V(2))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}else
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
inline bool operator < ( Facet const & f) const
|
||||
{
|
||||
return (!((*this)>f)&&((*this)!=f));
|
||||
}
|
||||
|
||||
inline bool operator <= ( Facet const & f) const
|
||||
{
|
||||
return (((*this)<f)||((*this)==f));
|
||||
}
|
||||
|
||||
inline bool operator >= ( Facet const & f) const
|
||||
{
|
||||
return (((*this)>f)||((*this)==f));
|
||||
}
|
||||
|
||||
int getFaceIndex()const
|
||||
{
|
||||
return numface;
|
||||
}
|
||||
|
||||
};//end class
|
||||
/** \addtogroup tetramesh */
|
||||
/*@{*/
|
||||
|
||||
/** Class UpdateTopology.
|
||||
This is class for Topology of a tetrahedralmesh.
|
||||
@param STL_VERT_CONT (Template Parameter) Specifies the type of the vertices container any the vertex type.
|
||||
@param STL_TETRA_CONT (Template Parameter) Specifies the type of the tetrahedrons container any the tetrahedrons type.
|
||||
*/
|
||||
template < class STL_VERT_CONT ,class STL_TETRA_CONT >
|
||||
class UpdateTopologyBase
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/// The vertex container
|
||||
typedef STL_VERT_CONT VertexContainer;
|
||||
|
||||
/// The tethaedhron container
|
||||
typedef STL_TETRA_CONT TetraContainer;
|
||||
|
||||
/// The vertex type
|
||||
typedef typename STL_VERT_CONT::value_type VertexType;
|
||||
|
||||
/// The tetrahedron type
|
||||
typedef typename STL_TETRA_CONT::value_type TetraType;
|
||||
|
||||
/// The type of vertex iterator
|
||||
typedef typename STL_VERT_CONT::iterator VertexIterator;
|
||||
|
||||
/// The type of tetra iterator
|
||||
typedef typename STL_TETRA_CONT::iterator TetraIterator;
|
||||
|
||||
/// The type of constant vertex iterator
|
||||
typedef typename STL_VERT_CONT::const_iterator const_VertexIterator;
|
||||
|
||||
/// The type of constant face iterator
|
||||
typedef typename STL_TETRA_CONT::const_iterator const_TetraIterator;
|
||||
|
||||
public:
|
||||
|
||||
/***********************************************/
|
||||
/** @Vertex-Tetrahedron Topology Funtions
|
||||
**/
|
||||
//@{
|
||||
|
||||
|
||||
/// Create the VT topology for tetrahedrons that are into containers.
|
||||
static void VTTopology( VertexContainer & vert, TetraContainer & tetra )
|
||||
{
|
||||
ClearVTTopology( vert, tetra );
|
||||
for( TetraIterator t = tetra.begin(); t != tetra.end(); ++t )
|
||||
if( !(*t).IsD() )
|
||||
for( int j = 0; j < 4; ++j )
|
||||
{
|
||||
(*t).VTp(j) = (*t).V(j)->VTp();
|
||||
(*t).VTi(j) = (*t).V(j)->VTi();
|
||||
(*t).V(j)->VTp() = &(*t);
|
||||
(*t).V(j)->VTi() = j;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Clear the vertex-tetra (VT) topology.
|
||||
static void ClearVTTopology( VertexContainer & vert, TetraContainer & tetra )
|
||||
{
|
||||
for( VertexIterator v = vert.begin(); v != vert.end(); ++v ) { v->VTp() = 0; v->VTi() = 0; }
|
||||
for( TetraIterator t = tetra.begin(); t != tetra.end(); ++t )
|
||||
if( ! (*t).IsD() )
|
||||
for( int j = 0; j < 4; ++j ) { (*t).VTp(j) = 0; (*t).VTi(j) = 0; }
|
||||
}
|
||||
|
||||
|
||||
/// Erase one tetrahedron from VTTopology of all his vertices.
|
||||
static void DetachVTTopology( TetraType *t )
|
||||
{
|
||||
if( ! (*t).IsD() )
|
||||
for( int i = 0; i < 4; i++ ) DetachVTTopology( t->V(i), t );
|
||||
}
|
||||
|
||||
|
||||
/// Erase one tetrahedron from VTTopology of one specified vertex.
|
||||
static void DetachVTTopology( VertexType *v, TetraType *t )
|
||||
{
|
||||
TetraType *lastt;
|
||||
int lastz;
|
||||
VTIterator<TetraType> Et( v->VTb(), v->VTi() );
|
||||
if( Et.Vt() == t )
|
||||
{
|
||||
v->VTb() = (TetraType *) t->VTp( v->VTi() );
|
||||
v->VTi() = t->VTi( v->VTi() );
|
||||
}
|
||||
else
|
||||
{
|
||||
lastz = Et.Vi();
|
||||
while( ( Et.Vt() != t ) && ( !Et.End() ) )
|
||||
{
|
||||
lastz = Et.Vi();
|
||||
lastt = Et.Vt();
|
||||
++Et;
|
||||
}
|
||||
/// In the list of the vertex v must be present the tetrahedron that you want to detach
|
||||
assert( Et.Vt() != NULL );
|
||||
lastt->VTp(lastz) = Et.Vt()->VTp( Et.Vi() );
|
||||
lastt->VTi(lastz) = Et.Vt()->VTi( Et.Vi() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Insert the tetrahedron t in VT topology for vertex v of index z.
|
||||
static void InsertVTTopology( VertexType *v, int z, TetraType *t )
|
||||
{
|
||||
if( ! (*t).IsD() )
|
||||
{
|
||||
t->VTp(z) = v->VTb();
|
||||
t->VTi(z) = v->VTi();
|
||||
v->VTb() = &(*t);
|
||||
v->VTi() = z;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Insert the tetrahedron t in VT topology for all his vertices.
|
||||
static void InsertVTTopology( TetraType *t )
|
||||
{
|
||||
assert( !( t->IsD() ) );
|
||||
for( int k = 0; k < 4; k++ )
|
||||
{
|
||||
assert( !( t->V(k)->IsD() ) );
|
||||
InsertVTTopology( t->V(k), k, t );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Test the Tetrahedron-Tetrahedron (TT) topology (by face).
|
||||
static void TestVTTopology( VertexContainer & vert, TetraContainer & tetra )
|
||||
{
|
||||
int i;
|
||||
for( VertexIterator vi = vert.begin(); vi != vert.end(); vi++ )
|
||||
if( !(*vi).IsD() )
|
||||
{
|
||||
TetraType *nextT = vi->VTb();
|
||||
int nextI = vi->VTi();
|
||||
int oldI;
|
||||
while( nextT != NULL )
|
||||
{
|
||||
assert( ( nextT->V(nextI) == &(*vi) ) );
|
||||
oldI = nextI;
|
||||
nextI = nextT->VTi(nextI);
|
||||
nextT = nextT->VTp(oldI);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*@}*/
|
||||
/***********************************************/
|
||||
/** @Tetrahedron-Tetrahedron Topology Funtions
|
||||
**/
|
||||
//@{
|
||||
///Build the Tetrahedron-Tetrahedron Topology (by Face)
|
||||
static void TTTopology(const VertexContainer &vert,TetraContainer &tetra)
|
||||
{
|
||||
vector <Facet<VertexType,TetraType> > VF;
|
||||
VertexType* v0;
|
||||
VertexType* v1;
|
||||
VertexType* v2;
|
||||
|
||||
for (TetraIterator ti=tetra.begin();ti!=tetra.end();ti++)
|
||||
if (!(*ti).IsD())
|
||||
{
|
||||
(*ti).TTi(0)=0;
|
||||
(*ti).TTi(1)=1;
|
||||
(*ti).TTi(2)=2;
|
||||
(*ti).TTi(3)=3;
|
||||
(*ti).TTp(0)=(&(*ti));
|
||||
(*ti).TTp(1)=(&(*ti));
|
||||
(*ti).TTp(2)=(&(*ti));
|
||||
(*ti).TTp(3)=(&(*ti));
|
||||
|
||||
v0=(*ti).V(Tetra::VofF(0,0));
|
||||
v1=(*ti).V(Tetra::VofF(0,1));
|
||||
v2=(*ti).V(Tetra::VofF(0,2));
|
||||
|
||||
VF.push_back(Facet<VertexType,TetraType>(v0,v1,v2,&(*ti),0));
|
||||
|
||||
v0=(*ti).V(Tetra::VofF(1,0));
|
||||
v1=(*ti).V(Tetra::VofF(1,1));
|
||||
v2=(*ti).V(Tetra::VofF(1,2));
|
||||
|
||||
VF.push_back(Facet<VertexType,TetraType>(v0,v1,v2,&(*ti),1));
|
||||
|
||||
v0=(*ti).V(Tetra::VofF(2,0));
|
||||
v1=(*ti).V(Tetra::VofF(2,1));
|
||||
v2=(*ti).V(Tetra::VofF(2,2));
|
||||
|
||||
VF.push_back(Facet<VertexType,TetraType>(v0,v1,v2,&(*ti),2));
|
||||
|
||||
v0=(*ti).V(Tetra::VofF(3,0));
|
||||
v1=(*ti).V(Tetra::VofF(3,1));
|
||||
v2=(*ti).V(Tetra::VofF(3,2));
|
||||
|
||||
VF.push_back(Facet<VertexType,TetraType>(v0,v1,v2,&(*ti),3));
|
||||
}
|
||||
sort(VF.begin(),VF.end());
|
||||
|
||||
TetraType *t0;
|
||||
TetraType *t1;
|
||||
int faceindex0;
|
||||
int faceindex1;
|
||||
int j;
|
||||
unsigned int i;
|
||||
for (i=0;i<VF.size()-1;i++)
|
||||
{
|
||||
j=i+1;
|
||||
if (VF[i]==VF[j])
|
||||
{
|
||||
t0=VF[i].getTetrahedron();
|
||||
t1=VF[j].getTetrahedron();
|
||||
faceindex0=VF[i].getFaceIndex();
|
||||
faceindex1=VF[j].getFaceIndex();
|
||||
t0->TTp(faceindex0)=(t1);
|
||||
t1->TTp(faceindex1)=(t0);
|
||||
t0->TTi(faceindex0)=(faceindex1);
|
||||
t1->TTi(faceindex1)=(faceindex0);
|
||||
i++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
///Connect trought Tetrahedron-Tetrahedron Topology t0 and t1 with faces i0 and i1
|
||||
static void _AttachTTTopology(TetraType *t0,int i0,TetraType *t1,int i1)
|
||||
{
|
||||
assert((i0>=0)&&(i0<4));
|
||||
assert((i1>=0)&&(i1<4));
|
||||
assert((!t0->IsD())&&(!t1->IsD()));
|
||||
t0->TTp(i0)=t1;
|
||||
t0->TTi(i0)=i1;
|
||||
t1->TTp(i1)=t0;
|
||||
t1->TTi(i1)=i0;
|
||||
assert( (((t0->TTp(i0))->TTp(t0->TTi(i0)))==t0));
|
||||
assert( (((t1->TTp(i1))->TTp(t1->TTi(i1)))==t1));
|
||||
}
|
||||
|
||||
///Detach Tetrahedron-Tetrahedron Topology
|
||||
static void DetachTTTopology(TetraType *t)
|
||||
{
|
||||
assert(!t->IsD());
|
||||
int i;
|
||||
for(i=0; i < 4; ++i)
|
||||
t->TTp(i)->TTp(t->TTi(i)) = t->TTp(i);
|
||||
}
|
||||
|
||||
|
||||
///Test the Tetrahedron-Tetrahedron Topology (by Face)
|
||||
static void TestTTTopology(VertexContainer &vert,TetraContainer &tetra)
|
||||
{
|
||||
int i;
|
||||
for (TetraIterator ti=tetra.begin();ti!=tetra.end();ti++)
|
||||
if ((!(*ti).IsD()))
|
||||
for (i=0;i<4;i++)
|
||||
{
|
||||
{
|
||||
assert( ((((*ti).TTp(i))->TTp((*ti).TTi(i)))==&(*ti)));
|
||||
|
||||
VertexType *v0=(*ti).V(Tetra::VofF(i,0));
|
||||
VertexType *v1=(*ti).V(Tetra::VofF(i,1));
|
||||
VertexType *v2=(*ti).V(Tetra::VofF(i,2));
|
||||
|
||||
TetraType *t1=(TetraType*)(*ti).TTp(i);
|
||||
assert (!t1->IsD());
|
||||
int z1=(*ti).TTi(i);
|
||||
|
||||
VertexType *vo0=(*t1).V(Tetra::VofF(z1,0));
|
||||
VertexType *vo1=(*t1).V(Tetra::VofF(z1,1));
|
||||
VertexType *vo2=(*t1).V(Tetra::VofF(z1,2));
|
||||
|
||||
assert((v0!=v1)&&(v0!=v2)&&(v1!=v2));
|
||||
assert((vo0!=vo1)&&(vo0!=vo2)&&(vo1!=vo2));
|
||||
|
||||
assert ((v0==vo0)||(v0==vo1)||(v0==vo2));
|
||||
assert ((v1==vo0)||(v1==vo1)||(v1==vo2));
|
||||
assert ((v2==vo0)||(v2==vo1)||(v2==vo2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///test if all and only the exernal vertex are set of border
|
||||
static void TestExternalVertex(VertexContainer &vert,TetraContainer &tetra)
|
||||
{
|
||||
TetraIterator ti;
|
||||
VertexIterator vi;
|
||||
|
||||
typedef pair <VertexType*, bool> VertBoolPair;
|
||||
map<VertexType*, bool> Inserted;
|
||||
typename map<VertexType*, bool>::iterator MapIte;
|
||||
|
||||
for (ti=tetra.begin();ti<tetra.end();ti++)
|
||||
{
|
||||
int i;
|
||||
if (!ti->IsD())
|
||||
{
|
||||
for (i=0;i<4;i++)
|
||||
if (ti->IsBorderF(i))
|
||||
{
|
||||
VertexType *v0=ti->V(Tetra::VofF(i,0));
|
||||
VertexType *v1=ti->V(Tetra::VofF(i,1));
|
||||
VertexType *v2=ti->V(Tetra::VofF(i,2));
|
||||
|
||||
MapIte = Inserted.find(v0);
|
||||
if ( MapIte == Inserted.end( ) )
|
||||
Inserted.insert (VertBoolPair(v0,true));
|
||||
|
||||
MapIte = Inserted.find(v1);
|
||||
if ( MapIte == Inserted.end( ) )
|
||||
Inserted.insert (VertBoolPair(v1,true));
|
||||
|
||||
MapIte = Inserted.find(v2);
|
||||
if ( MapIte == Inserted.end( ) )
|
||||
Inserted.insert (VertBoolPair(v2,true));
|
||||
|
||||
assert(!((v0->IsD())||(v1->IsD())||(v2->IsD())));
|
||||
assert ((v0->IsB())&&(v1->IsB())&&(v2->IsB()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (vi=vert.begin();vi<vert.end();vi++)
|
||||
{
|
||||
if (!vi->IsD())
|
||||
{
|
||||
if (vi->IsB())
|
||||
{
|
||||
MapIte = Inserted.find(&(*vi));
|
||||
//control if the extrenal vertex appartain to an external face
|
||||
assert ( MapIte != Inserted.end( ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///set the external vertex according to Tetra-Tetra topology
|
||||
static void setExternalVertices(VertexContainer &vert,TetraContainer &tetra)
|
||||
{
|
||||
|
||||
TetraIterator tt;
|
||||
VertexIterator vi;
|
||||
int i;
|
||||
for (vi=vert.begin();vi<vert.end();++vi)
|
||||
vi->ClearB();
|
||||
for (tt=tetra.begin();tt<tetra.end();++tt)
|
||||
if(!(*tt).IsD())
|
||||
{
|
||||
for(i=0;i<4;i++)
|
||||
{
|
||||
if ((*tt).IsBorderF(i))
|
||||
{
|
||||
(*tt).V(Tetra::VofF(i,0))->SetB();
|
||||
(*tt).V(Tetra::VofF(i,1))->SetB();
|
||||
(*tt).V(Tetra::VofF(i,2))->SetB();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*@}*/
|
||||
|
||||
private:
|
||||
|
||||
struct _triV
|
||||
{
|
||||
VertexType *v[3];
|
||||
|
||||
_triV(VertexType *v0,VertexType *v1,VertexType *v2)
|
||||
{
|
||||
v[0]=v0;
|
||||
v[1]=v1;
|
||||
v[2]=v2;
|
||||
sort(v,v+3);
|
||||
}
|
||||
|
||||
inline const VertexType * V(int index) const
|
||||
{
|
||||
return v[index];
|
||||
}
|
||||
|
||||
inline bool operator == ( _triV const & tv) const
|
||||
{
|
||||
return ((v[0]==tv.V(0))&&(v[1]==tv.V(1))&&(v[2]==tv.V(2)));
|
||||
}
|
||||
|
||||
inline bool operator != ( _triV const & tv) const
|
||||
{
|
||||
return !((*this) == tv);
|
||||
}
|
||||
|
||||
inline bool operator > ( _triV const & tv ) const
|
||||
{
|
||||
|
||||
if (v[0]!=tv.V(0))
|
||||
{
|
||||
if (v[0]>tv.V(0))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
if (v[1]!=tv.V(1))
|
||||
{
|
||||
if (v[1]>tv.V(1))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
if (v[2]!=tv.V(2))
|
||||
{
|
||||
if (v[2]>tv.V(2))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}else
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
inline bool operator < (_triV const & tv) const
|
||||
{
|
||||
return !(((*this)>tv)&&((*this)!=tv));
|
||||
}
|
||||
|
||||
inline bool operator <= (_triV const & tv) const
|
||||
{
|
||||
return (((*this)<tv)||((*this)==tv));
|
||||
}
|
||||
|
||||
inline bool operator >= ( _triV const & tv) const
|
||||
{
|
||||
return (((*this)>tv)||((*this)==tv));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
///this function is used to test if an edge is extern
|
||||
static bool IsExternEdge(TetraType *t,int edge)
|
||||
{
|
||||
std::vector < _triV > Faces;
|
||||
|
||||
assert((t->HasTTAdjacency())||(t->HasVTAdjacency()));
|
||||
if ((!t->V(Tetra::VofE(edge,0))->IsB())||(!t->V(Tetra::VofE(edge,1))->IsB()))
|
||||
return (false);
|
||||
|
||||
if (t->HasTTAdjacency())
|
||||
{
|
||||
PosLoop<TetraType> pl(t,Tetra::FofE(edge,0),edge,Tetra::VofE(edge,0));
|
||||
pl.Reset();
|
||||
//stops if one of faces incident to the edge is an extern face
|
||||
while ((!pl.LoopEnd())&&(!pl.T()->IsBorderF(Tetra::FofE(pl.E(),0)))&&(!pl.T()->IsBorderF(Tetra::FofE(pl.E(),1))))
|
||||
pl.NextT();
|
||||
if (pl.LoopEnd())
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{ //using vt adiacency
|
||||
VertexType *v0=t->V(Tetra::VofE(edge,0));
|
||||
VertexType *v1=t->V(Tetra::VofE(edge,1));
|
||||
assert(v0!=v1);
|
||||
VTIterator<TetraType> Vti(v0->VTb(),v0->VTi());
|
||||
int num=0;
|
||||
Faces.clear();
|
||||
Faces.reserve(40);
|
||||
while (!Vti.End())
|
||||
{
|
||||
//take the three faces incident on one vertex
|
||||
int f0=Tetra::FofV(Vti.Vi(),0);
|
||||
int f1=Tetra::FofV(Vti.Vi(),1);
|
||||
int f2=Tetra::FofV(Vti.Vi(),2);
|
||||
VertexType *vf0=Vti.Vt()->V(Tetra::VofF(f0,0));
|
||||
VertexType *vf1=Vti.Vt()->V(Tetra::VofF(f0,1));
|
||||
VertexType *vf2=Vti.Vt()->V(Tetra::VofF(f0,2));
|
||||
//if there is the edge then put the three vertex in the vector
|
||||
if ((vf0==v1)||(vf1==v1)||(vf2==v1))
|
||||
{
|
||||
Faces.push_back(_triV(vf0,vf1,vf2));
|
||||
num++;
|
||||
}
|
||||
}
|
||||
sort(Faces.begin(),Faces.end());
|
||||
//now look if one face is no shared from other tetrahedron
|
||||
//2 instances of same face in vector means it is internal face
|
||||
bool isExtern=false;
|
||||
typename std::vector < _triV >::iterator TVIo;
|
||||
typename std::vector < _triV >::iterator TVIn;
|
||||
TVIo=Faces.begin();
|
||||
TVIn=Faces.begin();
|
||||
TVIn++;
|
||||
int j=0;
|
||||
while (((*TVIo)==(*TVIn))&&(j<num))
|
||||
{
|
||||
//move 2 steps each iterator to frify each pair of faces
|
||||
TVIo++;
|
||||
TVIo++;
|
||||
TVIn++;
|
||||
TVIn++;
|
||||
j++;
|
||||
j++;
|
||||
}
|
||||
if (j>=num)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}; // end class
|
||||
|
||||
template <class TetraMeshType>
|
||||
class UpdateTopology: public UpdateTopologyBase<typename TetraMeshType::VertexContainer,
|
||||
typename TetraMeshType::TetraContainer>{
|
||||
public:
|
||||
static void TTTopology(TetraMeshType & tmesh){
|
||||
UpdateTopologyBase<typename TetraMeshType::VertexContainer,typename TetraMeshType::TetraContainer>::
|
||||
TTTopology(tmesh.vert,tmesh.tetra);
|
||||
}
|
||||
static void VTTopology(TetraMeshType & tmesh){
|
||||
UpdateTopologyBase<typename TetraMeshType::VertexContainer,typename TetraMeshType::TetraContainer>::
|
||||
VTTopology(tmesh.vert,tmesh.tetra);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
/*@}*/
|
||||
} // End namespace
|
||||
} // End namespace
|
||||
|
||||
|
||||
#endif
|
|
@ -1,202 +0,0 @@
|
|||
/****************************************************************************
|
||||
* VCGLib o o *
|
||||
* Visual and Computer Graphics Library o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2004 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
/****************************************************************************
|
||||
History
|
||||
|
||||
Revision 1.1 2004/22/04 14:32 pietroni
|
||||
Initial commit
|
||||
|
||||
|
||||
****************************************************************************/
|
||||
#ifndef __VCG_TETRA_TRI_CONVERTER
|
||||
#define __VCG_TETRA_TRI_CONVERTER
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include<vcg/space/tetra3.h>
|
||||
namespace vcg {
|
||||
namespace tetra {
|
||||
|
||||
|
||||
/** Class TriConverter.
|
||||
This is class for convetr tetrahedral mesh into triangle mesh
|
||||
@param STL_VERT_CONT (Template Parameter) Specifies the type of the vertices container any the vertex type.
|
||||
@param STL_TETRA_CONT (Template Parameter) Specifies the type of the tetrahedrons container any the tetrahedrons type.
|
||||
*/
|
||||
template < class TETRA_MESH ,class TRI_MESH >
|
||||
class TriConverter
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/// The tetrahedral mesh type
|
||||
typedef TETRA_MESH TetraMeshType;
|
||||
/// The triangle mesh type
|
||||
typedef TRI_MESH TriangleMeshType;
|
||||
|
||||
/// The tetrahedron type
|
||||
typedef typename TetraMeshType::TetraType TetraType;
|
||||
/// The triangle type
|
||||
typedef typename TriangleMeshType::FaceType FaceType;
|
||||
|
||||
/// The vertex type of tetrahedreal Mesh
|
||||
typedef typename TetraMeshType::VertexType TetraVertexType;
|
||||
/// The vertex type of triangular Mesh
|
||||
typedef typename TriangleMeshType::VertexType TriVertexType;
|
||||
|
||||
/// The type of vertex iterator on tetrahedral mesh
|
||||
typedef typename TetraMeshType::VertexIterator TetraVertexIterator;
|
||||
/// The type of vertex iterator on tetrahedral mesh
|
||||
typedef typename TriangleMeshType::VertexIterator TriVertexIterator;
|
||||
|
||||
/// The type of tetra iterator
|
||||
typedef typename TetraMeshType::TetraIterator TetraIterator;
|
||||
/// The type of tetra iterator
|
||||
typedef typename TriangleMeshType::FaceIterator FaceIterator;
|
||||
|
||||
/// The type of const tetra iterator
|
||||
typedef typename TetraMeshType::const_TetraIterator const_TetraIterator;
|
||||
/// The type of const face iterator
|
||||
typedef typename TriangleMeshType::ConstFaceIterator ConstFaceIterator;
|
||||
|
||||
/// The type of tetrahedrons container
|
||||
typedef typename TetraMeshType::TetraContainer TetraContainer;
|
||||
|
||||
/// The type of const vertex pointer of tetrahedral mesh
|
||||
typedef typename TetraMeshType::const_VertexPointer const_VertexPointer;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/***********************************************/
|
||||
/** @Convert to triangle-mesh functions
|
||||
**/
|
||||
//@{
|
||||
|
||||
///this function build a triangle mesh using the same pointers to the tetrahedral mesh vertex
|
||||
void Convert(TetraContainer &tetra,TriangleMeshType &trim)
|
||||
{
|
||||
TetraIterator ti;
|
||||
|
||||
TetraVertexType *v0;
|
||||
TetraVertexType *v1;
|
||||
TetraVertexType *v2;
|
||||
|
||||
trim.Clear();
|
||||
for (ti=tetra.begin();ti<tetra.end();ti++)
|
||||
{
|
||||
if (!(ti->IsD()))
|
||||
{
|
||||
if ((ti->IsBorderF(0))||(ti->IsBorderF(1))||(ti->IsBorderF(2))||(ti->IsBorderF(3)))
|
||||
for (int i=0;i<4;i++)
|
||||
if (ti->IsBorderF(i))
|
||||
{
|
||||
v0=ti->V(Tetra::VofF(i,0));
|
||||
v1=ti->V(Tetra::VofF(i,1));
|
||||
v2=ti->V(Tetra::VofF(i,2));
|
||||
FaceType f=FaceType();
|
||||
f.ClearFlags();
|
||||
f.V(0)=v0;
|
||||
f.V(1)=v1;
|
||||
f.V(2)=v2;
|
||||
trim.face.push_back(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct InsertedV{
|
||||
InsertedV( TriVertexType *_v,
|
||||
FaceType* _f,
|
||||
int _z):v(_v),f(_f),z(_z){}
|
||||
|
||||
TriVertexType *v;
|
||||
FaceType* f;
|
||||
int z;
|
||||
|
||||
const bool operator <(const InsertedV & o){
|
||||
return (v<o.v);
|
||||
}
|
||||
const bool operator ==(const InsertedV & o){
|
||||
return (v==o.v);
|
||||
}
|
||||
const bool operator !=(const InsertedV & o){
|
||||
return (v!=o.v);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
///this function build a triangle mesh using new pointers to the tetrahedral mesh vertex
|
||||
|
||||
void ConvertCopy(TetraContainer &tetra,TriangleMeshType &trim)
|
||||
{
|
||||
vector<InsertedV > newVertices;
|
||||
typename vector<InsertedV>::iterator curr,next;
|
||||
TriVertexIterator vi;
|
||||
vector<TriVertexType*> redirect;
|
||||
|
||||
Convert(tetra,trim);
|
||||
|
||||
FaceIterator fi;
|
||||
|
||||
for(fi = trim.face.begin(); fi != trim.face.end(); ++fi){
|
||||
newVertices.push_back(InsertedV( (*fi).V(0),&(*fi),0));
|
||||
newVertices.push_back(InsertedV( (*fi).V(1),&(*fi),1));
|
||||
newVertices.push_back(InsertedV( (*fi).V(2),&(*fi),2));
|
||||
}
|
||||
|
||||
sort(newVertices.begin(),newVertices.end());
|
||||
|
||||
|
||||
int pos = 0;
|
||||
curr = next = newVertices.begin();
|
||||
while( next != newVertices.end()){
|
||||
if((*curr)!=(*next))
|
||||
pos++;
|
||||
(*next).f->V( (*next).z) = (TriVertexType*)pos;
|
||||
curr = next;
|
||||
next++;
|
||||
}
|
||||
|
||||
typename vector<InsertedV>::iterator newE = unique(newVertices.begin(),newVertices.end());
|
||||
for(curr = newVertices.begin();curr!= newE;++curr)
|
||||
trim.vert.push_back(*((*curr).v));
|
||||
|
||||
for(vi = trim.vert.begin(); vi != trim.vert.end(); ++vi)
|
||||
redirect.push_back(&(*vi));
|
||||
|
||||
for(fi = trim.face.begin(); fi != trim.face.end(); ++fi){
|
||||
(*fi).V(0) = redirect[(int)(*fi).V(0)];
|
||||
(*fi).V(1) = redirect[(int)(*fi).V(1)];
|
||||
(*fi).V(2) = redirect[(int)(*fi).V(2)];
|
||||
}
|
||||
trim.vn = trim.vert.size();
|
||||
trim.fn = trim.face.size();
|
||||
}
|
||||
|
||||
};// End class
|
||||
} // End namespace
|
||||
} // End namespace
|
||||
|
||||
|
||||
#endif
|
|
@ -1,77 +0,0 @@
|
|||
|
||||
|
||||
/****************************************************************************
|
||||
* VCGLib o o *
|
||||
* Visual and Computer Graphics Library o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2004 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
/****************************************************************************
|
||||
History
|
||||
|
||||
$Log: not supported by cvs2svn $
|
||||
Revision 1.1 2006/12/03 14:55:44 ganovelli
|
||||
created
|
||||
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __VCGLIB_TETRASUBSET
|
||||
#define __VCGLIB_TETRASUBSET
|
||||
|
||||
#include <vector>
|
||||
namespace vcg {
|
||||
namespace tetra {
|
||||
|
||||
/** \addtogroup tetramesh */
|
||||
/*@{*/
|
||||
|
||||
/// assumes TTTopology has been computed
|
||||
template <class TetraPtrContainer>
|
||||
void Component(TetraPtrContainer & src, TetraPtrContainer & conn_com){
|
||||
|
||||
typename TetraPtrContainer::iterator ti;
|
||||
typedef typename TetraPtrContainer::value_type TetraPointer;
|
||||
|
||||
for(ti = src.begin(); ti != src.end(); ++ti)
|
||||
(*ti)->SetS();
|
||||
|
||||
while(!src.empty()){
|
||||
TetraPointer tp = src.back();
|
||||
src.pop_back();
|
||||
conn_com.push_back(tp);
|
||||
for(unsigned int i = 0; i < 4; ++i)
|
||||
if(!tp->TTp(i)->IsD())
|
||||
if(!tp->TTp(i)->IsS()){
|
||||
tp->TTp(i)->SetS();
|
||||
src.push_back(tp->TTp(i));
|
||||
}
|
||||
}
|
||||
for(ti = conn_com.begin(); ti != conn_com.end(); ++ti)
|
||||
(*ti)->ClearS();
|
||||
}
|
||||
|
||||
/*@}*/
|
||||
} // End namespace
|
||||
} // End namespace
|
||||
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue