/**************************************************************************** * 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. * * * ****************************************************************************/ #ifndef __VCGLIB_ZONOHEDRON #define __VCGLIB_ZONOHEDRON #include #include typedef unsigned int uint; namespace vcg { namespace tri { /** \addtogroup trimesh */ //@{ /** A class to build a Zonohedron. A zonohedron is a solid with a closed surface composed only of parallelograms. Given a set of input vectors (the sides of the parallelograms), it is defined by the convex hull of all the points which can be co Creates a pure-quad mesh (triangular bit-quad), (faces with 4 vertices are split into quads). USAGE: 1) Instantiate a Zonohedron. 2) Add input vectors at will to it, with addVector(s) 3) When you are done, call createMesh. */ template class Zonohedron{ public: typedef Point3 Vec3; Zonohedron(){} void addVector(Scalar x, Scalar y, Scalar z); void addVector(Vec3 v); void addVectors(const std::vector< Vec3 > ); const std::vector< Vec3 >& vectors() const { return vec; } template void createMesh( MeshType& output ); private: /* classes for internal use */ /****************************/ typedef int VecIndex; // a number in [0..n) /* the signature of a vertex (a 0 or 1 per input vector) */ struct Signature { std::vector< bool > v; Signature(){} Signature(int n){ v.resize(n,false); } bool operator == (const Signature & b) const { return (b.v == v); } bool operator < (const Signature & b) const { return (b.v < v); } Signature& set(VecIndex i, bool value){ v[i] = value; return *this; } Signature& set(VecIndex i, bool valueI, VecIndex j, bool valueJ){ v[i] = valueI; v[j] = valueJ; return *this; } }; struct Face { int vert[4]; // index to vertex array }; /* precomputed cross products for all pairs of vectors */ std::vector< Vec3 > precomputedCross; void precompteAllCrosses(){ precomputedCross.resize(n*n); for (int i=0; i0) return v; else if (v.X()<0) return -v; else if (v.Y()>0) return v; else if (v.Y()<0) return -v; else if (v.Z()>0) return v; return -v; } // returns signof: (i x j) * k bool signOf_IxJoK(VecIndex i, VecIndex j, VecIndex k){ bool invert = false; // sort i,j,k if (i=0) != invert ); // XOR } int n; // number of input vectors std::vector vec; // input vectors int vertCount; std::vector _face; typedef std::map< Signature, int > VertexMap; VertexMap vertexMap; // given a vertex signature, returns index of vert (newly created or not) VecIndex vertexIndex(const Signature &s){ typename VertexMap::iterator i; //Vec3 pos = s; //toPos(s); i = vertexMap.find( s ); if (i!= vertexMap.end() ) return i->second; else { int newVertex = vertCount++; //vertexMap.insert(s) vertexMap[s] = newVertex; return newVertex; } } // given two index of vectors, returns face Face& face(VecIndex i, VecIndex j){ assert(i!=j); assert( i*n + j < (int) _face.size() ); return _face[i*n + j]; } Vec3 toPos(const Signature &s) const{ Vec3 res(0,0,0); for (int i=0; i void Zonohedron::addVectors(std::vector< Zonohedron::Vec3 > input){ for (uint i=0; i void Zonohedron::addVector(Scalar x, Scalar y, Scalar z) { addVector( Vec3(x,y,z) ); } template void Zonohedron::addVector(Zonohedron::Vec3 v){ vec.push_back(v); } template template void Zonohedron::createMesh(MeshType &m){ typedef MeshType Mesh; typedef typename Mesh::VertexPointer MeshVertexPointer; typedef typename Mesh::VertexIterator MeshVertexIterator; typedef typename Mesh::FaceIterator MeshFaceIterator; typedef typename Mesh::FaceType MeshFace; createInternalMesh(); m.Clear(); Allocator::AddVertices(m,vertexMap.size()); Allocator::AddFaces(m,n*(n-1) * 2); // assign vertex positions MeshVertexIterator vi=m.vert.begin(); for (typename VertexMap::iterator i=vertexMap.begin(); i!=vertexMap.end(); i++){ (vi + i->second )->P() = toPos( i->first ); } // assegn FV connectivity MeshFaceIterator fi=m.face.begin(); for (int i=0; iV(w) = &* (vi + f.vert[(w+k*2)%4] ); } if (tri::HasPerFaceNormal(m)) { fi->N() = cross(i,j).normalized(); } if (tri::HasPerFaceFlags(m)) { fi->SetF(2); // quad diagonals are faux } fi++; } } } } //@} } // End Namespace TriMesh } // End Namespace vcg #endif // __VCGLIB_ZONOHEDRON