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

📄 dxf_read.pas

📁 一个比较完整的读写dxf文件的DELPHI程序
💻 PAS
📖 第 1 页 / 共 3 页
字号:
      DXF_entities_flg : ent.attflag   := ValInt;
      DXF_layer_name   : ent.layer     := ValStr;
      DXF_name         : ent.namestr   := ValStr;
      DXF_text_def     : ent.tagstr    := ValStr;
      DXF_text_prompt  : ent.promptstr := ValStr;
      DXF_extrusionx   : ent.OCS_Z.x   := Valdbl;
      DXF_extrusiony   : ent.OCS_Z.y   := Valdbl;
      DXF_extrusionz   : ent.OCS_Z.z   := Valdbl;
    end;
  until (Groupcode<=0); // end or fault;
  if Groupcode<0 then begin result:=false; exit; end;
  // we need to put the code=0, and valstr back, so the next entity starts
  // with the zero when neccessary
  go_back_to_last(Groupcode,fline);
  ent.OCS_Z := normalize(ent.OCS_Z); // for safety
  result := true;
end;

function DXF_Reader.read_generic(var layer:integer) : abstract_entity;
var ent : abstract_entity;
    s   : string;
begin
  result := nil;
  ent    := abstract_entity.create; // set everything to zero EVERY time
  if read_entity_data(ent) then begin
    layer := layer_num(ent.layer);
    if layer<0 then layer := DXF_Layers.Add(DXF_Layer.create(ent.layer));
    result := ent;
  end else ent.free;
end;

