unit Unit1;
{
  How to get entities properties.

  1. Create procedure of type:
    function(Entity: TsgDXFEntity): Integer of object;
    in this demo: function TForm1.ReadCADEntities(Entity: TsgDXFEntity): Integer;

   2. Create TsgCADIterate object:
     FCADParams: TsgCADIterate; in this demo

   3. Create TsgDXFImage object (in the demo it is made in Button1Click
     on Image1.Picture.LoadFromFile(OpenPictureDialog1.FileName);
     and stored in Image1.Picture.Graphic.

   4. Set (TsgDXFImage object).Converer.AutoInsert := True
     See TsgDXFImage(Image1.Picture.Graphic).Converter.AutoInsert := True; // to get all the elements inside of inserts

   5. Call (TsgDXFImage object).Converer.Iterate with parameters made in items 1. and 2.
     TsgDXFImage(Image1.Picture.Graphic).CurrentLayout.Iterate(TsgDXFImage(Image1.Picture.Graphic).Converter, ReadCADEntities, FinishReadCADEntities);

   6.  in procedure made in item 1. read all the entities:
       function ReadCADEntities(Entity: TsgDXFEntity): Integer;
       begin
       //  use Entity here, see documentation about properties of different classes,
       //  allows to get lines, text, arcs, etc.
       end;

   7. Implements finishing actions after entities' import
      function FinishReadCADEntities(Entity: TsgDXFEntity): Integer;
}

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtDlgs, ExtCtrls, DXFImage, DXFConv, Math, Extrusion,
  {$IFNDEF sgDXFONLY}
  DWG, HPGL2, SVG, CGM,
  {$ENDIF}
   sgConsts, MVFont;

type
  TForm1 = class(TForm)
    Image1: TImage;
    Panel1: TPanel;
    Button1: TButton;
    OpenPictureDialog1: TOpenPictureDialog;
    SaveDialog1: TSaveDialog;
    lblLayouts: TLabel;
    cbLayouts: TComboBox;
    btnSaveAsTxt: TButton;
    procedure Button1Click(Sender: TObject);
    procedure OpenPictureDialog1Show(Sender: TObject);
    procedure OpenPictureDialog1Close(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure cbLayoutsChange(Sender: TObject);
    procedure btnSaveAsTxtClick(Sender: TObject);
  private
    TextFile: TStringList;
    FCADParams: TsgCADIterate;
    procedure ImportSolid(Sender: TObject);
    procedure ImportLine(Sender: TObject);
    procedure ImportPoint(Sender: TObject);
    procedure ImportEllipse(Sender: TObject);
    procedure ImportArc(Sender: TObject);
    procedure ImportCircle(Sender: TObject);
    procedure ImportPolyLine(Sender: TObject);
    procedure ImportAttdef(Sender: TObject);
    procedure ImportText(Sender: TObject);
    procedure ImportSpline(Sender: TObject);
    procedure ImportViewPortBegin(Sender: TObject);
    procedure ImportViewPortEnd(Sender: TObject);
    { Private declarations }
  public
    function ReadCADEntities(Entity: TsgDXFEntity): Integer;
    function FinishReadCADEntities(Entity: TsgDXFEntity): Integer;
    { Public declarations }
  end;

var
  Form1: TForm1;
  Img: TsgDXFImage;

implementation

{$R *.dfm}

function PointToString(const P: TFPoint): string;
begin
  Result := ' X='+ FloatToStr(P.X)+ ' Y='+ FloatToStr(P.Y)+ ' Z='+ FloatToStr(P.Z);
end;

{ All elements inside inserts can be reached in the next procedure.
  Proc called for Inserts too }
function TForm1.ReadCADEntities(Entity: TsgDXFEntity): Integer;
const
  PS: array[psSolid..psDashDot] of string =
    ('psSolid','psDash','psDot','psDashDot');
var
  S: string;
  L: TsgDXFLayer;
  C: TColor;
begin
  Result := 0;
  S := #13#10'ClassName=' + Entity.ClassName + '; Entity name=' + Entity.EntName;
  DoScale2D(FCADParams); // calculates 2d scale and rotation
  // layer
  L := EntLayer(Entity, FCADParams.Insert);
  if L <> nil then S := S + ' layer = ' + L.Name;
  // color
  S := S + ' style = ' + PS[EntStyle(Entity)];
  C := EntColor(Entity, FCADParams.Insert);
  if C = clNone then
    S := S + ' color=black/white'
  else
    S := S + ' color = ' +  IntToHex(C, -6) + ' (' + ColorToString(C) + ')';
  // particular properties
  TextFile.Add(S);
  case Entity.EntType of
    ceLine:      ImportLine(Entity);    //Line - see dxfimage.pas TsgDXFImage.DrawArc
    cePoint:     ImportPoint(Entity);   //Point - see dxfimage.pas TsgDXFImage.DrawPoint
    ceCircle:    ImportCircle(Entity);  //Circle - see dxfimage.pas TsgDXFImage.DrawArc
    ceArc:       ImportArc(Entity);     //Arc - see dxfimage.pas TsgDXFImage.DrawArc
    ceEllipse:   ImportEllipse(Entity); //Ellipse - see dxfimage.pas TsgDXFImage.DrawArc
    cePolyline,
      cePath:    ImportPolyLine(Entity);//PolyLine - see dxfimage.pas TsgDXFImage.DrawPolyLine
    ceSpline,                           //Spline - see dxfimage.pas TsgDXFImage.DrawSpline
      ceLeader:  ImportSpline(Entity);  //Leader - see dxfimage.pas TsgDXFImage.DrawLeader
    ceText:      ImportText(Entity);    //Text - see dxfimage.pas TsgDXFImage.DrawText
    ceAttdef,
      ceAttrib:  ImportAttdef(Entity);  //Attdef - see dxfimage.pas TsgDXFImage.DrawText
    ceSolid,                            //Solid  - see dxfimage.pas TsgDXFImage.DrawSolid
      ce3dFace:  ImportSolid(Entity);   //Face - see dxfimage.pas TsgDXFImage.DrawFace
    ceViewport:
      begin
        Result := 1;
        ImportViewPortBegin(Entity);    //ViewPort - see dxfimage.pas TsgDXFImage.DrawViewPort
      end;
    (* Other entities (for future versions) see dxfimage.pas
    ceDimension:         Result := ImportDimension(Entity);
    ceInsert,
      ceMText:           Result := ImportInsert(Entity);
    cePolyPolygon,
      ceGradient,
      ceGradientPolygon,
      ceCurvePolygon,
      ceHatch:           ImportHatch(Entity);
    ceImageEnt:          ImportImage(Entity);
    ceRegion,
      ceBody, ce3DSolid: ImportACISEntity(Entity);
    ceOle2Frame:         ImportOle2Frame(Entity);
    ceFlatPoly:          ImportFlatPoly(Entity);
    ceFlatHatch:         ImportFlatHatch(Entity);
    ceXRef:              ImportXRef(Entity); *)
  end;
end;

function TForm1.FinishReadCADEntities(Entity: TsgDXFEntity): Integer;
begin
  case Entity.EntType of
    ceViewport:
      begin
        Result := 1;
        ImportViewPortEnd(Entity);
      end;
  else
    Result := 0;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
const
  Exts: array[0..17] of string = ( '.dxf', '.dwg', '.plt', '.hgl', '.rtl',
    '.hg', '.plo', '.hp', '.hp1', '.hp2', '.hpg', '.hpgl', '.hpgl2', '.gl2',
    '.prn', '.spl', '.svg', '.cgm');
var
  vFileExt: string;

  procedure ViewLayouts;
  var
    I: Integer;
  begin
    if Img <> nil then
    begin
      btnSaveAsTxt.Enabled := True;
      cbLayouts.Visible := True;
      lblLayouts.Visible := True;
      cbLayouts.Items.Clear;
      for I := 0 to Img.LayoutsCount - 1 do
        cbLayouts.Items.AddObject(Img.Layouts[I].Name, Img.Layouts[I]);
      cbLayouts.ItemIndex := Img.Converter.DefaultLayoutIndex;
      Img.CurrentLayout := Img.Layouts[cbLayouts.ItemIndex];
    end;
  end;
begin
  OpenPictureDialog1.FileName := '';
  if OpenPictureDialog1.Execute then
  begin
    vFileExt := ExtractFileExt(LowerCase(OpenPictureDialog1.FileName));
    case StrIndex(vFileExt, Exts) of
      0:	Img := TsgDXFImage.Create;
      {$IFNDEF sgDFONLY}
      1:	Img := TsgDWGImage.Create;
      2..15:	Img := TsgHPGLImage.Create;
      16:     Img := TsgSVGImage.Create;
      17:     Img := TsgCGMImage.Create;
      {$ENDIF}
      else	Img := nil;
    end;
    if Img <> nil then
    begin
      Img.LoadFromFile(OpenPictureDialog1.FileName);
      ViewLayouts;
      Image1.Picture.Assign(Img);
    end;
  end;
end;

procedure TForm1.OpenPictureDialog1Show(Sender: TObject);
begin
  {$IFNDEF sgDXFONLY}
  DWGPreview := True;
  {$ENDIF}
end;

procedure TForm1.OpenPictureDialog1Close(Sender: TObject);
begin
  {$IFNDEF sgDXFONLY}
  DWGPreview := False;
  {$ENDIF}
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  btnSaveAsTxt.Enabled := False;
  cbLayouts.Visible := False;
  lblLayouts.Visible := False;
  OpenPictureDialog1.Filter := GraphicFilter(TGraphic);
end;

procedure TForm1.cbLayoutsChange(Sender: TObject);
begin
  if cbLayouts.Items.Objects[cbLayouts.ItemIndex] <> nil then
    TsgDXFImage(Image1.Picture.Graphic).CurrentLayout := TsgDXFImage(Image1.Picture.Graphic).Layouts[cbLayouts.ItemIndex];
end;

procedure TForm1.btnSaveAsTxtClick(Sender: TObject);
begin
  TextFile := TStringList.Create;
  try
    if Image1.Picture.Graphic is TsgDXFImage then
    begin
      FCADParams.Matrix := IdentityMat;
      //TsgDXFImage(Image1.Picture.Graphic).Converter.OnViewPort := ImportViewPortEnd;
      TsgDXFImage(Image1.Picture.Graphic).Converter.ImportMode := imImport;
      TsgDXFImage(Image1.Picture.Graphic).Converter.AutoInsert := True; // to get all the elements inside of inserts
      //TsgDXFImage(Image1.Picture.Graphic).Converter.Iterate(ReadCADEntities, FCADParams);
      TsgDXFImage(Image1.Picture.Graphic).Converter.Params := @FCADParams;
      TsgDXFImage(Image1.Picture.Graphic).CurrentLayout.Iterate(TsgDXFImage(Image1.Picture.Graphic).Converter, ReadCADEntities, FinishReadCADEntities);
      SaveDialog1.FileName := ChangeFileExt(OpenPictureDialog1.FileName, '.txt');
      if SaveDialog1.Execute then
        TextFile.SaveToFile(SaveDialog1.FileName);
    end;
  finally
    TextFile.Free;
    TextFile := nil;
  end;
end;

procedure TForm1.ImportSolid(Sender: TObject);
var
  P: TFPoint;
  S: string;
begin
  P := PtXMat(TsgDXFSolid(Sender).Point, FCADParams.Matrix);
  S := S + ' P1: ';
  S := S + ' X=' + FloatToStr(P.X);
  S := S + ' Y=' + FloatToStr(P.Y);
  S := S + ' Z=' + FloatToStr(P.Z);
  S := S + #13#10;
  P := PtXMat(TsgDXFSolid(Sender).Point1, FCADParams.Matrix);
  S := S + ' P2: ';
  S := S + ' X=' + FloatToStr(P.X);
  S := S + ' Y=' + FloatToStr(P.Y);
  S := S + ' Z=' + FloatToStr(P.Z);
  S := S + #13#10;
  P := PtXMat(TsgDXFSolid(Sender).Point3, FCADParams.Matrix);
  S := S + ' P3: ';
  S := S + ' X=' + FloatToStr(P.X);
  S := S + ' Y=' + FloatToStr(P.Y);
  S := S + ' Z=' + FloatToStr(P.Z);
  S := S + #13#10;
  P := PtXMat(TsgDXFSolid(Sender).Point2, FCADParams.Matrix);
  S := S + ' P4: ';
  S := S + ' X=' + FloatToStr(P.X);
  S := S + ' Y=' + FloatToStr(P.Y);
  S := S + ' Z=' + FloatToStr(P.Z);
  TextFile.Add(S);
end;

procedure TForm1.ImportLine(Sender: TObject);
var
  P: TFPoint;
  S: string;
begin
  S := ' LineWeight=' + FloatToStr(TsgDXFLine(Sender).LineWeight) + '; ';
  S := S + ' LineTypeScale=' + FloatToStr(TsgDXFLine(Sender).LineTypeScale) + '; ';
  S := S + ' ZThick=' + FloatToStr(TsgDXFLine(Sender).ZThick) + '; ';
  S := S + #13#10;
  P := PtXMat(TsgDXFLine(Sender).Point, FCADParams.Matrix);
  S := S + ' Begin point: ';
  S := S + #13#10;
  S := S + ' X=' + FloatToStr(P.X);
  S := S + ' Y=' + FloatToStr(P.Y);
  S := S + ' Z=' + FloatToStr(P.Z);
  S := S + #13#10;
  P := PtXMat(TsgDXFLine(Sender).Point1, FCADParams.Matrix);
  S := S + ' End point: ';
  S := S + #13#10;
  S := S + ' X=' + FloatToStr(P.X);
  S := S + ' Y=' + FloatToStr(P.Y);
  S := S + ' Z=' + FloatToStr(P.Z);
  TextFile.Add(S);
end;

procedure TForm1.ImportPoint(Sender: TObject);
var
  P: TFPoint;
  S: string;
begin
  P := PtXMat(TsgDXFPoint(Sender).Point, FCADParams.Matrix);
  S := ' Point: ' + #13#10 + PointToString(P);
  S := S + #13#10;
end;

procedure TForm1.ImportEllipse(Sender: TObject);
var
  P: TFPoint;
  S: string;
begin
    P := PtXMat(TsgDXFEllipse(Sender).Point, FCADParams.Matrix);
    S := S + ' Center point: ';
    S := S + ' X=' + FloatToStr(P.X);
    S := S + ' Y=' + FloatToStr(P.Y);
    S := S + ' Z=' + FloatToStr(P.Z);
    S := S + #13#10;
    S := S + ' Start Angle: ' + FloatToStr(TsgDXFEllipse(Sender).StartAngle);
    S := S + #13#10;
    S := S + ' End Angle: ' + FloatToStr(TsgDXFEllipse(Sender).EndAngle);
    S := S + #13#10;
    S := S + ' Rx: ' + FloatToStr(TsgDXFEllipse(Sender).Radius);
    S := S + ' Ry: ' + FloatToStr(TsgDXFEllipse(Sender).Radius * TsgDXFEllipse(Sender).Ratio);
    TextFile.Add(S);
end;

procedure TForm1.ImportArc(Sender: TObject);
var
  P: TFPoint;
  S: string;
begin
  P := PtXMat(TsgDXFArc(Sender).Point, FCADParams.Matrix);
  S := S + ' Center point: ';
  S := S + ' X=' + FloatToStr(P.X);
  S := S + ' Y=' + FloatToStr(P.Y);
  S := S + ' Z=' + FloatToStr(P.Z);
  S := S + #13#10' Start Angle: ' + FloatToStr(TsgDXFArc(Sender).StartAngle);
  S := S + #13#10' End Angle: ' + FloatToStr(TsgDXFArc(Sender).EndAngle);
  S := S + #13#10' Rx: ' + FloatToStr(TsgDXFArc(Sender).Radius);
  TextFile.Add(S);
end;

procedure TForm1.ImportCircle(Sender: TObject);
var
  P: TFPoint;
  S: string;
begin
    P := PtXMat(TsgDXFCircle(Sender).Point, FCADParams.Matrix);
    S := S + ' Center point: ';
    S := S + ' X=' + FloatToStr(P.X);
    S := S + ' Y=' + FloatToStr(P.Y);
    S := S + ' Z=' + FloatToStr(P.Z);
    TextFile.Add(S);
end;

procedure TForm1.ImportPolyLine(Sender: TObject);
var
  P: TFPoint;
  S: string;
  I: Integer;
  Vertex: TsgDXFVertex;
begin
  S := S + ' Vertexes: ';
  for I := 0 to TsgDXFPolyLine(Sender).Count - 1 do
  begin
    S := S + #13#10;
    S := S + ' P' + IntToStr(I + 1) + ': ';
    Vertex := TsgDXFVertex(TsgDXFPolyLine(Sender).Entities[I]);
    P := PtXMat(Vertex.Point, FCADParams.Matrix);
    S := S + ' X=' + FloatToStr(P.X);
    S := S + ' Y=' + FloatToStr(P.Y);
    S := S + ' Z=' + FloatToStr(P.Z);
  end;
  TextFile.Add(S);
end;

function ImportTextFont(Sender: TObject): string;
var
  vText: TsgDXFText;

  function ImportMTextFontStyle(AStyle: TmvFontStyles): string;
  begin
    if fmBold in AStyle then Result := '  fmBold' + #13#10;
    if fmItalic in AStyle then Result := Result + '  fmItalic' + #13#10;
    if fmUnderline in AStyle then Result := Result + '  fmUnderline' + #13#10;
    if fmStrikeOut in AStyle then Result := Result + '  fmStrikeOut' + #13#10;
    if fmCondensed in AStyle then Result := Result + '  fmCondensed' + #13#10;
    if fmUpward in AStyle then Result := Result + '  fmUpward' + #13#10;
    if fmDownward in AStyle then Result := Result + '  fmDownward' + #13#10;
  end;

begin
  vText := TsgDXFText(Sender);
  if vText.Style <> nil then
  begin
    Result := Result + ' Text Style:' + #13#10;
    Result := Result + '  BigFont=' + vText.Style.BigFont + #13#10;
    Result := Result + '  WidthFactor=' + FloatToStr(vText.Style.WidthFactor) + #13#10;
  end;
  Result := ' Font: Name=' + vText.FontName + '; ';
  Result := Result + ' Height=' + IntToStr(vText.Font.Height) + '; ';
  Result := Result + ' Color=$' + IntToHex(vText.Font.Color, 8) + '; ' + #13#10;
  Result := Result + ' Style:' + #13#10 + ImportMTextFontStyle(vText.Font.Style);
  Result := Result + ' Thickness=' + FloatToStr(vText.GetThickness);
  Result := Result + #13#10' Generation=' + IntToStr(vText.Generation);
  Result := Result + #13#10' VAlign=' + IntToStr(vText.VAlign);
  Result := Result + #13#10' HAlign=' + IntToStr(vText.HAlign);
end;

procedure TForm1.ImportAttdef(Sender: TObject);
begin
  ImportText(Sender);
  TextFile.Add('Tag: '+TsgDXFAttdef(Sender).Tag);
end;

procedure TForm1.ImportText(Sender: TObject);
var
  P: TFPoint;
  S: string;
begin
  DoScale2D(FCADParams);
  P := PtXMat(TsgDXFText(Sender).StartPoint, FCADParams.Matrix);
  S := S + ' Start point: ';
  S := S + #13#10' X=' + FloatToStr(P.X);
  S := S + #13#10' Y=' + FloatToStr(P.Y);
  S := S + #13#10' Z=' + FloatToStr(P.Z);
  S := S + ' Angle=' + FloatToStr(TsgDXFText(Sender).Rotation + FCADParams.Angle);
  S := S + #13#10 + ImportTextFont(Sender);
  S := S + #13#10' Text: ' + TsgDXFText(Sender).Text;
  TextFile.Add(S);
end;

procedure TForm1.ImportSpline(Sender: TObject);
var
  vSpline: TsgDXFSpline absolute Sender;
  P: TFPoint;
  S: string;
  I: Integer;
begin
  if vSpline.FitCount > 0 then
  begin
    S := S + ' Fit points of Spline: ';
    for I := 0 to vSpline.FitCount - 1 do
    begin
      S := S + #13#10 + ' P' + IntToStr(I + 1) + ': ';
      P := PtXMat(PFPoint(vSpline.Fit[I])^, FCADParams.Matrix);
      S := S + PointToString(P);
    end;
    S := S + #13#10;
  end;
  if vSpline.ControlCount > 0 then
  begin
    S := S + ' Control points of Spline: ';
    for I := 0 to vSpline.ControlCount - 1 do
    begin
      S := S + #13#10 + ' P' + IntToStr(I + 1) + ': ';
      P := PtXMat(PFPoint(vSpline.Controls[I])^, FCADParams.Matrix);
      S := S + PointToString(P);
    end;
    S := S + #13#10;
  end;
  TextFile.Add(S);
end;

procedure TForm1.ImportViewPortBegin(Sender: TObject);
var
  V: TsgDXFViewPort absolute Sender;
  S: string;
begin
  S := 'Rect:'
    + #13#10'   Left= ' + FloatToStr(V.Rect.Left)
    + #13#10'   Top= ' + FloatToStr(V.Rect.Top)
    + #13#10'   Z1= ' + FloatToStr(V.Rect.Z1)
    + #13#10'   Right= ' + FloatToStr(V.Rect.Right)
    + #13#10'   Bottom= ' + FloatToStr(V.Rect.Bottom)
    + #13#10'   Z2= ' + FloatToStr(V.Rect.Z2);
  S := S + #13#10'---ENTITIES below are displayed in this VIEWPORT---';
  TextFile.Add(S);
end;

procedure TForm1.ImportViewPortEnd(Sender: TObject);
begin
  TextFile.Add('-----ENTITIES above are displayed in VIEWPORT-----');
end;

end.


