1

I am trying to write a vtk file from my C++ code. I have two versions, one ASCII and the other binary. The ASCII version works well.

I want to do something similar to this post : Error writing binary VTK files

Here is my code :

std::ofstream file;
  if(is_binary)
    file.open("test.vtk", std::ios::out | std::ios::binary);
  else
    file.open("test.vtk");

  file << "# vtk DataFile Version 2.0" << std::endl
       << "Comment if needed" << std::endl;

  if(is_binary)
    file << "BINARY"<< std::endl << std::endl;
  else
    file << "ASCII"<< std::endl << std::endl;

  file << "DATASET POLYDATA" << std::endl << "POINTS " << nb_particles << " float"  << std::endl;
  for(size_t cell_i=0;cell_i<n_cells;cell_i++)
      for(size_t i =0; i<cells[cell_i].size();++i)
        {
          if(is_binary)
            {
              double rx = cells[cell_i][field::rx][i];
              double ry = cells[cell_i][field::ry][i];
              double rz = cells[cell_i][field::rz][i];

              SwapEnd(rx);
              SwapEnd(ry);
              SwapEnd(rz);

              file.write(reinterpret_cast<char*>(&rx), sizeof(double));
              file.write(reinterpret_cast<char*>(&ry), sizeof(double));
              file.write(reinterpret_cast<char*>(&rz), sizeof(double));
            }
          else
            {
              Vec3d tmp = grid.particle_position(cell_i,i);
              file << tmp.x << " " << tmp.y << " " << tmp.z << std::endl;
            }
        }
  if(is_binary)
    file << std::endl;

  file << "POINT_DATA " << nb_particles << std::endl;

  if(has_id_field)
    {
      file<< "SCALARS index int 1" << std::endl<< "LOOKUP_TABLE default" << std::endl;
      for(size_t cell_i=0;cell_i<n_cells;cell_i++)
        for(size_t i =0; i<cells[cell_i].size();++i)
          {
            if(is_binary)
              {
                uint64_t id = cells[cell_i][field::id][i];

                SwapEnd(id);

                file.write(reinterpret_cast<char*>(&id), sizeof(uint64_t));
              }
            else
              file << cells[cell_i][field::id][i] << std::endl;
          }
      if(is_binary)
        file << std::endl;
    }

  if(has_type_field)
    {
      file<< "SCALARS type int 1" << std::endl<< "LOOKUP_TABLE default" << std::endl;
      for(size_t cell_i=0;cell_i<n_cells;cell_i++)
        for(size_t i =0; i<cells[cell_i].size();++i)
          {
            if(is_binary)
              {
                uint8_t type;

                SwapEnd(type);

                file.write(reinterpret_cast<char*>(&type), sizeof(uint8_t));
              }
            else
              file << static_cast<int>(cells[cell_i][field::type][i]) << std::endl;
          }
      if(is_binary)
        file << std::endl;
    }

  file.close();

with the function :

void SwapEnd(T& var)
{
  char* varArray = reinterpret_cast<char*>(&var);
  for(long i = 0; i < static_cast<long>(sizeof(var)/2); i++)
    std::swap(varArray[sizeof(var) - 1 - i],varArray[i]);
}

My system is little endian :

lscpu | grep "Byte Order"
Byte Order:            Little Endian

paraview make an error on the reading the output file :

vtkPolyDataReader (0x3863800): Unrecognized keyword: @aic�9h��8

What am I not doing well ?

Kafka
  • 720
  • 6
  • 21
  • This is something you should probably work out for yourself. Get a simple set of data and a known working binary writer (you even linked one). Output the simple data using your binary writer and also the know good one. Go through the 2 outputs in a binary (hex?) viewer and find out where they diverge. This should be enough information to then fix your problem. If you've done that and still dont know then show the difference here as an edit to your question. – Mike Vine Apr 24 '19 at 11:58

1 Answers1

2

ok, the problem was the size of datas when I wrote the binary. This following peace of code works. Hope that can help someone.

 std::ofstream file;
  if(is_binary)
    file.open("test.vtk", std::ios::out | std::ios::binary);
  else
    file.open("test.vtk");

  file << "# vtk DataFile Version 2.0" << std::endl
       << "Comment if needed" << std::endl;

  if(is_binary)
    file << "BINARY"<< std::endl << std::endl;
  else
    file << "ASCII"<< std::endl << std::endl;

  file << "DATASET POLYDATA" << std::endl << "POINTS " << nb_particles << " double"  << std::endl;
  for(size_t cell_i=0;cell_i<n_cells;cell_i++)
      for(size_t i =0; i<cells[cell_i].size();++i)
        {
          if(is_binary)
            {
              double rx = cells[cell_i][field::rx][i];
              double ry = cells[cell_i][field::ry][i];
              double rz = cells[cell_i][field::rz][i];

              SwapEnd(rx);
              SwapEnd(ry);
              SwapEnd(rz);

              file.write(reinterpret_cast<char*>(&rx), sizeof(double));
              file.write(reinterpret_cast<char*>(&ry), sizeof(double));
              file.write(reinterpret_cast<char*>(&rz), sizeof(double));
            }
          else
            {
              Vec3d tmp = grid.particle_position(cell_i,i);
              file << tmp.x << " " << tmp.y << " " << tmp.z << std::endl;
            }
        }
  if(is_binary)
    file << std::endl;

  file << "POINT_DATA " << nb_particles << std::endl;

  if(has_id_field)
    {
      file<< "SCALARS index int 1" << std::endl<< "LOOKUP_TABLE default" << std::endl;
      for(size_t cell_i=0;cell_i<n_cells;cell_i++)
        for(size_t i =0; i<cells[cell_i].size();++i)
          {
            if(is_binary)
              {
                uint64_t id = cells[cell_i][field::id][i];

                int id_i = static_cast<int>(id);

                SwapEnd(id_i);

                file.write(reinterpret_cast<char*>(&id_i), sizeof(int));
              }
            else
              file << cells[cell_i][field::id][i] << std::endl;
          }
      if(is_binary)
        file << std::endl;
    }

  if(has_type_field)
    {
      file<< "SCALARS type int 1" << std::endl<< "LOOKUP_TABLE default" << std::endl;
      for(size_t cell_i=0;cell_i<n_cells;cell_i++)
        for(size_t i =0; i<cells[cell_i].size();++i)
          {
            if(is_binary)
              {
                uint8_t type= cells[cell_i][field::type][i];

                int type_i = static_cast<int>(type);

                SwapEnd(type_i);

                file.write(reinterpret_cast<char*>(&type_i), sizeof(int));
              }
            else
              file << static_cast<int>(cells[cell_i][field::type][i]) << std::endl;
          }
      if(is_binary)
        file << std::endl;
    }

  file.close();
Kafka
  • 720
  • 6
  • 21