Skip to content
Snippets Groups Projects
WbWriterVtkXmlBinary.cpp 68.9 KiB
Newer Older
//=======================================================================================
// ____          ____    __    ______     __________   __      __       __        __
// \    \       |    |  |  |  |   _   \  |___    ___| |  |    |  |     /  \      |  |
//  \    \      |    |  |  |  |  |_)   |     |  |     |  |    |  |    /    \     |  |
//   \    \     |    |  |  |  |   _   /      |  |     |  |    |  |   /  /\  \    |  |
//    \    \    |    |  |  |  |  | \  \      |  |     |   \__/   |  /  ____  \   |  |____
//     \    \   |    |  |__|  |__|  \__\     |__|      \________/  /__/    \__\  |_______|
//      \    \  |    |   ________________________________________________________________
//       \    \ |    |  |  ______________________________________________________________|
//        \    \|    |  |  |         __          __     __     __     ______      _______
//         \         |  |  |_____   |  |        |  |   |  |   |  |   |   _  \    /  _____)
//          \        |  |   _____|  |  |        |  |   |  |   |  |   |  | \  \   \_______
//           \       |  |  |        |  |_____   |   \_/   |   |  |   |  |_/  /    _____  |
//            \ _____|  |__|        |________|   \_______/    |__|   |______/    (_______/
//  This file is part of VirtualFluids. VirtualFluids 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 3 of
//  the License, or (at your option) any later version.
//
//  VirtualFluids 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
//  for more details.
//  You should have received a copy of the GNU General Public License along
//  with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
//
//! \file WbWriterVtkXmlBinary.cpp
//! \ingroup writer
//! \author Soeren Freudiger, Sebastian Geller
//=======================================================================================
LEGOLAS\lenz's avatar
LEGOLAS\lenz committed
#include <basics/utilities/UbLogger.h>
#include <basics/writer/WbWriterVtkXmlASCII.h>
#include <basics/writer/WbWriterVtkXmlBinary.h>
LEGOLAS\lenz's avatar
LEGOLAS\lenz committed
#include <cstring>
#include <fstream>
#include <string>
LEGOLAS\lenz's avatar
LEGOLAS\lenz committed

using namespace std;

