Записать файл vtk в двоичном формате - PullRequest
0 голосов
/ 24 апреля 2019

Я пытаюсь написать файл vtk из моего кода C ++.У меня есть две версии, одна ASCII и другая двоичная.Версия ASCII работает хорошо.

Я хочу сделать что-то похожее на этот пост: Ошибка записи двоичных файлов VTK

Вот мой код:

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();

с функцией:

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]);
}

Моя система имеет младший порядковый номер:

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

Paraview делает ошибку при чтении выходного файла:

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

Что я не очень хорошо?

1 Ответ

0 голосов
/ 25 апреля 2019

хорошо, проблема была в размере данных, когда я писал двоичный файл. Это следующее спокойствие кода работает. Надеюсь, что это может кому-то помочь.

 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();
...