How to Explode a Block

Discuss and ask questions about CAD VCL (Delphi and C++ Builder).

Moderators: SDS, support, admin

Post Reply
FieldConsult
Posts: 54
Joined: 14 Mar 2015, 22:33

How to Explode a Block

Post by FieldConsult » 16 Mar 2015, 22:33

Hi:

Can you show a code for exploding blocks.

Thanks!

sanket
Posts: 4
Joined: 03 Dec 2018, 13:22

Re: How to Explode a Block

Post by sanket » 22 Jan 2019, 17:51

Hi,

Even I am having the same query. Can anyone please help ?

support
Posts: 3253
Joined: 30 Mar 2005, 11:36
Contact:

Re: How to Explode a Block

Post by support » 01 Feb 2019, 19:45

Hello,

Below you will find the requested sample code.

Code: Select all

interface

uses

..., CADImage, DXFConv, sgFunction, sgConsts;

...

implementation

{$R *.dfm}

procedure ExplodeInsert(ACADImage: TsgCADImage; AInsert: TsgDXFInsert);
var
  I, J: Integer;
  vBlockEnt: TsgDXFEntity;
  vDXFInsert: TsgDXFInsert;
  vDXFLine: TsgDXFLine;
  vDXFLWPolyline: TsgDXFPolyline;
  vDXFCircle: TsgDXFCircle;

  vMatrix: TFMatrix;
  vPoint, vScale, vExtrusion: TFPoint;
  vAngle: Double;
begin
  vMatrix := AInsert.GetMatrix;

  // Iterate through entities in the block
  for I := 0 to AInsert.Block.Count - 1 do
  begin
    vBlockEnt := AInsert.Block.Entities[I];
    case vBlockEnt.EntType of
        ceLine: // LINE entity
          begin
            // Create a copy of the entity which is inside the block
            vDXFLine := TsgDXFLine.Create;
            vDXFLine.AssignEntity(vBlockEnt);
            // Multiply coordinates of the created entity by the transformation matrix
            vDXFLine.Point := FPointXMat(vDXFLine.Point, vMatrix);
            vDXFLine.Point1 := FPointXMat(vDXFLine.Point1, vMatrix);
            ACADImage.Converter.Loads(vDXFLine);
            ACADImage.CurrentLayout.AddEntity(vDXFLine);
          end;
        ceLWPolyline: // LWPOLYLINE entity
          begin
            vDXFLWPolyline := TsgDXFLWPolyline.Create;
            vDXFLWPolyline.AssignEntity(vBlockEnt);
            for J := 0 to vDXFLWPolyline.Count - 1 do
              vDXFLWPolyline.Vertexes[J].Point := FPointXMat(vDXFLWPolyline.Vertexes[J].Point, vMatrix);
            ACADImage.Converter.Loads(vDXFLWPolyline);
            ACADImage.CurrentLayout.AddEntity(vDXFLWPolyline);
          end;
        ceCircle: // CIRCLE entity
          begin
            vDXFCircle := TsgDXFCircle.Create;
            vDXFCircle.AssignEntity(vBlockEnt);
            vDXFCircle.Point := FPointXMat(vDXFCircle.Point, vMatrix);
            vDXFCircle.Radius := DistanceFVector(AffineTransformPoint(MakeFPoint(0, vDXFCircle.Radius, 0), vMatrix));
            ACADImage.Converter.Loads(vDXFCircle);
            ACADImage.CurrentLayout.AddEntity(vDXFCircle);
          end;
        ceInsert: // nested INSERT entity
          begin
            //ExplodeInsert(ACADImage, vSrcEnt as TsgDXFInsert);
            vDXFInsert := TsgDXFInsert.Create;
            vDXFInsert.AssignEntity(vBlockEnt);
            ExtractMatrixParams(FMatXMat(TsgDXFInsert(vBlockEnt).GetMatrix, vMatrix), vPoint, vScale, vExtrusion, vAngle);
            vDXFInsert.Point := vPoint;
            vDXFInsert.Scale := vScale;
            vDXFInsert.Extrusion := vExtrusion;
            vDXFInsert.Angle := vAngle;
            ACADImage.Converter.Loads(vDXFInsert);
            ACADImage.CurrentLayout.AddEntity(vDXFInsert);
          end;
    end;
  end;
  // Delete the INSERT after exploding
  ACADImage.Converter.RemoveEntity(AInsert, True);
  // Recalculate the CAD image extents
  ACADImage.GetExtents();
