@ -41,76 +41,14 @@ namespace Implementation {
template < class Vertex , std : : size_t vertexSize = Vertex : : Size > class Clean {
public :
inline Clean ( std : : vector < UnsignedInt > & indices , std : : vector < Vertex > & vertices ) : indices ( indices ) , vertices ( vertices ) { }
void operator ( ) ( typename Vertex : : Type epsilon = Math : : TypeTraits < typename Vertex : : Type > : : epsilon ( ) ) {
if ( indices . empty ( ) ) return ;
/* Get mesh bounds */
Vertex min , max ;
for ( std : : size_t i = 0 ; i ! = Vertex : : Size ; + + i ) {
min [ i ] = std : : numeric_limits < typename Vertex : : Type > : : max ( ) ;
max [ i ] = std : : numeric_limits < typename Vertex : : Type > : : min ( ) ;
}
for ( auto it = vertices . cbegin ( ) ; it ! = vertices . cend ( ) ; + + it )
for ( std : : size_t i = 0 ; i ! = vertexSize ; + + i )
if ( ( * it ) [ i ] < min [ i ] )
min [ i ] = ( * it ) [ i ] ;
else if ( ( * it ) [ i ] > max [ i ] )
max [ i ] = ( * it ) [ i ] ;
/* Make epsilon so large that std::size_t can index all vertices
inside mesh bounds . */
Vertex size = max - min ;
for ( std : : size_t i = 0 ; i ! = Vertex : : Size ; + + i )
if ( static_cast < typename Vertex : : Type > ( size [ i ] / std : : numeric_limits < std : : size_t > : : max ( ) ) > epsilon )
epsilon = static_cast < typename Vertex : : Type > ( size [ i ] / std : : numeric_limits < std : : size_t > : : max ( ) ) ;
/* First go with original vertex coordinates, then move them by
epsilon / 2 in each direction . */
Vertex moved ;
for ( std : : size_t moving = 0 ; moving < = vertexSize ; + + moving ) {
/* Under each index is pointer to face which contains given vertex
and index of vertex in the face . */
std : : unordered_map < Math : : Vector < vertexSize , std : : size_t > , HashedVertex , IndexHash > table ;
/* Reserve space for all vertices */
table . reserve ( vertices . size ( ) ) ;
/* Go through all faces' vertices */
for ( auto it = indices . begin ( ) ; it ! = indices . end ( ) ; + + it ) {
/* Index of a vertex in vertexSize-dimensional table */
std : : size_t index [ vertexSize ] ;
for ( std : : size_t ii = 0 ; ii ! = vertexSize ; + + ii )
index [ ii ] = ( vertices [ * it ] [ ii ] + moved [ ii ] - min [ ii ] ) / epsilon ;
/* Try inserting the vertex into table, if it already
exists , change vertex pointer of the face to already
existing vertex */
HashedVertex v ( * it , table . size ( ) ) ;
auto result = table . insert ( std : : pair < Math : : Vector < vertexSize , std : : size_t > , HashedVertex > ( Math : : Vector < vertexSize , std : : size_t > : : from ( index ) , v ) ) ;
* it = result . first - > second . newIndex ;
}
/* Shrink vertices array */
std : : vector < Vertex > newVertices ( table . size ( ) ) ;
for ( auto it = table . cbegin ( ) ; it ! = table . cend ( ) ; + + it )
newVertices [ it - > second . newIndex ] = vertices [ it - > second . oldIndex ] ;
std : : swap ( newVertices , vertices ) ;
Clean ( std : : vector < UnsignedInt > & indices , std : : vector < Vertex > & vertices ) : indices ( indices ) , vertices ( vertices ) { }
/* Move vertex coordinates by epsilon/2 in next direction */
if ( moving ! = Vertex : : Size ) {
moved = Vertex ( ) ;
moved [ moving ] = epsilon / 2 ;
}
}
}
void operator ( ) ( typename Vertex : : Type epsilon = Math : : TypeTraits < typename Vertex : : Type > : : epsilon ( ) ) ;
private :
class IndexHash {
public :
inline std : : size_t operator ( ) ( const Math : : Vector < vertexSize , std : : size_t > & data ) const {
std : : size_t operator ( ) ( const Math : : Vector < vertexSize , std : : size_t > & data ) const {
return * reinterpret_cast < const std : : size_t * > ( Utility : : MurmurHash2 ( ) ( reinterpret_cast < const char * > ( & data ) , sizeof ( data ) ) . byteArray ( ) ) ;
}
} ;
@ -148,6 +86,74 @@ template<class Vertex, std::size_t vertexSize = Vertex::Size> inline void clean(
Implementation : : Clean < Vertex , vertexSize > ( indices , vertices ) ( epsilon ) ;
}
namespace Implementation {
template < class Vertex , std : : size_t vertexSize > void Clean < Vertex , vertexSize > : : operator ( ) ( typename Vertex : : Type epsilon ) {
if ( indices . empty ( ) ) return ;
/* Get mesh bounds */
Vertex min , max ;
for ( std : : size_t i = 0 ; i ! = Vertex : : Size ; + + i ) {
min [ i ] = std : : numeric_limits < typename Vertex : : Type > : : max ( ) ;
max [ i ] = std : : numeric_limits < typename Vertex : : Type > : : min ( ) ;
}
for ( auto it = vertices . cbegin ( ) ; it ! = vertices . cend ( ) ; + + it )
for ( std : : size_t i = 0 ; i ! = vertexSize ; + + i )
if ( ( * it ) [ i ] < min [ i ] )
min [ i ] = ( * it ) [ i ] ;
else if ( ( * it ) [ i ] > max [ i ] )
max [ i ] = ( * it ) [ i ] ;
/* Make epsilon so large that std::size_t can index all vertices
inside mesh bounds . */
Vertex size = max - min ;
for ( std : : size_t i = 0 ; i ! = Vertex : : Size ; + + i )
if ( static_cast < typename Vertex : : Type > ( size [ i ] / std : : numeric_limits < std : : size_t > : : max ( ) ) > epsilon )
epsilon = static_cast < typename Vertex : : Type > ( size [ i ] / std : : numeric_limits < std : : size_t > : : max ( ) ) ;
/* First go with original vertex coordinates, then move them by
epsilon / 2 in each direction . */
Vertex moved ;
for ( std : : size_t moving = 0 ; moving < = vertexSize ; + + moving ) {
/* Under each index is pointer to face which contains given vertex
and index of vertex in the face . */
std : : unordered_map < Math : : Vector < vertexSize , std : : size_t > , HashedVertex , IndexHash > table ;
/* Reserve space for all vertices */
table . reserve ( vertices . size ( ) ) ;
/* Go through all faces' vertices */
for ( auto it = indices . begin ( ) ; it ! = indices . end ( ) ; + + it ) {
/* Index of a vertex in vertexSize-dimensional table */
std : : size_t index [ vertexSize ] ;
for ( std : : size_t ii = 0 ; ii ! = vertexSize ; + + ii )
index [ ii ] = ( vertices [ * it ] [ ii ] + moved [ ii ] - min [ ii ] ) / epsilon ;
/* Try inserting the vertex into table, if it already
exists , change vertex pointer of the face to already
existing vertex */
HashedVertex v ( * it , table . size ( ) ) ;
auto result = table . insert ( std : : pair < Math : : Vector < vertexSize , std : : size_t > , HashedVertex > ( Math : : Vector < vertexSize , std : : size_t > : : from ( index ) , v ) ) ;
* it = result . first - > second . newIndex ;
}
/* Shrink vertices array */
std : : vector < Vertex > newVertices ( table . size ( ) ) ;
for ( auto it = table . cbegin ( ) ; it ! = table . cend ( ) ; + + it )
newVertices [ it - > second . newIndex ] = vertices [ it - > second . oldIndex ] ;
std : : swap ( newVertices , vertices ) ;
/* Move vertex coordinates by epsilon/2 in next direction */
if ( moving ! = Vertex : : Size ) {
moved = Vertex ( ) ;
moved [ moving ] = epsilon / 2 ;
}
}
}
}
} }
# endif