unit Main;
{$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.

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, DXFExport, ExtCtrls, ExtDlgs, Menus, sgConsts, sgFunction
  {$IFDEF DEMO}, fInfo {$ENDIF}, sgLists;

type

  TfmDXFExporter = class(TForm)
    shpRectGreen: TShape;
    shpRectDotDashed: TShape;
    shpEllipseHor: TShape;
    shpCircle: TShape;
    btnFormShapes: TButton;
    SaveDialog: TSaveDialog;
    btnEmf2dxf: TButton;
    OpenPictureDialog: TOpenPictureDialog;
    btnPaintTo: TButton;
    lblSimple: TLabel;
    lblTextTimesBig: TLabel;
    lblTextAr: TLabel;
    btnSaveAsEMF: TButton;
    lblText16: TLabel;
    shpEllipseVer: TShape;
    shpRect: TShape;
    btnFormEmfDxf: TButton;
    MainMenu: TMainMenu;
    File1: TMenuItem;
    Exit1: TMenuItem;
    N2: TMenuItem;
    SaveAs1: TMenuItem;
    Save1: TMenuItem;
    Open1: TMenuItem;
    About1: TMenuItem;
    AboutDXFExporter1: TMenuItem;
    SaveEMFDialog: TSaveDialog;
    MakeDXFdirectly1: TMenuItem;
    cbParseWhite: TCheckBox;
    cbAlternativeBlack: TCheckBox;
    cbUse01MM: TCheckBox;
    cbAutoCADVer: TCheckBox;
    btnEmfs2DXF: TButton;
    edtPenWidthRatio: TEdit;
    lblPenWidthRatio: TLabel;
    lblDefaultHatchPatternScale: TLabel;
    edtDefaultHatchPatternScale: TEdit;
    edtDefaultLTypeScale: TEdit;
    lblLTypeScale: TLabel;
    cbUseUnicode: TCheckBox;
    lblUnitSize: TLabel;
    edtUnitSize: TEdit;
    cbBezierAsPolyline: TCheckBox;
    cbUseMetafileRatio: TCheckBox;
    btnMultiEmf2dxf: TButton;
    procedure btnFormShapesClick(Sender: TObject);
    procedure btnEmf2dxfClick(Sender: TObject);
    procedure btnPaintToClick(Sender: TObject);
    procedure btnSaveAsEMFClick(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure btnFormEmfDxfClick(Sender: TObject);
    procedure AboutDXFExporter1Click(Sender: TObject);
    procedure Exit1Click(Sender: TObject);
    procedure btnEmfs2DXFClick(Sender: TObject);
    procedure btnMultiEmf2dxfClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    procedure SetPenRatio(AExprt: TsgDXFExport);
    procedure SetDefaultHatchPatternScale(AExprt: TsgDXFExport);
    procedure SetDefaultLTypeScale(AExprt: TsgDXFExport);
    procedure SetUnitSize(AExprt: TsgDXFExport);
    procedure SetDXFParams(AExprt: TsgDXFExport);
  public
  end;



const countBezier = 13;
const arrBezier: array [0..countBezier-1] of TPoint = (
       (X:200;Y:230), (X:190;Y:310), (X:280;Y:330), (X:310;Y:310), (X:340;Y:290),
       (X:390;Y:270), (X:355;Y:225), (X:330;Y:240), (X:305;Y:255), (X:415;Y:255),
       (X:440;Y:240),  (X:480;Y:220), (X:430;Y:200));
const countPolyline = 13;
const arrPolyline: array [0..countPolyline-1] of TPoint = (
       (X:300;Y:200), (X:290;Y:280), (X:380;Y:300), (X:410;Y:280), (X:440;Y:260),
       (X:490;Y:240), (X:455;Y:195), (X:430;Y:210), (X:405;Y:225), (X:515;Y:225),
       (X:540;Y:210),  (X:580;Y:190), (X:530;Y:170));

var
  fmDXFExporter: TfmDXFExporter;

implementation

{$R *.DFM}


procedure TfmDXFExporter.btnEmf2dxfClick(Sender: TObject);
var
  vDXF: TsgDXFExport;
begin
  if not OpenPictureDialog.Execute then Exit;
  vDXF := TsgDXFExport.Create;
  try
    SetDXFParams(vDXF);
    vDXF.LoadFromFile(OpenPictureDialog.FileName);
    vDXF.SaveToFile(ChangeFileExt(OpenPictureDialog.FileName, '.dxf'));
  finally
    vDXF.Free;
  end;
end;

procedure TfmDXFExporter.btnEmfs2DXFClick(Sender: TObject);
var
  vDXF: TsgDXFExport;
  vLayer: TsgExpDXFLayer;
  I: Integer;
begin
  OpenPictureDialog.Options := OpenPictureDialog.Options + [ofAllowMultiSelect];
  if not OpenPictureDialog.Execute then Exit;
  vDXF := TsgDXFExport.Create;
  try
    SetDXFParams(vDXF);
    for I := 0 to OpenPictureDialog.Files.Count - 1 do
    begin
      vLayer := TsgExpDXFLayer.Create(ChangeFileExt(ExtractFileName(OpenPictureDialog.Files.Strings[I]), ''));//, IntToStr(I));
      vDXF.CurrentLayer := vLayer;
      vDXF.LoadFromFile(OpenPictureDialog.Files.Strings[I]);
    end;
    vDXF.SaveToFile(ExtractFilePath(OpenPictureDialog.FileName)+'WMFs-LAYERS.dxf');
  finally
    vDXF.Free;
  end;
end;

procedure TfmDXFExporter.btnMultiEmf2dxfClick(Sender: TObject);
var
  vDXF: TsgDXFExport;
  I: Integer;
begin
  OpenPictureDialog.Options := OpenPictureDialog.Options + [ofAllowMultiSelect];
  if not OpenPictureDialog.Execute then Exit;
  for I := 0 to OpenPictureDialog.Files.Count - 1 do
  begin
    vDXF := TsgDXFExport.Create;
    try
      SetDXFParams(vDXF);
      vDXF.LoadFromFile(OpenPictureDialog.Files.Strings[I]);
      vDXF.SaveToFile(ChangeFileExt(OpenPictureDialog.Files.Strings[I], '.dxf'));
    finally
      vDXF.Free;
    end;
  end;
end;

procedure TfmDXFExporter.btnPaintToClick(Sender: TObject);
var
  E: TsgDXFExport;
begin
  if not SaveDialog.Execute then Exit;
  E := TsgDXFExport.Create;
  DXFExport.OffsetY := Height; // Set OffsetY = height of the drawing
  // also you can use OffseX - OffsetY and OffsetX are for with metafiles only
  try
    PaintTo(E.Canvas.Handle, 0, 0);
    E.EndDraw;
    E.SaveToFile(SaveDialog.FileName);
  finally
    E.Free;
  end;
end;

procedure TfmDXFExporter.btnSaveAsEMFClick(Sender: TObject);
var
  vMet: TMetafile;
  vMetCanvas: TMetafileCanvas;
begin
  if not SaveEMFDialog.Execute then Exit;
  vMet := TMetafile.Create;
  try
    vMet.Width := Width;
    vMet.Height := Height;
    vMetCanvas := TMetafileCanvas.Create(vMet, 0);
    try
      PaintTo(vMetCanvas.Handle, 0, 0);
    finally
      vMetCanvas.Free;
    end;
    vMet.SaveToFile(SaveEMFDialog.FileName);
  finally
    vMet.Free;
  end;
end;

procedure TfmDXFExporter.FormCreate(Sender: TObject);
begin
{$IFDEF DEMO}
  fInfo.CreateInfoFrame(Handle, Point(btnPaintTo.Left + btnPaintTo.Width + 10, btnPaintTo.Top));
{$ENDIF}
end;

procedure TfmDXFExporter.FormPaint(Sender: TObject);
var
  vPos: TPoint;
begin
  Canvas.Pen.Color := clBlack;
  Canvas.PenPos := Point(180, 34);
  Canvas.LineTo(400, 34);
  Canvas.PenPos := Point(200, 200);
  Canvas.LineTo(250, 250);
  Canvas.Pen.Width := 20;
  Canvas.LineTo(150, 250);
  Canvas.Pen.Width := 0;
  Canvas.LineTo(200, 200);
  Canvas.Pen.Width := 5;
  Canvas.Pen.Color := TColor(RGB(149,122,165));
  Windows.PolyBezier(Canvas.Handle, arrBezier, countBezier);
  Canvas.Pen.Color := TColor($BD8D7E);
  Canvas.Pen.Width := 0;
  Canvas.Polyline(arrPolyline);
  //Windows.PolyLine(Canvas.Handle, arrPolyline, countPolyline);
  vPos := Point(380,160);
  Canvas.Pen.Color := TColor($08181);
  Canvas.Arc(10 +vPos.X, 10 +vPos.Y, 100+vPos.X, 200+vPos.Y, 55+vPos.X, 200+vPos.Y, 90+vPos.X, 20+vPos.Y);
  Canvas.Arc(120+vPos.X, 10 +vPos.Y, 210+vPos.X, 200+vPos.Y, 200+vPos.X, 20+vPos.Y, 165+vPos.X, 200+vPos.Y);
  Canvas.Arc(150+vPos.X, 100+vPos.Y, 250+vPos.X, 200+vPos.Y, 55+vPos.X, 200+vPos.Y, 90+vPos.X, 20+vPos.Y);
  Canvas.Arc(10 +vPos.X, 220+vPos.Y, 110+vPos.X, 270+vPos.Y, 80+vPos.X, 160+vPos.Y, -190+vPos.X, vPos.Y);
  Canvas.Arc(100+vPos.X, 220+vPos.Y, 200+vPos.X, 270+vPos.Y, -100+vPos.X, vPos.Y, 170+vPos.X, 160+vPos.Y);
end;

procedure TfmDXFExporter.btnFormEmfDxfClick(Sender: TObject);
var
  E: TsgDXFExport;
  vMet: TMetafile;
  vMetCanvas: TMetafileCanvas;
begin
  if not SaveDialog.Execute then Exit;
  E := TsgDXFExport.Create;
  SetDXFParams(E);
  try
    vMet := TMetafile.Create;
    try
      vMet.Width := Width;
      vMet.Height := Height;
      vMetCanvas := TMetafileCanvas.Create(vMet, 0);
      try
        // in the next line it is needed to draw elements in scale 1 pixel to 1 mm
        // linewidth - 1 pixel = 0.1 mm in DXF
        PaintTo(vMetCanvas.Handle, 0, 0);
      finally
        vMetCanvas.Free;
      end;
      E.LoadFromMetafile(vMet);
    finally
      vMet.Free;
    end;
    E.SaveToFile(SaveDialog.FileName);
  finally
    E.Free;
  end;
end;

//This method is obsolete but can be used.
//"Add entities" demo describes how to implement a new way
// of adding entities one by one.
procedure TfmDXFExporter.btnFormShapesClick(Sender: TObject);
var
  vDXF: TsgDXFExport;
  Data: TdxfExportData;
  vLayer: TsgExpDXFLayer;
  Pt: PexpPoint;
  I: Integer;
  vPatternDataList: TList;
  vPData: PdxfHatchPatternData;
  vDash1, vDash2, vDash3, vDash4, vDash5, vDash6, vDash7, L: Single;
  vDimStyle: TsgDimensionStyle;

  procedure FreeDataPoints;
  var
    J, K: Integer;
  begin
    for K := 0 to Data.Points.Count - 1 do
    begin
      for J := 0 to TList(Data.Points[K]).Count - 1 do
        Dispose(PexpPoint(TList(Data.Points[K]).Items[J]));
      TList(Data.Points[K]).Free;
    end;
    Data.Points.Free;
  end;

begin
//This method is obsolete but can be used.
//"Add entities" demo describes how to implement a new way
// of adding entities one by one.

  if not SaveDialog.Execute then
    Exit;
  vDXF := TsgDXFExport.Create;
  try
    if cbAutoCADVer.Checked then
      vDXF.AutoCADVer := R14
    else
      vDXF.AutoCADVer := R2000;
    //line types
    vDXF.AddLType('_SOLID',[5, 0]);
    vDXF.AddLType('_DASH',[5,-2]);
    vDXF.AddLType('_DOT', [2,-2]);
    vDXF.AddLType('_DASHDOT', [5,-2,2,-2]);
    vDXF.AddLType('_DASHDOTDOT', [5,-2,2,-2,2,-2]);
    vDXF.AddLType('ACADISO06W100', [24,-3,0,-3,0,-3,0,-3]);
    FillChar(Data, SizeOf(Data), 0);
    // blocks
    vDXF.BeginBlock('1');
      Data.Point.X := 0;
      Data.Point.Y := -3;
      Data.Point1.X := 10;
      Data.Point1.Y := 0;
      vDXF.AddRectangle(Data);

      FillChar(Data, SizeOf(Data), 0);

      Data.FHeight := 1;
      Data.Text := 'Block';
      Data.Point.X := 1;
      Data.Point.Y := -2;
      vDXF.AddText(Data);
    vDXF.EndBlock;

    vDXF.BeginBlock('2');
      FillChar(Data, SizeOf(Data), 0);
      Data.Color := DXF_OLIVE;
      Data.Point.X := 0;
      Data.Point.Y := 0;
      Data.Radius := 40;
      vDXF.AddCircle(Data);
    vDXF.EndBlock;

    vDXF.BeginBlock('3');
      FillChar(Data, SizeOf(Data), 0);
      Data.Color := clRed;
      Data.Count := 1;
      Data.Points := TList.Create;
      Data.Points.Add(TList.Create); // hatch can consist of more that one bound
      New(Pt);
      Pt^.X := 300;
      Pt^.Y := -100;
      Pt^.Z := 0.0;
      TList(Data.Points[0]).Add(Pt);
      New(Pt);
      Pt^.X := 0;
      Pt^.Y := -100;
      Pt^.Z := 0.0;
      TList(Data.Points[0]).Add(Pt);
      New(Pt);
      Pt^.X := 100;
      Pt^.Y := 0;
      Pt^.Z := 0.0;
      TList(Data.Points[0]).Add(Pt);
      Data.Style := Byte(hsFDiagonal);
      vDXF.Offset := 50;
      vDXF.AddHatch(Data);
      FreeDataPoints;
    vDXF.EndBlock;
    vDXF.BeginBlock('4'); // Bezier
      FillChar(Data, SizeOf(Data), 0);
      Data.Color := DXF_PURPLE;
      Data.Count := High(arrBezier)-Low(arrBezier)+1;
      Data.Points := TList.Create;
      Data.Points.Add(TList.Create);
      for I := 0 to Data.Count - 1 do
      begin
        New(Pt);
        Pt^.X := arrBezier[I].X;
        Pt^.Y := -arrBezier[I].Y;
        Pt^.Z := 0;
        TList(Data.Points[0]).Add(Pt);
      end;
      vDXF.AddPolyBezier(Data, 0);
      FreeDataPoints;
    vDXF.EndBlock;
    vDXF.SetLayerByString('0');

    // Entities

    // MTEXT (style=italic+underlined, font= "Courier New")
    FillChar(Data, SizeOf(Data), 0);
    Data.FHeight := 9;
    Data.Rotation := 0;
    Data.Text := '{\fCourier New|i1;\LRegister on www.cadsofttools.com}';
    Data.Point := MakeExpPoint(370, 60, 0);
    vDXF.AddMText(Data);

    // TEXT
    FillChar(Data, SizeOf(Data), 0);
    Data.FHeight := 50;
    Data.Rotation := 0;
    Data.Text := 'DXF Exporter';
    Data.Point := MakeExpPoint(57, 76, 0);
    vDXF.AddText(Data);

    // LINE
    FillChar(Data, SizeOf(Data), 0);
    Data.Color := DXF_TEAL;
    Data.Text := 'ACADISO06W100';// linetype
    Data.Thickness := 10;
    Data.Point := MakeExpPoint(10, 10, 0);
    Data.Point1 := MakeExpPoint(200, 10, 0);
    vDXF.AddLine(Data);

    // Rectangle POLYLINE
    FillChar(Data, SizeOf(Data), 0);
    Data.Color := clYellow;
    Data.Point.X := 80;
    Data.Point.Y := 10;
    Data.Point1.X := 120;
    Data.Point1.Y := 30;
    vDXF.AddRectangle(Data);

    // POLYLINE (closed)
    FillChar(Data, SizeOf(Data), 0);
    Data.Color := $224AF5;
    Data.GlobalWidth := 5;// Constant width DXF code 43
    Data.Points := TList.Create;
    Data.Points.Add(TList.Create);
    New(Pt);
    Pt^ := MakeExpPoint(310, -190, 0);
    TList(Data.Points[0]).Add(Pt);
    New(Pt);
    Pt^ := MakeExpPoint(-60, -100, 0);
    TList(Data.Points[0]).Add(Pt);
    New(Pt);
    Pt^ := MakeExpPoint(-60, 100, 0);
    TList(Data.Points[0]).Add(Pt);
    New(Pt);
    Pt^ := MakeExpPoint(20, 170, 0);
    TList(Data.Points[0]).Add(Pt);
    New(Pt);
    Pt^ := MakeExpPoint(600, 170, 0);
    TList(Data.Points[0]).Add(Pt);
    New(Pt);
    Pt^ := MakeExpPoint(680, 100, 0);
    TList(Data.Points[0]).Add(Pt);
    New(Pt);
    Pt^ := MakeExpPoint(680, -100, 0);
    TList(Data.Points[0]).Add(Pt);
    Data.Count := Data.Points.Count;
    Data.Flags := 1; // closed
    vDXF.AddPolyLine(Data, 0);// one boundary
    FreeDataPoints;

    // CIRCLE
    FillChar(Data, SizeOf(Data), 0);
    Data.Color := DXF_OLIVE;
    Data.Text := '_DASHDOT';
    Data.Thickness := 1;
    Data.Point := MakeExpPoint(12, 12, 0);
    Data.Radius := 45;
    vDXF.AddCircle(Data);

    // SOLID
    FillChar(Data, SizeOf(Data), 0);
    Data.Color := DXF_LIME;
    Data.Point := MakeExpPoint(240, -50, 0);
    Data.Point1 := MakeExpPoint(300, -40, 0);
    Data.Point2 := MakeExpPoint(260, -90, 0);
    Data.Point3 := MakeExpPoint(310, -80, 0);
    vDXF.AddSolid(Data);

    // ARC
    FillChar(Data, SizeOf(Data), 0);
    Data.Color := clGreen;
    Data.Text := '_DASH';
    Data.Thickness := 3;
    Data.Point.X := 100;
    Data.Point.Y := 20;
    Data.Radius := 30;
    Data.StartAngle := -90;
    Data.EndAngle := 90;
    vDXF.AddArc(Data);

    // ELLIPSE + elliptic HATCH
    FillChar(Data, SizeOf(Data), 0);
    Data.Point := MakeExpPoint(20, -70, 0);// center point
    Data.Point1 := MakeExpPoint(30, 30, 0);// endpoint of major axis (relative to the center)
    Data.Radius := 0.6;// ratio of minor axis to major axis
    Data.Color := 221;
    vDXF.AddEllipse(Data);
    // Data are not cleared for creation of HATCH with elliptic boundary!
    Data.Color := 240;
    Data.Style := Byte(hsCross);
    Data.SelfType := Byte(hbtEllipse);
    vDXF.AddHatch(Data);

    //================begin of HATCH with pattern data=============
    vLayer := TsgExpDXFLayer.Create('Hatch_with_pattern_data');
    vDXF.CurrentLayer := vLayer;
    FillChar(Data, SizeOf(Data), 0);
    Data.Color := $68190;
    Data.Points := TList.Create;
    // first boundary
    Data.Points.Add(TList.Create);
    New(Pt);
    Pt^ := MakeExpPoint(400, 0.0, 0.0);
    TList(Data.Points[0]).Add(Pt);
    New(Pt);
    Pt^ := MakeExpPoint(400, -100.0, 0.0);
    TList(Data.Points[0]).Add(Pt);
    New(Pt);
    Pt^ := MakeExpPoint(600, -100.0, 0.0);
    TList(Data.Points[0]).Add(Pt);
    New(Pt);
    Pt^ := MakeExpPoint(600, 0.0, 0.0);
    TList(Data.Points[0]).Add(Pt);
    New(Pt);
    Pt^ := MakeExpPoint(400, 0.0, 0.0);
    TList(Data.Points[0]).Add(Pt);
    // second boundary
    Data.Points.Add(TList.Create);
    New(Pt);
    Pt^ := MakeExpPoint(420, -30.0, 0.0);
    TList(Data.Points[1]).Add(Pt);
    New(Pt);
    Pt^ := MakeExpPoint(430, -70.0, 0.0);
    TList(Data.Points[1]).Add(Pt);
    New(Pt);
    Pt^ := MakeExpPoint(560, -80.0, 0.0);
    TList(Data.Points[1]).Add(Pt);
    New(Pt);
    Pt^ := MakeExpPoint(580, -50.0, 0.0);
    TList(Data.Points[1]).Add(Pt);
    New(Pt);
    Pt^ := MakeExpPoint(540, -20.0, 0.0);
    TList(Data.Points[1]).Add(Pt);
    New(Pt);
    Pt^ := MakeExpPoint(420, -30.0, 0.0);
    TList(Data.Points[1]).Add(Pt);
    // third boundary
    Data.Points.Add(TList.Create);
    New(Pt);
    Pt^ := MakeExpPoint(490, -35.0, 0.0);
    TList(Data.Points[2]).Add(Pt);
    New(Pt);
    Pt^ := MakeExpPoint(460, -60.0, 0.0);
    TList(Data.Points[2]).Add(Pt);
    New(Pt);
    Pt^ := MakeExpPoint(540, -50.0, 0.0);
    TList(Data.Points[2]).Add(Pt);
    New(Pt);
    Pt^ := MakeExpPoint(490, -35.0, 0.0);
    TList(Data.Points[2]).Add(Pt);
    // pattern data
    {
    vDash1 := 12;
    vDash2 := -4;
    vPatternDataList := TList.Create;
    New(vPData);
    vPData^.Angle := 45;
    vPData^.BasePointX := 0;
    vPData^.BasePointY := 0;
    vPData^.OffsetX := 0;
    vPData^.OffsetY := 5.656854;
    vPData^.DashLengths := TList.Create;
    vPData^.DashLengths.Add(Pointer(vDash1));
    vPData^.DashLengths.Add(Pointer(vDash2));
    vPatternDataList.Add(vPData);
    New(vPData);
    vPData^.Angle := 135;
    vPData^.BasePointX := 2.828427;
    vPData^.BasePointY := 2.828427;
    vPData^.OffsetX := 0;
    vPData^.OffsetY := 5.656854;
    vPData^.DashLengths := TList.Create;
    vPData^.DashLengths.Add(Pointer(vDash1));
    vPData^.DashLengths.Add(Pointer(vDash2));
    vPatternDataList.Add(vPData);
    Data.Style := Byte(hsPatternData);
    Data.Scale.X := 5;
    Data.Rotation := 0.0;
    Data.Count := Data.Points.Count;
    vDXF.AddHatchEx(Data, vPatternDataList, 'AR-HBONE', hidsNormal, hptPredefined);
    {}

    {"SOFT-GOLD" hatch custom pattern data example}
    L := 1;
    vDash1 := 2 * L;
    vDash2 := - 2 * L;
    vDash3 := L;
    vDash4 := - L;
    vDash5 := - 3 * L;
    vDash6 := vDash2 + vDash5;
    vDash7 := 2 * vDash1;
    vPatternDataList := TList.Create;
    New(vPData);
    vPData^.Angle := 0;
    vPData^.BasePointX := 0;
    vPData^.BasePointY := 0;
    vPData^.OffsetX := 8 * L;
    vPData^.OffsetY := 7 * L;
    vPData^.DashLengths := TsgSingleList.Create;
    vPData^.DashLengths.Add(vDash1);
    vPData^.DashLengths.Add(vDash4);
    vPData^.DashLengths.Add(vDash1);
    vPData^.DashLengths.Add(vDash5);
    vPatternDataList.Add(vPData);
    New(vPData);
    vPData^.Angle := 0;
    vPData^.BasePointX := 0;
    vPData^.BasePointY := 4 * L;
    vPData^.OffsetX := 8 * L;
    vPData^.OffsetY := 7 * L;
    vPData^.DashLengths := TsgSingleList.Create;
    vPData^.DashLengths.Add(vDash1);
    vPData^.DashLengths.Add(vDash4);
    vPData^.DashLengths.Add(vDash1);
    vPData^.DashLengths.Add(vDash5);
    vPatternDataList.Add(vPData);
    New(vPData);
    vPData^.Angle := 0;
    vPData^.BasePointX := 0;
    vPData^.BasePointY := 2 * L;
    vPData^.OffsetX := 8 * L;
    vPData^.OffsetY := 7 * L;
    vPData^.DashLengths := TsgSingleList.Create;
    vPData^.DashLengths.Add(vDash1);
    vPData^.DashLengths.Add(vDash2);
    vPData^.DashLengths.Add(vDash3);
    vPData^.DashLengths.Add(vDash5);
    vPatternDataList.Add(vPData);
    New(vPData);
    vPData^.Angle := 90;
    vPData^.BasePointX := 0;
    vPData^.BasePointY := 0;
    vPData^.OffsetX := 8 * L;
    vPData^.OffsetY := 7 * L;
    vPData^.DashLengths := TsgSingleList.Create;
    vPData^.DashLengths.Add(vDash2);
    vPData^.DashLengths.Add(vDash1);
    vPData^.DashLengths.Add(vDash5);
    vPatternDataList.Add(vPData);
    New(vPData);
    vPData^.Angle := 90;
    vPData^.BasePointX := 2 * L;
    vPData^.BasePointY := 0;
    vPData^.OffsetX := 8 * L;
    vPData^.OffsetY := 7 * L;
    vPData^.DashLengths := TsgSingleList.Create;
    vPData^.DashLengths.Add(vDash1);
    vPData^.DashLengths.Add(vDash6);
    vPatternDataList.Add(vPData);
    New(vPData);
    vPData^.Angle := 90;
    vPData^.BasePointX := 3 * L;
    vPData^.BasePointY := 0;
    vPData^.OffsetX := 8 * L;
    vPData^.OffsetY := 7 * L;
    vPData^.DashLengths := TsgSingleList.Create;
    vPData^.DashLengths.Add(vDash7);
    vPData^.DashLengths.Add(vDash5);
    vPatternDataList.Add(vPData);
    New(vPData);
    vPData^.Angle := 90;
    vPData^.BasePointX := 5 * L;
    vPData^.BasePointY := 0;
    vPData^.OffsetX := 8 * L;
    vPData^.OffsetY := 7 * L;
    vPData^.DashLengths := TsgSingleList.Create;
    vPData^.DashLengths.Add(vDash1);
    vPData^.DashLengths.Add(vDash6);
    vPatternDataList.Add(vPData);
    Data.Style := Byte(hsPatternData);
    Data.Scale.X := 1;
    Data.Rotation := 0.0;
    Data.Count := Data.Points.Count;
    vDXF.AddHatchEx(Data, vPatternDataList, 'SOFT-GOLD', hidsNormal, hptUserDefined);

    { "EARTH" hatch predefined pattern data example
    vDash1 := 0.25;
    vDash2 := -0.25;
    vPatternDataList := TList.Create;
    New(vPData);
    vPData^.Angle := 0;
    vPData^.BasePointX := 0;
    vPData^.BasePointY := 0;
    vPData^.OffsetX := vDash1;
    vPData^.OffsetY := vDash1;
    vPData^.DashLengths := TList.Create;
    vPData^.DashLengths.Add(Pointer(vDash1));
    vPData^.DashLengths.Add(Pointer(vDash2));
    vPatternDataList.Add(vPData);
    New(vPData);
    vPData^.Angle := 0;
    vPData^.BasePointX := 0;
    vPData^.BasePointY := 0.09375;
    vPData^.OffsetX := vDash1;
    vPData^.OffsetY := vDash1;
    vPData^.DashLengths := TList.Create;
    vPData^.DashLengths.Add(Pointer(vDash1));
    vPData^.DashLengths.Add(Pointer(vDash2));
    vPatternDataList.Add(vPData);
    New(vPData);
    vPData^.Angle := 0;
    vPData^.BasePointX := 0;
    vPData^.BasePointY := 0.1875;
    vPData^.OffsetX := vDash1;
    vPData^.OffsetY := vDash1;
    vPData^.DashLengths := TList.Create;
    vPData^.DashLengths.Add(Pointer(vDash1));
    vPData^.DashLengths.Add(Pointer(vDash2));
    vPatternDataList.Add(vPData);
    New(vPData);
    vPData^.Angle := 90;
    vPData^.BasePointX := 0.03125;
    vPData^.BasePointY := 0.21875;
    vPData^.OffsetX := vDash2;
    vPData^.OffsetY := vDash1;
    vPData^.DashLengths := TList.Create;
    vPData^.DashLengths.Add(Pointer(vDash1));
    vPData^.DashLengths.Add(Pointer(vDash2));
    vPatternDataList.Add(vPData);
    New(vPData);
    vPData^.Angle := 90;
    vPData^.BasePointX := 0.125;
    vPData^.BasePointY := 0.21875;
    vPData^.OffsetX := vDash2;
    vPData^.OffsetY := vDash1;
    vPData^.DashLengths := TList.Create;
    vPData^.DashLengths.Add(Pointer(vDash1));
    vPData^.DashLengths.Add(Pointer(vDash2));
    vPatternDataList.Add(vPData);
    New(vPData);
    vPData^.Angle := 90;
    vPData^.BasePointX := 0.21875;
    vPData^.BasePointY := 0.21875;
    vPData^.OffsetX := vDash2;
    vPData^.OffsetY := vDash1;
    vPData^.DashLengths := TList.Create;
    vPData^.DashLengths.Add(Pointer(vDash1));
    vPData^.DashLengths.Add(Pointer(vDash2));
    vPatternDataList.Add(vPData);
    Data.Style := Byte(hsPatternData);
    Data.Scale.X := 20;
    Data.Rotation := 0.0;
    Data.Count := Data.Points.Count;
    vDXF.AddHatchEx(Data, vPatternDataList, 'EARTH', hidsNormal, hptPredefined);
    {}

    // POLYLINE (based on the border of the previous HATCH)
    Data.Color := $424F35;
    for I := 0 to Data.Points.Count - 1 do
      vDXF.AddPolyLine(Data, I);
    // vPatternDataList - do not delete!!!
    FreeDataPoints;
    //================end of Hatch with pattern data=============

    //=====================begin of Dimensions ==================
    vLayer := TsgExpDXFLayer.Create('Dimensions');
    vDXF.CurrentLayer := vLayer;
    FillChar(Data, SizeOf(Data), 0);
    Data.Color := DXF_WHITE;
    Data.Point := MakeExpPoint(400, 10.0, 0.0);
    Data.Point1 := MakeExpPoint(430, 30.0, 0.0);
    vDXF.AddRectangle(Data);

    FillChar(Data, SizeOf(Data), 0);
    vDimStyle.Arrow1 := datOpen;
    vDimStyle.Arrow2 := datNone;
    vDimStyle.ArrowSize := 3.0;
    vDimStyle.ExtLineExt := 0.5;
    vDimStyle.ExtLineOffset := 0.1;
    vDimStyle.TextOffset := 0.1;
    vDimStyle.TextHeight := 1;
    Data.StyleObject := @vDimStyle;
    Data.Color := DXF_GREEN;
    Data.Text := 'Text override';
    Data.Point := MakeExpPoint(440, 20.0, 0.0);
    Data.Point1 := MakeExpPoint(430, 10.0, 0.0);
    Data.Point2 := MakeExpPoint(430, 30.0, 0.0);
    vDXF.AddDimension(Data);

    FillChar(Data, SizeOf(Data), 0);
    vDimStyle.Arrow1 := datClosed;
    vDimStyle.Arrow2 := datClosedFilled;
    vDimStyle.ArrowSize := 1.0;
    vDimStyle.ExtLineExt := 0.1;
    vDimStyle.ExtLineOffset := 0.1;
    vDimStyle.TextOffset := 0.1;
    vDimStyle.TextHeight := 0.5;
    Data.StyleObject := @vDimStyle;
    Data.Color := DXF_GREEN;
    Data.Point := MakeExpPoint(410, 35.0, 0.0);
    Data.Point1 := MakeExpPoint(400, 30.0, 0.0);
    Data.Point2 := MakeExpPoint(430, 30.0, 0.0);
    vDXF.AddDimension(Data);

    FillChar(Data, SizeOf(Data), 0);
    vDimStyle.Arrow1 := datClosedFilled;
    vDimStyle.Arrow2 := datClosedBlank;
    vDimStyle.ArrowSize := 5.0;
    vDimStyle.ExtLineExt := 0.5;
    vDimStyle.ExtLineOffset := 0.4;
    vDimStyle.TextOffset := 0.4;
    vDimStyle.TextHeight := 2;
    Data.StyleObject := @vDimStyle;
    Data.Color := DXF_TEAL;
    Data.Point := MakeExpPoint(390, 20.0, 0.0);
    Data.Point1 := MakeExpPoint(400, 10.0, 0.0);
    Data.Point2 := MakeExpPoint(400, 30.0, 0.0);
    vDXF.AddDimension(Data);

    FillChar(Data, SizeOf(Data), 0);
    vDimStyle.Arrow1 := datOrigin;
    vDimStyle.Arrow2 := datOrigin2;
    vDimStyle.ArrowSize := 2.0;
    vDimStyle.ExtLineExt := 0.18;
    vDimStyle.ExtLineOffset := 0.2;
    vDimStyle.TextOffset := 0.2;
    vDimStyle.TextHeight := 1.5;
    Data.StyleObject := @vDimStyle;
    Data.Color := DXF_TEAL;
    Data.Point := MakeExpPoint(410, 5.0, 0.0);
    Data.Point1 := MakeExpPoint(400, 10.0, 0.0);
    Data.Point2 := MakeExpPoint(430, 10.0, 0.0);
    vDXF.AddDimension(Data);
    //=====================end of Dimensions ====================
    FillChar(Data, SizeOf(Data), 0);
    vLayer := TsgExpDXFLayer.Create('Blocks');
    vDXF.CurrentLayer := vLayer;
    Data.Thickness := 0;
    Data.Text := '1';
    Data.Point.X := 70;
    Data.Point.Y := -30;
    Data.Scale.X := 3;
    Data.Scale.Y := 3;
    vDXF.Insert(Data);

    Data.Text := '1';
    Data.Point.Y := -40;
    Data.Scale.X := 5;
    Data.Scale.Y := 5;
    vDXF.Insert(Data);

    Data.Point.Y := -60;
    Data.Scale.X := 10;
    Data.Scale.Y := 10;
    vDXF.Insert(Data);

    FillChar(Data, SizeOf(Data), 0);
    Data.Text := '2';
    Data.Point.X := 12;
    Data.Point.Y := 80;
    Data.Scale.X := 1;
    Data.Scale.Y := 1;
    vDXF.Insert(Data);

    FillChar(Data, SizeOf(Data), 0);
    vLayer := TsgExpDXFLayer.Create('Hatch');
    vDXF.CurrentLayer := vLayer;
    Data.Text := '3';
    Data.Point.X := 120;
    Data.Point.Y := 80;
    Data.Scale.X := 1;
    Data.Scale.Y := 1;
    vDXF.Insert(Data);
    FillChar(Data, SizeOf(Data), 0);
    vLayer := TsgExpDXFLayer.Create('Bezier');
    vDXF.CurrentLayer := vLayer;
    Data.Text := '4';
    Data.Point.X := 0;
    Data.Point.Y := 200;
    Data.Scale.X := 1;
    Data.Scale.Y := 1;
    vDXF.Insert(Data);
    vDXF.SaveToFile(SaveDialog.FileName);
  finally
    vDXF.Free;
  end;
end;

procedure TfmDXFExporter.AboutDXFExporter1Click(Sender: TObject);
begin
  ShowMessage('DXF Exporter SDK ' + #13 +
    'www.cadsofttools.com');
end;

procedure TfmDXFExporter.Exit1Click(Sender: TObject);
begin
  Close;
end;


procedure TfmDXFExporter.SetPenRatio(AExprt: TsgDXFExport);
var
  DS: Char;
begin
  DS := SetDecimalSeparator('.');
  try
    AExprt.PenWidthRatio := ConvToFloatDef(edtPenWidthRatio.Text, -1.0);
  finally
    SetDecimalSeparator(DS);
  end;
end;

procedure TfmDXFExporter.SetDefaultHatchPatternScale(AExprt: TsgDXFExport);
var
  DS: Char;
begin
  DS := SetDecimalSeparator('.');
  try
    AExprt.DefaultHatchPatternScale := ConvToFloatDef(edtDefaultHatchPatternScale.Text, 1.0);
    if AExprt.DefaultHatchPatternScale < 0 then
    begin
      Windows.MessageBox(Handle, PChar('Value "'+edtDefaultHatchPatternScale.Text+
        '" is discarded.'#13'The HatchScale value must be more than 0.'), PChar('Warning'), MB_OK or MB_ICONWARNING);
      edtDefaultHatchPatternScale.Text := '1.0';
      AExprt.DefaultHatchPatternScale := 1.0;
    end;
  finally
    SetDecimalSeparator(DS);
  end;
end;

procedure TfmDXFExporter.SetDefaultLTypeScale(AExprt: TsgDXFExport);
var
  DS: Char;
begin
  DS := SetDecimalSeparator('.');
  try
    AExprt.DefaultLTypeScale := ConvToFloatDef(edtDefaultLTypeScale.Text, 1.0);
    if AExprt.DefaultLTypeScale < 0 then
    begin
      Windows.MessageBox(Handle, PChar('Value "'+edtDefaultLTypeScale.Text+
        '" is discarded.'#13'The LTypeScale value must be more than 0.'), PChar('Warning'), MB_OK or MB_ICONWARNING);
      edtDefaultLTypeScale.Text := '1.0';
      AExprt.DefaultLTypeScale := 1.0;
    end;
  finally
    SetDecimalSeparator(DS);
  end;
end;

procedure TfmDXFExporter.SetUnitSize(AExprt: TsgDXFExport);
var
  DS: Char;
begin
  DS := SetDecimalSeparator('.');
  try
    AExprt.UnitSize := ConvToFloatDef(edtUnitSize.Text, 1.0);
    if AExprt.UnitSize < 0 then
    begin
      Windows.MessageBox(Handle, PChar('Value "'+edtUnitSize.Text+
        '" is discarded.'#13'The UnitSize value must be more than 0.'), PChar('Warning'), MB_OK or MB_ICONWARNING);
      edtUnitSize.Text := '1.0';
      AExprt.UnitSize := 1.0;
    end;
  finally
    SetDecimalSeparator(DS);
  end;
end;

procedure TfmDXFExporter.SetDXFParams(AExprt: TsgDXFExport);
begin
  AExprt.BezierAsPolylines := cbBezierAsPolyline.Checked;
  AExprt.IsParseWhite := cbParseWhite.Checked;
  AExprt.UseUnicode := cbUseUnicode.Checked;
  AExprt.UseMetafileRatio := cbUseMetafileRatio.Checked;
  AExprt.Use01MM := cbUse01MM.Checked;
  if cbAutoCADVer.Checked then
    AExprt.AutoCADVer := R14
  else
    AExprt.AutoCADVer := R2000;
  AlternativeBlack := cbAlternativeBlack.Checked;
  SetPenRatio(AExprt);
  SetDefaultHatchPatternScale(AExprt);
  SetDefaultLTypeScale(AExprt);
  SetUnitSize(AExprt);
end;

end.
