unit Unit1;
{$INCLUDE CADSoftTools.INC}
//If you see error "File not found: 'CADSoftTools.INC'",
//then please contact info@cadsofttools.com to get a compilable version.
//If you have a compilable version, you need to copy the contents of
// Lib7/LibXE5win32/LibXE5win64... to Lib directory according to your
// Delphi version and target CPU platform.

{
  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 TsgCADImage object (in the demo it is made on Button1Click
     on Image1.Picture.LoadFromFile(OpenPictureDialog1.FileName);
     and stored in Image1.Picture.Graphic.

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

   5. Call (TsgCADImage object).Converer.Iterate with parameters made in items 1. and 2.
     TsgCADImage(Image1.Picture.Graphic).CurrentLayout.Iterate(TsgCADImage(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, CADImage, DXFConv, DXF, Math,
  DWG, HPGL2, SVG, CGM,
  sgConsts, MVFont,
  {$IFDEF DEMO}
  fInfo,
  {$ENDIF}
  sgFunction;

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);
    procedure ImportFlatPolyLine(Sender: TObject);
    { Private declarations }
  public
    function ReadCADEntities(Entity: TsgDXFEntity): Integer;
    function FinishReadCADEntities(Entity: TsgDXFEntity): Integer;
    { Public declarations }
  end;

var
  Form1: TForm1;
  Img: TsgCADImage;

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 cadmage.pas TsgCADImage.DrawArc
    cePoint:     ImportPoint(Entity);   //Point - see cadmage.pas TsgCADImage.DrawPoint
    ceCircle:    ImportCircle(Entity);  //Circle - see cadmage.pas TsgCADImage.DrawArc
    ceArc:       ImportArc(Entity);     //Arc - see cadmage.pas TsgCADImage.DrawArc
    ceEllipse:   ImportEllipse(Entity); //Ellipse - see cadmage.pas TsgCADImage.DrawArc
    cePolyline,
      cePath:    ImportPolyLine(Entity);//PolyLine - see cadmage.pas TsgCADImage.DrawPolyLine
    ceFlatPoly:  ImportFlatPolyLine(Entity);//FlatPoly - see cadmage.pas TsgCADImage.DrawPolyLine
    ceSpline,                           //Spline - see cadmage.pas TsgCADImage.DrawSpline
      ceLeader:  ImportSpline(Entity);  //Leader - see cadmage.pas TsgCADImage.DrawLeader
    ceText:      ImportText(Entity);    //Text - see cadmage.pas TsgCADImage.DrawText
    ceAttdef,
      ceAttrib:  ImportAttdef(Entity);  //Attdef - see cadmage.pas TsgCADImage.DrawText
    ceSolid,                            //Solid  - see cadmage.pas TsgCADImage.DrawSolid
      ce3dFace:  ImportSolid(Entity);   //Face - see cadmage.pas TsgCADImage.DrawFace
    ceViewport:
      begin
        Result := 1;
        ImportViewPortBegin(Entity);    //ViewPort - see cadmage.pas TsgCADImage.DrawViewPort
      end;
  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));
    Img.Free;
    Img := nil;
    case StrIndex(vFileExt, Exts) of
      0:	Img := TsgCADdxfImage.Create;
      {$IFNDEF sgDFONLY}
      1:	Img := TsgDWGImage.Create;
      2..15:	Img := TsgHPGLImage.Create;
      16:     Img := TsgSVGImage.Create;
      17:     Img := TsgCGMImage.Create;
      {$ENDIF}
    end;
    if Img <> nil then
    begin
      Img.LoadFromFile(OpenPictureDialog1.FileName);
      ViewLayouts;
      Image1.Picture.Assign(Img);
    end;
  end;
end;

procedure TForm1.OpenPictureDialog1Show(Sender: TObject);
begin
  CADPreview := True;
end;

procedure TForm1.OpenPictureDialog1Close(Sender: TObject);
begin
  CADPreview := False;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  btnSaveAsTxt.Enabled := False;
  cbLayouts.Visible := False;
  lblLayouts.Visible := False;
  OpenPictureDialog1.Filter := GraphicFilter(TGraphic);
  {$IFDEF DEMO}
  fInfo.CreateInfoFrame(Handle, Point(10, 50));
  {$ENDIF}
end;

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

procedure TForm1.btnSaveAsTxtClick(Sender: TObject);
begin
  TextFile := TStringList.Create;
  try
    if Image1.Picture.Graphic is TsgCADImage then
    begin
      FCADParams.Matrix := cnstIdentityMat;
      TsgCADImage(Image1.Picture.Graphic).Converter.ImportMode := imImport;
      TsgCADImage(Image1.Picture.Graphic).Converter.AutoInsert := True; // to get all the elements inside of inserts
      TsgCADImage(Image1.Picture.Graphic).Converter.Params := @FCADParams;
      TsgCADImage(Image1.Picture.Graphic).CurrentLayout.Iterate(TsgCADImage(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 := FPointXMat(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 := FPointXMat(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 := FPointXMat(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 := FPointXMat(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 := FPointXMat(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 := FPointXMat(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 := FPointXMat(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 := FPointXMat(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 := FPointXMat(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 := FPointXMat(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 := FPointXMat(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;

procedure TForm1.ImportFlatPolyLine(Sender: TObject);
var
  Point: TFPoint;
  S: string;
  I, J, vCount, vIndex: Integer;

  procedure AddPoints(I: Integer);
  begin
    S := S + '   P' + ': ' + #13#10;
    Point := TsgFlatPoly(Sender).XY[I];
    S := S + '    X=' + FloatToStr(Point.X);
    S := S + '    Y=' + FloatToStr(Point.Y) + #13#10;;
  end;
begin
  S := S + ' 2D Points: ';
  S := S + #13#10;

  vIndex := 0;
  for I := 0 to TsgFlatPoly(Sender).Counts.Count-1 do
  begin
    vCount := Integer(TsgFlatPoly(Sender).Counts[I]);
    //if (vIndex + vCount) > FP.PCount then Break;
    if vCount > 2 then
    begin
      S := S + '   SubEntity ¹ ' + IntToStr(I) + ' - polyline' + #13#10;
      for J := vIndex to (vIndex + vCount - 1) do
      begin
        AddPoints(J);
      end;
    end
    else
      if vCount = 2 then
      begin
        S := S + '   SubEntity ¹ ' + IntToStr(I) + ' - single line' + #13#10;
        AddPoints(vIndex);
        AddPoints(vIndex+1);
      end;
    Inc(vIndex, vCount);
  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 := FPointXMat(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 := FPointXMat(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 := FPointXMat(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.
