Как использовать Fortran для чтения информации о лице из файла * .obj - PullRequest
0 голосов
/ 04 апреля 2020

Проблема

Как современный Фортран может перемещаться по файлу с двойной косой чертой между записями, как в формате * .obj? Цель состоит в извлечении индекса вершины (первая запись) и игнорировании нормального индекса вершины (вторая запись).

Пример

Например, для этого фрагмента

f 297//763 298//763 296//763
f 296//764 298//764 295//764
f 384//765 385//765 382//765
f 384//766 382//766 383//766

цель состоит в том, чтобы создать массив, подобный этому:

face ( 1 ) = [297, 298, 296]
face ( 2 ) = [296, 298, 295]
face ( 3 ) = [384, 385, 382]
face ( 4 ) = [384, 382, 383]

Дополнительные баллы за ответ, который будет принят в более богатом формате, например

f a//b//c  d//e//f g//h//i j//k//l

Другие сообщения

Ответ для [ Как получить файл Wavefront .obj с 3 лицами (traingle) указывает на удаленный блог. Этот пост [ Как читать числовые данные c из строки в FORTRAN не имеет отношения к делу.

Ссылки

Три ссылки в формате * .obj: Объектные файлы (.obj) , B1. Объектные файлы (.obj) , Wavefront .obj file

1 Ответ

2 голосов
/ 04 апреля 2020

Как предлагается в комментариях, мы можем заменить / пробелом, используя sed et c. Мы также можем сканировать каждый символ один за другим в Фортране (см. Ниже). Затем мы читаем все целые числа в vals и выбираем нужную часть как vals( 1:6:2 ). Аналогичный подход можно использовать для f a//b//c d//e//f ... et c, изменив 1: 6: 2 на 1: 12: 3 et c.

[test.f90]
program main
    implicit none
    character(100) buf
    integer vals(10), ios, i

    open(10, file="test.dat", status="old")
    do
        read(10, "(a)", iostat=ios) buf
        if (ios /= 0) exit

        do i = 1, len(buf)
            if (buf(i:i) == "/") buf(i:i) = " "   !! replace "/" by " "
        enddo

        read(buf(2:), *) vals( 1:6 )  !! read all items
        print *, vals( 1:6:2 )  !! select items 1, 3, 5
    enddo
    close(10)
end

[test.dat]
f 297//763 298//763 296//763
f 296//764 298//764 295//764
f 384//765 385//765 382//765
f 384//766 382//766 383//766

$ gfortran test.f90 && ./a.out
     297         298         296
     296         298         295
     384         385         382
     384         382         383

Просто для удовольствия, вот аналогичный код в Python, который короче благодаря replace() и split(). Если у нас есть похожие программы, я думаю, что приведенный выше код также может стать короче.

dat = []
for line in open("test.dat").readlines():
    dat.append( line[1:] .replace("/", " ") .split() [::2] )

import numpy as np
face = np.array(dat, dtype=int)
print(face)

$ python test.py
[[297 298 296]
 [296 298 295]
 [384 385 382]
 [384 382 383]]
...