【问题标题】:Generating XML VTK files with binary datapoints使用二进制数据点生成 XML VTK 文件
【发布时间】:2020-10-26 17:16:11
【问题描述】:

我要生成二进制 vtk 文件。

我写了一个代码,可以先生成正确的ascii vtk文件,然后对其进行一些修改,让它可以生成正确的二进制vtk文件。

我在将第一个 acsii 转换为二进制时遇到了问题,请参阅以下代码中的 if 开关。

#include <fstream>
int main()
{
    std::ofstream fout;
    bool is_binary = true;
    fout.open("new.vtu");
    fout << "<?xml version=\"1.0\"?>\n";
    fout << "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" compressor=\"vtkZLibDataCompressor\">\n";
    fout << "<UnstructuredGrid>\n";
    fout << "<Piece NumberOfPoints=\"4\" NumberOfCells=\"2\">\n";
    fout << "<PointData Scalars=\"\" Vectors=\"\">\n";

    if (is_binary)
    {
        fout << "<DataArray type=\"Float64\" Name=\"solution\" NumberOfComponents=\"3\" format=\"binary\">\n";
        double x[] = {56.25, 6.25, 0, 100, 6.25, 0, 56.25, 0, 0, 100, 0, 0};
        for (int i = 0; i < 12; i++)
        {
            double value = x[i];
            fout.write((char *)(&value), sizeof(double));
        }
        fout << "\n";
    }
    else
    {
        fout << "<DataArray type=\"Float64\" Name=\"solution\" NumberOfComponents=\"3\" format=\"ascii\">\n";
        fout << "56.25 6.25 0\n";
        fout << "100 6.25 0\n";
        fout << "56.25 0 0\n";
        fout << "100 0 0\n";
    }

    fout << "</DataArray>\n";
    fout << "</PointData>\n";
    fout << "<Points>\n";
    fout << "<DataArray type=\"Float64\" NumberOfComponents=\"3\" format=\"ascii\">\n";
    fout << "7.5 2.5 0\n";
    fout << "10 2.5 0\n";
    fout << "7.5 0 0\n";
    fout << "10 0 0\n";
    fout << "</DataArray>\n";
    fout << "</Points>\n";
    fout << "<Cells>\n";
    fout << "<DataArray type=\"Int32\" Name = \"connectivity\" format=\"ascii\">\n";
    fout << "0 2 1\n";
    fout << "1 2 3\n";
    fout << "</DataArray>\n";
    fout << "<DataArray type=\"Int32\" Name = \"offsets\" format=\"ascii\">\n";
    fout << "3\n";
    fout << "6\n";
    fout << "</DataArray>\n";
    fout << "<DataArray type=\"Int8\" Name = \"types\" format=\"ascii\">\n";
    fout << "5\n";
    fout << "5\n";
    fout << "5\n";
    fout << "5\n";
    fout << "</DataArray>\n";
    fout << "</Cells>\n";
    fout << "</Piece>\n";
    fout << "</UnstructuredGrid>\n";
    fout << "</VTKFile>\n";
    fout.close();
    return 0;
}

如果is_binary = false,代码可以生成正确的vtk文件,但是如果is_binary = true,代码不能生成正确的vtk文件。

如果我用paraview 打开 vtk 文件,它会抱怨:

Error parsing the XMKL in stream at line 7, column 0, bute index 311: not well-formed(invalid token)

Visit也打不开我的文件。

代码是用g++ main.cpp编译的,我的机器是little endian。

我已经看过很多话题了

谁能帮帮我?但我仍然无法弄清楚我做错了什么。

感谢您的宝贵时间。

追加

感谢 Botje 先生提出应该使用 base64 编码的建议。

现在我已经使用base64编码了,但是bug还是存在的。

base64.h 复制自 https://github.com/superwills/NibbleAndAHalf/blob/master/NibbleAndAHalf/base64.h