Anna Wellmann's avatar
Anna Wellmann committed
ofstream createFileStream(const std::string &vtkFilename)
LEGOLAS\lenz's avatar
LEGOLAS\lenz committed
{
    ofstream outputFileStream(vtkFilename.c_str(), ios::out | ios::binary);
    if (!outputFileStream) {
        outputFileStream.clear();
Anna Wellmann's avatar
Anna Wellmann committed
        const std::string path = UbSystem::getPathFromString(vtkFilename);
        if (!path.empty()) {
            UbSystem::makeDirectory(path);
            outputFileStream.open(vtkFilename.c_str(), ios::out | ios::binary);
Anna Wellmann's avatar
Anna Wellmann committed
        if (!outputFileStream) throw UbException(UB_EXARGS, "couldn't open file " + vtkFilename);
    return outputFileStream;
}
Anna Wellmann's avatar
Anna Wellmann committed
void addCollectionHeader(std::ofstream &outputFileStream)
{
    std::string endian = UbSystem::isLittleEndian() ? "LittleEndian" : "BigEndian";
    outputFileStream << "<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"" << endian << "\" >" << endl;
    outputFileStream << "   <Collection>" << endl;
}

void addCollectionDatasetsForTimeStep(std::ofstream &outputFileStream, const vector<string> &filenames, double timeStep, bool separateGroups)
{
    int group = 0, part = 0;
    for (size_t i = 0; i < filenames.size(); i++) {
Anna Wellmann's avatar
Anna Wellmann committed
        outputFileStream << "       <DataSet timestep=\"" << timeStep << "\" group=\"" << group << "\" part=\"" << part << "\" file=\"" << filenames[i] << "\"/>" << endl;
        if (separateGroups)
std::string getCollectionEndString()
{
    return "   </Collection>\n</VTKFile>";
}

void finalizeCollectionFile(std::ofstream &outputFileStream)
{
    outputFileStream << getCollectionEndString();
    outputFileStream.close();
}

std::string WbWriterVtkXmlBinary::writeCollectionForTimeSeries(const std::string &filename,
                                                               const std::map<uint, std::vector<std::string>> &filesNamesForTimeSteps, bool separateGroups) const
{
    std::string vtkFilename = filename + ".pvd";
    ofstream out = createFileStream(vtkFilename);
    addCollectionHeader(out);
    for (auto [timeStep, filenames]: filesNamesForTimeSteps) {
        addCollectionDatasetsForTimeStep(out, filenames, timeStep, separateGroups);
    }
    finalizeCollectionFile(out);
    return vtkFilename;
}

string WbWriterVtkXmlBinary::writeCollection(const string &filename, const vector<string> &filenames,
                                             const double &timeStep, const bool &separateGroups) const
{
    std::string vtkFilename = filename + ".pvd";
    ofstream out = createFileStream(vtkFilename);
    addCollectionHeader(out);
    addCollectionDatasetsForTimeStep(out, filenames, timeStep, separateGroups);
    finalizeCollectionFile(out);
    return vtkFilename;
LEGOLAS\lenz's avatar
LEGOLAS\lenz committed
}
Anna Wellmann's avatar
Anna Wellmann committed

LEGOLAS\lenz's avatar
LEGOLAS\lenz committed
/*===============================================================================*/
string WbWriterVtkXmlBinary::addFilesToCollection(const string &filename, const vector<string> &filenames,
                                                  const double &timeStep, const bool &separateGroups) const
LEGOLAS\lenz's avatar
LEGOLAS\lenz committed
{
    string vtkfilename = filename;
    fstream test(vtkfilename.c_str(), ios::in);
    if (!test) {
        test.clear();
        vtkfilename += ".pvd";
        test.open(vtkfilename.c_str(), ios::in);
        if (!test)
            return this->writeCollection(filename, filenames, timeStep, separateGroups);
    }

    fstream out(vtkfilename.c_str(), ios::in | ios::out);
    out.seekp(-(int)getCollectionEndString().size() - 1, ios_base::end);

    int group = 0;
    for (size_t i = 0; i < filenames.size(); i++) {
        out << "       <DataSet timestep=\"" << timeStep << "\" group=\"" << group << "\" part=\"" << i << "\" file=\""
            << filenames[i] << "\"/>" << endl;
        if (separateGroups)
    out <<  getCollectionEndString();
LEGOLAS\lenz's avatar
LEGOLAS\lenz committed
}
/*===============================================================================*/
string WbWriterVtkXmlBinary::writeParallelFile(const string &filename, vector<string> &pieceSources,
                                               vector<string> &pointDataNames, vector<string> &cellDataNames) const
LEGOLAS\lenz's avatar
LEGOLAS\lenz committed
{
    string vtkfilename = filename + ".pvtu";
    UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeParallelFile to " << vtkfilename << " - start");

    std::ofstream out = createFileStream(vtkfilename);
Anna Wellmann's avatar
Anna Wellmann committed
    out << "<?xml version=\"1.0\"?>\n";
    out << "<VTKFile type=\"PUnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">"
        << "\n";
Anna Wellmann's avatar
Anna Wellmann committed
    out << "  <PUnstructuredGrid GhostLevel=\"1\">"
        << "\n";
    out << "    <PPointData>\n";
    for (size_t s = 0; s < pointDataNames.size(); s++)
Anna Wellmann's avatar
Anna Wellmann committed
        out << "      <PDataArray type=\"Float64\" Name=\"" << pointDataNames[s] << "\"/>\n";
    out << "    </PPointData>\n";
    if (cellDataNames.size() > 0) {
        out << "    <PCellData>\n";
        for (size_t s = 0; s < cellDataNames.size(); s++)
Anna Wellmann's avatar
Anna Wellmann committed
            out << "      <PDataArray type=\"Float64\" Name=\"" << cellDataNames[s] << "\"/>\n";
        out << "    </PCellData>\n";
    }
Anna Wellmann's avatar
Anna Wellmann committed
    out << "    <PPoints>\n";
    out << "      <PDataArray type=\"Float32\" NumberOfComponents=\"3\"/>\n";
    out << "    </PPoints>\n";

    for (size_t s = 0; s < pieceSources.size(); s++)
        out << "    <Piece Source=\"" << pieceSources[s] << "\"/>\n";
    out << "  </PUnstructuredGrid>\n";
    out << "</VTKFile>";
    out << endl;
    out.close();
    UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeParallelFile to " << vtkfilename << " - end");

    return vtkfilename;
LEGOLAS\lenz's avatar
LEGOLAS\lenz committed
}
LEGOLAS\lenz's avatar
LEGOLAS\lenz committed
/*===============================================================================*/

void writeVtkHeader(ofstream &out, int numberOfNodes, int numberOfCells)
{
    out << "<?xml version=\"1.0\"?>\n";
    out << "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"
        << "\n";
    out << "   <UnstructuredGrid>"
        << "\n";
    out << "      <Piece NumberOfPoints=\"" << numberOfNodes << "\" NumberOfCells=\"" << numberOfCells << "\">\n";
}
int writePointHeader(ofstream &out, int offset, int bytesPerByteVal, int bytesPoints)
{
    out << "         <Points>\n";
    out << "            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\"" << offset
        << "\"  />\n";
    out << "         </Points>\n";
    offset += (bytesPerByteVal + bytesPoints);
int writeCellHeader(ofstream &out, int offset, int bytesPerByteVal, int bytesCellConnectivity, int bytesCellOffsets,
                    int bytesCellTypes)
{
    out << "         <Cells>\n";
    out << "            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\"" << offset
        << "\" />\n";
    offset += (bytesPerByteVal + bytesCellConnectivity);
    out << "            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\"" << offset
        << "\" />\n";
    offset += (bytesPerByteVal + bytesCellOffsets);
    out << "            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\"" << offset << "\" />\n ";
    offset += (bytesPerByteVal + bytesCellTypes);
    out << "         </Cells>\n";
int writeDataHeader(ofstream &out, vector<string> &datanames, int offset, int bytesPerByteVal, int bytesScalarData)
{
    out << "         <CellData>\n";
    for (size_t s = 0; s < datanames.size(); ++s) {
        out << "            <DataArray type=\"Float32\" Name=\"" << datanames[s] << "\" format=\"appended\" offset=\""
            << offset << "\" /> \n";
        offset += (bytesPerByteVal + bytesScalarData);
    }
    out << "         </CellData>\n";
    return offset;
}

void writeAppendDataHeader(ofstream &out)
{
    out << "      </Piece>\n";
    out << "   </UnstructuredGrid>\n";
    out << "   <AppendedData encoding=\"raw\">\n";
    out << "_";
void writePoints(ofstream &out, int bytesPerByteVal, int bytesPoints, vector<UbTupleFloat3> &nodes)
{
    out.write((char *)&bytesPoints, bytesPerByteVal);
    for (int n = 0; n < (int)nodes.size(); n++) {
        out.write((char *)&val<1>(nodes[n]), sizeof(float));
        out.write((char *)&val<2>(nodes[n]), sizeof(float));
        out.write((char *)&val<3>(nodes[n]), sizeof(float));
    }
void writeCellConnectivity(ofstream &out, int bytesPerByteVal, int bytesCellConnectivity, vector<UbTupleInt2> &cells)
{
    out.write((char *)&bytesCellConnectivity, bytesPerByteVal);
    for (int c = 0; c < (int)cells.size(); c++) {
        out.write((char *)&val<1>(cells[c]), sizeof(int));
        out.write((char *)&val<2>(cells[c]), sizeof(int));
void writeCellOffsets(ofstream &out, int bytesPerByteVal, int bytesCellOffsets, int numberOfCells)
{
    out.write((char *)&bytesCellOffsets, bytesPerByteVal);
    int itmp;
    for (int c = 1; c <= numberOfCells; c++) {
        itmp = 2 * c;
        out.write((char *)&itmp, sizeof(int));
    }
void writeCellTypes(ofstream &out, int bytesPerByteVal, int bytesCellTypes, int numberOfCells)
{
    out.write((char *)&bytesCellTypes, bytesPerByteVal);
    unsigned char vtkCellType = 3;
    for (int c = 0; c < numberOfCells; c++) {
        out.write((char *)&vtkCellType, sizeof(unsigned char));
    }
}

void writeCellData(ofstream &out, int bytesPerByteVal, int bytesScalarData, vector<string> &datanames,
                   vector<vector<float>> &celldata)
{
    for (size_t s = 0; s < datanames.size(); ++s) {
        out.write((char *)&bytesScalarData, bytesPerByteVal);
        for (size_t d = 0; d < celldata[s].size(); ++d) {
            // loake kopie machen, da in celldata "doubles" sind
            float tmp = (float)celldata[s][d];
            out.write((char *)&tmp, sizeof(float));
        }
    }
}

void writeEndOfVtkFile(ofstream &out)
    out << "\n</AppendedData>\n";
    out << "</VTKFile>";
    out << endl;
    out.close();
}

/*===============================================================================*/
string WbWriterVtkXmlBinary::writeLines(const string &filename, vector<UbTupleFloat3> &nodes,
                                        vector<UbTupleInt2> &lines)
{
    string vtkfilename = filename + getFileExtension();
    UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeLines to " << vtkfilename << " - start");

    ofstream out = createFileStream(vtkfilename);

    int nofNodes = (int)nodes.size();
    int nofCells = (int)lines.size();

    int bytesPerByteVal = 4; //==sizeof(int)
    int bytesPoints = 3 /*x1/x2/x3        */ * nofNodes * sizeof(float);
    int bytesCellConnectivity = 2 /*nodes per line */ * nofCells * sizeof(int);
    int bytesCellOffsets = 1 /*offset per line */ * nofCells * sizeof(int);
    int bytesCellTypes = 1 /*type of line */ * nofCells * sizeof(unsigned char);

    int offset = 0;

    writeVtkHeader(out, nofNodes, nofCells);
    offset = writePointHeader(out, offset, bytesPerByteVal, bytesPoints);
    writeCellHeader(out, offset, bytesPerByteVal, bytesCellConnectivity, bytesCellOffsets, bytesCellTypes);
    writeAppendDataHeader(out);

    writePoints(out, bytesPerByteVal, bytesPoints, nodes);
    writeCellConnectivity(out, bytesPerByteVal, bytesCellConnectivity, lines);
    writeCellOffsets(out, bytesPerByteVal, bytesCellOffsets, nofCells);
    writeCellTypes(out, bytesPerByteVal, bytesCellTypes, nofCells);
    writeEndOfVtkFile(out);
    UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeLines to " << vtkfilename << " - end");

    return vtkfilename;
LEGOLAS\lenz's avatar
LEGOLAS\lenz committed
}
/*===============================================================================*/
std::string WbWriterVtkXmlBinary::writePolyLines(const std::string &filename,
                                                 real *coordinatesX, real *coordinatesY, real *coordinatesZ,
                                                 uint numberOfCoordinates)
{
    std::vector<UbTupleFloat3> nodes;
    std::vector<UbTupleInt2> lines;

    auto actualNodeNumber = 0;

    for (uint i = 0; i < numberOfCoordinates - 1; i++) {
        nodes.push_back(makeUbTuple(float(coordinatesX[i]), float(coordinatesY[i]), float(coordinatesZ[i])));
        nodes.push_back(makeUbTuple(float(coordinatesX[i + 1]), float(coordinatesY[i + 1]), float(coordinatesZ[i + 1])));
        lines.push_back(makeUbTuple(actualNodeNumber, actualNodeNumber + 1));
        actualNodeNumber += 2;
    }
    return WbWriterVtkXmlBinary::writeLines(filename, nodes, lines);
}

std::string WbWriterVtkXmlBinary::writePolyLines(const std::string & filename, std::vector<real>& coordinatesX,
                                                 std::vector<real>& coordinatesY,  std::vector<real>& coordinatesZ)
{
    return this->writePolyLines(filename, coordinatesX.data(), coordinatesY.data(), coordinatesZ.data(),
                                                                       (uint)coordinatesX.size());
}

/*===============================================================================*/
string WbWriterVtkXmlBinary::writeLinesWithLineData(const string &filename, vector<UbTupleFloat3> &nodes,
                                                    vector<UbTupleInt2> &lines, vector<string> &datanames,
                                                    vector<vector<float>> &celldata)
{
    string vtkfilename = filename + getFileExtension();
    UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeLinesWithLineData to " << vtkfilename << " - start");

    ofstream out = createFileStream(vtkfilename);

    int nofNodes = (int)nodes.size();
    int nofCells = (int)lines.size();

    int bytesPerByteVal = 4; //==sizeof(int)
    int bytesPoints = 3 /*x1/x2/x3        */ * nofNodes * sizeof(float);
    int bytesCellConnectivity = 2 /*nodes per line */ * nofCells * sizeof(int);
    int bytesCellOffsets = 1 /*offset per line */ * nofCells * sizeof(int);
    int bytesCellTypes = 1 /*type of line */ * nofCells * sizeof(unsigned char);
    int bytesScalarData = 1 /*scalar        */ * nofCells * sizeof(float);

    int offset = 0;

    writeVtkHeader(out, nofNodes, nofCells);
    offset = writePointHeader(out, offset, bytesPerByteVal, bytesPoints);
    offset = writeCellHeader(out, offset, bytesPerByteVal, bytesCellConnectivity, bytesCellOffsets, bytesCellTypes);
    writeDataHeader(out, datanames, offset, bytesPerByteVal, bytesScalarData);
    writeAppendDataHeader(out);

    writePoints(out, bytesPerByteVal, bytesPoints, nodes);
    writeCellConnectivity(out, bytesPerByteVal, bytesCellConnectivity, lines);
    writeCellOffsets(out, bytesPerByteVal, bytesCellOffsets, nofCells);
    writeCellTypes(out, bytesPerByteVal, bytesCellTypes, nofCells);
    writeCellData(out, bytesPerByteVal, bytesScalarData, datanames, celldata);
    writeEndOfVtkFile(out);

    UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeLinesWithLineData to " << vtkfilename << " - end");

    return vtkfilename;
}

LEGOLAS\lenz's avatar
LEGOLAS\lenz committed
/*===============================================================================*/
// std::string WbWriterVtkXmlBinary::writeLinesWithNodeData(const string& filename,vector<UbTupleFloat3 >& nodes,
// vector<UbTupleInt2 >& lines, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata)
//{
//   string vtkfilename = filename+getFileExtension();
//   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeLinesWithNodeData to "<<vtkfilename<<" - start");
//
//   ofstream out(vtkfilename.c_str(),ios::out | ios::binary);
//   if(!out)
//   {
//      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
//      string path = UbSystem::getPathFromString(vtkfilename);
//      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
//      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
//   }
//
//   int nofNodes = (int)nodes.size();
//   int nofCells = (int)lines.size();
//
//   int bytesPerByteVal      = 4; //==sizeof(int)
//   int bytesPoints          = 3 /*x1/x2/x3        */ * nofNodes * sizeof(float);
//   int bytesCellConnectivity = 2 /*nodes per line  */ * nofCells * sizeof(int  );
//   int bytesCellOffsets     = 1 /*offset per line */ * nofCells * sizeof(int  );
//   int bytesCellTypes       = 1 /*type of line    */ * nofCells * sizeof(unsigned char);
//   int bytesScalarData      = 1 /*scalar          */ * nofNodes * sizeof(float);
//
//   int offset = 0;
//   //VTK FILE
//   out<<"<?xml version=\"1.0\"?>\n";
//   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
//   out<<"   <UnstructuredGrid>"<<"\n";
//   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n";
//
//   //POINTS SECTION
//   out<<"         <Points>\n";
//   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset
//   <<"\"  />\n"; out<<"         </Points>\n"; offset += (bytesPerByteVal + bytesPoints);
//
//   //CELLS SECTION
//   out<<"         <Cells>\n";
//   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\"
//   />\n"; offset += (bytesPerByteVal + bytesCellConnectivity); out<<"            <DataArray type=\"Int32\"
//   Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n"; offset += (bytesPerByteVal +
//   bytesCellOffsets); out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<<
//   offset <<"\" />\n "; offset += (bytesPerByteVal + bytesCellTypes); out<<"         </Cells>\n";
//
//   //DATA SECTION
//   out<<"         <PointData>\n";
//   for(size_t s=0; s<datanames.size(); ++s)
//   {
//      out<< "            <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"appended\" offset=\""<<
//      offset <<"\" /> \n"; offset += (bytesPerByteVal + bytesScalarData);
//   }
//   out<<"         </PointData>\n";
//
//   out<<"      </Piece>\n";
//   out<<"   </UnstructuredGrid>\n";
//
//   // AppendedData SECTION
//   out<<"   <AppendedData encoding=\"raw\">\n";
//   out<<"_";
//
//   //POINTS SECTION
//   out.write((char*)&bytesPoints,bytesPerByteVal);
//   for(int n=0; n<nofNodes; n++)
//   {
//      out.write((char*)&val<1>(nodes[n]),sizeof(float));
//      out.write((char*)&val<2>(nodes[n]),sizeof(float));
//      out.write((char*)&val<3>(nodes[n]),sizeof(float));
//   }
//
//   //CELLS SECTION
//   //cellConnectivity
//   out.write( (char*)&bytesCellConnectivity, bytesPerByteVal );
//   for(int c=0; c<nofCells; c++)
//   {
//      out.write( (char*)&val<1>(lines[c]), sizeof(int) );
//      out.write( (char*)&val<2>(lines[c]), sizeof(int) );
//   }
//
//   //cellOffsets
//   out.write( (char*)&bytesCellOffsets, bytesPerByteVal );
//   int itmp;
//   for(int c=1; c<=nofCells; c++)
//   {
//      itmp = 3 * c;
//      out.write( (char*)&itmp, sizeof(int) );
//   }
//
//   //cellTypes
//   out.write( (char*)&bytesCellTypes, bytesPerByteVal );
//   unsigned char vtkCellType = 5;
//   for(int c=0; c<nofCells; c++)
//   {
//      out.write( (char*)&vtkCellType, sizeof(unsigned char) );
//   }
//
//   //DATA SECTION
//   //scalarData
//   for(size_t s=0; s<datanames.size(); ++s)
//   {
//      out.write((char*)&bytesScalarData,bytesPerByteVal);
//      for(size_t d=0; d<nodedata[s].size(); ++d)
//      {
//         //loake kopie machen, da in nodedata "doubles" sind
//         float tmp = (float)nodedata[s][d];
//         out.write((char*)&tmp,sizeof(float));
//      }
//   }
//   out<<"\n</AppendedData>\n";
//   out<<"</VTKFile>";
//   out<<endl;
//   out.close();
//   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeLinesWithNodeData to "<<vtkfilename<<" - end");
//
//   return vtkfilename;
//
//}
LEGOLAS\lenz's avatar
LEGOLAS\lenz committed
/*===============================================================================*/
string WbWriterVtkXmlBinary::writeTriangles(const string &filename, vector<UbTupleFloat3> &nodes,
                                            vector<UbTupleInt3> &triangles)
LEGOLAS\lenz's avatar
LEGOLAS\lenz committed
{
    string vtkfilename = filename + getFileExtension();
    UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeTriangles to " << vtkfilename << " - start");

    ofstream out = createFileStream(vtkfilename);

    int nofNodes = (int)nodes.size();
    int nofCells = (int)triangles.size();

    int bytesPerByteVal      = 4; //==sizeof(int)
    int bytesPoints          = 3 /*x1/x2/x3 - coord    */ * nofNodes * sizeof(float);
    int bytesCellConnectivity = 3 /*nodes per triangle  */ * nofCells * sizeof(int);
    int bytesCellOffsets     = 1 /*offset per triangle */ * nofCells * sizeof(int);
    int bytesCellTypes       = 1 /*type of triangle    */ * nofCells * sizeof(unsigned char);

    int offset = 0;
    // VTK FILE
    out << "<?xml version=\"1.0\"?>\n";
    out << "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"
        << "\n";
    out << "   <UnstructuredGrid>"
        << "\n";
    out << "      <Piece NumberOfPoints=\"" << nofNodes << "\" NumberOfCells=\"" << nofCells << "\">\n";

    // POINTS SECTION
    out << "         <Points>\n";
    out << "            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\"" << offset
        << "\"  />\n";
    out << "         </Points>\n";
    offset += (bytesPerByteVal + bytesPoints);

    // CELLS SECTION
    out << "         <Cells>\n";
    out << "            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\"" << offset
        << "\" />\n";
    offset += (bytesPerByteVal + bytesCellConnectivity);
    out << "            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\"" << offset
        << "\" />\n";
    offset += (bytesPerByteVal + bytesCellOffsets);
    out << "            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\"" << offset << "\" />\n ";
    offset += (bytesPerByteVal + bytesCellTypes);
    out << "         </Cells>\n";

    out << "      </Piece>\n";
    out << "   </UnstructuredGrid>\n";

    // AppendedData SECTION
    out << "   <AppendedData encoding=\"raw\">\n";
    out << "_";

    // POINTS SECTION
    out.write((char *)&bytesPoints, bytesPerByteVal);
    for (int n = 0; n < nofNodes; n++) {
        out.write((char *)&val<1>(nodes[n]), sizeof(float));
        out.write((char *)&val<2>(nodes[n]), sizeof(float));
        out.write((char *)&val<3>(nodes[n]), sizeof(float));
    }

    // CELLS SECTION
    // cellConnectivity
    out.write((char *)&bytesCellConnectivity, bytesPerByteVal);
    for (int c = 0; c < nofCells; c++) {
        out.write((char *)&val<1>(triangles[c]), sizeof(int));
        out.write((char *)&val<2>(triangles[c]), sizeof(int));
        out.write((char *)&val<3>(triangles[c]), sizeof(int));
    }

    // cellOffsets
    out.write((char *)&bytesCellOffsets, bytesPerByteVal);
    int itmp;
    for (int c = 1; c <= nofCells; c++) {
        itmp = 3 * c;
        out.write((char *)&itmp, sizeof(int));
    }

    // cellTypes
    out.write((char *)&bytesCellTypes, bytesPerByteVal);
    unsigned char vtkCellType = 5;
    for (int c = 0; c < nofCells; c++) {
        out.write((char *)&vtkCellType, sizeof(unsigned char));
    }

    out << "\n</AppendedData>\n";
    out << "</VTKFile>";
    out << endl;
    out << flush;
    out.close();
    UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeTriangles to " << vtkfilename << " - end");

    return vtkfilename;
LEGOLAS\lenz's avatar
LEGOLAS\lenz committed
}
/*===============================================================================*/
string WbWriterVtkXmlBinary::writeTrianglesWithNodeData(const string &filename, vector<UbTupleFloat3> &nodes,
                                                        vector<UbTupleInt3> &cells, vector<string> &datanames,
                                                        vector<vector<double>> &nodedata)
LEGOLAS\lenz's avatar
LEGOLAS\lenz committed
{
    string vtkfilename = filename + getFileExtension();
    UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeTrianglesWithNodeData to " << vtkfilename << " - start");

    ofstream out = createFileStream(vtkfilename);

    int nofNodes = (int)nodes.size();
    int nofCells = (int)cells.size();

    int bytesPerByteVal      = 4; //==sizeof(int)
    int bytesPoints          = 3 /*x1/x2/x3        */ * nofNodes * sizeof(float);
    int bytesCellConnectivity = 3 /*nodes per tri   */ * nofCells * sizeof(int);
    int bytesCellOffsets     = 1 /*offset per tri  */ * nofCells * sizeof(int);
    int bytesCellTypes       = 1 /*type of tri     */ * nofCells * sizeof(unsigned char);
    int bytesScalarData      = 1 /*scalar          */ * nofNodes * sizeof(float);

    int offset = 0;
    // VTK FILE
    out << "<?xml version=\"1.0\"?>\n";
    out << "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"
        << "\n";
    out << "   <UnstructuredGrid>"
        << "\n";
    out << "      <Piece NumberOfPoints=\"" << nofNodes << "\" NumberOfCells=\"" << nofCells << "\">\n";

    // POINTS SECTION
    out << "         <Points>\n";
    out << "            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\"" << offset
        << "\"  />\n";
    out << "         </Points>\n";
    offset += (bytesPerByteVal + bytesPoints);

    // CELLS SECTION
    out << "         <Cells>\n";
    out << "            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\"" << offset
        << "\" />\n";
    offset += (bytesPerByteVal + bytesCellConnectivity);
    out << "            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\"" << offset
        << "\" />\n";
    offset += (bytesPerByteVal + bytesCellOffsets);
    out << "            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\"" << offset << "\" />\n ";
    offset += (bytesPerByteVal + bytesCellTypes);
    out << "         </Cells>\n";

    // DATA SECTION
    out << "         <PointData>\n";
    for (size_t s = 0; s < datanames.size(); ++s) {
        out << "            <DataArray type=\"Float32\" Name=\"" << datanames[s] << "\" format=\"appended\" offset=\""
            << offset << "\" /> \n";
        offset += (bytesPerByteVal + bytesScalarData);
    }
    out << "         </PointData>\n";

    out << "      </Piece>\n";
    out << "   </UnstructuredGrid>\n";

    // AppendedData SECTION
    out << "   <AppendedData encoding=\"raw\">\n";
    out << "_";

    // POINTS SECTION
    out.write((char *)&bytesPoints, bytesPerByteVal);
    for (int n = 0; n < nofNodes; n++) {
        out.write((char *)&val<1>(nodes[n]), sizeof(float));
        out.write((char *)&val<2>(nodes[n]), sizeof(float));
        out.write((char *)&val<3>(nodes[n]), sizeof(float));
    }

    // CELLS SECTION
    // cellConnectivity
    out.write((char *)&bytesCellConnectivity, bytesPerByteVal);
    for (int c = 0; c < nofCells; c++) {
        out.write((char *)&val<1>(cells[c]), sizeof(int));
        out.write((char *)&val<2>(cells[c]), sizeof(int));
        out.write((char *)&val<3>(cells[c]), sizeof(int));
    }

    // cellOffsets
    out.write((char *)&bytesCellOffsets, bytesPerByteVal);
    int itmp;
    for (int c = 1; c <= nofCells; c++) {
        itmp = 3 * c;
        out.write((char *)&itmp, sizeof(int));
    }

    // cellTypes
    out.write((char *)&bytesCellTypes, bytesPerByteVal);
    unsigned char vtkCellType = 5;
    for (int c = 0; c < nofCells; c++) {
        out.write((char *)&vtkCellType, sizeof(unsigned char));
    }

    // DATA SECTION
    // scalarData
    for (size_t s = 0; s < datanames.size(); ++s) {
        out.write((char *)&bytesScalarData, bytesPerByteVal);
        for (size_t d = 0; d < nodedata[s].size(); ++d) {
            // loake kopie machen, da in nodedata "doubles" sind
            float tmp = (float)nodedata[s][d];
            out.write((char *)&tmp, sizeof(float));
        }
    }
    out << "\n</AppendedData>\n";
    out << "</VTKFile>";
    out << endl;
    out.close();
    UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeTrianglesWithNodeData to " << vtkfilename << " - end");

    return vtkfilename;
LEGOLAS\lenz's avatar
LEGOLAS\lenz committed
}
/*===============================================================================*/
string WbWriterVtkXmlBinary::writeQuads(const string &filename, vector<UbTupleFloat3> &nodes,
                                        vector<UbTupleInt4> &cells)
LEGOLAS\lenz's avatar
LEGOLAS\lenz committed
{
    string vtkfilename = filename + getFileExtension();
    UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeQuads to " << vtkfilename << " - start");

    ofstream out = createFileStream(vtkfilename);

    int nofNodes = (int)nodes.size();
    int nofCells = (int)cells.size();

    int bytesPerByteVal      = 4; //==sizeof(int)
    int bytesPoints          = 3 /*x1/x2/x3        */ * nofNodes * sizeof(float);
    int bytesCellConnectivity = 4 /*nodes per quad  */ * nofCells * sizeof(int);
    int bytesCellOffsets     = 1 /*offset per quad */ * nofCells * sizeof(int);
    int bytesCellTypes       = 1 /*type of quad    */ * nofCells * sizeof(unsigned char);

    int offset = 0;
    // VTK FILE
    out << "<?xml version=\"1.0\"?>\n";
    out << "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"
        << "\n";
    out << "   <UnstructuredGrid>"
        << "\n";
    out << "      <Piece NumberOfPoints=\"" << nofNodes << "\" NumberOfCells=\"" << nofCells << "\">\n";

    // POINTS SECTION
    out << "         <Points>\n";
    out << "            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\"" << offset
        << "\"  />\n";
    out << "         </Points>\n";
    offset += (bytesPerByteVal + bytesPoints);

    // CELLS SECTION
    out << "         <Cells>\n";
    out << "            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\"" << offset
        << "\" />\n";
    offset += (bytesPerByteVal + bytesCellConnectivity);
    out << "            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\"" << offset
        << "\" />\n";
    offset += (bytesPerByteVal + bytesCellOffsets);
    out << "            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\"" << offset << "\" />\n ";
    offset += (bytesPerByteVal + bytesCellTypes);
    out << "         </Cells>\n";

    out << "      </Piece>\n";
    out << "   </UnstructuredGrid>\n";

    // AppendedData SECTION
    out << "   <AppendedData encoding=\"raw\">\n";
    out << "_";

    // POINTS SECTION
    out.write((char *)&bytesPoints, bytesPerByteVal);
    for (int n = 0; n < nofNodes; n++) {
        out.write((char *)&val<1>(nodes[n]), sizeof(float));
        out.write((char *)&val<2>(nodes[n]), sizeof(float));
        out.write((char *)&val<3>(nodes[n]), sizeof(float));
    }

    // CELLS SECTION
    // cellConnectivity
    out.write((char *)&bytesCellConnectivity, bytesPerByteVal);
    for (int c = 0; c < nofCells; c++) {
        out.write((char *)&val<1>(cells[c]), sizeof(int));
        out.write((char *)&val<2>(cells[c]), sizeof(int));
        out.write((char *)&val<4>(cells[c]), sizeof(int));
        out.write((char *)&val<3>(cells[c]), sizeof(int));
    }

    // cellOffsets
    out.write((char *)&bytesCellOffsets, bytesPerByteVal);
    int itmp;
    for (int c = 1; c <= nofCells; c++) {
        itmp = 4 * c;
        out.write((char *)&itmp, sizeof(int));
    }

    // cellTypes
    out.write((char *)&bytesCellTypes, bytesPerByteVal);
    unsigned char vtkCellType = 8;
    for (int c = 0; c < nofCells; c++) {
        out.write((char *)&vtkCellType, sizeof(unsigned char));
    }
    out << "\n</AppendedData>\n";
    out << "</VTKFile>";
    out << endl;
    out << flush;
    out.close();
    UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeQuads to " << vtkfilename << " - end");

    return vtkfilename;
LEGOLAS\lenz's avatar
LEGOLAS\lenz committed
}
/*===============================================================================*/
string WbWriterVtkXmlBinary::writeQuadsWithNodeData(const string &filename, vector<UbTupleFloat3> &nodes,
                                                    vector<UbTupleInt4> &cells, vector<string> &datanames,
                                                    vector<vector<double>> &nodedata)
LEGOLAS\lenz's avatar
LEGOLAS\lenz committed
{
    string vtkfilename = filename + getFileExtension();
    UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeQuadsWithNodeData to " << vtkfilename << " - start");

    ofstream out = createFileStream(vtkfilename);

    int nofNodes = (int)nodes.size();
    int nofCells = (int)cells.size();

    int bytesPerByteVal      = 4; //==sizeof(int)
    int bytesPoints          = 3 /*x1/x2/x3        */ * nofNodes * sizeof(float);
    int bytesCellConnectivity = 4 /*nodes per quad  */ * nofCells * sizeof(int);
    int bytesCellOffsets     = 1 /*offset per quad */ * nofCells * sizeof(int);
    int bytesCellTypes       = 1 /*type of quad    */ * nofCells * sizeof(unsigned char);
    int bytesScalarData      = 1 /*scalar          */ * nofNodes * sizeof(float);

    int offset = 0;
    // VTK FILE
    out << "<?xml version=\"1.0\"?>\n";
    out << "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"
        << "\n";
    out << "   <UnstructuredGrid>"
        << "\n";
    out << "      <Piece NumberOfPoints=\"" << nofNodes << "\" NumberOfCells=\"" << nofCells << "\">\n";

    // POINTS SECTION
    out << "         <Points>\n";
    out << "            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\"" << offset
        << "\"  />\n";
    out << "         </Points>\n";
    offset += (bytesPerByteVal + bytesPoints);

    // CELLS SECTION
    out << "         <Cells>\n";
    out << "            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\"" << offset
        << "\" />\n";
    offset += (bytesPerByteVal + bytesCellConnectivity);
    out << "            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\"" << offset
        << "\" />\n";
    offset += (bytesPerByteVal + bytesCellOffsets);
    out << "            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\"" << offset << "\" />\n ";
    offset += (bytesPerByteVal + bytesCellTypes);
    out << "         </Cells>\n";

    // DATA SECTION
    out << "         <PointData>\n";
    for (size_t s = 0; s < datanames.size(); ++s) {
        out << "            <DataArray type=\"Float64\" Name=\"" << datanames[s] << "\" format=\"appended\" offset=\""
            << offset << "\" /> \n";
        offset += (bytesPerByteVal + bytesScalarData);
    }
    out << "         </PointData>\n";

    out << "      </Piece>\n";
    out << "   </UnstructuredGrid>\n";

    // AppendedData SECTION
    out << "   <AppendedData encoding=\"raw\">\n";
    out << "_";

    // POINTS SECTION
    out.write((char *)&bytesPoints, bytesPerByteVal);
    for (int n = 0; n < nofNodes; n++) {
        out.write((char *)&val<1>(nodes[n]), sizeof(float));
        out.write((char *)&val<2>(nodes[n]), sizeof(float));
        out.write((char *)&val<3>(nodes[n]), sizeof(float));
    }

    // CELLS SECTION
    // cellConnectivity
    out.write((char *)&bytesCellConnectivity, bytesPerByteVal);
    for (int c = 0; c < nofCells; c++) {
        out.write((char *)&val<1>(cells[c]), sizeof(int));
        out.write((char *)&val<2>(cells[c]), sizeof(int));
        out.write((char *)&val<4>(cells[c]), sizeof(int));
        out.write((char *)&val<3>(cells[c]), sizeof(int));
    }

    // cellOffsets
    out.write((char *)&bytesCellOffsets, bytesPerByteVal);
    int itmp;
    for (int c = 1; c <= nofCells; c++) {
        itmp = 4 * c;
        out.write((char *)&itmp, sizeof(int));
    }

    // cellTypes
    out.write((char *)&bytesCellTypes, bytesPerByteVal);
    unsigned char vtkCellType = 8;
    for (int c = 0; c < nofCells; c++) {
        out.write((char *)&vtkCellType, sizeof(unsigned char));
    }

    // DATA SECTION
    // scalarData
    for (size_t s = 0; s < datanames.size(); ++s) {
        out.write((char *)&bytesScalarData, bytesPerByteVal);
        for (size_t d = 0; d < nodedata[s].size(); ++d) {
            // loake kopie machen, da in nodedata "doubles" sind
            float tmp = (float)nodedata[s][d];
            out.write((char *)&tmp, sizeof(float));
        }
    }
    out << "\n</AppendedData>\n";
    out << "</VTKFile>";
    out << endl;
    out.close();
    UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeQuadsWithNodeData to " << vtkfilename << " - end");

    return vtkfilename;
LEGOLAS\lenz's avatar
LEGOLAS\lenz committed
}
/*===============================================================================*/
string WbWriterVtkXmlBinary::writeQuadsWithCellData(const string &filename, vector<UbTupleFloat3> &nodes,
                                                    vector<UbTupleInt4> &cells, vector<string> &datanames,
                                                    vector<vector<double>> &celldata)
LEGOLAS\lenz's avatar
LEGOLAS\lenz committed
{
    string vtkfilename = filename + getFileExtension();
    UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeQuadsWithCellData to " << vtkfilename << " - start");

    ofstream out = createFileStream(vtkfilename);

    int nofNodes = (int)nodes.size();
    int nofCells = (int)cells.size();

    int bytesPerByteVal      = 4; //==sizeof(int)
    int bytesPoints          = 3 /*x1/x2/x3        */ * nofNodes * sizeof(float);
    int bytesCellConnectivity = 4 /*nodes per quad  */ * nofCells * sizeof(int);
    int bytesCellOffsets     = 1 /*offset per quad */ * nofCells * sizeof(int);
    int bytesCellTypes       = 1 /*type of quad    */ * nofCells * sizeof(unsigned char);
    int bytesScalarData      = 1 /*scalar          */ * nofCells * sizeof(float);

    int offset = 0;
    // VTK FILE
    out << "<?xml version=\"1.0\"?>\n";
    out << "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"
        << "\n";
    out << "   <UnstructuredGrid>"
        << "\n";
    out << "      <Piece NumberOfPoints=\"" << nofNodes << "\" NumberOfCells=\"" << nofCells << "\">\n";

    // POINTS SECTION
    out << "         <Points>\n";
    out << "            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\"" << offset
        << "\"  />\n";
    out << "         </Points>\n";
    offset += (bytesPerByteVal + bytesPoints);

    // CELLS SECTION
    out << "         <Cells>\n";
    out << "            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\"" << offset
        << "\" />\n";
    offset += (bytesPerByteVal + bytesCellConnectivity);
    out << "            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\"" << offset
        << "\" />\n";
    offset += (bytesPerByteVal + bytesCellOffsets);
    out << "            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\"" << offset << "\" />\n ";
    offset += (bytesPerByteVal + bytesCellTypes);
    out << "         </Cells>\n";

    // DATA SECTION
    out << "         <CellData>\n";
    for (size_t s = 0; s < datanames.size(); ++s) {
        out << "            <DataArray type=\"Float32\" Name=\"" << datanames[s] << "\" format=\"appended\" offset=\""
            << offset << "\" /> \n";
        offset += (bytesPerByteVal + bytesScalarData);
    }
    out << "         </CellData>\n";

    out << "      </Piece>\n";
    out << "   </UnstructuredGrid>\n";

    // AppendedData SECTION
    out << "   <AppendedData encoding=\"raw\">\n";
    out << "_";

    // POINTS SECTION
    out.write((char *)&bytesPoints, bytesPerByteVal);
    for (int n = 0; n < nofNodes; n++) {
        out.write((char *)&val<1>(nodes[n]), sizeof(float));
        out.write((char *)&val<2>(nodes[n]), sizeof(float));