【问题标题】:How to read a binary structured_points data file generated in Fortran by C++ and VTK?如何读取 C++ 和 VTK 在 Fortran 中生成的二进制结构化点数据文件?
【发布时间】:2019-02-22 03:46:55
【问题描述】:

我是 VTK 新手,我正在尝试在 vtk 中读取二进制结构化点(图像数据)文件,但在空白窗口中出现“读取二进制数据时出错”错误。我正在使用一个简单的fortran程序来创建数据文件(高斯场数据)如下,

 program gaussian

            implicit none
            integer i, j, k
            character(1) c

    open(unit=100, file='energyDensity.vtk',
 1        form="unformatted",access="stream")
    write(100) '# vtk DataFile Version 3.0', new_line(c)
    write(100) 'First time trying vtk import \n', new_line(c)
    write(100) 'BINARY', new_line(c)
    write(100) 'DATASET STRUCTURED_POINTS', new_line(c)
    write(100) 'DIMENSIONS 101 101 101', new_line(c)
    write(100) 'ORIGIN 0 0 0', new_line(c)
    write(100) 'SPACING 1 1 1', new_line(c)
    write(100) 'POINT_DATA 1030301', new_line(c)
    write(100) 'SCALARS volume_scalars double 1', new_line(c)
    write(100) 'LOOKUP_TABLE default', new_line(c)


            do k = -50,50
            do j = -50,50
            do i = -50,50

            write(100) 50.*exp(float((-(i*i+j*j+k*k))/25)) 

            enddo
            enddo
            enddo
    close(100)

endprogram

如果数据是 ASCII 格式,VTK 可以很好地读取和绘制数据(见下图)

我在VTK中使用下面的代码C++来读取数据(没有任何endian设置),

vtkNew<vtkStructuredPointsReader> reader;
  reader->SetFileName (argv[1]);
  reader->Update();

我尝试在互联网上进行大量搜索,但找不到以二进制形式读取结构化点数据的正确方法。似乎也没有办法为结构化点阅读器设置字节序。我不确定在这里做什么。任何帮助将不胜感激。

【问题讨论】:

  • 您确定数据正确吗? Paraview 或 Visit 是否正确打开您的二进制数据?
  • 弗拉基米尔,Paraview 设法打开了文件,但情节与上图完全不同。 Paraview 显示了四个奇怪的球体(规则间隔),这没有意义。所以,不,paraview 没有正确读取二进制文件。我不知道如何解决这个问题。在导入像 Mathematica 这样的软件时,我在 Fortran 中生成二进制文件的方式(如上面的代码)对我来说一直很好。

标签: c++ fortran vtk


【解决方案1】:

你的写作过程中有几个问题。

首先,您正在写入单精度数据(通过使用float()),但您在VTK 标头中声称数据是double

其次,遗留 VTK 文件中的二进制数据应该是大端的。

您还在 (-(i*i+j*j+k*k))/25) 中进行整数除法,但这可能是有意的(或无意的)。

这工作正常

 program gaussian

   use iso_fortran_env

            implicit none
            integer i, j, k
            character(1) c

    open(unit=100, file='energyDensity.vtk', &
         form="unformatted",access="stream")
    write(100) '# vtk DataFile Version 3.0', new_line(c)
    write(100) 'First time trying vtk import \n', new_line(c)
    write(100) 'BINARY', new_line(c)
    write(100) 'DATASET STRUCTURED_POINTS', new_line(c)
    write(100) 'DIMENSIONS 101 101 101', new_line(c)
    write(100) 'ORIGIN 0 0 0', new_line(c)
    write(100) 'SPACING 1 1 1', new_line(c)
    write(100) 'POINT_DATA 1030301', new_line(c)
    write(100) 'SCALARS volume_scalars double 1', new_line(c)
    write(100) 'LOOKUP_TABLE default', new_line(c)


            do k = -50,50
            do j = -50,50
            do i = -50,50

            write(100) SwapB64(exp(real((-(i*i+j*j+k*k)), real64) / 25))

            enddo
            enddo
            enddo
    close(100)
contains

    elemental function SwapB64(x) result(res)
      real(real64) :: res
      real(real64),intent(in) :: x
      character(8) :: bytes
      integer(int64) :: t
      real(real64) :: rbytes, rt
      equivalence (rbytes, bytes)
      equivalence (t, rt)

      rbytes = x

      t = ichar(bytes(8:8),int64)

      t = ior( ishftc(ichar(bytes(7:7),int64),8),  t )

      t = ior( ishftc(ichar(bytes(6:6),int64),16), t )

      t = ior( ishftc(ichar(bytes(5:5),int64),24), t )

      t = ior( ishftc(ichar(bytes(4:4),int64),32), t )

      t = ior( ishftc(ichar(bytes(3:3),int64),40), t )

      t = ior( ishftc(ichar(bytes(2:2),int64),48), t )

      t = ior( ishftc(ichar(bytes(1:1),int64),56), t )

      res = rt

    end function
endprogram

【讨论】:

  • 弗拉基米尔,感谢您的回复。 VTK 用户指南对只接受 big_endian 的传统格式不是很清楚。顺便说一句,使用“open”语句中的“convert”参数将数据转换为 fortran 中的 big_endian 有一个非常简单的技巧。我将在下面发布对我有用的代码。此外,将 float 更改为 real(kind=8) 也有帮助。浮点数在 ASCII 格式下工作得很好,所以我忘了把它改成双倍。是的,我故意除以 25(高斯以这种方式快速衰减)。非常感谢。
  • @phd-applicant 我确实知道该功能,但我不喜欢它。各种编译器提供了各种优点,但没有什么是真正可移植的。
  • @VladimirF, FLOATREAL 采用默认整数输入的标准特定名称。标准的某些版本中的表 16.3 列出了它。
【解决方案2】:

按照 Vladimir 关于仅接受 big_endian 的传统格式的建议,对我上面的 fortran 代码进行了一些简单的更改就可以解决问题。将“open”文件语句中的“convert”参数设置为“big_endian”解决了最大的问题。还要将float改为“real(real64)”,以与vtk数据文件中的double数据类型保持一致。

    program gaussian

    use iso_fortran_env

            implicit none
            integer i, j, k
            character(1) c
            real(real64) x

    open(unit=100, file='energyDensity.vtk',
 1        form="unformatted",access="stream",convert="big_endian")
    write(100) '# vtk DataFile Version 3.0', new_line(c)
    write(100) 'First time trying vtk import \n', new_line(c)
    write(100) 'BINARY', new_line(c)
    write(100) 'DATASET STRUCTURED_POINTS', new_line(c)
    write(100) 'DIMENSIONS 101 101 101', new_line(c)
    write(100) 'ORIGIN 0 0 0', new_line(c)
    write(100) 'SPACING 1 1 1', new_line(c)
    write(100) 'POINT_DATA 1030301', new_line(c)
    write(100) 'SCALARS volume_scalars double 1', new_line(c)
    write(100) 'LOOKUP_TABLE default', new_line(c)


            do k = -50,50
            do j = -50,50
            do i = -50,50

            x=50.*exp(real((-(i*i+j*j+k*k))/25,real64))

            write(100) x

            enddo
            enddo
            enddo
    close(100)

    endprogram

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2013-02-17
  • 1970-01-01
  • 1970-01-01
  • 2012-04-29
  • 2023-03-26
  • 1970-01-01
  • 1970-01-01
  • 2016-10-21
相关资源
最近更新 更多