diff --git a/vcg/complex/algorithms/create/zonohedron.h b/vcg/complex/algorithms/create/zonohedron.h new file mode 100644 index 00000000..5085daed --- /dev/null +++ b/vcg/complex/algorithms/create/zonohedron.h @@ -0,0 +1,295 @@ +/**************************************************************************** +* 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