Creating a block from a dxf file

If you have any comments or questions about our developing tools, please do not hesitate to contact us at this forum

Moderators: admin, SDS, support

Creating a block from a dxf file

Postby hls » 03 Nov 2010, 08:57

I need to insert an existing .dxf file as blocks into the main CADImage (TsgDrawingNavigator). I read the .dxf and copy all entities to a block (the layers/linetype will be done later, the testfile has only 1 polyline in layer 0).

When I run the program I see the new block in the drawing. As soon as I, for example, zoom with the Navigator I got a run-time error.

The source:
Code: Select all
procedure TTestDlg.Button9Click(Sender: TObject);
var
  InsCADFile:TsgCADImage;
  Ent:TsgDXFEntity;
  i:integer;
  Conv:TsgDXFConverter;
  Block:TsgDXFBlock;
  Ins:TsgDXFInsert;
  MainConv:TsgDXFConverter;
  vLine:TsgDXFLine;
begin
  InsCADFile:=TsgCADImage.Create;

  try
    InsCADFile:=GetCADFile('c:\test.dxf');   // Only one polyline
    Conv:=InsCADFile.Converter;

    Block:=TsgDXFBlock.Create;
    Block.Name:='$'+IntToHex(Integer(Pointer(Block)),8);

    for i:=0 to Conv.Counts[csEntities]-1 do begin
      Ent:=TsgDXFEntityClass(TsgDXFEntity(Conv.Entities[i]).ClassType).Create;
      Ent.AssignEntity(TsgDXFEntity(Conv.Entities[i]));
      Block.AddEntity(Ent);
    end;
   
    //Manually add a Line works fine:
    //vLine := TsgDXFLine.Create;
    //vLine.Point  := MakeFPoint( 80, 100, 0);// first point
    //vLine.Point1 := MakeFPoint(150, 150, 0);// second point
    //vLine.SetColor(clBlue);
    //Block.AddEntity(vLine);

    MainConv:=Img.Converter;// current TsgCADImage=Img
    ShowMessage(IntToStr(MainConv.Counts[csEntities]));

    for i:=0 to Block.Count-1 do begin
      MainConv.OnCreate(Block.Entities[i]);
      MainConv.Loads(Block.Entities[i]);
    end;

    MainConv.OnCreate(Block);
    MainConv.Sections[csBlocks].AddEntity(Block);
    MainConv.Loads(Block);

    Ins:=TsgDXFInsert.Create;
    MainConv.OnCreate(Ins);
    Ins.Block:=Block;
    Ins.Point:=MakeFPoint(100, 100, 0);
    MainConv.Sections[csEntities].AddEntity(Ins);
    MainConv.Loads(Ins);

    Img.GetExtents;

    fDNavigator.Invalidate;
    DNavigator.FitToSize;
    DNavigator.Refresh;

    ShowMessage(IntToStr(MainConv.Counts[csEntities])); // 1 Entity is added that is correct

  finally
    InsCADFile.Free;
  end;

end;



I don't want to use the AddScaledDXF funtion, because I need to save all as one large dxf file.

Can you please help me with this?
Thank you!

Frank
hls
 
Posts: 5
Joined: 03 Nov 2010, 08:45

Re: Creating a block from a dxf file

Postby hls » 03 Nov 2010, 14:28

Follow up of the above question:
I managed to create a block from a dxf file.
A few questions:
Is this the right method to do this, or is there a better way (this requires a lot of extra programming for dim styles and so on)?
The newly create block is not shown in colors (only black). However, in the dxf file, that is created after inserting the file as a block, all correct colors are shown. Do you know what I do wrong here?

Thank you!

Frank

