{*******************************************}
{ TClusteringTool and Editor Dialog         }
{ Copyright (c) 2012-2020 by Steema Software}
{*******************************************}
unit TeeClusteringToolEditor;
{$I TeeDefs.inc}

interface

uses
  {$IFDEF MSWINDOWS}
  Windows, Messages,
  {$ENDIF}

  SysUtils, Classes,

  Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, ComCtrls,
  TeCanvas, TeEngine, TeeClusteringTool, TeeToolSeriesEdit, TeePenDlg, TeeProcs;

type
  TClusteringToolEditor = class(TSeriesToolEditor)
    PageControl1: TPageControl;
    TabSheet1: TTabSheet;
    TabCalc: TTabSheet;
    Panel2: TPanel;
    Button4: TButton;
    Label4: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    Label2: TLabel;
    LLambda: TLabel;
    Label7: TLabel;
    LDepth: TLabel;
    CBMethod: TComboFlat;
    CBDistance: TComboFlat;
    CBLinkage: TComboFlat;
    ECount: TEdit;
    ELambda: TEdit;
    EQTMin: TEdit;
    EQTMax: TEdit;
    EDepth: TEdit;
    UDDepth: TUpDown;
    Label3: TLabel;
    TabSheet2: TTabSheet;
    CBColorEach: TCheckBox;
    CBBounds: TCheckBox;
    LBClusters: TListBox;
    Memo1: TMemo;
    Label8: TLabel;
    TBTransp: TTrackBar;
    TabFormat: TTabSheet;
    PageFormat: TPageControl;
    TabCentroids: TTabSheet;
    TabCenter: TTabSheet;
    TabBorder: TTabSheet;
    TabPattern: TTabSheet;
    procedure CBDistanceChange(Sender: TObject);
    procedure ELambdaChange(Sender: TObject);
    procedure CBMethodChange(Sender: TObject);
    procedure CBLinkageChange(Sender: TObject);
    procedure ECountChange(Sender: TObject);
    procedure EQTMinChange(Sender: TObject);
    procedure EQTMaxChange(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure CBColorEachClick(Sender: TObject);
    procedure CBBoundsClick(Sender: TObject);
    procedure LBClustersClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure TBTranspChange(Sender: TObject);
    procedure PageControl1Change(Sender: TObject);
    procedure PageFormatChange(Sender: TObject);
  private
    { Private declarations }
    Tool : TClusteringTool;

    procedure FillClusters;
  public
    { Public declarations }
  end;

implementation

{$IFNDEF LCL}
{$R *.DFM}
{$ELSE}
{$R *.lfm}
{$ENDIF}

uses
  Chart, TeePoEdi, TeeBrushDlg, TeeClustering;

procedure TClusteringToolEditor.CBDistanceChange(Sender: TObject);
begin
  Tool.Distance:=TDistanceMethod(CBDistance.ItemIndex);

  LLambda.Enabled:=(Tool.Distance=dmMinkowski);
  ELambda.Enabled:=LLambda.Enabled;
end;

procedure TClusteringToolEditor.ELambdaChange(Sender: TObject);
begin
  Tool.MinkowskiLambda:=StrToFloat(ELambda.Text);
end;

procedure TClusteringToolEditor.CBMethodChange(Sender: TObject);
begin
  Tool.Method:=TClusteringMethod(CBMethod.ItemIndex);

  EDepth.Enabled:=(Tool.Method=cmHierarchical);
  UDDepth.Enabled:=EDepth.Enabled;
  LDepth.Enabled:=EDepth.Enabled;

  ECount.Enabled:=(Tool.Method<>cmQT);

  if ECount.Enabled then
     if Tool.Method=cmKMeans then
        ECount.Text:=IntToStr(Tool.KMeans.NumClusters)
     else
        ECount.Text:=IntToStr(Tool.Hierarchical.NumClusters);

  EQTMin.Enabled:=(Tool.Method=cmQT);
  EQTMax.Enabled:=EQTMin.Enabled;

  FillClusters;
end;

procedure TClusteringToolEditor.CBLinkageChange(Sender: TObject);
begin
  Tool.Linkage:=TLinkageMethod(CBLinkage.ItemIndex);
end;

procedure TClusteringToolEditor.ECountChange(Sender: TObject);
begin
  if Tool.Method=cmKMeans then
     Tool.KMeans.NumClusters:=StrToInt(ECount.Text)
  else
     Tool.Hierarchical.NumClusters:=StrToInt(ECount.Text)
end;

procedure TClusteringToolEditor.EQTMinChange(Sender: TObject);
begin
  Tool.QTClustering.MinCount:=StrToInt(EQTMin.Text);
end;

procedure TClusteringToolEditor.EQTMaxChange(Sender: TObject);
begin
  Tool.QTClustering.MaxDiameter:=StrToFloat(EQTMax.Text);
end;

procedure TClusteringToolEditor.FormShow(Sender: TObject);
begin
  inherited;

  Tool:=TClusteringTool(Tag);

  if Assigned(Tool) then
  with Tool do
  begin
    CBMethod.ItemIndex:=Ord(Method);
    CBDistance.ItemIndex:=Ord(Distance);
    CBLinkage.ItemIndex:=Ord(Linkage);

    CBColorEach.Checked:=ColorEach;
    CBBounds.Checked:=ShowBounds;

    ECount.Enabled:=Method<>cmQT;

    if ECount.Enabled then
       if Method=cmKMeans then
          ECount.Text:=IntToStr(KMeans.NumClusters)
       else
          ECount.Text:=IntToStr(Hierarchical.NumClusters);

    ELambda.Text:=FloatToStr(MinkowskiLambda);
    EQTMin.Text:=IntToStr(QTClustering.MinCount);
    EQTMax.Text:=FloatToStr(QTClustering.MaxDiameter);

    TBTransp.Position:=Transparency;

    FillClusters;
  end;
end;

procedure TClusteringToolEditor.Button4Click(Sender: TObject);
begin
  Tool.Execute;
  FillClusters;
end;

procedure TClusteringToolEditor.CBColorEachClick(Sender: TObject);
begin
  Tool.ColorEach:=CBColorEach.Checked;
end;

procedure TClusteringToolEditor.CBBoundsClick(Sender: TObject);
begin
  Tool.ShowBounds:=CBBounds.Checked;
end;

procedure TClusteringToolEditor.LBClustersClick(Sender: TObject);
var tmp : TCluster;
begin
  tmp:=TCluster(LBClusters.Items.Objects[LBClusters.ItemIndex]);

  with Memo1.Lines do
  begin
    Clear;

    Add('Points: '+IntToStr(tmp.Count));

    with Tool.Data(tmp) do
         Add('Center: '+FormatFloat('0.000',X)+' '+FormatFloat('0.000',Y));

    with Tool.GetStats(tmp) do
    begin
      Add('Covariance: '+FormatFloat('0.0000',CoVariance));
      Add('Correlation: '+FormatFloat('0.0000',Correlation));
      Add('Sum of Squares: '+FormatFloat('0.0000',SumOfSquares));
    end;
  end;
end;

procedure TClusteringToolEditor.FillClusters;
var t : Integer;
begin
  Memo1.Lines.Clear;
  LBClusters.Items.Clear;

  with Tool.Clusters do
  for t:=0 to Count-1 do
      LBClusters.Items.AddObject(IntToStr(t), Items[t]);

  if LBClusters.Items.Count>0 then
  begin
    LBClusters.ItemIndex:=0;
    LBClustersClick(Self);
  end;
end;

procedure TClusteringToolEditor.FormCreate(Sender: TObject);
begin
  inherited;
  PageControl1.ActivePage:=TabSheet1;
end;

procedure TClusteringToolEditor.TBTranspChange(Sender: TObject);
begin
  Tool.Transparency:=TBTransp.Position;
end;

procedure TClusteringToolEditor.PageControl1Change(Sender: TObject);
begin
  inherited;

  if PageControl1.ActivePage=TabFormat then
     PageFormatChange(Self);
end;

procedure TClusteringToolEditor.PageFormatChange(Sender: TObject);
begin
  inherited;

  if PageFormat.ActivePage.ControlCount=0 then
     if PageFormat.ActivePage=TabCentroids then
        TSeriesPointerEditor.InsertForm(Tool.Centroids,TabCentroids)
     else
     if PageFormat.ActivePage=TabCenter then
        TSeriesPointerEditor.InsertForm(Tool.Centers,TabCenter)
     else
     if PageFormat.ActivePage=TabBorder then
        TPenDialog.InsertForm(Tool.Pen,TabBorder)
     else
     if PageFormat.ActivePage=TabPattern then
        TBrushDialog.AddDialog(Tool.Brush,TabPattern);
end;

initialization
  RegisterClass(TClusteringToolEditor);
end.
