如何读取C ++和VTK在Fortran中生成的二进制structured_points数据文件?

问题描述 投票:2回答:2

我是VTK的新手,我正在尝试在vtk中读取二进制structured_points(图像数据)文件,但是在空白窗口中出现“读取二进制数据错误”错误。我正在使用一个简单的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会很好地读取和绘制数据(见下图)

enter image description here

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

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

我试过在互联网上搜索了很多但是找不到以二进制方式读取structured_points数据的正确方法。似乎没有办法为结构化点读者设置endian的东西。我不知道这里做了什么。任何帮助将非常感激。

c++ fortran vtk
2个回答
2
投票

您的写作程序有几个问题。

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

其次,传统VTK文件中的二进制数据应该是big-endian。

你也在(-(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

1
投票

根据弗拉基米尔关于只接受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
© www.soinside.com 2019 - 2024. All rights reserved.