写入二进制文件
Writing To a Binary File
我正在尝试用 Fortran 90 编写一个 STL 二进制文件。该文件具有以下格式
HEADER: An 80 byte ASCII header - TITLE
A 4 byte unsigned long integer, NO. OF FACETS
FORMAT FOR EACH FACET:
Normal vector, 3 floating values of 4 bytes each;
Vertex 1 XYZ coordinates, 3 floating values of 4 bytes each;
Vertex 2 XYZ coordinates, 3 floating values of 4 bytes each;
Vertex 3 XYZ coordinates, 3 floating values of 4 bytes each;
An unsigned integer, of 2 bytes, that should be zero;
我正在尝试创建一个未格式化的文件来写入相关信息,但无法定义正确的记录长度。假设我有N个切面,我正在使用以下命令打开和写入信息
open(unit = 1, status = 'replace', iostat = ioerror, format = 'unformatted', access = 'direct', recl = 84 + N * 50, file = 'c:\temp\test.stl')
我能否发出第一个写入语句来写出 header 信息,然后发出第二个写入语句(在 do 循环内)来写出构面信息?
如果是这样,由于我有 header 和具有不同记录长度的方面信息,我需要为每个写入语句提供的记录编号是多少。
write(1,rec=?), *header information*
do,i=1,N,1
write(1,rec=?), *facet information*
enddo
这很有趣。我编写了一个小程序,它使用 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
我正在尝试用 Fortran 90 编写一个 STL 二进制文件。该文件具有以下格式
HEADER: An 80 byte ASCII header - TITLE
A 4 byte unsigned long integer, NO. OF FACETS
FORMAT FOR EACH FACET:
Normal vector, 3 floating values of 4 bytes each;
Vertex 1 XYZ coordinates, 3 floating values of 4 bytes each;
Vertex 2 XYZ coordinates, 3 floating values of 4 bytes each;
Vertex 3 XYZ coordinates, 3 floating values of 4 bytes each;
An unsigned integer, of 2 bytes, that should be zero;
我正在尝试创建一个未格式化的文件来写入相关信息,但无法定义正确的记录长度。假设我有N个切面,我正在使用以下命令打开和写入信息
open(unit = 1, status = 'replace', iostat = ioerror, format = 'unformatted', access = 'direct', recl = 84 + N * 50, file = 'c:\temp\test.stl')
我能否发出第一个写入语句来写出 header 信息,然后发出第二个写入语句(在 do 循环内)来写出构面信息?
如果是这样,由于我有 header 和具有不同记录长度的方面信息,我需要为每个写入语句提供的记录编号是多少。
write(1,rec=?), *header information*
do,i=1,N,1
write(1,rec=?), *facet information*
enddo
这很有趣。我编写了一个小程序,它使用 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