diff --git a/include/Algo/Export/export.h b/include/Algo/Export/export.h index 1ffb7ee9b254e753f32ee3f763c8a534a713995c..7ea4aae63887dbad430235cb4b9dabd2e5cea198 100644 --- a/include/Algo/Export/export.h +++ b/include/Algo/Export/export.h @@ -103,6 +103,110 @@ bool exportTrian(typename PFP::MAP& map, const VertexAttribute bool exportVTU(typename PFP::MAP& map, const VertexAttribute& position, const char* filename); +template +bool exportVTUCompressed(typename PFP::MAP& map, const VertexAttribute& position, const char* filename); + + +template +class VTUExporter +{ +protected: + typedef typename PFP::MAP MAP; + typedef typename PFP::VEC3 VEC3; + + typename PFP::MAP& m_map; + const VertexAttribute& m_position; + + unsigned int nbtotal; + bool noPointData; + bool noCellData; + bool closed; + + std::ofstream fout ; + + std::vector triangles; + std::vector quads; + std::vector others; + std::vector others_begin; + + std::vector bufferTri; + std::vector bufferQuad; + std::vector bufferOther; + + +public: + + VTUExporter(typename PFP::MAP& map, const VertexAttribute& position); + + ~VTUExporter(); + + /** + * @brief start writing header of vru file + * @param filename + * @return true if ok + */ + bool init(const char* filename); + + + /** + * @brief add a vertex attribute of type scalar + * @param attrib + * @param vtkType Float32/Int32 + * @param name Data name if none then used Attribute's name + */ + template + void addVertexAttributeScal(const VertexAttribute& attrib, const std::string& vtkType, const std::string& name=""); + + /** + * @brief add a vertex attribute of type vector + * @param attrib + * @param vtkType Float32/Int32 + * @param nbComp number components in attribute (if none comute for size of attribute) + * @param name Data name if none then used Attribute's name + */ + template + void addVertexAttributeVect(const VertexAttribute& attrib, const std::string& vtkType, unsigned int nbComp=0, const std::string& name=""); + + + /** + * @brief finish adding vertex attributes data + */ + void endVertexAttributes(); + + /** + * @brief add a face attribute of type scalar + * @param attrib + * @param vtkType Float32/Int32 + * @param name Data name if none then used Attribute's name + */ + template + void addFaceAttributeScal(const FaceAttribute& attrib, const std::string& vtkType, const std::string& name=""); + + /** + * @brief add a face aatribute of type vector + * @param attrib + * @param vtkType Float32/Int32 + * @param nbComp number components in attribute (if none comute for size of attribute) + * @param name Data name if none then used Attribute's name + */ + template + void addFaceAttributeVect(const FaceAttribute& attrib, const std::string& vtkType, unsigned int nbComp=0, const std::string& name=""); + + + /** + * @brief finish adding face attributes data + */ + void endFaceAttributes(); + + + /** + * @brief finalize file writing & close (automatically called at destruction) + * @return true if ok + */ + bool close(); + +}; + /** diff --git a/include/Algo/Export/export.hpp b/include/Algo/Export/export.hpp index 5cda59953c5383461bd788114156961d924f7ffb..c5b3bc910836de165873ccc0fe96a4260ac7b2ec 100644 --- a/include/Algo/Export/export.hpp +++ b/include/Algo/Export/export.hpp @@ -28,6 +28,8 @@ #include "Topology/generic/traversor2.h" #include "Topology/generic/cellmarker.h" +#include "Utils/compress.h" + namespace CGoGN { @@ -1049,7 +1051,6 @@ bool exportVTU(typename PFP::MAP& map, const VertexAttribute indices[i] = count++; } - std::vector triangles; std::vector quads; std::vector others; @@ -1094,37 +1095,34 @@ bool exportVTU(typename PFP::MAP& map, const VertexAttribute fout << "" << std::endl; fout << "" << std::endl; - fout << " " << std::endl; - fout << " " << std::endl; - fout << " " << std::endl; - fout << " " << std::endl; + fout << "" << std::endl; + fout << "" << std::endl; + fout << "" << std::endl; + fout << "" << std::endl; for (unsigned int i = position.begin(); i != position.end(); position.next(i)) { const VEC3& P = position[i]; - fout << " " << P[0]<< " " << P[1]<< " " << P[2] << std::endl; + fout << P[0]<< " " << P[1]<< " " << P[2] << std::endl; } - fout << " " << std::endl; - fout << " " << std::endl; - fout << " " << std::endl; - fout << " " << std::endl; + fout << "" << std::endl; + fout << "" << std::endl; + fout << "" << std::endl; + fout << "" << std::endl; for (unsigned int i=0; i fout << std::endl; } - fout << " " << std::endl; - fout << " " ; + fout << "" << std::endl; + fout << "" ; unsigned int offset = 0; for (unsigned int i=0; i { unsigned int length = others_begin[i] - others_begin[i-1]; offset += length; - if (i%200 ==0) - fout << std::endl<< " "; + if (i%20 ==0) + fout << std::endl; fout << " "<< offset; fout << std::endl; } - fout << std::endl << " " << std::endl; - fout << " "; + fout << std::endl << "" << std::endl; + fout << ""; for (unsigned int i=0; i" << std::endl; - fout << " " << std::endl; - fout << " " << std::endl; - fout << " " << std::endl; + fout << std::endl << "" << std::endl; + fout << "" << std::endl; + fout << "" << std::endl; + fout << "" << std::endl; + fout << "" << std::endl; + + fout.close(); + return true; +} + + +template +bool exportVTUCompressed(typename PFP::MAP& map, const VertexAttribute& position, const char* filename) +{ + if (map.dimension() != 2) + { + CGoGNerr << "Surface::Export::exportVTU works only with map of dimension 2"<< CGoGNendl; + return false; + } + + typedef typename PFP::MAP MAP; + typedef typename PFP::VEC3 VEC3; + + // open file + std::ofstream fout ; + fout.open(filename, std::ios::out) ; + + if (!fout.good()) + { + CGoGNerr << "Unable to open file " << filename << CGoGNendl ; + return false ; + } + + VertexAutoAttribute indices(map,"indices_vert"); + + unsigned int count=0; + for (unsigned int i = position.begin(); i != position.end(); position.next(i)) + { + indices[i] = count++; + } + + std::vector triangles; + std::vector quads; + std::vector others; + std::vector others_begin; + triangles.reserve(2048); + quads.reserve(2048); + others.reserve(2048); + others_begin.reserve(2048); + + TraversorF trav(map) ; + for(Dart d = trav.begin(); d != trav.end(); d = trav.next()) + { + unsigned int degree = map.faceDegree(d); + Dart f=d; + switch(degree) + { + case 3: + triangles.push_back(indices[f]); f = map.phi1(f); + triangles.push_back(indices[f]); f = map.phi1(f); + triangles.push_back(indices[f]); + break; + case 4: + quads.push_back(indices[f]); f = map.phi1(f); + quads.push_back(indices[f]); f = map.phi1(f); + quads.push_back(indices[f]); f = map.phi1(f); + quads.push_back(indices[f]); + break; + + default: + others_begin.push_back(others.size()); + do + { + others.push_back(indices[f]); f = map.phi1(f); + + } while (f!=d); + break; + } + } + others_begin.push_back(others.size()); + + unsigned int nbtotal = triangles.size()/3 + quads.size()/4 + others_begin.size()-1; + + fout << "" << std::endl; + fout << "" << std::endl; + fout << "" << std::endl; + fout << "" << std::endl; + fout << "" << std::endl; + fout << "" << std::endl; + + { + std::vector bufferV3; + bufferV3.reserve(position.nbElements()); + for (unsigned int i = position.begin(); i != position.end(); position.next(i)) + bufferV3.push_back(position[i]); + Utils::zlibWriteCompressed((unsigned char*)(&bufferV3[0]),bufferV3.size()*sizeof(VEC3), fout); + } + + fout << "" << std::endl; + fout << "" << std::endl; + fout << "" << std::endl; + fout << "" << std::endl; + + std::vector bufferInt; + bufferInt.reserve(triangles.size()+quads.size()+others.size()); + + for (unsigned int i=0; i" << std::endl; + fout << "" ; + + bufferInt.clear(); + + unsigned int offset = 0; + for (unsigned int i=0; i" << std::endl; + fout << ""; + + for (unsigned int i=0; i" << std::endl; + fout << "" << std::endl; + fout << "" << std::endl; + fout << "" << std::endl; fout << "" << std::endl; fout.close(); @@ -1197,6 +1366,377 @@ bool exportVTU(typename PFP::MAP& map, const VertexAttribute + +template +VTUExporter::VTUExporter(typename PFP::MAP& map, const VertexAttribute& position): + m_map(map),m_position(position), + nbtotal(0),noPointData(true),noCellData(true),closed(false) +{ + if (map.dimension() != 2) + { + CGoGNerr << "Surface::Export::exportVTU works only with map of dimension 2"<< CGoGNendl; + } + +} + +template +bool VTUExporter::init(const char* filename) +{ + + // open file + fout.open(filename, std::ios::out) ; + + if (!fout.good()) + { + CGoGNerr << "Unable to open file " << filename << CGoGNendl ; + return false; + } + + VertexAutoAttribute indices(m_map,"indices_vert"); + + unsigned int count=0; + for (unsigned int i = m_position.begin(); i != m_position.end(); m_position.next(i)) + { + indices[i] = count++; + } + + triangles.reserve(4096); + quads.reserve(4096); + others.reserve(4096); + others_begin.reserve(4096); + + bufferTri.reserve(4096); + bufferQuad.reserve(4096); + bufferOther.reserve(4096); + + TraversorF trav(m_map) ; + for(Dart d = trav.begin(); d != trav.end(); d = trav.next()) + { + unsigned int degree = m_map.faceDegree(d); + Dart f=d; + switch(degree) + { + case 3: + bufferTri.push_back(d); + triangles.push_back(indices[f]); f = m_map.phi1(f); + triangles.push_back(indices[f]); f = m_map.phi1(f); + triangles.push_back(indices[f]); + break; + case 4: + bufferQuad.push_back(d); + quads.push_back(indices[f]); f = m_map.phi1(f); + quads.push_back(indices[f]); f = m_map.phi1(f); + quads.push_back(indices[f]); f = m_map.phi1(f); + quads.push_back(indices[f]); + break; + + default: + bufferOther.push_back(d); + others_begin.push_back(others.size()); + do + { + others.push_back(indices[f]); f = m_map.phi1(f); + + } while (f!=d); + break; + } + } + others_begin.push_back(others.size()); + + nbtotal = triangles.size()/3 + quads.size()/4 + others_begin.size()-1; + + fout << "" << std::endl; + fout << "" << std::endl; + fout << "" << std::endl; + fout << "" << std::endl; + + return true; +} + +template +template +void VTUExporter::addVertexAttributeScal(const VertexAttribute& attrib, const std::string& vtkType, const std::string& name) +{ + if (!noCellData) + { + CGoGNerr << "VTUExporter::addVertexAttribute: endFaceAttributes before adding VertexAttribute"<< CGoGNendl; + return; + } + + if (noPointData) + { + fout << "" << std::endl; + noPointData = false; + } + + if (name.size() != 0) + fout << "" << std::endl; + else + fout << "" << std::endl; + + for (unsigned int i = attrib.begin(); i != attrib.end(); attrib.next(i)) + fout << attrib[i] << std::endl; + + fout << "" << std::endl; + +} + +template +template +void VTUExporter::addVertexAttributeVect(const VertexAttribute& attrib, const std::string& vtkType, unsigned int nbComp, const std::string& name) +{ + if (!noCellData) + { + CGoGNerr << "VTUExporter::addVertexAttribute: endFaceAttributes before adding VertexAttribute"<< CGoGNendl; + return; + } + + if (noPointData) + { + fout << "" << std::endl; + noPointData = false; + } + + if (nbComp==0) + nbComp = sizeof(T)/(unsigned int)(2*(vtkType[vtkType.size()-1]-'0')); // Float32 -> 2*2=4 bytes Int64 -> 8 bytes + + if (name.size() != 0) + fout << "" << std::endl; + else + fout << "" << std::endl; + + for (unsigned int i = attrib.begin(); i != attrib.end(); attrib.next(i)) + { + const T& a = attrib[i]; + for (unsigned int j=0;j" << std::endl; +} + + + +template +void VTUExporter::endVertexAttributes() +{ + if (!noPointData) + fout << "" << std::endl; + + noPointData = true; +} + + + + +template +template +void VTUExporter::addFaceAttributeScal(const FaceAttribute& attrib, const std::string& vtkType, const std::string& name) +{ + if (!noPointData) + { + CGoGNerr << "VTUExporter::addFaceAttribute: endVertexAttributes before adding FaceAttribute"<< CGoGNendl; + return; + } + + if (noCellData) + { + fout << "" << std::endl; + noCellData = false; + } + + if (name.size() != 0) + fout << "" << std::endl; + else + fout << "" << std::endl; + + + for (typename std::vector::iterator it = bufferTri.begin(); it != bufferTri.end(); ++it) + fout << attrib[*it] << std::endl; + for (typename std::vector::iterator it = bufferQuad.begin(); it != bufferQuad.end(); ++it) + fout << attrib[*it] << std::endl; + for (typename std::vector::iterator it = bufferOther.begin(); it != bufferOther.end(); ++it) + fout << attrib[*it] << std::endl; + fout << "" << std::endl; + +} + + +template +template +void VTUExporter::addFaceAttributeVect(const FaceAttribute& attrib, const std::string& vtkType, unsigned int nbComp, const std::string& name) +{ + if (!noPointData) + { + CGoGNerr << "VTUExporter::addFaceAttribute: endVertexAttributes before adding FaceAttribute"<< CGoGNendl; + return; + } + + if (noCellData) + { + fout << "" << std::endl; + noCellData = false; + } + + if (nbComp==0) + nbComp = sizeof(T)/(unsigned int)(2*(vtkType[vtkType.size()-1]-'0')); // Float32 -> 2*2=4 bytes Int64 -> 8 bytes + + if (name.size() != 0) + fout << "" << std::endl; + else + fout << "" << std::endl; + + for (typename std::vector::iterator it = bufferTri.begin(); it != bufferTri.end(); ++it) + { + const T& a = attrib[*it]; + for (unsigned int j=0;j::iterator it = bufferQuad.begin(); it != bufferQuad.end(); ++it) + { + const T& a = attrib[*it]; + for (unsigned int j=0;j::iterator it = bufferOther.begin(); it != bufferOther.end(); ++it) + { + const T& a = attrib[*it]; + for (unsigned int j=0;j" << std::endl; + +} + +template +void VTUExporter::endFaceAttributes() +{ + if (!noCellData) + fout << "" << std::endl; + + noCellData = true; +} + + +template +bool VTUExporter::close() +{ + if (!noPointData) + endVertexAttributes(); + + if (!noCellData) + endFaceAttributes(); + + fout << "" << std::endl; + fout << "" << std::endl; + + for (unsigned int i = m_position.begin(); i != m_position.end(); m_position.next(i)) + { + const VEC3& P = m_position[i]; + fout << P[0]<< " " << P[1]<< " " << P[2] << std::endl; + } + + fout << "" << std::endl; + fout << "" << std::endl; + fout << "" << std::endl; + fout << "" << std::endl; + + for (unsigned int i=0; i" << std::endl; + fout << "" ; + + unsigned int offset = 0; + for (unsigned int i=0; i" << std::endl; + fout << ""; + for (unsigned int i=0; i" << std::endl; + fout << "" << std::endl; + fout << "" << std::endl; + fout << "" << std::endl; + fout << "" << std::endl; + + fout.close(); + closed=true; + return true; +} + +template +VTUExporter::~VTUExporter() +{ + if (!closed) + close(); + closed = true; +} + + } // namespace Export } diff --git a/include/Utils/compress.h b/include/Utils/compress.h new file mode 100644 index 0000000000000000000000000000000000000000..392482cfa0aa403e3fba1bca5648e4d531635d2c --- /dev/null +++ b/include/Utils/compress.h @@ -0,0 +1,42 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* version 0.1 * +* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library 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 Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef _CGOGN_COMPRESS_H_ +#define _CGOGN_COMPRESS_H_ + + +#include + +namespace CGoGN +{ +namespace Utils +{ + +void zlibWriteCompressed( unsigned char* input, unsigned int nbBytes, std::ofstream& fout); + +} +} + +#endif + diff --git a/src/Utils/compress.cpp b/src/Utils/compress.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9a892f64fd660772a07d539859013b396b9e28bc --- /dev/null +++ b/src/Utils/compress.cpp @@ -0,0 +1,79 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* version 0.1 * +* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library 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 Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#include +#include "Utils/compress.h" +#include "zlib.h" + +namespace CGoGN +{ + +namespace Utils +{ + +void zlibWriteCompressed( unsigned char* input, unsigned int nbBytes, std::ofstream& fout) +{ + const int CHUNK=16384; + int level = 6; // compression level + unsigned char* out = new unsigned char[CHUNK]; + + z_stream strm; + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + int ret = deflateInit(&strm, level); + assert(ret == Z_OK); + + unsigned char* ptrData = input; + int remain = nbBytes; + + while (remain >0) + { + strm.avail_in = std::min(remain,CHUNK); // taille buffer + strm.next_in = ptrData; // ptr buffer + + do + { + strm.avail_out = CHUNK; + strm.next_out = out; + if (remain>= CHUNK) + ret = deflate(&strm, 0); + else + ret = deflate(&strm, 1); + assert(ret != Z_STREAM_ERROR); + unsigned int have = CHUNK - strm.avail_out; + fout.write((char*)out, have); + } while (strm.avail_out == 0); + + remain -= CHUNK; + ptrData += CHUNK; + } + +// assert(ret == Z_STREAM_END); + deflateEnd(&strm); + delete[] out; +} + +} +}