end;
Mikhail
Technical Support E-mail: support@cadsofttools.com
Chat support on Skype: cadsofttools.support

AlexBV
Posts: 10
Joined: 08 May 2020, 23:33

Re: How to Explode a Block

Post by AlexBV » 08 May 2020, 23:55

How to do the same for Text and MText ??

What I really want is to have the coordinates of all the strokes within TEXT and MText..
Thank you !!

Ax

support
Posts: 3253
Joined: 30 Mar 2005, 11:36
Contact:

Re: How to Explode a Block

Post by support » 14 May 2020, 00:40

Hello,

You can convert each line of TsgDXFMText entity to a single-line TsgDXFText entity using the following code.

Code: Select all

procedure ExplodeInsert(ACADImage: TsgCADImage; AInsert: TsgDXFInsert);
var
  I, J: Integer;
  vBlockEnt: TsgDXFEntity;
  vDXFInsert: TsgDXFInsert;
  vDXFLine: TsgDXFLine;
  vDXFLWPolyline: TsgDXFPolyline;
  vDXFCircle: TsgDXFCircle;
  vDXFText: TsgDXFText;
  vDXFMText: TsgDXFMText;

  vMatrix: TFMatrix;
  vPoint, vScale, vExtrusion: TFPoint;
  vAngle: Double;
begin
  vMatrix := AInsert.GetMatrix;

  // Iterate through entities in the block
  for I := 0 to AInsert.Block.Count - 1 do
  begin
    vBlockEnt := AInsert.Block.Entities[I];
    case vBlockEnt.EntType of
        ceLine: // LINE entity
          begin
            // Create a copy of the entity which is inside the block
            vDXFLine := TsgDXFLine.Create;
            vDXFLine.AssignEntity(vBlockEnt);
            // Multiply coordinates of the created entity by the transformation matrix
            vDXFLine.Point := FPointXMat(vDXFLine.Point, vMatrix);
            vDXFLine.Point1 := FPointXMat(vDXFLine.Point1, vMatrix);
            ACADImage.Converter.Loads(vDXFLine);
            ACADImage.CurrentLayout.AddEntity(vDXFLine);
          end;
        ceText: // TEXT entity
          begin
            vDXFText := TsgDXFText.Create;
            vDXFText.AssignEntity(vBlockEnt);
            if vDXFText.InsideMText then
              vDXFText.Point1 := FPointXMat(AInsert.Point, FMatByTranslate(vDXFText.Point1))
            else
              vDXFText.Point := FPointXMat(vDXFText.Point, vMatrix);
            ACADImage.Converter.Loads(vDXFText);
            ACADImage.CurrentLayout.AddEntity(vDXFText);
          end;
        ceLWPolyline: // LWPOLYLINE entity
          begin
            vDXFLWPolyline := TsgDXFLWPolyline.Create;
            vDXFLWPolyline.AssignEntity(vBlockEnt);
            for J := 0 to vDXFLWPolyline.Count - 1 do
              vDXFLWPolyline.Vertexes[J].Point := FPointXMat(vDXFLWPolyline.Vertexes[J].Point, vMatrix);
            ACADImage.Converter.Loads(vDXFLWPolyline);
            ACADImage.CurrentLayout.AddEntity(vDXFLWPolyline);
          end;
        ceCircle: // CIRCLE entity
          begin
            vDXFCircle := TsgDXFCircle.Create;
            vDXFCircle.AssignEntity(vBlockEnt);
            vDXFCircle.Point := FPointXMat(vDXFCircle.Point, vMatrix);
            vDXFCircle.Radius := DistanceFVector(AffineTransformPoint(MakeFPoint(0, vDXFCircle.Radius, 0), vMatrix));
            ACADImage.Converter.Loads(vDXFCircle);
            ACADImage.CurrentLayout.AddEntity(vDXFCircle);
          end;
        ceInsert: // nested INSERT entity
          begin
            vDXFInsert := TsgDXFInsert.Create;
            vDXFInsert.AssignEntity(vBlockEnt);
            ExtractMatrixParams(FMatXMat(TsgDXFInsert(vBlockEnt).GetMatrix, vMatrix), vPoint, vScale, vExtrusion, vAngle);
            vDXFInsert.Point := vPoint;
            vDXFInsert.Scale := vScale;
            vDXFInsert.Extrusion := vExtrusion;
            vDXFInsert.Angle := vAngle;
            ACADImage.Converter.Loads(vDXFInsert);
            ACADImage.CurrentLayout.AddEntity(vDXFInsert);
          end;
        ceMText:  // MTEXT entity
          begin
            vDXFMText := vBlockEnt as TsgDXFMText;
            // Extract TEXT entities from the MTEXT
            ExplodeInsert(ACADImage, vDXFMText);
          end;
    end;
  end;
  // Delete the INSERT after exploding
  ACADImage.Converter.RemoveEntity(AInsert, True);
  // Recalculate the CAD image extents
  ACADImage.GetExtents();