{ These ones are straightforward, so we'll use a crafty TClass parameter }
function DXF_Reader.general_purpose_read(obj_type:TClass; var entity:DXF_Entity; var layer:integer) : boolean;
var ent   : abstract_entity;
begin
  entity := nil;
  ent := read_generic(layer);
  if ent<>nil then begin
    with ent do begin
      if      obj_type = Point_  then entity := Point_. create(OCS_Z,p1,colour)
      else if obj_type = Text_   then entity := Text_.  create(OCS_Z,p1,p2,tagstr,rad_hgt,colour,flag_72)
      else if obj_type = Line_   then entity := Line_.  create(p1,p2,colour)
      else if obj_type = Circle_ then entity := Circle_.create(OCS_Z,p1,rad_hgt,colour)
      else if obj_type = Arc_    then entity := Arc_.   create(OCS_Z,p1,rad_hgt,angle1,angle2,colour)
      // face3ds and solids can have 3 or 4 points, if 4=3, then 3 used
      else if obj_type = Face3D_ then begin
        if p1_eq_p2_3d(p3,p4) then entity := Face3D_.create(3, @p1, colour,true)
        else                       entity := Face3D_.create(4, @p1, colour,true)
      end
      else if obj_type = Solid_ then begin
        if p1_eq_p2_3d(p3,p4) then entity := Solid_.create(OCS_Z,3, @p1, colour,thickness)
        else                       entity := Solid_.create(OCS_Z,4, @p1, colour,thickness)
      end
      else if obj_type = Attdef_  then entity := Attdef_.create(OCS_Z,p1,p2,namestr,tagstr,promptstr,flag_70,flag_72,rad_hgt,colour)
      else if obj_type = Attrib_  then entity := Attrib_.create(OCS_Z,p1,p2,namestr,tagstr,flag_70,flag_72,rad_hgt,colour);
    end;
    ent.Free;
    result := true;
  end;
end;

{ INSERTs may have ATTRIBs + BLOCKs which makes it a little more complicated }
function DXF_Reader.read_insert(var entity:DXF_Entity; var layer:integer) : boolean;
var ent,ent2 : abstract_entity;
    code,num : integer;
    atts     : array[0..255] of Attrib_;
begin
  result := true;
  entity := nil;
  num := 0;
  ent := read_generic(layer);
  if ent<>nil then begin
    if ent.attflag=1 then begin
      repeat
        result := (Nextgroupcode=0);
        if result and (ValStr='ATTRIB') then begin
          ent2 := read_generic(layer);
          if ent2<>nil then with ent2 do begin
            atts[num] := Attrib_.create(OCS_Z,p1,p2,namestr,tagstr,flag_70,flag_72,rad_hgt,colour);
            ent2.Free;
            inc(num);
          end else result := false;
        end;
      until (not result) or (ValStr='SEQEND');
      if result then Nextgroupcode; // remove the SEQEND put back
    end;
    with ent do begin
      if fv1=0 then fv1 := 1;
      if fv2=0 then fv2 := 1;
      if fv3=0 then fv3 := 1;
      entity := Insert_.create(OCS_Z,p1,aPoint3D(fv1,fv2,fv3),angle1,colour,num,@atts[0],namestr);
      try
        Insert_(entity).update_block_links(block_list);
      except
        entity.Free;
        entity := nil;
        raise DXF_read_exception.Create('Cannot reference an undefined BLOCK'+EOL+EOL+
        '(File may not have been saved with BLOCKs)'+EOL,line_num);
      end;
    end;
    ent.Free;
  end
  else result := false;
end;

// POLYLINEs have variable number of points...
// Modified to accept polyface mesh variety of polyline ...
//   I've ignored the invisible flag for edges
// Modified to accept polygon MxN grid mesh ...
// It's a bit messy - you could simplify it a bit - but hey - what do you
// expect from free code.
function DXF_Reader.read_polyline(var entity:DXF_Entity; var layer:integer) : boolean;
var ent1,ent2    : abstract_entity;
    vertices,lp1 : integer;
    faces        : integer;
    tempvert     : array[0..max_vertices_per_polyline-1] of Point3D;
    tempface     : array[0..4095] of polyface;
    closed_poly  : boolean;
    M,N,mn       : integer;
label vertex_overflow;
begin
  result := false; closed_poly := false; entity := nil;
  ent1   := abstract_entity.create;
  // read initial polyline data
  if not read_entity_data(ent1) then begin ent1.Free; exit; end;
  layer    := layer_num(ent1.layer);
  if (layer=-1) then layer := DXF_Layers.Add(DXF_Layer.create(ent1.layer));
  vertices := 0; faces := 0;
  ent2     := abstract_entity.create;
  //////////////////////////////////////////
  //////////////////////////////////////////
  if (ent1.flag_70 and (64+16))=0 then begin
    // THIS IS A NORMAL POLYLINE
    repeat
      if (NextGroupCode=0) and (ValStr = 'VERTEX') then begin
        ent2.clear;
        if read_entity_data(ent2) then begin
          tempvert[vertices] := ent2.p1; inc(vertices);
          if vertices>=max_vertices_per_polyline then goto vertex_overflow;
        end else begin ent1.Free; ent2.Free; exit; end; // error
      end;
    until fLine='SEQEND';
    // this should set result to true, because 0 SEQEND is next
    result := NextGroupCode=0;
    if ((ent1.flag_70) and 1)=1 then closed_poly := true;
    entity := Polyline_.create(ent1.OCS_Z,vertices,@tempvert[0],ent1.colour,closed_poly);
  end
  //////////////////////////////////////////
  //////////////////////////////////////////
  else if (ent1.flag_70 and 16)=16 then begin
    // THIS IS A POLYGON MESH - a grid of vertices joined along M & N
    M := ent1.flag_71; N := ent1.flag_72; mn := 0;
    repeat
      if (NextGroupCode=0) and (ValStr = 'VERTEX') then begin
        if read_entity_data(ent2) then begin
          inc(mn);
          if (ent2.Flag_70 and 64)=64 then begin
            tempvert[vertices] := ent2.p1; inc(vertices);
            if vertices>=max_vertices_per_polyline then goto vertex_overflow;
          end else begin ent1.Free; ent2.Free; exit; end; // error
        end else begin ent1.Free; ent2.Free; exit; end; // error
      end;
    until fLine='SEQEND';
    result := NextGroupCode=0;
    if mn<>M*N then begin ent1.Free; ent2.Free; exit; end; // error
    entity := Polygon_mesh_.create(vertices,M,N,@tempvert[0],ent1.flag_70,ent1.colour);
  end
  //////////////////////////////////////////
  //////////////////////////////////////////
  else if (ent1.flag_70 and 64)=64 then begin
    // THIS IS A POLYFACE MESH - a vertex array with facets
    repeat
      if (NextGroupCode=0) and (ValStr = 'VERTEX') then begin
        if read_entity_data(ent2) then begin
          if (ent2.Flag_70 and (128+64))=(128+64) then begin
            // this is a normal coordinate vertex
            tempvert[vertices] := ent2.p1; inc(vertices);
            if vertices>=max_vertices_per_polyline then goto vertex_overflow;
          end else if (ent2.Flag_70 and (128))=(128) then begin
            // this is a face definition vertex
            // negative indices indicate invisible edges (ignored for now)
            tempface[faces].nf[0] := Abs(ent2.flag_71)-1; // index 1..n -> 0..n-1
            tempface[faces].nf[1] := Abs(ent2.flag_72)-1;
            tempface[faces].nf[2] := Abs(ent2.flag_73)-1;
            tempface[faces].nf[3] := Abs(ent2.flag_74)-1;
            inc(faces);
          end else begin ent1.Free; ent2.Free; exit; end; // error
        end else begin ent1.Free; ent2.Free; exit; end; // error
      end;
    until fLine='SEQEND';
    result := NextGroupCode=0;
    entity := Polyface_mesh_.create(vertices,faces,@tempvert[0],@tempface[0],ent1.colour);
  end;
  //////////////////////////////////////////
  //////////////////////////////////////////
  ent1.Free; ent2.Free;
  exit; // next bit only when vertices overflow
vertex_overflow:
  ent1.Free; ent2.Free;
  raise DXF_read_exception.Create('Polyline contained more than '+
    IntToStr(max_vertices_per_polyline)+' vertices',line_num);
end;

function DXF_Reader.read_entity(s,endstr:string; var entity:DXF_Entity; var layer:integer) : boolean;
begin
  entity := nil; result := false;
  if (s='POINT') then begin if not general_purpose_read(Point_,entity,layer) then
    raise DXF_read_exception.Create('Error reading POINT entity',line_num); end
  else if (s='INSERT') then begin if not read_insert(entity,layer) then
    raise DXF_read_exception.Create('Error reading INSERT entity',line_num); end
  else if (s='TEXT') then begin if not general_purpose_read(Text_,entity,layer) then
    raise DXF_read_exception.Create('Error reading TEXT entity',line_num); end
  else if (s='LINE') then begin if not general_purpose_read(Line_,entity,layer) then
    raise DXF_read_exception.Create('Error reading LINE entity',line_num); end
  else if (s='POLYLINE') then begin if not read_polyline(entity,layer) then
    raise DXF_read_exception.Create('Error reading POLYLINE entity',line_num); end
  else if (s='3DFACE') then begin if not general_purpose_read(Face3D_,entity,layer) then
    raise DXF_read_exception.Create('Error reading 3DFACE entity',line_num); end
  else if (s='SOLID') then begin if not general_purpose_read(Solid_,entity,layer) then
    raise DXF_read_exception.Create('Error reading SOLID entity',line_num); end
  else if (s='CIRCLE') then begin if not general_purpose_read(Circle_,entity,layer) then
    raise DXF_read_exception.Create('Error reading CIRCLE entity',line_num); end
  else if (s='ARC') then begin if not general_purpose_read(Arc_,entity,layer) then
    raise DXF_read_exception.Create('Error reading ARC entity',line_num); end
  else if (s='ATTDEF') then begin if not general_purpose_read(AttDef_,entity,layer) then
    raise DXF_read_exception.Create('Error reading ATTDEF entity',line_num); end
  else if (s='ATTRIB') then begin if not general_purpose_read(Attrib_,entity,layer) then
    raise DXF_read_exception.Create('Error reading ATTRIB entity',line_num); end
  else if (s=endstr) then result := true
  else if skipped<>nil then Skipped.Add(s);
end;
///////////////////////////////////////////////////////////////////////////////
// Main routines to use
///////////////////////////////////////////////////////////////////////////////
function DXF_Reader.read_file : boolean;
var lp1 : integer;
begin
  result := true;
  thinking_bar(nil,'Reading DXF file...');
  try
    mark_position;
    if not (move_to_header_section and read_header) then begin
      Thinking(nil,'No Header or invalid Header section in DXF file');
      Sleep(message_delay_ms);
      goto_marked_position;
    end;
    mark_position;
    if not (move_to_tables_section and read_tables) then begin
      Thinking(nil,'No Layers or invalid Tables section in DXF file');
      Sleep(message_delay_ms);
      goto_marked_position;
    end;
    mark_position;
    if not (move_to_blocks_section and read_blocks) then begin
      Thinking(nil,'No Blocks or invalid Blocks section in DXF file');
      Sleep(message_delay_ms);
      goto_marked_position;
    end;
    mark_position;
    thinking_bar(nil,'Reading DXF file...');
    if not (move_to_entity_section and read_entities) then
      raise DXF_read_exception.Create('No Entities or invalid Entities section in DXF file',-1);
  except
    on E:DXF_read_exception do begin
      stopped_thinking;
      MessageBox(0,@E.message[1],'DXF Read Error',MB_ICONWARNING);
    end;
    on E:EAccessViolation do begin
      stopped_thinking;
      MessageDlg(E.message, mtWarning, [mbOK], 0);
    end;
  end;
  if p1_eq_p2_3D(min_extents,origin3D) or p1_eq_p2_3D(max_extents,origin3D) then begin
    thinking(nil,'File contained no Max/Min extents. Scanning...');
    sleep(message_delay_ms); // just a delay to let the message be visible
    for lp1:=0 to DXF_layers.count-1 do
      DXF_Layer(DXF_Layers[lp1]).max_min_extents(max_extents,min_extents);
  end;
  stopped_thinking;
end;

function DXF_Reader.remove_empty_layers : boolean;
var lp1   : integer;
    layer : DXF_layer;
begin
   for lp1 := DXF_Layers.count-1 downto 0 do begin
     layer :=  DXF_Layers[lp1];
     if layer.num_lists=0 then begin
       DXF_Layers.Remove(layer);
       layer.Free;
     end;
  end;
  result := (DXF_Layers.count>0);
end;

// Hand over ownership of the layers, the owner of the entity lists
// is now responsible for their destruction
function DXF_Reader.release_control_of_layers : TList;
begin
  result     := DXF_Layers;
  DXF_Layers := nil;
end;

// Since we're not reading all groupcodes, we offer the chance
// to dump the main titles into a list so we can see what
// we've missed
procedure DXF_Reader.set_skipped_list(s:TStrings);
begin
  skipped := s;
end;
///////////////////////////////////////////////////////////////////////////////
// DXF File exception
///////////////////////////////////////////////////////////////////////////////
constructor DXF_read_exception.create(err_msg:string; line:integer);
begin
  if line>-1 then
    message := err_msg + #13#10 + 'Error occured at or near line number ' + IntToStr(line)
  else message := err_msg;
end;

initialization
end.


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -