⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dxf_read.pas

📁 一个比较完整的读写dxf文件的DELPHI程序
💻 PAS
📖 第 1 页 / 共 3 页
字号:
///////////////////////////////////////////////////////////////////////////////
//                                                                           //
//                         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 + -