#include <fstream>
#include <iostream>
#include "base64.h"
int main()
{
    std::ofstream fout;
    bool is_binary = true;
    fout.open("new.vtu",  std::ios::binary);
    fout << "<?xml version=\"1.0\"?>\n";
    fout << "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" compressor=\"vtkZLibDataCompressor\">\n";
    fout << "<UnstructuredGrid>\n";
    fout << "<Piece NumberOfPoints=\"4\" NumberOfCells=\"2\">\n";
    fout << "<PointData Scalars=\"\" Vectors=\"\">\n";

    if (is_binary)
    {
        fout << "<DataArray type=\"Float64\" Name=\"solution\" NumberOfComponents=\"3\" format=\"binary\">\n";
        double x[] = {56.25, 6.25, 0, 100, 6.25, 0, 56.25, 0, 0, 100, 0, 0};
        int result_size;
        char *encoding = base64((char *)x, sizeof(double) * 12, &result_size);
        std::cout << result_size << std::endl;
        fout.write(encoding, result_size);
        free(encoding);
    }
    else
    {
        fout << "<DataArray type=\"Float64\" Name=\"solution\" NumberOfComponents=\"3\" format=\"ascii\">\n";
        fout << "56.25 6.25 0\n";
        fout << "100 6.25 0\n";
        fout << "56.25 0 0\n";
        fout << "100 0 0\n";
    }

    fout << "</DataArray>\n";
    fout << "</PointData>\n";
    fout << "<Points>\n";
    fout << "<DataArray type=\"Float64\" NumberOfComponents=\"3\" format=\"ascii\">\n";
    fout << "7.5 2.5 0\n";
    fout << "10 2.5 0\n";
    fout << "7.5 0 0\n";
    fout << "10 0 0\n";
    fout << "</DataArray>\n";
    fout << "</Points>\n";
    fout << "<Cells>\n";
    fout << "<DataArray type=\"Int32\" Name = \"connectivity\" format=\"ascii\">\n";
    fout << "0 2 1\n";
    fout << "1 2 3\n";
    fout << "</DataArray>\n";
    fout << "<DataArray type=\"Int32\" Name = \"offsets\" format=\"ascii\">\n";
    fout << "3\n";
    fout << "6\n";
    fout << "</DataArray>\n";
    fout << "<DataArray type=\"Int8\" Name = \"types\" format=\"ascii\">\n";
    fout << "5\n";
    fout << "5\n";
    fout << "5\n";
    fout << "5\n";
    fout << "</DataArray>\n";
    fout << "</Cells>\n";
    fout << "</Piece>\n";
    fout << "</UnstructuredGrid>\n";
    fout << "</VTKFile>\n";
    fout.close();
    return 0;
}

【问题讨论】:

  • 您没有以二进制模式打开输出文件。你在 Windows 上运行吗?
  • 我的平台是ubuntu。
  • @RetiredNinja 先生,即使使用fout.open("new.vtu", std::ios::binary);,代码仍然无法获得正确答案。
  • 它在 Linux 上不会改变任何东西,但在 Windows 上可以,这就是我问的原因。
  • 先生,我会注意到,以后,您还有什么建议吗?

标签: c++ xml binary vtk


【解决方案1】:

您不能在 XML 文件中转储二进制垃圾并期望它能够正常工作!

vtk file format 上的快速 Google 搜索告诉我,您需要先将您的浮点数 base64 编码为 XML 安全字符,以用于 format="binary"

您可以在 Internet 上找到许多(仅标头)base64 库,我确信 StackOverflow 有几个现成的实现。

【讨论】:

  • 先生,感谢您的建议。现在我看看base64编码,我修改了我的代码。我仍然发现该文件的格式仍然不正确。你能给我另一个帮助吗?对不起我的愚蠢。
  • 那么现在的“错误”是什么?我认为您的 XML 阅读器不再抱怨无效字节了。
  • 先生,现在错误是Can not read point data array "solution" for PointData in piece 0. The data array in the element may be too short
  • 耸耸肩。不知道。文件是否通过常规 XML VTK 验证?
  • 尝试不同的工具,看看它是否能提供更多细节。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多