end;
Mikhail
Technical Support E-mail: support@cadsofttools.com
Chat support on Skype: cadsofttools.support

AlexBV
Posts: 10
Joined: 08 May 2020, 23:33

Re: How to Explode a Block

Post by AlexBV » 23 May 2020, 18:20

Mikhail,
Excellent and very illustrative code.

My additional question is Is it possible to get the actual Text strokes, as polylines without the use of the font file. ?
I saw a function called GetTextPolylines .... somewhere .. should it be it ?
What Ia am doing is to convert each entity to a very different plane (actually two simultaneous planes).. that is what I was wondering if I could extract the very primitive text strokes.
Other way to do it is to read the shx file (which I do not know how ... at the moment)

Thanks for your patience

Alex

support
Posts: 3253
Joined: 30 Mar 2005, 11:36
Contact:

Re: How to Explode a Block

Post by support » 25 May 2020, 19:45

Hello Alex,

You are right. There is a TsgDXFConverter.GetTextPolylines function which converts a TsgDXFText object (AText) into a TList of lists of points (AList):

Code: Select all

function TsgDXFConverter.GetTextPolylines(const AText: TsgDXFText; const AList: TList): Integer;
To create polylines from the TList received with the use of this function, use the following procedure:

Code: Select all

  procedure CreatePolylines(ACADImage: TsgCADImage; const AList: TList);
  var
    I, J: Integer;
    vPoly: TsgDXFPolyline;
    vVertex: TsgDXFVertex;
    vContour: TList;
  begin
    for I := 0 to AList.Count - 1 do
    begin
      vPoly := TsgDXFPolyline.Create();
      vPoly.Color := clRed;
      vPoly.Closed := False;
      vContour := AList[I];
      for J := 0 to vContour.Count - 1 do
      begin
        vVertex := TsgDXFVertex.Create();
        vVertex.Point := TFPoint(vContour[J]^);
        vPoly.AddEntity(vVertex);
      end;
      ACADImage.Converter.Loads(vPoly);
      ACADImage.CurrentLayout.AddEntity(vPoly);
    end;
    ACADImage.GetExtents();
    vContour.Free;
  end;
To free the TList of lists, please use sgConsts.FreeRecordListOfList procedure.

Mikhail
Technical Support E-mail: support@cadsofttools.com
Chat support on Skype: cadsofttools.support

AlexBV
Posts: 10
Joined: 08 May 2020, 23:33

Re: How to Explode a Block

Post by AlexBV » 26 May 2020, 22:59

Thank you Mikhail,
Implemented and working fine !!

Post Reply