📄 dxf_read.pas
字号:
///////////////////////////////////////////////////////////////////////////////
// //
// DXF File reader object/code //
// ㎎ohn Biddiscombe //
// Rutherford Appleton Laboratory, UK //
// j.biddiscombe@rl.ac.uk //
// DXF code release 3.0 - July 1997 //
// //
///////////////////////////////////////////////////////////////////////////////
// //
// Thanks very much to John F Herbster for the original DXF reader class //
// that got this started --- extract from his header follows... //
// //
// Pgm. 07/14/95 by John F Herbster, CIS:72714,3445, Houston, TX. //
// for Rick Rogers (CIS:74323,3573). //
// //
///////////////////////////////////////////////////////////////////////////////
unit DXF_read;
interface
uses
{ Borland }
Windows,SysUtils,StdCtrls,ComCtrls,Dialogs,Classes,Graphics,
{ Mine }
DXF_structs,DXF_Utils,Thinkbox,Math;
const
message_delay_ms = 1500;
EOL = #13#10;
// Thanks to Ian L. Kaplan, whose code contained these ID's
// I've changed a few names here and there
const
DXF_start = 0;
DXF_text_def = 1;
DXF_name = 2;
DXF_text_prompt = 3;
DXF_othername2 = 4;
DXF_entity_handle = 5;
DXF_line_type = 6;
DXF_text_style = 7;
DXF_layer_name = 8;
DXF_var_name = 9;
DXF_primary_X = 10; DXF_primary_Y = 20;
DXF_primary_Z = 30;
DXF_other_X_1 = 11; DXF_other_Y_1 = 21;
DXF_other_Z_1 = 31;
DXF_other_X_2 = 12; DXF_other_Y_2 = 22;
DXF_other_Z_2 = 32;
DXF_other_X_3 = 13; DXF_other_Y_3 = 23;
DXF_other_Z_3 = 33;
DXF_elevation = 38;
DXF_thickness = 39;
DXF_floatval = 40;
DXF_floatvals1 = 41;
DXF_floatvals2 = 42;
DXF_floatvals3 = 43;
DXF_repeat = 49;
DXF_angle1 = 50; DXF_angle2 = 51;
DXF_angle3 = 52; DXF_angle4 = 53;
DXF_angle5 = 54; DXF_angle6 = 55;
DXF_angle7 = 56; DXF_angle8 = 57;
DXF_angle9 = 58;
DXF_visible = 60;
DXF_colornum = 62;
DXF_entities_flg = 66;
DXF_ent_ident = 67;
DXF_view_state = 69;
DXF_70Flag = 70;
DXF_71Flag = 71; DXF_72Flag = 72;
DXF_73Flag = 73; DXF_74Flag = 74;
DXF_extrusionx = 210;
DXF_extrusiony = 220;
DXF_extrusionz = 230;
DXF_comment = 999;
///////////////////////////////////////////////////////////////////////////////
// DXF_Reader class definition
///////////////////////////////////////////////////////////////////////////////
Const
MaxSizeOfBuf = 4096;
type
tCharArray = array [0..MaxSizeOfBuf-1] of char;
type
abstract_entity = class;
DXF_Reader = class
private
// used when reading data from the file
IO_chan : file;
SizeOfBuf : integer;
num_in_buf : integer;
ii : integer;
EC,fCode : integer;
pBuf : ^tCharArray;
Line_num : longint;
fLine : shortstring;
progress : TProgressBar;
// useful bits to make parsing easier...
file_pos : integer;
marked_pos : integer;
backflag : boolean;
procedure go_back_to_last(code:integer; str:shortstring);
procedure mark_position;
procedure goto_marked_position;
//
procedure go_back_to_start;
function NextGroupCode: integer;
function ValStr: shortstring;
function ValDbl: double;
function ValInt: integer;
function code_and_string(var group:integer; var s:string) : boolean;
function code_and_double(var group:integer; var d:double) : boolean;
function read_2Dpoint(var p1:Point3D) : boolean;
function skip_upto_section(name:string) : boolean;
// lowest level read function
function read_entity_data(ent:abstract_entity) : boolean;
function read_generic(var layer:integer) : abstract_entity;
// we can read most entities with this one
function general_purpose_read(obj_type:TClass; var entity:DXF_Entity; var layer:integer) : boolean;
// inserts/polylines need a little more complexity
function read_insert(var entity:DXF_Entity; var layer:integer) : boolean;
function read_polyline(var entity:DXF_Entity; var layer:integer) : boolean;
// this calls the others above
function read_entity(s,endstr:string; var entity:DXF_Entity; var layer:integer) : boolean;
public
// Extents in (x,y) of the dataset
min_extents : Point3D;
max_extents : Point3D;
// We will read the Entities in the layers into this list
DXF_Layers : TList;
colour_BYLAYER : boolean;
skipped : TStrings;
// Constructors and destructors
Constructor Create (const aName: shortstring);
Destructor Destroy; override;
// Header section
function move_to_header_section : boolean;
function read_header : boolean;
function get_min_extent : Point3D;
function get_max_extent : Point3D;
// Blocks section
function move_to_blocks_section : boolean;
function read_blocks : boolean;
function read_block : boolean;
function block_list : Entity_List;
// Tables section
function move_to_tables_section : boolean;
function read_tables : boolean;
function read_layer_information : boolean;
function read_vport_information : boolean;
function layer_num(layername:string) : integer;
// Entities section
function move_to_entity_section : boolean;
function read_entities : boolean;
// These are the main routines to use
function read_file : boolean;
function remove_empty_layers : boolean;
function release_control_of_layers : TList;
procedure set_skipped_list(s:TStrings);
end;
///////////////////////////////////////////////////////////////////////////////
// This is a simple class used only during file reads, it should not be used
// as a base for any objects.
// It is to allow all entities to be read using the same basic structure
// even though they all use different group codes
// Add extra group codes if you need to recognize them
///////////////////////////////////////////////////////////////////////////////
abstract_entity = class
p1,p2,p3,p4 : Point3D;
rad_hgt : double;
angle1,angle2 : double;
fv1,fv2,fv3 : double;
thickness : double;
colour : integer;
flag_70,flag_71,flag_72,flag_73,flag_74 : integer;
attflag : integer;
namestr,tagstr,promptstr : string;
layer : string;
elev : double;
OCS_Z : Point3D;
procedure clear;
end;
///////////////////////////////////////////////////////////////////////////////
// DXF file read exceptions will be this type
///////////////////////////////////////////////////////////////////////////////
type
DXF_read_exception = class(Exception)
line_number : integer;
constructor create(err_msg:string; line:integer);
end;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// implementation
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
implementation
///////////////////////////////////////////////////////////////////////////////
// abstract_entity implementation
// used when reading vertexes - just to make sure all flags are reset
// quicker than using create/destroy for each vertex.
///////////////////////////////////////////////////////////////////////////////
procedure abstract_entity.clear;
begin
InitInstance(self);
end;
///////////////////////////////////////////////////////////////////////////////
// DXFReader implementation
///////////////////////////////////////////////////////////////////////////////
Constructor DXF_Reader.Create (const aName: shortstring);
begin
Inherited Create;
AssignFile(IO_chan,aName);
Reset(IO_chan,1);
SizeOfBuf := MaxSizeOfBuf;
GetMem(pBuf,SizeOfBuf);
DXF_Layers := TList.Create;
colour_BYLAYER := false;
Line_num := 0;
backflag := false;
progress := Thinking_box.bar;
progress.position := 0;
progress.max := FileSize(IO_chan) div MaxSizeOfBuf;
min_extents := origin3D;
max_extents := origin3D;
end;
destructor DXF_Reader.Destroy;
var lp1 : integer;
begin
if (DXF_Layers<>nil) then
for lp1 := 0 to DXF_Layers.count-1 do DXF_Layer(DXF_Layers[lp1]).Free;
DXF_Layers.Free;
CloseFile(IO_chan);
FreeMem(pBuf,SizeOfBuf);
Inherited Destroy;
end;
{ --------------------------------------------------------------------------- }
{ Routines for fetching codes and values
{ --------------------------------------------------------------------------- }
procedure DXF_Reader.go_back_to_start;
begin
Reset(IO_chan,1);
num_in_buf := 0;
ii := 0;
end;
procedure DXF_Reader.go_back_to_last(code:integer; str:shortstring);
begin
fCode := code;
fLine := str;
backflag := true;
end;
procedure DXF_Reader.mark_position;
begin
marked_pos := File_pos + ii;
end;
procedure DXF_Reader.goto_marked_position;
begin
Seek(IO_chan,marked_pos);
File_pos := marked_pos;
num_in_buf := 0;
ii := 0;
end;
function DXF_Reader.NextGroupCode: integer;
function GotMore: boolean;
begin
file_pos := FilePos(IO_chan);
BlockRead(IO_chan,pBuf^,SizeOfBuf,num_in_buf); ec:=IoResult; ii:=0;
If (ec=0) and (num_in_buf=0) then ec:=-1; GotMore:=(ec=0);
progress.position := progress.position+1;
end{GotMore};
// Sometimes you get (download) a bad DXF file which has a couple of blank
// lines in it. The commented retry code, can be used to skip blank lines, but you
// should only use it as an emergency fix because you'll often find blank lines
// in TEXT entities and other text strings.
function GotLine: boolean;
const CR=#13; LF=#10;
var c: char;
// label retry;
begin
// retry:
byte(fLine[0]):=0;
While (ii<num_in_buf) or GotMore do begin
c:=pBuf^[ii]; inc(ii);
If (c<>CR) and (c<>LF) and (length(fLine)<255) then begin
inc(fLine[0]); fLine[length(fLine)]:=c
end
else begin // Extra code added to handle C/Unix style LF not CR/LF
if (c=CR) then begin
if (ii<num_in_buf) or GotMore then begin
if pBuf^[ii]=LF then begin inc(ii); break; end;
end;
end else if (c=LF) then break;
end;
end;
GotLine:=(ec=0) and ((c=CR) or (c=LF));
inc(Line_num);
// if fLine='' then goto retry;
end;
begin {NextGroupCode}
if backflag then begin
result := fCode;
backflag := false;
end
else begin
repeat
if not GotLine then begin
fCode:=-2;
Result:=fCode;
exit;
end;
until fLine<>'';
Val(fLine,fCode,ec);
If ec<>0 then fCode:=-2
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -