![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | 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)
| ||