![]() |
wie kann ich bestimmte Infos aus Textdokument einlesen?
Hallo Leute,
weiß Jemand vielleicht, wie ich alle Koordinaten aus einem Textdokument (*.stl Datei im ASCII Format) einlesen und dann in einer Liste speichern kann? Da ich mich mit Text- oder StringVerarbeitung in Delphi nicht gut auskenne. *.stl Datei (ASCII Format) sieht wie folgendes aus:
Code:
Jedes 3D-Objekt besteht aus vielen kleinen Dreiecken und jedes Dreieck besteht aus 1x normal (Nomalvektor) und 3x vertex (Koordinaten der 3 Eckpunkten von jedem Dreieck).
solid ascii
facet normal 2.445222e-016 0.000000e+000 1.000000e+000 outer loop vertex -2.007874e+000 1.968504e+000 5.905512e-002 vertex -2.007874e+000 -1.968504e+000 5.905512e-002 vertex -1.574803e-001 -1.968504e+000 5.905512e-002 endloop endfacet facet normal 2.445222e-016 -5.090141e-032 1.000000e+000 outer loop vertex -1.574803e-001 -1.968504e+000 5.905512e-002 vertex -1.574803e-001 1.968504e+000 5.905512e-002 vertex -2.007874e+000 1.968504e+000 5.905512e-002 endloop endfacet . . . . facet normal 7.071068e-001 -1.471962e-016 7.071068e-001 outer loop vertex -1.574803e-001 1.968504e+000 5.905512e-002 vertex -1.574803e-001 -1.968504e+000 5.905512e-002 vertex -3.937008e-002 -1.968504e+000 -5.905512e-002 endloop endfacet endsolid Meine Frage ist: wie kann ich vom Anfang bis zum Ende der *.stl Datei alle Normalvektoren (als type: TVektor) und alle Koordinaten der 3 Eckpunkten von jedem Dreieck in einer Liste speichern (die Liste soll dynamisch sein, weil die Länge der Liste vorher nicht bekannt ist)? Typen sehen ungefähr wie folgendes aus:
Code:
Ich bitte euch um die Hilfe und bin sehr dankbar für die Antwort wie immer ;-)
type
TVektor = record x, y, z: real; end; TDreieck = record n: TVektor; // n ist Normalvektor p: array[1..3] of TVektor; //p hat Koordinaten von 3 Eckpunkten end; . . . . Var hDreieck : ^TDreieck; Gruss Lee |
AW: wie kann ich bestimmte Infos aus Textdokument einlesen?
Versuch es mal hiermit.
Ich habe die von dir gezeigten daten ins Clipboard kopiert und von dort in die StringList geschrieben. Alle Daten wurden korrekt gelesen. Du solltest das mit list.LoadFromFile machen.
Delphi-Quellcode:
type
TVektor = record x, y, z: real; end; TDreieck = record n: TVektor; // n ist Normalvektor p: array[1..3] of TVektor; //p hat Koordinaten von 3 Eckpunkten end; Var hDreieck : ^TDreieck; Dreiecke:Array of TDreieck; PROCEDURE TMain.Test; const recstart='facet normal'; recline='vertex'; var list:TStrings; line:integer; data:TDreieck; FUNCTION FindLine(const s:string; raiseerr:boolean):boolean; begin while (line<list.count) and (Copy(Trim(list[line]),1,Length(s))<>s) do inc(line); if line<list.count then result:=true else if not raiseerr then result:=false else raise Exception.Create(s+' nicht gefunden.'); end; FUNCTION ReadNumber(const s:string; var i:integer):real; var j:integer; begin j:=i; while s[j]<>' ' do dec(j); result:=StrToFloat(Copy(s,j+1,i-j)); while s[j]=' ' do dec(j); i:=j; end; PROCEDURE ReadLine(var v:TVektor); var s:string; i:integer; begin s:=Trim(list[line]); i:=Length(s); v.z:=ReadNumber(s,i); v.y:=ReadNumber(s,i); v.x:=ReadNumber(s,i); inc(line); end; PROCEDURE ReadRecord; var i:integer; begin ReadLine(data.n); for i:=1 to 3 do begin FindLine(recline,true); ReadLine(data.p[i]); end; SetLength(Dreiecke,Length(Dreiecke)+1); Dreiecke[High(dreiecke)]:=data; end; // var f:TextFile; i,j:integer; // nur zur Kontrolle benutzt begin Dreiecke:=nil; list:=TStringList.Create; try try list.text:=Clipboard.AsText; // oder List.LoadFromFile('Filename'); line:=0; while FindLine(recstart,false) do ReadRecord; except On E:Exception do begin ShowMessage(E.Message); Dreiecke:=nil; end; end; finally list.free; end; end; |
AW: wie kann ich bestimmte Infos aus Textdokument einlesen?
Morgen alle,
vielen Dank für die nette Antwort, Klaus! Ich werde später selbst auch mal probieren, ob die bei mir geht. l.g Lee |
AW: wie kann ich bestimmte Infos aus Textdokument einlesen?
Zitat:
Zwei Fragen an dich, Klaus: 1)für SetLength(Dreiecke,Length(Dreiecke)+1), Length(Dreiecke)+1 darf nur zwischen 0...255 sein, oder? Wenn ein 3D-Objekt z.B nur aus weniger als 255 Dreiecken besteht, ist es in Ordnung, aber wenn es aus 10000 Dreiecken besteht, wie mache ich mit dieser Funktion Dreiecke[256], Dreiecke[257]....bis Dreiecke[10000]? 2)wie kann man nach dem Einlesen der *.stl Datei und nach dem Schreiben aller Koordinaten in Variable "Dreiecke"(array of TDreieck) alle dort gespeicherte Koordinaten wieder in Clipboard kopieren? Damit kann ich alle in Variable "Dreiecke" gespeicherten Koordinaten mit den original Koordinaten mal vergleichen und überprüfen, ob es richtig ist. Danke für die Antwort im Voraus! l.g Lee |
AW: wie kann ich bestimmte Infos aus Textdokument einlesen?
Zitat:
Zu (1) : Wie kommst du auf die Beschränkung bei SetLength? Ein dynamisches Array kannst du High(integer) lang machen. Somit dürfte die einzige Beschränkung der verfügbare Speicherplatz sein. Zu (2) : So :
Delphi-Quellcode:
Mit CopyDreiecke(false) stellst du die Daten ins Clipboard, mit CopyDreiecke(true) in die Datei "Log.txt" im Programmverzeichnis.
PROCEDURE CopyDreiecke(tofile:boolean);
var list:TStrings; FUNCTION ToStr(v:real):String; begin result:=FloatToStrF(v,ffExponent,7,3)+' '; if result[1]<>'-' then result:=' '+result; end; PROCEDURE AddVector(const v:TVektor); type TxVector=Array[0..2] of real; var s,s1:string; i:integer; begin for i:=0 to High(TxVector) do s:=s+ToStr(TxVector(v)[i]); list.Add(s); end; var i,j:integer; begin list:=TStringList.Create; try try if Length(Dreiecke)=0 then raise Exception.Create('Dreiecke ist leer.'); for i:=0 to High(Dreiecke) do with Dreiecke[i] do begin AddVector(n); for j:=Low(p) to High(p) do AddVector(p[j]); list.Add(''); end; if tofile then list.SaveToFile(ExtractFilePath(ParamStr(0))+'Log.txt') else Clipboard.AsText:=List.Text; ShowMessage('fertig.'); except On E:Exception do ShowMessage(E.Message); end; finally list.free; end; end; |
AW: wie kann ich bestimmte Infos aus Textdokument einlesen?
Zitat:
Morgen Alle, alles klar, danke für die hilfreiche Antwort:) l.g Lee |
AW: wie kann ich bestimmte Infos aus Textdokument einlesen?
Hallo Klaus,
ich hab dein Programm vereinfacht, aber es funktioniert einfach nicht (die *.exe Datei kann nicht mehr geschlossen werden nach der Durchführung), es scheint, dass Fehler irgendwo aufgetreten sind (wegen unendlicher Schleife???).
Code:
könntest du vielleicht für mich die Fehler mal suchen und dann korrigieren?
type
TVektor = record x, y, z: real; end; TDreieck = record n: TVektor; // n ist Normalvektor p: array[1..3] of TVektor; //p hat Koordinaten von 3 Eckpunkten end; Var Dreiecke:Array of TDreieck; function ReadNumber(const s:string; var i:integer):real; var j:integer; begin j:=i; while s[j]<>' ' do dec(j); result:=StrToFloat(Copy(s,j+1,i-j)); while s[j]=' ' do dec(j); i:=j; end; procedure TForm1.Button2Click(Sender: TObject); const s1='facet normal'; s2='vertex'; s3='endsolid'; var s:string; //i:integer; j:integer; L:integer; List:TStrings; Line:integer; data:TDreieck; begin Dreiecke:=nil; List:=TStringList.Create; List.LoadFromFile(OpenDialog1.FileName); Line:=1; while (Copy(Trim(List[Line]),1,Length(s3))<>s3) do begin s:=Trim(List[Line]); L:=Length(s); if (Copy(s,1,Length(s1))=s1) then begin data.n.z:=ReadNumber(s,L); data.n.y:=ReadNumber(s,L); data.n.x:=ReadNumber(s,L); inc(Line); while (Copy(s,1,Length(s2))<>s2) do inc(Line); for j:=1 to 3 do begin data.p[j].z:=ReadNumber(s,L); data.p[j].y:=ReadNumber(s,L); data.p[j].x:=ReadNumber(s,L); inc(line); end; SetLength(Dreiecke,Length(Dreiecke)+1); Dreiecke[High(dreiecke)]:=data; end else inc(Line); end; end; Vielen Dank! lg Lee |
AW: wie kann ich bestimmte Infos aus Textdokument einlesen?
Zitat:
eigentlich verspüre ich keine große Lust den Korrektor zu spielen, wenn jemand, dem ich einen perfekt funktionierenden Code lieferte, diesen vermeintlich "vereinfacht" und in nicht funktionierenden Code umwandelt. Hab's mir trotzdem mal angeschaut, und ohne viel zu suchen tippe ich darauf dass das Programm in der Zeile while (Copy(s,1,Length(s2))<>s2) do inc(Line); festhängt. Warum ?! Weil du zwar korrekt den Zeilenzähler erhöhst, aber die neue Zeile nicht in s stellst. In der Zeile while (Copy(s,1,Length(s2))<>s2) do inc(Line); prüfst du gegen s und das enthält "facet normal ...." Also wird "vertex" nicht gefunden, und wenn du dann noch die Überlaufprüfung abgeschaltet hast .... Was mir noch auffiel: Du gibst List nicht frei. Du sprachst in einem der Beiträge von 10000 Dreiecken. Für 1 Dreieck werden ca. 270 Chars gebraucht für 10000 Dreiecke also 2.7 MB (oder 5.4 MB bei WideChars). Irgendwann kriegst du dann eine Out of Memory Exception. Das von mir gewählte Konstrukt sorgt dafür, dass 1) list immer freigegeben wird 2) Dreiecke auf nil gesetzt wird, wenn ein Fehler auftritt. Deine "Vereinfachung" sorgt für 1) unsicheren Code 2) Memory Leaks Denk mal darüber nach, ob solch eine Vereinfachung wirklich sinnvoll ist. |
AW: wie kann ich bestimmte Infos aus Textdokument einlesen?
Liste der Anhänge anzeigen (Anzahl: 2)
[QUOTE=Amateurprofi;1168431]
Zitat:
Ich hab dein erstes Programm (stl-Datei einlesen) gerade probiert, aber leider hab ich folgende Fehlermeldungen bekommen. ![]() ![]() Wegen Fehlermeldung von "PROCEDURE TMain.Test;" (in erstem Bild) hab ich folgende code, die eigentlich zu Procedure TMain.Test gehört, in "procedure TForm1.Button2Click(Sender: TObject);" geschrieben. const recstart='facet normal'; recline='vertex'; var list:TStrings; line:integer; data:TDreieck; Dann hab ich das Programm wieder durchgeführt durch Drücken von Button2 "Koordinaten der STL einlesen", bekomme ich zweite Fehlermeldung (in 2. Bild) |
AW: wie kann ich bestimmte Infos aus Textdokument einlesen?
Folgende ist mein Programm (code von dir gemacht), durch Drücken von Button2 werden STL-Datei eingelesen, und durch Drücken von Button3 wird die Liste in Log.txt gespeichert.
Delphi-Quellcode:
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, GLScene, GLMisc, GLVectorFileObjects, GLWin32Viewer, GLFileSTL, Menus, ComCtrls, StdCtrls, ExtCtrls, GLTexture, GLObjects, GLHUDObjects; type TVektor = record x, y, z: real; end; TDreieck = record n: TVektor; p: array[1..3] of TVektor; end; . . . Var Form1: TForm1; Dreiecke:array of TDreieck; . . . //PROCEDURE TMain.Test; <--bekomme ich Fehlermeldun FUNCTION FindLine(const s:string; raiseerr:boolean):boolean; var line:integer; list:TStrings; begin while (line<list.count) and (Copy(Trim(list[line]),1,Length(s))<>s) do inc(line); if line<list.count then result:=true else if not raiseerr then result:=false else raise Exception.Create(s+' nicht gefunden.'); end; FUNCTION ReadNumber(const s:string; var i:integer):real; var j:integer; begin j:=i; while s[j]<>' ' do dec(j); result:=StrToFloat(Copy(s,j+1,i-j)); while s[j]=' ' do dec(j); i:=j; end; PROCEDURE ReadLine(var v:TVektor); var s:string; i:integer; list:TStrings; line:integer; begin s:=Trim(list[line]); i:=Length(s); v.z:=ReadNumber(s,i); v.y:=ReadNumber(s,i); v.x:=ReadNumber(s,i); inc(line); end; PROCEDURE ReadRecord; const recline='vertex'; var i:integer; data:TDreieck; begin ReadLine(data.n); for i:=1 to 3 do begin FindLine(recline,true); ReadLine(data.p[i]); end; SetLength(Dreiecke,Length(Dreiecke)+1); Dreiecke[High(dreiecke)]:=data; end; // var f:TextFile; i,j:integer; // nur zur Kontrolle benutzt PROCEDURE CopyDreiecke(tofile:boolean); var list:TStrings; FUNCTION ToStr(v:real):String; begin result:=FloatToStrF(v,ffExponent,7,3)+' '; if result[1]<>'-' then result:=' '+result; end; PROCEDURE AddVector(const v:TVektor); type TxVector=Array[0..2] of real; var s:string; i:integer; list:TStrings; begin for i:=0 to High(TxVector) do s:=s+ToStr(TxVector(v)[i]); list.Add(s); end; var i,j:integer; begin list:=TStringList.Create; try try if Length(Dreiecke)=0 then raise Exception.Create('Dreiecke ist leer.'); for i:=0 to High(Dreiecke) do with Dreiecke[i] do begin AddVector(n); for j:=Low(p) to High(p) do AddVector(p[j]); list.Add(''); end; if tofile then list.SaveToFile(ExtractFilePath(ParamStr(0))+'Log.txt'); //else Clipboard.AsText:=List.Text; ShowMessage('fertig.'); except On E:Exception do ShowMessage(E.Message); end; finally list.free; end; end; procedure TForm1.Button3Click(Sender: TObject); begin CopyDreiecke(true); end; procedure TForm1.Button2Click(Sender: TObject); const recstart='facet normal'; recline='vertex'; var list:TStrings; line:integer; data:TDreieck; begin Dreiecke:=nil; list:=TStringList.Create; try try //list.text:=Clipboard.AsText; List.LoadFromFile(OpenDialog1.FileName); line:=0; while FindLine(recstart,false) do ReadRecord; except On E:Exception do begin ShowMessage(E.Message); Dreiecke:=nil; end; end; finally list.free; end; end; end. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:11 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz