如何读取由 C++ 和 VTK 在 Fortran 中生成的二进制 structured_points 数据文件?
How to read a binary structured_points data file generated in Fortran by C++ and VTK?
我是 VTK 的新手,我正在尝试读取 vtk 中的二进制 structured_points(图像数据)文件,但出现 "Error reading binary data" 错误和空白 window。我正在使用一个简单的 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++ 读取数据(没有任何字节序设置),
vtkNew<vtkStructuredPointsReader> reader;
reader->SetFileName (argv[1]);
reader->Update();
我尝试在互联网上搜索了很多,但找不到以二进制形式读取 structured_points 数据的正确方法。似乎也没有办法为结构化点 reader 设置字节序。我不确定在这里做什么。任何帮助将不胜感激。
你的写作过程有几个问题。
首先,您正在编写单精度数据(通过使用 float()
),但您声称该数据在 VTK header.
中是 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
遵循 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
我是 VTK 的新手,我正在尝试读取 vtk 中的二进制 structured_points(图像数据)文件,但出现 "Error reading binary data" 错误和空白 window。我正在使用一个简单的 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++ 读取数据(没有任何字节序设置),
vtkNew<vtkStructuredPointsReader> reader;
reader->SetFileName (argv[1]);
reader->Update();
我尝试在互联网上搜索了很多,但找不到以二进制形式读取 structured_points 数据的正确方法。似乎也没有办法为结构化点 reader 设置字节序。我不确定在这里做什么。任何帮助将不胜感激。
你的写作过程有几个问题。
首先,您正在编写单精度数据(通过使用 float()
),但您声称该数据在 VTK header.
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
遵循 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