Как прочитать двоичный файл данных structd_points, сгенерированный в Fortran C ++ и VTK? - PullRequest
0 голосов
/ 22 февраля 2019

Я новичок в VTK и пытаюсь прочитать двоичный файл structd_points (data image) в vtk, но получаю ошибку «Ошибка чтения двоичных данных» с пустым окном.Я использую простую программу на Фортране для создания файла данных (данные поля Гаусса) следующим образом:

 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

VTK хорошо читает и отображает данные, если данные в формате ASCII (см. Рисунок ниже)

enter image description here

Я использую следующий код C ++ в VTK для чтения данных (без настройки для порядка байтов),

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

Я пытался много искать в интернете, но не смог найти правильный способ чтения данных structd_points в двоичном формате.Кажется, что нет способа установить порядок байтов для читателя структурированных точек.Я не уверен, что здесь делать.Любая помощь будет принята с благодарностью.

Ответы [ 2 ]

0 голосов
/ 23 февраля 2019

Следуя советам Владимира по поводу устаревших форматов, принимающих только big_endian, несколько простых изменений в моем коде на языке фортран, приведенных выше, помогли мне.Установка параметра «convert» в выражении «open» файла на «big_endian» решила самую большую проблему.Кроме того, float следует изменить на «real (real64)», чтобы он соответствовал типу данных double в файле данных vtk.

    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
0 голосов
/ 22 февраля 2019

В вашей процедуре записи есть несколько проблем.

Во-первых, вы пишете данные одинарной точности (используя 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
...