home *** CD-ROM | disk | FTP | other *** search
- {$N+ } { 8087 Math Coprocessor on }
- {$E+ } { include 8087 emulation }
- {$V- } { relaxed VAR-string check }
-
- UNIT AcadDXF; { Der Autocad DXF-Interpreter Version 1.2 30.6.1991 }
-
- INTERFACE
-
- TYPE DXFErr = (ok, filenotfound, syntax, eof_reached);
-
- function InterpretDXF(name : string):DXFErr;
- Procedure InitDXF;
-
- { Der DXF-Interpreter bedient sich der graphischen Primitive des Kernels.
- Vor der ersten Benutzung muß einmal InitDXF aufgerufen werden, um alle
- Systemvariablen zu initialisieren und die Tabellen zu löschen.
- Die Funktion InterpretDXF zeichnet eine DXF-Grafik in den aktuell ge-
- setzten Viewport. Als name ist der volle Suchpfad ohne die Dateiexten-
- sion DXF.
- Zurückgeliefert wird ein Fehlercode:
-
- ok : Die Grafik wurde erfolgreich erstellt.
- filenotfound : Unter dem angegebenen Namen existiert keine Datei.
- syntax : Die Zeichnung wurde abgebrochen, weil ein
- fataler syntaktischer Fehler erkannt wurde.
- eof_reached : Die DXF-Datei enthält nicht die EOF-Markierung.
-
- }
-
- IMPLEMENTATION
-
- USES Kernel;
-
- CONST NLayer = 32; { Anzahl der von uns verwalteten Lagen }
- NLtypes = 16; { Anzahl der Linientypen }
- MaxEle = 8; { Anzahl der Strichelemente pro Linie }
-
- TYPE NameStr = String[15];
-
- Layer = record
- name : NameStr; { Name des Layers }
- flags : integer;
- color : integer; { Farbe ordinal }
- ltype : NameStr; { Linienstil }
- end;
-
- Ltype = record
- name : NameStr; { Name des Linientyps }
- desc : NameStr; { Beschreibung }
- flags : integer; { Flags }
- just : integer; { Justierungscode }
- nE : integer; { Anzahl Elemente }
- Totlen: double; { Gesamtlänge Linie }
- Eles : array[1..MaxEle] of double;{ Elemente }
- end;
-
- VAR f: text;
-
- Layers : array[1..NLayer] of Layer; { Die Layer-Liste }
- Ltypes : array[1..NLtypes] of Ltype; { Die Linientypen }
-
- PolyLayer : string; { Daten für Polylinien : }
- PolyMode : integer; { -1 = aus, 0 = nicht init. , 1 = init }
- PolyFirstX: double;
- PolyFirstY: double;
- PolyLastX : double;
- PolyLastY : double;
-
- Aspect : double;
-
- { Autocad-Systemvariablen }
-
- LIMMIN_X : double; { Zeichnungsgrenzen links unten }
- LIMMIN_Y : double;
- LIMMAX_X : double; { Zeichnungsgrenzen rechts oben }
- LIMMAX_Y : double;
- EXTMIN_X : double; { tatsächliche Grenze links unten }
- EXTMIN_Y : double;
- EXTMAX_X : double; { tatsächliche Grenze rechts oben }
- EXTMAX_Y : double;
- VIEWCTR_X : double; { Zentrum des Ausschnitts }
- VIEWCTR_Y : double;
- TDCREATE : double; { Datum der Erstellung }
- TDUPDATE : double; { Datum der letzten Modifikation }
- PDMODE : integer;
- PDSIZE : double;
-
-
- CONST NVars = 9; { Schlüsselworte aus Headerblock }
- SysWords : array[1..NVars] of NameStr =
- ('$LIMMIN' , '$LIMMAX' , '$EXTMIN' , '$EXTMAX',
- '$VIEWCTR' , '$TDCREATE' , '$TDUPDATE', '$PDMODE',
- '$PDSIZE');
-
- NEnt = 10; { Schlüsselworte aus Entityblock }
- EntityWords : array[1..NEnt] of NameStr =
- ('ENDSEC', 'LINE' , 'ARC' , 'POINT',
- 'CIRCLE', 'TEXT' , 'POLYLINE', 'VERTEX',
- 'SEQEND', 'SOLID');
-
- NTab = 4; { Schlüsselworte aus Tabellenblock}
- TabWords : array[1..NTab] of NameStr =
- ('LTYPE' , 'LAYER' , 'STYLE', 'VIEW');
-
-
- procedure InitSysVars; { Initialisierung aller Systemvariablen }
- Var i,j : integer;
- begin
- Aspect := 3*PortMaxX / (4*PortMaxY); { Höhen/Breitenverhältnis }
- PolyLayer := ''; { PolyLinemodus aus }
- PolyMode := -1;
- PolyFirstX:= 0;
- PolyLastX := 0;
- PolyLastX := 0;
- PolyLastY := 0;
- LIMMIN_X := 0;
- LIMMIN_Y := 0;
- LIMMAX_X := 15;
- LIMMAX_Y := 11.25;
- EXTMIN_X := 0;
- EXTMIN_Y := 0;
- EXTMAX_X := 12;
- EXTMAX_Y := 9;
- VIEWCTR_X := 5;
- VIEWCTR_Y := 5;
- TDCREATE := 0;
- TDUPDATE := 0;
- PDMODE := 0;
- PDSIZE := 0.1;
-
- for i := 1 to NLtypes do
- With Ltypes[i] do
- begin
- name := '';
- desc := '';
- just := 0;
- totlen := 0;
- nE := 0;
- for j := 1 to MaxEle do
- Eles[j] := 0; { Strichelemente löschen }
- end;
- end;
-
-
- procedure AddLType(lt: LType); { Linientyp hinzufügen }
- Var i : integer;
- begin
- i := 1;
- while (ltypes[i].name <> '') and (i < NLtypes) do
- i := succ(i);
- if Ltypes[i].name = '' then
- begin
- ltypes[i] := lt;
- end;
- end;
-
-
- procedure AddLayer(Lname: NameStr; Lflags,Lcolor : integer; Lltype : NameStr);
- Var i : integer;
- begin
- i := 1;
- while (Layers[i].name <> '') and (i < NLayer) do
- i := succ(i); { suche einen freien Eintrag }
- if Layers[i].name = '' then
- With Layers[i] do
- begin
- name := LName;
- flags := Lflags;
- color := Lcolor;
- ltype := LLtype;
- end;
- end;
-
-
- procedure RemoveLayer(Lname: NameStr);
- Var i : integer;
- begin
- i := 1;
- while (Layers[i].name <> Lname) and (i < NLayer) do
- i := succ(i);
- if Layers[i].name = LName then
- With Layers[i] do
- begin
- name := '';
- flags := 0;
- color := 0;
- ltype := '';
- end;
- end;
-
-
- function GetLayerColor(Var LName : NameStr):integer;
- Var i : integer;
- begin
- i := 1;
- while (Layers[i].name <> Lname) and (i < NLayer) do
- i := succ(i);
- if Layers[i].name = LName then
- GetLayerColor := Layers[i].color
- else
- GetLayerColor := 1;
- end;
-
-
- Procedure InitDXF;
- Var AktLine : String;
- Name,LineType : String;
- Color : LongInt;
- i : integer;
- Begin
- for i := 1 to NLayer do
- With Layers[i] do { Alle Layer löschen }
- begin
- name := '';
- flags := 0;
- color := 0;
- ltype := '';
- end;
- If GetInitFileListFirst('AutoCad','Layer',AktLine) Then
- Repeat
- If GetParaName(AktLine,Name) and GetParaInteger(AktLine,Color) Then
- Begin
- if Not GetParaName(AktLine,LineType) Then
- LineType := 'CONTINUOUS';
- AddLayer(Name,0,Color,LineType);
- End;
- Until Not GetInitFileListNext('Layer',AktLine)
- Else AddLayer('0',0,15,'CONTINUOUS');
- End;
-
-
- { Scale und XScale nehmen die Transformation der Autocad-Koordinaten in das
- einfache Kernel-Koordinatensystem vor. Die Verzerrung durch das Seiten/
- Höhenverhältnis des Bildschirms wird nicht berücksichtigt. }
-
- procedure Scale(Var x1,y1 : double);
- begin
- x1 := (PortMaxX * (x1-LIMMIN_X)) / (LIMMAX_X-LIMMIN_X);
- y1 := PortMaxY - ((PortMaxY * (y1-LIMMIN_Y)) / (LIMMAX_Y-LIMMIN_Y));
- end;
-
-
- procedure XScale(Var r: double);
- begin
- r := (PortMaxX * r) / (LIMMAX_X-LIMMIN_X);
- end;
-
- procedure YScale(Var r: double);
- begin
- r := (PortMaxY * r) / (LIMMAX_Y-LIMMIN_Y);
- end;
-
-
- { Die Elementar-Prozeduren von Autocad arbeiten im Autocad-Koordinatensystem
- und bedienen sich der Skalierungsprozeduren }
-
- procedure DXFLine(x1,y1,x2,y2: double; layer: NameStr); { Linie }
- begin
- Scale(x1,y1);
- Scale(x2,y2);
- Line(Integer(Round(x1)),Integer(Round(y1)),
- Integer(Round(x2)),Integer(Round(y2)),GetLayerColor(layer));
- end;
-
-
- procedure DXFArc(x,y,aa,ae,r : double; layer: NameStr); { Kreissegment }
- begin
- Scale(x,y);
- YScale(r);
- Arc(Integer(Round(x)),Integer(Round(y)),
- Integer(Round(aa)),Integer(Round(ae)),
- Integer(Round(r)),GetLayerColor(layer));
- end;
-
-
- procedure DXFPoint(x,y : double; layer: NameStr); { Punkt }
- Var len : double;
- begin
- len := PDSIZE / 2;
- Case PDMODE of
- 0,1 : begin
- Scale(x,y);
- SetPoint(Integer(Round(x)),Integer(Round(y)),GetLayerColor(layer));
- end;
- 2 : begin
- DXFLine(x-len,y ,x+len,y,layer);
- DXFLine(x ,y-len,x ,y+len,layer);
- end;
- 3 : begin
- DXFLine(x-len,y-len,x+len,y+len,layer);
- DXFLine(x+len,y-len,x-len,y+len,layer);
- end;
- end;
- end;
-
-
- procedure DXFCircle(x,y,r : double; layer: NameStr); { Vollkreis }
- begin
- Scale(x,y);
- XScale(r);
- Circle(Integer(Round(x)),Integer(Round(y)),
- Integer(Round(r)),GetLayerColor(layer));
- end;
-
-
- procedure DXFText(x,y,h : double; str: string; layer: NameStr); { Text }
- Var X0, Y0, FakX, FakY : Integer;
- begin
- y := y + h/4;
- Scale(x,y);
- YScale(h);
- X0 := Integer(Round(x));
- Y0 := Integer(Round(y));
- FakX := Integer(Round(h));
- FakY := Integer(Round(h));
- DrawText(X0,Y0,FakX,FakY,Str,GetLayerColor(layer));
- End;
-
-
- { GetNextGroup liest aus der DXF-Datei die nächste Gruppe und liefert als
- direktes Ergebnis den Gruppencode zurück. Je nach Art der Gruppe (Text,
- integer oder real ) wird einer der VAR-Parameter belegt. Bei Fehlern
- wird 99 zurückgeliefert. }
-
- Function GetNextGroup(Var str: string; Var re: double; Var int: integer):integer;
- Var line: string;
- code: integer;
- err : integer;
- i : integer;
- begin
- if eof(f) then GetNextGroup := 99 { Fehlercode }
- else
- begin
- readln(f,line); { Gruppencode lesen }
- val(line, code, err);
- GetNextGroup := code;
- if err = 0 then
- begin
- readln(f,line);
- Case code of
- 0.. 9 : str := line;
- 10..59 : val(line, re, err);
- 60..79 : val(line, int, err);
- end;
- if err <> 0 then GetNextGroup := 99;
- end
- else GetNextGroup := 99;
- end;
- end;
-
- { Die Autocad DXF-Datei besteht aus vier Teilen, die grösstenteils fakultativ
- sind. Für jeden Teil der Datei existiert eine eigene Prozedur zur Bear-
- beitung. }
-
- procedure ProcHeader; { Verarbeitet den Abschnitt "Header" }
- Var code : integer;
- str : string;
- re : double;
- re1 : double;
- re2 : double;
- int : integer;
- code2: integer;
- index: integer;
- begin
- repeat
- Code := GetNextGroup(str, re, int);
- if code = 9 then { Autocad-Systemvariable }
- begin
- index := 1;
- while (SysWords[index] <> str) and (index < NVars) do
- index := succ(index);
- if SysWords[index] = str then
- Case index of
-
- 1 : begin
- code := GetNextGroup(str, re1, int);
- code2 := GetNextGroup(str, re2, int);
- if (code = 10) and (code2 = 20) then
- begin
- LIMMIN_X := re1;
- LIMMIN_Y := re2;
- end;
- end;
-
- 2 : begin
- code := GetNextGroup(str, re1, int);
- code2 := GetNextGroup(str, re2, int);
- if (code = 10) and (code2 = 20) then
- begin
- LIMMAX_X := re1 ;
- LIMMAX_Y := re2 ;
- end;
- end;
-
- 3 : begin
- code := GetNextGroup(str, re1, int);
- code2 := GetNextGroup(str, re2, int);
- if (code = 10) and (code2 = 20) then
- begin
- EXTMIN_X := re1;
- EXTMIN_Y := re2;
- end;
- end;
-
- 4 : begin
- code := GetNextGroup(str, re1, int);
- code2 := GetNextGroup(str, re2, int);
- if (code = 10) and (code2 = 20) then
- begin
- EXTMAX_X := re1;
- EXTMAX_Y := re2;
- end;
- end;
-
- 5 : begin
- code := GetNextGroup(str, re1, int);
- code2 := GetNextGroup(str, re2, int);
- if (code = 10) and (code2 = 20) then
- begin
- VIEWCTR_X := re1;
- VIEWCTR_Y := re2;
- end;
- end;
-
- 6 : begin
- code := GetNextGroup(str, re1, int);
- if (code = 10) then TDCREATE := re1;
- end;
-
- 7 : begin
- code := GetNextGroup(str, re1, int);
- if (code = 10) then TDUPDATE := re1;
- end;
-
- 8 : begin
- code := GetNextGroup(str, re1, int);
- if code = 70 then PDMODE := int;
- end;
-
- 9 : begin
- code := GetNextGroup(str, re1, int);
- if code = 40 then PDSIZE := re1;
- end;
-
- end; { Case }
- end;
- until (code = 0) or (code = 99); { Ende bei Code 0 oder Err }
- end;
-
-
- procedure ProcTables; { Verarbeitet den Abschnitt "Tables" }
- Var Code : integer;
- str : string;
- re : double;
- int : integer;
- index : integer;
-
- procedure ProcLtype; { Subblock A "LTYPE" }
- Var code : integer;
- str : string;
- re : double;
- int : integer;
- i : integer;
- lt : LType;
- begin
- code := GetNextGroup(str,re,int); { Anzahl Einträge überlesen }
-
- repeat
- code := GetNextGroup(str,re,int);
- if (code = 0) and (str = 'LTYPE') then
- begin
- code := GetNextGroup(lt.name,re,int);
- code := GetNextGroup(str,re,lt.flags);
- code := GetNextGroup(lt.desc,re,int);
- code := GetNextGroup(str,re,lt.just);
- code := GetNextGroup(str,re,lt.nE);
- code := GetNextGroup(str,lt.totlen,int);
- if lt.nE > MaxEle then lt.nE := MaxEle;
- for i := 1 to lt.nE do
- code := GetNextGroup(str,lt.Eles[i],int);
-
- if code = 40 then
- AddLtype(lt);
- end;
- until (code = 0) and ((str = 'ENDTAB') or (str = 'EOF'));
- end;
-
- procedure ProcLayer; { Subblock B "LAYER" }
- Var code : integer;
- str : string;
- re : double;
- int : integer;
- name : NameStr;
- ltyp : NameStr;
- color: integer;
- flags: integer;
- begin
- code := GetNextGroup(str,re,int); { Anzahl Einträge überlesen }
-
- repeat
- code := GetNextGroup(str,re,int);
- if (code = 0) and (str = 'LAYER') then
- begin
- code := GetNextGroup(name,re,int);
- code := GetNextGroup(str,re,flags);
- code := GetNextGroup(str,re,color);
- code := GetNextGroup(ltyp,re,int);
- if code = 6 then
- AddLayer(name,flags,color,ltyp);
- end;
- until (code = 0) and ((str = 'ENDTAB') or (str = 'EOF'));
- end;
-
- procedure ProcStyle; { Subblock C "STYLE" }
- begin
- { für zukünftige Erweiterungen }
- end;
-
- procedure ProcView; { Subblock D "View" }
- begin
- { für zukünftige Erweiterungen }
- end;
-
-
-
- begin
- repeat
- repeat { Suche die nächste Tabelle }
- Code := GetNextGroup(str, re, int);
- until (code = 99) or ((code = 0) and ((str='TABLE') or (str = 'ENDSEC')));
- if (code = 0) and (str = 'TABLE') then
- begin { eine von 4 Tabellen gefunden }
- Code := GetNextGroup(str,re,int);
- if Code = 2 then
- begin
- index := 1;
- while (TabWords[index] <> str) and (index < NTab) do
- index := succ(index);
- if TabWords[index] = str then
- Case index of
- 1 : ProcLtype; { Tabelle "LTYPE" für Linientypen }
- 2 : ProcLayer; { Tabelle "LAYER" für Layertypen }
- 3 : ProcStyle; { Tabelle "STYLE" für Schriftstile }
- 4 : ProcView; { Tabelle "View" für Ausschnitte }
- end; { Case }
- end;
- end;
- until (Code = 99) or ((code = 0) and (str = 'ENDSEC'));
- end;
-
- procedure ProcBlocks; { Verarbeitet den Abschnitt "Blocks" }
- begin
- { für zukünftige Erweiterungen }
- end;
-
- procedure ProcEntities; { Verarbeitet den Abschnitt "Entities" }
- Var code : integer;
- str : string;
- re : double;
- re1 : double;
- re2 : double;
- re3 : double;
- re4 : double;
- re5 : double;
- int : integer;
- code2: integer;
- index: integer;
- ready: boolean;
- lay : NameStr;
- i : integer;
- FirstX : double;
- FirstY : double;
- begin
- ready := false;
- repeat
- Code := GetNextGroup(str, re, int);
- if code = 0 then
- begin
- index := 1;
- for i := 1 to length(str) do str[i] := Upcase(str[i]);
- while (EntityWords[index] <> str) and (index < NEnt) do
- index := succ(index);
- if EntityWords[index] = str then
- Case index of
- 1 : ready := true; { ENDSEC erreicht }
-
- 2 : begin { Line }
- code := GetNextGroup(lay, re5, int);
- code := GetNextGroup(str, re1, int);
- if code = 62 then
- { Farbe nicht von Layer }
- code := GetNextGroup(str, re1, int);
-
- code := GetNextGroup(str, re2, int);
- code := GetNextGroup(str, re3, int);
- code2 := GetNextGroup(str, re4, int);
- if (code = 11) and (code2 = 21) then
- DXFLine(re1,re2,re3,re4,lay)
- else
- write(#7);
- end;
-
- 3 : begin { Arc }
- code := GetNextGroup(lay, re5, int);
- code := GetNextGroup(str, re1, int);
- code := GetNextGroup(str, re2, int);
- code := GetNextGroup(str, re3, int);
- code := GetNextGroup(str, re4, int);
- code2 := GetNextGroup(str, re5, int);
- if (code = 50) and (code2 = 51) then
- DXFArc(re1,re2,re4,re5,re3,lay);
- end;
-
- 4 : begin { Point }
- code := GetNextGroup(lay,re1,int);
- code := GetNextGroup(str,re1,int);
- if code = 62 then
- code := GetNextGroup(str, re1, int);
- code2:= GetNextGroup(str,re2,int);
- if (code = 10) and (code2 = 20) then
- DXFpoint(re1,re2,lay);
- end;
-
- 5 : begin { Circle }
- code := GetNextGroup(lay,re1,int);
- code := GetNextGroup(str,re1,int);
- code := GetNextGroup(str,re2,int);
- code2:= GetNextGroup(str,re3,int);
- if (code = 20) and (code2 = 40) then
- DXFCircle(re1,re2,re3,lay);
- end;
-
- 6 : begin { Text }
- code := GetNextGroup(lay,re1,int);
- code := GetNextGroup(str,re1,int);
- code := GetNextGroup(str,re2,int);
- code := GetNextGroup(str,re3,int);
- code2:= GetNextGroup(str,re4,int);
- if (code = 40) and (code2 = 1) then
- DXFText(re1,re2,re3,str,lay);
- end;
-
- 7 : begin { Polyline }
- code := GetNextGroup(lay,re1,int);
- { code2:= GetNextGroup(str,re1,int); }
- { if code = 8 then }
- begin
- PolyLayer := lay;
- PolyMode := 0;
- end;
- end;
-
- 8 : begin { Vertex }
- code := GetNextGroup(lay,re1,int);
- code := GetNextGroup(str,re1,int);
- if code = 62 then
- code := GetNextGroup(str, re1, int);
- code2:= GetNextGroup(str,re2,int);
- if (code = 10) and (code2=20) then
- Case PolyMode of
- 0 : begin { erster Punkt }
- PolyLastX := re1;
- PolyLastY := re2;
- PolyFirstX:= re1;
- PolyFirstY:= re2;
- PolyMode := 1;
- end;
-
- 1 : begin { weiterer Punkt }
- DXFLine(PolyLastX,PolyLasty,re1,re2,PolyLayer);
- PolyLastX := re1;
- PolyLastY := re2;
- end;
- end;
- end;
-
- 9 : begin
- { code := GetNextGroup(lay,re1,int); }
- PolyLayer := '';
- PolyMode := -1; { abschalten }
- { DXFLine(PolyFirstX,PolyFirstY,PolyLastX,PolyLastY,PolyLayer);}
- end;
-
- 10 : begin { Solid }
- code := GetNextGroup(lay,re1,int); { layer }
- code2:= GetNextGroup(str,re1,int);
- code2:= GetNextGroup(str,re2,int); { P1 }
- FirstX := re1;
- FirstY := re2;
- PolyLastX := re1;
- PolyLastY := re2;
- code := GetNextGroup(str,re1,int); { P2 }
- code := GetNextGroup(str,re2,int);
- DXFLine(PolyLastX,PolyLasty,re1,re2,lay);
- PolyLastX := re1;
- PolyLastY := re2;
- code := GetNextGroup(str,re1,int); { P3 }
- code := GetNextGroup(str,re2,int);
- DXFLine(PolyLastX,PolyLasty,re1,re2,lay);
- PolyLastX := re1;
- PolyLastY := re2;
- code := GetNextGroup(str,re1,int);
- code := GetNextGroup(str,re2,int); { P4 }
- if (re1 = PolyLastX) and (re2 = PolyLastY)
- then
- begin
- re1 := FirstX;
- re2 := FirstY;
- end;
- DXFLine(PolyLastX,PolyLasty,re1,re2,lay);
- end;
- else write(#7);
- end; { Case }
- end;
- until (code = 99) OR ready; { Ende bei Code 0 oder Err }
- end;
-
-
- function InterpretDXF(name : string):DXFErr;
- Var ready : boolean;
- re : double;
- int : integer;
- str : string;
- code : integer;
-
- begin
- HideMouse;
- ready := false;
- InitSysVars;
- assign(f,name);
- {$i- }
- reset(f);
- {$i+ }
- if ioresult <> 0 then InterpretDXF := filenotfound
- else
- begin
- InterpretDXF := ok;
- repeat
- repeat
- Code := GetNextGroup(str, re, int);
- until (code = 0) or (code = 99); { aufsynchronisieren }
- if code = 99 then InterpretDXF := syntax
- else
- begin
- if str = 'EOF' then ready := true;
- if str = 'SECTION' then
- begin
- Code := GetNextGroup(str,re,int);
- if Code = 2 then
- begin
- if str = 'HEADER' then ProcHeader;
- if str = 'TABLES' then ProcTables;
- if str = 'BLOCKS' then ProcBlocks;
- If str = 'ENTITIES'then ProcEntities;
- end;
- end;
- end;
- until (Code = 99) or ready;
- if not ready then InterpretDXF := syntax;
- close(f);
- end;
- ShowMouse;
- end;
-
-
- end.
-
-
- { Revisionen :
-
- 1.0 7.12.1990
- 1.1 15.12.1990 Polylinien sind jetzt robuster (Corel Draw Import)
- 1.2 30. 6.1991 Endung .dxf wird nicht mehr angehangen
-
- }