2015-12-07 2 views
2

Я пытающегося писать STL двоичный файл в Fortran 90. Файл имеет следующий форматЗапись в двоичный файл

HEADER: ASCII заголовок 80 байт - TITLE

A 4 байт без знака long integer, NO. Фасок

формата для каждого FACET:

нормального вектор, 3 плавающих значений 4 байта каждых;

Координаты вершин 1 XYZ, 3 плавающие значения по 4 байта каждый;

Координаты Vertex 2 XYZ, 3 плавающие значения по 4 байта каждый;

Координаты Vertex 3 XYZ, 3 плавающие значения по 4 байта каждый;

Целочисленное целое число без знака, равное 2 байтам, которое должно быть равным нулю;

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

Может ли я выдавать первый оператор записи выписывать информацию заголовка с последующей вторым оператором записи (в пределах делать петлю) выписать информацию о фасете?

Если да, то какой номер записи мне нужно иметь для каждого из операторов записи, поскольку у меня есть заголовок и информация о фасете с разными длинами записей.

write(1,rec=?), *header information* 
do,i=1,N,1 
    write(1,rec=?), *facet information* 
enddo 
+0

Вы уверены, что файл формата Unformatted Fortran подходит для этого? – francescalus

+1

Прямой доступ кажется плохим выбором дизайна. Поток будет намного лучше, учитывая заголовок. Как вы получили 'recl = 84 + N * 50'? Для этого следует использовать инструкцию запроса. –

+0

Поскольку записи имеют разную длину, прямой доступ не подходит, как уже отмечалось. –

ответ

2

Это было интересно. Я взломал небольшую программу, которая создает очень простую пирамиду, используя доступ к STREAM. Кажется, что работает:

program write_stl 
    use ISO_FORTRAN_ENV 
    implicit none 
    integer, parameter :: u = 400 
    character(len=*), parameter :: fname = 'pyramid.stl' 
    integer :: ios 
    integer(kind=4) :: num_facets 
    character(len=80) :: title 
    real(kind=4), dimension(3) :: top_vertex, front_vertex, left_vertex, right_vertex 

    top_vertex = (/0.0, 0.0, 2.0/) 
    front_vertex = (/0.0, -1.0, 0.0/) 
    left_vertex = (/-1.0, 1.0, 0.0/) 
    right_vertex = (/1.0, 1.0, 0.0/) 

    open(unit=u, file=fname, access='stream', status='replace', & 
     action='write', iostat=ios) 
    call check(ios, 'open') 

    title = "Testpyramid" 
    write(u, iostat=ios) title 
    call check(ios, 'write title') 
    num_facets = 4 
    write(u, iostat=ios) num_facets 
    call check(ios, 'write number of facets') 
    ! bottom facet 
    call write_facet(u, front_vertex, left_vertex, right_vertex) 
    call write_facet(u, top_vertex, right_vertex, left_vertex) 
    call write_facet(u, top_vertex, left_vertex, front_vertex) 
    call write_facet(u, top_vertex, front_vertex, right_vertex) 

    close(u, iostat=ios) 
    call check(ios, 'close') 

contains 

    subroutine check(ios, operation) 
     implicit none 
     integer, intent(in) :: ios 
     character(len=*), intent(in) :: operation 
     if (ios == 0) return 
     write(*, '(A, I0, 2A)') "Encountered error ", ios, " while performing ", operation 
     stop 1 
    end subroutine check 

    subroutine write_facet(u, vertex1, vertex2, vertex3) 
     implicit none 
     integer, intent(in) :: u 
     real(kind=4), dimension(3), intent(in) :: vertex1, vertex2, vertex3 
     real(kind=4), dimension(3) :: normal 
     integer(kind=2), parameter :: zero = 0 

     normal = calc_normal(vertex1, vertex2, vertex3) 
     write(u, iostat=ios) normal 
     call check(ios, 'write normal') 
     write(u, iostat=ios) vertex1 
     call check(ios, 'write vertex') 
     write(u, iostat=ios) vertex2 
     call check(ios, 'write vertex') 
     write(u, iostat=ios) vertex3 
     call check(ios, 'write vertex') 
     write(u, iostat=ios) zero 
     call check(ios, 'write zero') 
    end subroutine write_facet 

    function calc_normal(vec1, vec2, vec3) 
     implicit none 
     real(kind=4), dimension(3), intent(in) :: vec1, vec2, vec3 
     real(kind=4), dimension(3) :: calc_normal 
     real(kind=4), dimension(3) :: d1, d2 
     d1 = vec2 - vec1 
     d2 = vec3 - vec1 
     calc_normal(1) = d1(2) * d2(3) - d1(3) * d2(2) 
     calc_normal(2) = d1(3) * d2(1) - d1(1) * d2(3) 
     calc_normal(3) = d1(1) * d2(2) - d1(2) * d2(1) 
     calc_normal = calc_normal/norm(calc_normal) 
    end function calc_normal 

    function norm(vec) 
     implicit none 
     real(kind=4), dimension(3), intent(in) :: vec 
     real(kind=4) :: norm 

     norm = sqrt(vec(1)**2 + vec(2)**2 + vec(3)**2) 
    end function norm 

end program write_stl 
+0

Спасибо за пример chw21! Полагаю, что я пошел по неверному пути, написав как неформатированный файл, как некоторые из вас указали. – HarRad