|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
|||
|
|||
Запись и чтение разно-типизированного файла
Доброго всем.
Есть стандартный файл литографии STL - дока в сети есть но всёже приведу Его структура: 80 первых байт текст - комменты 4 байта число элементов (треугольников) (тип Dword) 4 по 4 Real32 - нормаль XYZ и координаты ХYZ вершин треугольника 2 байта вспомогательная инфа. и того 80 + 4 + 50 + 50 +50 +.....+50(раз элементов). составляю типы: Код:
type triangle=record nv:single tx:single ty:single tz:single tc:word end type mstl=record comm:string // 80 numt:dword // 4 ztrian:triangle // 50 end К тому же не ясно, как перебирать в таком типе все треугольники (50 байт 4х4 +2) при чтении указывать как массив(максючисло треуг.допустим 6000000): ztrian:array [0..6000000] of triangle . А как писать обратно в такой файл? и если писать массив то запишется весь??? (6000000???) а мне надо скажем 10000 всего? Что не делаю то I/O error или вместо данных (достоверно прочтёных в фирменной программе) получаю не координаты и сумашедшие числа... ХЕЛП... |
#2
|
|||
|
|||
1. Читать через TFileStream
2. Перед чтением надо память выделять Как-то так: Код:
type TSTLItem = record nv:single tx:single ty:single tz:single tc:word end; TSTLStruct = record Comm : AnsiString; Count : DWORD; Items : Array Of TSTLItem; end; procedure ReadSTLFile(FileName : String; var Data : TSTLStruct); var I : Integer; F : TFileStream; begin F := TFileStream.Create(FileName, fmOpenRead); Try SetLength(Data.Comm,80); F.ReadBuffer(Data.Comm[1],80); F.ReadBuffer(Data.Count,sizeOf(DWORD)); SetLength(Data.Items,Data.Count); For I := 0 To Data.Count-1 Do Begin F.ReadBuffer(Data.Items[i].nv,SizeOf(Single)); // Здесь читаем остальные поля текущего треугольника End; Finally F.Free; end; end; |
#3
|
||||
|
||||
ТС похоже немного заблуждается, если судить по описанию бинарной версии данного формата, то структура записей должна быть слегка другой, с чтением из буфера не дружу, но вот такой вариант загрузил координаты треугольников тестового чайника из teapot.stl
Код:
type TSTLItem = record ni: single; nj: single; nk: single; x1: single; y1: single; z1: single; x2: single; y2: single; z2: single; x3: single; y3: single; z3: single; tc: word; end; TSTLStruct = record Comm : String[80]; Count : DWORD; Items : Array Of TSTLItem; end; var Data : TSTLStruct; StlFile: TFileStream; b: dword; begin StlFile:= TFileStream.Create(FileName, fmOpenRead); StlFile.Seek(0, soFromBeginning); StlFile.Read(Data.comm,80); StlFile.Read(Data.Count,4); SetLength(Data.Items,Data.Count); for b:= 0 to Data.Count-1 do begin StlFile.Read(Data.Items[b].ni,4); StlFile.Read(Data.Items[b].nj,4); StlFile.Read(Data.Items[b].nk,4); StlFile.Read(Data.Items[b].x1,4); StlFile.Read(Data.Items[b].y1,4); StlFile.Read(Data.Items[b].z1,4); StlFile.Read(Data.Items[b].x2,4); StlFile.Read(Data.Items[b].y2,4); StlFile.Read(Data.Items[b].z2,4); StlFile.Read(Data.Items[b].x3,4); StlFile.Read(Data.Items[b].y3,4); StlFile.Read(Data.Items[b].z3,4); StlFile.Read(Data.Items[b].tc,2); end; StlFile.Free; end; Я не понял Вашего вопроса, но всё же Вам на него отвечу! |
#4
|
|||
|
|||
Прочитать могу только < примерно 40000 треугольников и а если ставлю больше то Stack Overflow, если не ставлю размер - то вообще не компилит.
Вот моя полная процедура: Код:
procedure TForm1.Button1Click(Sender: TObject); // загрузить файл точек/бинарник/треугольники type striangle=packed record // 50_и байтная запись 1 треугольника trnormx:single; // 4 trnormy:single; // 4 trnormz:single; // 4 tr3dx1: Single; // 4 tr3dy1: Single; // 4 tr3dz1: Single; // 4 tr3dx2: Single; // 4 tr3dy2: Single; // 4 tr3dz2: Single; // 4 tr3dx3: Single; // 4 tr3dy3: Single; // 4 tr3dz3: Single; // 4 trattr: word; // 2 end; type StlRec= packed record SName: array[1..80] of Char;//string[80]; // array of char сработал правильно Snum: dword; msstri: array [0..60000]of striangle; // множество записей треугольничных записей - 60000 уже не берёт end; var i,ii,jj,sl:integer; sss,stru:string; Buf: array[1..127] of Char; mash:single; NumRead: integer; Infl: file of Single; //stlf: file; stlperm: StlRec; stlf: file of StlRec; begin mash:=strtofloat(Edit1.text); if OpenDialog1.Execute then begin if OpenDialog1.FilterIndex=3 then // STL bin file begin AssignFile(stlf,OpenDialog1.FileName); Reset(stlf); DlnStr:=80; // BlockRead(stlf,,DlnStr,NumRead); //читаем файл в массив read(stlf,stlperm); // SetLength(stlperm.msstri, stlperm.Snum); // попытка дать размер массиву треугольников DlnStr:=1; // ntri:=FilePos(stlf);// - возвращает текущую позицию чтения/записи в файл // BlockRead(stlf,ntri,DlnStr,NumRead); DlnStr:=NumRead; //получили реальную длину файла CloseFile(stlf); ii:=21; i:=0; // ntri:=Fbind[20]; // запоминаем число треугольников для процедуры вывода графики // memo1.Clear; // SendMessage(memo1.Handle, WM_SETREDRAW, 0, 0) ; // запрещаем перерисовку для ускорения вывода jlc:=stlperm.Snum; // while i<(stlperm.Snum-1) do while i<(19999) do begin // ii:=ii+1; // stlperm.msstri[] // перепрыгиваем направление нормали треугольника triangle3dx1[i]:= stlperm.msstri[i].tr3dx1; // заполняем массив точками triangle3dy1[i]:= stlperm.msstri[i].tr3dy1; // заполняем массив точками triangle3dz1[i]:= stlperm.msstri[i].tr3dz1; // заполняем массив точками triangle3dx2[i]:= stlperm.msstri[i].tr3dx2; // заполняем массив точками triangle3dy2[i]:= stlperm.msstri[i].tr3dy2; // заполняем массив точками triangle3dz2[i]:= stlperm.msstri[i].tr3dz2; // заполняем массив точками triangle3dx3[i]:= stlperm.msstri[i].tr3dx3; // заполняем массив точками triangle3dy3[i]:= stlperm.msstri[i].tr3dy3; // заполняем массив точками triangle3dz3[i]:= stlperm.msstri[i].tr3dz3; // заполняем массив точками i:=i+1; ii:=i; // memo1.Lines.Add(floattostrf(points3dx[i],fffixed,6,3)+' '+floattostrf(points3dy[i],fffixed,6,3)+' '+floattostrf(points3dz[i],fffixed,6,3)); // i:=i+1; end; // SendMessage(memo1.Handle, WM_SETREDRAW, 1, 0); // разрешаем перерисовку // RedrawWindow(memo1.Handle, nil, 0,RDW_ERASE or RDW_FRAME or RDW_INVALIDATE or RDW_ALLCHILDREN); end; // open STL end;// open file l_point:=true; label1.Tag:=ii; end; В принципе работает он но на малое число - 20000 точно берёт. Видел примеры что делают через Read/Seek по записям - но там нет заголовочной инфы и какие-то примеры не полноценные... Спасибо, попробую. |
#5
|
|||
|
|||
Alegun Ваш код работает, спасибо, только число переменных больше и Data надо объявить (о, Вы уже дописали код ))), и в принципе я читал потом не в переменную файла а в массив типа single - всё нормально прочиталось и массив заполнился.
С этого массива сразу читал точки и в OpenGl строил треугольники - всё чётко. Всем спасибо )) |
#6
|
||||
|
||||
Способом копипасты довёл число треугольников в текстовом варианте больше чем 160000 штук, затем первёл в бинарный формат - прекрасно под D7 полученный файл и открывается и грузится в структуру, наверное с типами у вас неразбериха, отсюда и преполнение
З.Ы. Есть менее затратный вариант - подключить к проекту assimp32.dll, порт объявы под делфи в сетке вроде на неё есть, а это умеет работать со многими форматами, в том числе и с двумя вариантами *.stl Я не понял Вашего вопроса, но всё же Вам на него отвечу! |
Этот пользователь сказал Спасибо Alegun за это полезное сообщение: | ||
-=#PupaJr#=- (22.08.2016)
|