zonohedron.h
Go to the documentation of this file.
00001 /****************************************************************************
00002 * VCGLib                                                            o o     *
00003 * Visual and Computer Graphics Library                            o     o   *
00004 *                                                                _   O  _   *
00005 * Copyright(C) 2004                                                \/)\/    *
00006 * Visual Computing Lab                                            /\/|      *
00007 * ISTI - Italian National Research Council                           |      *
00008 *                                                                    \      *
00009 * All rights reserved.                                                      *
00010 *                                                                           *
00011 * This program is free software; you can redistribute it and/or modify      *
00012 * it under the terms of the GNU General Public License as published by      *
00013 * the Free Software Foundation; either version 2 of the License, or         *
00014 * (at your option) any later version.                                       *
00015 *                                                                           *
00016 * This program is distributed in the hope that it will be useful,           *
00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
00019 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
00020 * for more details.                                                         *
00021 *                                                                           *
00022 ****************************************************************************/
00023 
00024 #ifndef __VCGLIB_ZONOHEDRON
00025 #define __VCGLIB_ZONOHEDRON
00026 
00027 namespace vcg {
00028 namespace tri {
00053 template <class Scalar>
00054 class Zonohedron{
00055 public:
00056 
00057     typedef Point3<Scalar> Vec3;
00058 
00059     Zonohedron(){}
00060 
00061     void addVector(Scalar x, Scalar y, Scalar z);
00062     void addVector(Vec3 v);
00063     void addVectors(const std::vector< Vec3 > );
00064 
00065     const std::vector< Vec3 >& vectors() const {
00066         return vec;
00067     }
00068 
00069     template<class MeshType>
00070     void createMesh( MeshType& output );
00071 
00072 private:
00073 
00074     /* classes for internal use */
00075     /****************************/
00076 
00077     typedef int VecIndex; //  a number in [0..n)
00078 
00079     /* the signature of a vertex (a 0 or 1 per input vector) */
00080     struct Signature {
00081         std::vector< bool > v;
00082         Signature(){}
00083         Signature(int n){ v.resize(n,false); }
00084 
00085         bool operator == (const Signature & b) const {
00086             return (b.v == v);
00087         }
00088         bool operator < (const Signature & b) const {
00089             return (b.v < v);
00090         }
00091         Signature& set(VecIndex i, bool value){
00092             v[i] = value;
00093             return *this;
00094         }
00095         Signature& set(VecIndex i, bool valueI, VecIndex j, bool valueJ){
00096             v[i] = valueI;
00097             v[j] = valueJ;
00098             return *this;
00099         }
00100     };
00101 
00102     struct Face {
00103         int vert[4]; // index to vertex array
00104     };
00105 
00106     /* precomputed cross products for all pairs of vectors */
00107     std::vector< Vec3 > precomputedCross;
00108 
00109     void precompteAllCrosses(){
00110         precomputedCross.resize(n*n);
00111         for (int i=0; i<n; i++) for (int j=0; j<n; j++) {
00112             precomputedCross[i*n+j] =  vec[i] ^ vec[j] ;
00113         }
00114     }
00115 
00116     Vec3 cross(VecIndex i, VecIndex j){
00117         return precomputedCross[i*n+j];
00118     }
00119 
00120     // given a vector, returns a copy pointing a unique verse
00121     static Vec3 uniqueVerse(Vec3 v){
00122         if (v.X()>0) return v;
00123         else if (v.X()<0) return -v;
00124         else if (v.Y()>0) return v;
00125         else if (v.Y()<0) return -v;
00126         else if (v.Z()>0) return v;
00127         return -v;
00128     }
00129 
00130     static Vec3 altVec(int i) {
00131         return Vec3(1, i, i*i);
00132     }
00133 
00134     static Scalar tripleProduct( const Vec3 &a, const Vec3 &b, const Vec3 & c){
00135         return ( a ^ b ) * c;
00136     }
00137 
00138     // returns signof:  (i x j) * k
00139     bool signOf_IxJoK(VecIndex i, VecIndex j, VecIndex k){
00140         const float EPSILON_SQUARED = 1e-12;
00141         bool invert = false;
00142         // sort i,j,k
00143         if (i<j) { std::swap(i,j); invert = !invert; }
00144         if (j<k) { std::swap(j,k); invert = !invert;
00145             if (i<j) { std::swap(i,j); invert = !invert; }
00146         }
00147 
00148         //Scalar res = Vec3::dot( Vec3::cross( vec[i] , vec[j] ) , vec[k] );
00149         Scalar res =  cross( i , j ) * vec[k] ;
00150 
00151         if (res*res<=EPSILON_SQUARED) {
00152             // three coplanar vectors!
00153             // use derivative...
00154             //res =  uniqueVerse( cross(i,j) ) * cross(j,k) ;
00155             res =  tripleProduct( altVec(i), vec[j], vec[k]) +
00156                    tripleProduct( vec[i], altVec(j), vec[k]) +
00157                    tripleProduct( vec[i], vec[j], altVec(k)) ;
00158             if (res*res<=EPSILON_SQUARED) {
00159                 // zero derivative (happens, if three colinear vectors, or...)
00160                 res =  tripleProduct( vec[i], altVec(j), altVec(k)) +
00161                        tripleProduct( altVec(i), vec[j], altVec(k)) +
00162                        tripleProduct( altVec(i), altVec(j), vec[k]) ;
00163             }
00164             if (res*res<=EPSILON_SQUARED) {
00165                 // zero second derivative (happens if three zero-vectors, i.e. never? or...)
00166                 res = tripleProduct( altVec(i), altVec(j), altVec(k) );
00167             }
00168         }
00169 
00170         return ( (res>=0) != invert ); // XOR
00171     }
00172 
00173     int n; // number of input vectors
00174     std::vector<Vec3> vec; // input vectors
00175 
00176     int vertCount;
00177     std::vector<Face> _face;
00178 
00179     typedef std::map< Signature, int > VertexMap;
00180     VertexMap vertexMap;
00181 
00182     // given a vertex signature, returns index of vert (newly created or not)
00183     VecIndex vertexIndex(const Signature &s){
00184         typename VertexMap::iterator i;
00185         //Vec3 pos = s; //toPos(s);
00186         i = vertexMap.find( s );
00187         if (i!= vertexMap.end() ) return i->second;
00188         else {
00189             int newVertex = vertCount++;
00190             //vertexMap.insert(s)
00191             vertexMap[s] = newVertex;
00192             return newVertex;
00193         }
00194     }
00195 
00196     // given two index of vectors, returns face
00197     Face& face(VecIndex i, VecIndex j){
00198         assert(i!=j);
00199         assert( i*n + j < (int) _face.size() );
00200         return _face[i*n + j];
00201     }
00202 
00203     Vec3 toPos(const Signature &s) const{
00204         Vec3 res(0,0,0);
00205         for (int i=0; i<n; i++)
00206             if (s.v[i]) res += vec[i];
00207         return res;
00208     }
00209 
00210     void createInternalMesh() {
00211 
00212         n = vec.size();
00213         precompteAllCrosses();
00214 
00215         // allocate faces
00216         _face.resize( n*n );
00217 
00218         vertCount = 0;
00219         vertexMap.clear();
00220 
00221         for (int i=0; i<n; i++) {
00222             //::showProgress(i,n);
00223             for (int j=0; j<n; j++) if(i!=j)  {
00224                 Signature s(n);
00225                 for (int k=0; k<n; k++) if ((k!=j) && (k!=i))
00226                 {
00227                     s.set( k , signOf_IxJoK( i,j,k ) );
00228                 }
00229                 face(i,j).vert[0] = vertexIndex( s.set(i,false, j,false) );
00230                 face(i,j).vert[1] = vertexIndex( s.set(i,false, j,true ) );
00231                 face(i,j).vert[2] = vertexIndex( s.set(i,true,  j,true ) );
00232                 face(i,j).vert[3] = vertexIndex( s.set(i,true,  j,false) );
00233             }
00234         }
00235     }
00236 
00237 
00238 };
00239 
00240 
00241 template<class Scalar>
00242 void Zonohedron<Scalar>::addVectors(std::vector< Zonohedron<Scalar>::Vec3 > input){
00243     for (size_t i=0; i<input.size(); i++) {
00244         addVector( input[i]);
00245     }
00246 }
00247 
00248 template<class Scalar>
00249 void Zonohedron<Scalar>::addVector(Scalar x, Scalar y, Scalar z) {
00250     addVector( Vec3(x,y,z) );
00251 }
00252 
00253 
00254 template<class Scalar>
00255 void Zonohedron<Scalar>::addVector(Zonohedron<Scalar>::Vec3 v){
00256     vec.push_back(v);
00257 }
00258 
00259 
00260 template<class Scalar>
00261 template<class MeshType>
00262 void Zonohedron<Scalar>::createMesh(MeshType &m){
00263     typedef MeshType Mesh;
00264     typedef typename Mesh::VertexPointer  MeshVertexPointer;
00265     typedef typename Mesh::VertexIterator MeshVertexIterator;
00266     typedef typename Mesh::FaceIterator   MeshFaceIterator;
00267     typedef typename Mesh::FaceType   MeshFace;
00268 
00269     createInternalMesh();
00270 
00271     m.Clear();
00272     Allocator<MeshType>::AddVertices(m,vertexMap.size());
00273   Allocator<MeshType>::AddFaces(m,n*(n-1) * 2);
00274 
00275     // assign vertex positions
00276     MeshVertexIterator vi=m.vert.begin();
00277     for (typename VertexMap::iterator i=vertexMap.begin(); i!=vertexMap.end(); i++){
00278         (vi + i->second )->P() = toPos( i->first );
00279     }
00280 
00281     // assegn FV connectivity
00282   MeshFaceIterator fi=m.face.begin();
00283 
00284     for (int i=0; i<n; i++) {
00285         for (int j=0; j<n; j++) if (i!=j) {
00286             const Face &f( face(i,j) );
00287             for (int k=0; k<2; k++) { // two tri faces per quad
00288                 for (int w=0; w<3; w++) {
00289                     fi->V(w) = &* (vi + f.vert[(w+k*2)%4] );
00290                 }
00291                 if (tri::HasPerFaceNormal(m)) {
00292                     fi->N() = cross(i,j).normalized();
00293                 }
00294                 if (tri::HasPerFaceFlags(m)) {
00295                     fi->SetF(2); // quad diagonals are faux
00296                 }
00297                 fi++;
00298             }
00299         }
00300     }
00301 
00302 
00303 }
00304 
00305 
00307 
00308 } // End Namespace TriMesh
00309 } // End Namespace vcg
00310 
00311 #endif // __VCGLIB_ZONOHEDRON


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:38:48