Python: анализ двоичного файла stl - PullRequest
3 голосов
/ 27 сентября 2011

У меня возникли некоторые трудности при разборе двоичного файла STL с помощью Python (32.7-битная версия 2.7.1 и Windows 7 64).Файл имеет размер около 450 КБ, но мой анализатор неожиданно перестает работать после синтаксического анализа 244 треугольников из ~ 8600, за исключением struct.unpack:

Для распаковки исключения требуется строковый аргумент длиной 12

Позиция курсора в файле - строка 33, строка 929. Но строка содержит около 3400 символов.Так что, похоже, это не проблема перевода строки.

Это код:

import struct

normals = []
points = []
triangles = []
bytecount = []

fb = [] # debug list

def unpack (f, sig, l):
    s = f.read (l)
    fb.append(s)
    return struct.unpack(sig, s)

def read_triangle(f):
    n = unpack(f,"<3f", 12)
    p1 = unpack(f,"<3f", 12)
    p2 = unpack(f,"<3f", 12)
    p3 = unpack(f,"<3f", 12)
    b = unpack(f,"<h", 2)

    normals.append(n)
    l = len(points)
    points.append(p1)
    points.append(p2)
    points.append(p3)
    triangles.append((l, l+1, l+2))
    bytecount.append(b[0])


def read_length(f):
    length = struct.unpack("@i", f.read(4))
    return length[0]

def read_header(f):
    f.seek(f.tell()+80)

def write_as_ascii(outfilename):
    f = open(outfilename, "w")
    f.write ("solid "+outfilename+"\n")
    for n  in range(len(triangles)):
        f.write ("facet normal {} {} {}\n".format(normals[n][0],normals[n][1],normals[n][2]))
        f.write ("outer loop\n")
        f.write ("vertex {} {} {}\n".format(points[triangles[n][0]][0],points[triangles[n][0]][1],points[triangles[n][0]][2]))
        f.write ("vertex {} {} {}\n".format(points[triangles[n][1]][0],points[triangles[n][1]][1],points[triangles[n][1]][2]))
        f.write ("vertex {} {} {}\n".format(points[triangles[n][2]][0],points[triangles[n][2]][1],points[triangles[n][2]][2]))
        f.write ("endloop\n")
        f.write ("endfacet\n")
    f.write ("endsolid "+outfilename+"\n")
    f.close()

def main():
    infilename = r"cupHemis46_28.stl"
    outfilename = r"cupHemis46_28_ascii_test.stl"

    try:
        f = open ( infilename, "r")

        read_header(f)
        l = read_length(f)
        try:
            while True:
                read_triangle(f)
        except Exception, e:
            print "Exception",e[0]
        print len(normals), len(points), len(triangles), l
        write_as_ascii(outfilename)

    except Exception, e:
        print e


if __name__ == '__main__':
    main()

Функция unpack (не из struct) собирает все строки, которые будут записаны в файл,Когда я сравниваю оба файла, они кажутся равными, вплоть до позиции файла, где распаковка перестает работать.Я открыл двоичный файл с помощью Notepad ++, следующий символ - «SUB».

Существуют ли какие-либо ограничения на распаковку, о которых я не знаю, касающиеся размера файла или ограничения в символах или чего-то еще?Что-то не так с моим кодом?Заранее спасибо.

1 Ответ

10 голосов
/ 27 сентября 2011

Ваша функция распаковки вызывает f.read дважды.Я подозреваю, что вы вышли из конца файла.

У вас также будут проблемы с чтением файла в текстовом режиме в Windows.Любые случайные вхождения \r\n будут читаться как \n.Чтобы избежать этой проблемы, внесите следующие изменения.

f = open(infilename, "rb")
...