Code: Select all
procedure TTestDlg.Button11Click(Sender: TObject);
var
  vExp:TsgCADtoDXF;

  procedure CopyLineTypes(Source,Target:TsgDXFConverter);
  var
    i,j:integer;
    LineTypeName:string;
    sL:TsgDXFLineType;
    tL:TsgDXFLineType;
    Check:boolean;
  begin
    for i:=0 to Source.Sections[csLTypes].Count-1 do begin
      sL:=TsgDXFLineType(Source.Sections[csLTypes].Entities[i]);
      LineTypeName:=sL.Name;
      Check:=true;

      for j:=0 to Target.Sections[csLTypes].Count-1 do begin
        tL:=TsgDXFLineType(Target.Sections[csLTypes].Entities[j]);

        if CompareText(LineTypeName,tL.Name)=0 then begin
          Check:=false;
        end;
      end;

      if Check then begin
        tL:=TsgDXFLineType.Create;
        tL.AssignEntity(sL);

        Target.Loads(tL);
        Target.Sections[csLTypes].AddEntity(tL);
      end;

    end;
  end;


  procedure CopyLayers(Source,Target:TsgDXFConverter);
  var
    i,j:integer;
    LayerName:string;
    sL:TsgDXFLayer;
    tL:TsgDXFLayer;
    Check:boolean;
  begin
    for i:=0 to Source.Sections[csLayers].Count-1 do begin
      sL:=TsgDXFlayer(Source.Sections[csLayers].Entities[i]);

      LayerName:=sL.Name;
      Check:=true;

      for j:=0 to Target.Sections[csLayers].Count-1 do begin
        tL:=TsgDXFlayer(Target.Sections[csLayers].Entities[j]);

        if CompareText(LayerName,tL.Name)=0 then begin
          Check:=false;
        end;
      end;

      if Check then begin
        tL:=TsgDXFlayer.Create;
        Target.Sections[csLayers].AddEntity(tL);
        tL.AssignEntity(sL);
        tL.SetLType(Target.LTypeByName(sL.LineType.Name));
        Target.Loads(tL);
        Target.OnCreate(tL);
      end;

    end;
  end;

  function CreateBlockFromEntities(Source,Target:TsgDXFConverter):TsgDXFBlock;
  var
    i:integer;
    tEnt:TsgDXFEntity;
    sEnt:TsgDXFEntity;
  begin
    Result:=TsgDXFBlock.Create;
    Result.Name:='$'+IntToHex(Integer(Pointer(Result)),8);

    for i:=0 to Source.Counts[csEntities]-1 do begin
      sEnt:=TsgDXFEntity(Source.Entities[i]);

      tEnt:=TsgDXFEntityClass(TsgDXFEntity(Source.Entities[i]).ClassType).Create;
      tEnt.AssignEntity(sEnt);

      if tEnt.LineType<>nil then begin
        tEnt.SetLType(Target.LTypeByName(tEnt.LineType.Name));
      end;

      tEnt.Layer:=Target.LayerByName(sEnt.Layer.Name);

      if Source.Entities[i] is TsgDXFText then begin
        with tEnt as TsgDXFText do begin
          Style:=Target.StyleByName(Style.Name);
        end;
      end;

      Result.AddEntity(tEnt);
    end;

  end;


  function InsertFileAsBlock(const FileName:string;Target:TsgDXFConverter):boolean;
  var
    InsCADFile:TsgCADImage;
    InsConv:TsgDXFConverter;
    DxfIns:TsgDXFInsert;
    Block:TsgDXFBlock;
    i:integer;
  begin
    Result:=false;
    InsCADFile:=TsgCADImage.Create;

    try
      InsCADFile:=GetCADFile(FileName);
      InsConv:=InsCADFile.Converter;

      CopyLineTypes(InsConv,Target);
      CopyLayers(InsConv,Target);

      try
        Block:=CreateBlockFromEntities(InsConv,Target);

        for i:=0 to Block.Count-1 do begin
          Target.OnCreate(Block.Entities[i]);
          Target.Loads(Block.Entities[i]);
        end;

        Target.OnCreate(Block);
        Target.Sections[csBlocks].AddEntity(Block);
        Target.Loads(Block);

        DxfIns:=TsgDXFInsert.Create;
        Target.OnCreate(DxfIns);
        DxfIns.Block:=Block;
        DxfIns.Point:=MakeFPoint(100, 100, 0);

        Target.Sections[csEntities].AddEntity(DxfIns);
        Target.Loads(DxfIns);

        Result:=true;

      finally
      end;

    finally
      InsCADFile.Free;
    end;
  end;


begin
  if InsertFileAsBlock('c:\test.dxf',Img.Converter) then begin
    Img.GetExtents;

    fDNavigator.Invalidate;
    DNavigator.FitToSize;
    DNavigator.Refresh;

    vExp:=tsgCADtoDXF.Create(Img);
    vExp.SaveToFile('c:\total.dxf');
    vExp.Free;
  end;
end;

hls
 
Posts: 5
Joined: 03 Nov 2010, 08:45

Re: Creating a block from a dxf file

Postby support » 09 Nov 2010, 14:06

Hello Frank.
Concerning the first question - the method you use is correct. Testing of your sample code (adapted to Viewer demo project) also doesn't revealed any incorrectnesses. Probably the error somewhere in your project. The problem can be with the file too. You can try another file or provide us with access to your testing file with polyline.

Alexander.
Please post questions to the forum or write to support@cadsofttools.com
support
 
Posts: 2226
Joined: 30 Mar 2005, 08:36
Location: Russia

Re: Creating a block from a dxf file

Postby hls » 09 Nov 2010, 14:19

Hello Alexander,

Thank you for your answer. Now I know I use the correct method.

I just found that I have to place the AddEntity function for the new layer after assigning all data to that new layer.

Wrong:

Code: Select all
      if Check then begin
        tL:=TsgDXFlayer.Create;
        Target.Sections[csLayers].AddEntity(tL);
        tL.AssignEntity(sL);
        tL.SetLType(Target.LTypeByName(sL.LineType.Name));
        Target.Loads(tL);
        Target.OnCreate(tL);
      end;



Right:

Code: Select all
   if Check then
    begin
      tL := TsgDXFlayer.Create;
      tL.AssignEntity(sL);
      tL.SetLType(Target.LTypeByName(sL.LineType.Name));
      Target.Sections[csLayers].AddEntity(tL);
      Target.Loads(tL);
      Target.OnCreate(tL);
    end;



This solves also the issue that the block are drawn only black instead of colored.

That only leaves my question about the attributes, see my other post. I hope you find some time for that one....

Thanks a lot!

Frank
hls
 
Posts: 5
Joined: 03 Nov 2010, 08:45


Return to CADImportVCL + DXFExportVCL

Who is online

Users browsing this forum: No registered users and 1 guest

cron