📄 dxf_read.pas
字号:
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 + -