1900 lines
		
	
	
		
			54 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			1900 lines
		
	
	
		
			54 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
{
 | 
						|
     Apophysis Copyright (C) 2001-2004 Mark Townsend
 | 
						|
 | 
						|
     This program is free software; you can redistribute it and/or modify
 | 
						|
     it under the terms of the GNU General Public License as published by
 | 
						|
     the Free Software Foundation; either version 2 of the License, or
 | 
						|
     (at your option) any later version.
 | 
						|
 | 
						|
     This program is distributed in the hope that it will be useful,
 | 
						|
     but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
     GNU General Public License for more details.
 | 
						|
 | 
						|
     You should have received a copy of the GNU General Public License
 | 
						|
     along with this program; if not, write to the Free Software
 | 
						|
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
						|
}
 | 
						|
//{$D-,L-,O+,Q-,R-,Y-,S-}
 | 
						|
unit Editor;
 | 
						|
 | 
						|
interface
 | 
						|
 | 
						|
uses
 | 
						|
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 | 
						|
  ExtCtrls, StdCtrls, ComCtrls, Math, Menus, ToolWin, Registry, MyTypes,
 | 
						|
  ControlPoint, Render, cmap, Grids, ValEdit;
 | 
						|
 | 
						|
const
 | 
						|
//  PixelCountMax = 32768;
 | 
						|
  WM_PTHREAD_COMPLETE = WM_APP + 5438;
 | 
						|
 | 
						|
type
 | 
						|
  TEditForm = class(TForm)
 | 
						|
    GrphPnl: TPanel;
 | 
						|
    GraphImage: TImage;
 | 
						|
    StatusBar: TStatusBar;
 | 
						|
    ControlPanel: TPanel;
 | 
						|
    lblTransform: TLabel;
 | 
						|
    PrevPnl: TPanel;
 | 
						|
    PreviewImage: TImage;
 | 
						|
    EditPopup: TPopupMenu;
 | 
						|
    mnuLockSel: TMenuItem;
 | 
						|
    MenuItem1: TMenuItem;
 | 
						|
    mnuDelete: TMenuItem;
 | 
						|
    mnuDuplicate: TMenuItem;
 | 
						|
    MenuItem2: TMenuItem;
 | 
						|
    mnuAdd: TMenuItem;
 | 
						|
    mnuAutoZoom: TMenuItem;
 | 
						|
    N1: TMenuItem;
 | 
						|
    mnuUndo: TMenuItem;
 | 
						|
    mnuRedo: TMenuItem;
 | 
						|
    QualityPopup: TPopupMenu;
 | 
						|
    mnuLowQuality: TMenuItem;
 | 
						|
    mnuMediumQuality: TMenuItem;
 | 
						|
    mnuHighQuality: TMenuItem;
 | 
						|
    N3: TMenuItem;
 | 
						|
    mnuResetLocation: TMenuItem;
 | 
						|
    mnuVerticalFlipAll: TMenuItem;
 | 
						|
    N4: TMenuItem;
 | 
						|
    mnuHorizintalFlipAll: TMenuItem;
 | 
						|
    N5: TMenuItem;
 | 
						|
    mnuFlipVertical: TMenuItem;
 | 
						|
    mnuFlipHorizontal: TMenuItem;
 | 
						|
    cbTransforms: TComboBox;
 | 
						|
    N6: TMenuItem;
 | 
						|
    PageControl: TPageControl;
 | 
						|
    TabSheet1: TTabSheet;
 | 
						|
    Label7: TLabel;
 | 
						|
    Label8: TLabel;
 | 
						|
    Label9: TLabel;
 | 
						|
    Label10: TLabel;
 | 
						|
    Label11: TLabel;
 | 
						|
    Label12: TLabel;
 | 
						|
    txtAx: TEdit;
 | 
						|
    txtAy: TEdit;
 | 
						|
    txtBx: TEdit;
 | 
						|
    txtBy: TEdit;
 | 
						|
    txtCx: TEdit;
 | 
						|
    txtCy: TEdit;
 | 
						|
    chkPreserve: TCheckBox;
 | 
						|
    XForm: TTabSheet;
 | 
						|
    lbla: TLabel;
 | 
						|
    Label1: TLabel;
 | 
						|
    Label2: TLabel;
 | 
						|
    Label3: TLabel;
 | 
						|
    Label4: TLabel;
 | 
						|
    Label5: TLabel;
 | 
						|
    Label6: TLabel;
 | 
						|
    Label29: TLabel;
 | 
						|
    txtA: TEdit;
 | 
						|
    txtB: TEdit;
 | 
						|
    txtC: TEdit;
 | 
						|
    txtD: TEdit;
 | 
						|
    txtE: TEdit;
 | 
						|
    txtF: TEdit;
 | 
						|
    txtP: TEdit;
 | 
						|
    txtSymmetry: TEdit;
 | 
						|
    TabSheet3: TTabSheet;
 | 
						|
    VEVars: TValueListEditor;
 | 
						|
    TabSheet2: TTabSheet;
 | 
						|
    GroupBox1: TGroupBox;
 | 
						|
    scrlXFormColor: TScrollBar;
 | 
						|
    pnlXFormColor: TPanel;
 | 
						|
    txtXFormColor: TEdit;
 | 
						|
    GroupBox2: TGroupBox;
 | 
						|
    Label20: TLabel;
 | 
						|
    Label21: TLabel;
 | 
						|
    pnlBackColor: TPanel;
 | 
						|
    chkUseXFormColor: TCheckBox;
 | 
						|
    chkFlameBack: TCheckBox;
 | 
						|
    pnlReference: TPanel;
 | 
						|
    procedure FormCreate(Sender: TObject);
 | 
						|
    procedure GraphImageMouseMove(Sender: TObject; Shift: TShiftState; X,
 | 
						|
      Y: integer);
 | 
						|
    procedure GraphImageMouseDown(Sender: TObject; Button: TMouseButton;
 | 
						|
      Shift: TShiftState; X, Y: integer);
 | 
						|
    procedure GraphImageMouseUp(Sender: TObject; Button: TMouseButton;
 | 
						|
      Shift: TShiftState; X, Y: integer);
 | 
						|
    procedure FormShow(Sender: TObject);
 | 
						|
    procedure mnuDeleteClick(Sender: TObject);
 | 
						|
    procedure mnuAddClick(Sender: TObject);
 | 
						|
    procedure mnuDupClick(Sender: TObject);
 | 
						|
    procedure mnuAutoZoomClick(Sender: TObject);
 | 
						|
    procedure mnuLockClick(Sender: TObject);
 | 
						|
    procedure mnuXFlipClick(Sender: TObject);
 | 
						|
    procedure mnuYFlipClick(Sender: TObject);
 | 
						|
    procedure btnCloseClick(Sender: TObject);
 | 
						|
    procedure FormResize(Sender: TObject);
 | 
						|
    procedure txtPKeyPress(Sender: TObject; var Key: Char);
 | 
						|
    procedure CornerEditKeyPress(Sender: TObject; var Key: Char);
 | 
						|
    procedure CornerEditExit(Sender: TObject);
 | 
						|
    procedure txtPExit(Sender: TObject);
 | 
						|
    procedure DrawPreview;
 | 
						|
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
 | 
						|
    procedure mnuUndoClick(Sender: TObject);
 | 
						|
    procedure mnuRedoClick(Sender: TObject);
 | 
						|
    procedure FormDestroy(Sender: TObject);
 | 
						|
    procedure mnuLowQualityClick(Sender: TObject);
 | 
						|
    procedure mnuHighQualityClick(Sender: TObject);
 | 
						|
    procedure mnuMediumQualityClick(Sender: TObject);
 | 
						|
    procedure mnuResetLocationClick(Sender: TObject);
 | 
						|
    procedure mnuVerticalFlipAllClick(Sender: TObject);
 | 
						|
    procedure mnuHorizintalFlipAllClick(Sender: TObject);
 | 
						|
    procedure mnuFlipVerticalClick(Sender: TObject);
 | 
						|
    procedure mnuFlipHorizontalClick(Sender: TObject);
 | 
						|
    procedure GraphImageDblClick(Sender: TObject);
 | 
						|
    procedure cbTransformsChange(Sender: TObject);
 | 
						|
    procedure CoefKeyPress(Sender: TObject; var Key: Char);
 | 
						|
    procedure CoefExit(Sender: TObject);
 | 
						|
    procedure scrlXFormColorScroll(Sender: TObject;
 | 
						|
      ScrollCode: TScrollCode; var ScrollPos: Integer);
 | 
						|
    procedure scrlXFormColorChange(Sender: TObject);
 | 
						|
    procedure chkUseXFormColorClick(Sender: TObject);
 | 
						|
    procedure chkFlameBackClick(Sender: TObject);
 | 
						|
    procedure pnlBackColorClick(Sender: TObject);
 | 
						|
    procedure pnlReferenceClick(Sender: TObject);
 | 
						|
    procedure txtXFormColorExit(Sender: TObject);
 | 
						|
    procedure txtXFormColorKeyPress(Sender: TObject; var Key: Char);
 | 
						|
    procedure txtSymmetryExit(Sender: TObject);
 | 
						|
    procedure txtSymmetryKeyPress(Sender: TObject; var Key: Char);
 | 
						|
    procedure VEVarsKeyPress(Sender: TObject; var Key: Char);
 | 
						|
    procedure VEVarsExit(Sender: TObject);
 | 
						|
    procedure VEVarsValidate(Sender: TObject; ACol, ARow: Integer;
 | 
						|
      const KeyName, KeyValue: String);
 | 
						|
  private
 | 
						|
    bm: TBitmap;
 | 
						|
    cmap: TColorMap;
 | 
						|
 //   cp1: TControlPoint;
 | 
						|
    PreviewDensity: double;
 | 
						|
    procedure UpdateFlame(DrawMain: boolean);
 | 
						|
    procedure DeleteTriangle(t: integer);
 | 
						|
    procedure UpdateFlameX;
 | 
						|
  public
 | 
						|
    cp: TControlPoint;
 | 
						|
    Render: TRenderer;
 | 
						|
    { Options}
 | 
						|
    UseFlameBackground, UseTransformColors: boolean;
 | 
						|
    BackGroundColor, ReferenceTrianglecolor: integer;
 | 
						|
    procedure UpdateDisplay;
 | 
						|
    procedure AutoZoom;
 | 
						|
    procedure DrawGraph;
 | 
						|
  end;
 | 
						|
 | 
						|
var
 | 
						|
  EditForm: TEditForm;
 | 
						|
  GraphZoom: double;
 | 
						|
  CornerCaught: boolean;
 | 
						|
  TriangleCaught: boolean;
 | 
						|
  SelectedTriangle: integer;
 | 
						|
  SelectedCorner: integer;
 | 
						|
  SelLocked: boolean;
 | 
						|
  Drawing: boolean;
 | 
						|
  HasChanged: boolean;
 | 
						|
  oldx, oldy: double;
 | 
						|
  intoldx, intoldy: integer;
 | 
						|
  clr: array[-1..11] of TColor;
 | 
						|
  EditedVariation: integer;
 | 
						|
  pcenterx, pcentery, pscale: double;
 | 
						|
 | 
						|
procedure ShowSelectedInfo;
 | 
						|
function ColorValToColor(c: TColorMap; index: double): TColor;
 | 
						|
function FlipTriangleVertical(t: TTriangle): TTriangle;
 | 
						|
function FlipTriangleHorizontal(t: TTriangle): TTriangle;
 | 
						|
function RotateTriangle(t: TTriangle; rad: double): TTriangle;
 | 
						|
function OffsetTriangle(t: TTriangle; range: double): TTriangle;
 | 
						|
function ScaleTriangle(t: TTriangle; scale: double): TTriangle;
 | 
						|
function RotateTriangleCenter(t: TTriangle; rad: double): TTriangle;
 | 
						|
function RotateTrianglePoint(t: TTriangle; x, y, rad: double): TTriangle;
 | 
						|
function Centroid(t: TTriangle): TSPoint;
 | 
						|
function OffsetTriangleRandom(t: TTriangle): TTriangle;
 | 
						|
function ScaleTriangleCenter(t: TTriangle; scale: double): TTriangle;
 | 
						|
procedure ScaleAll;
 | 
						|
 | 
						|
implementation
 | 
						|
 | 
						|
uses Main, Global, Adjust, Mutate;
 | 
						|
 | 
						|
const
 | 
						|
  SUB_BATCH_SIZE = 1000;
 | 
						|
  SC_MyMenuItem1 = WM_USER + 1;
 | 
						|
 | 
						|
var
 | 
						|
  oldTriangle: TTriangle;
 | 
						|
  gCenterX: double;
 | 
						|
  gCentery: double;
 | 
						|
  gxlength: double;
 | 
						|
  gylength: double;
 | 
						|
 | 
						|
{$R *.DFM}
 | 
						|
 | 
						|
{ Triangle transformations }
 | 
						|
 | 
						|
function OffsetTriangleRandom(t: TTriangle): TTriangle;
 | 
						|
var
 | 
						|
  r: integer;
 | 
						|
begin
 | 
						|
  r := random(3);
 | 
						|
  Result.x[r] := t.x[r] + random - 0.5;
 | 
						|
  Result.y[r] := t.y[r] + random - 0.5;
 | 
						|
end;
 | 
						|
 | 
						|
function FlipTriangleVertical(t: TTriangle): TTriangle;
 | 
						|
begin
 | 
						|
  Result := t;
 | 
						|
  Result.y[0] := -t.y[0];
 | 
						|
  Result.y[1] := -t.y[1];
 | 
						|
  Result.y[2] := -t.y[2];
 | 
						|
end;
 | 
						|
 | 
						|
function FlipTriangleHorizontal(t: TTriangle): TTriangle;
 | 
						|
begin
 | 
						|
  Result := t;
 | 
						|
  Result.x[0] := -t.x[0];
 | 
						|
  Result.x[1] := -t.x[1];
 | 
						|
  Result.x[2] := -t.x[2];
 | 
						|
end;
 | 
						|
 | 
						|
function ScaleTriangle(t: TTriangle; scale: double): TTriangle;
 | 
						|
begin
 | 
						|
  Result.y[0] := scale * t.y[0];
 | 
						|
  Result.y[1] := scale * t.y[1];
 | 
						|
  Result.y[2] := scale * t.y[2];
 | 
						|
  Result.x[0] := scale * t.x[0];
 | 
						|
  Result.x[1] := scale * t.x[1];
 | 
						|
  Result.x[2] := scale * t.x[2];
 | 
						|
end;
 | 
						|
 | 
						|
function Centroid(t: TTriangle): TSPoint;
 | 
						|
begin
 | 
						|
  Result.x := (t.x[0] + t.x[1] + t.x[2]) / 3;
 | 
						|
  Result.y := (t.y[0] + t.y[1] + t.y[2]) / 3;
 | 
						|
end;
 | 
						|
 | 
						|
function ScaleTriangleCenter(t: TTriangle; scale: double): TTriangle;
 | 
						|
var
 | 
						|
  xr, yr: double;
 | 
						|
  z: TSPoint;
 | 
						|
begin
 | 
						|
  z := Centroid(t);
 | 
						|
  xr := z.x;
 | 
						|
  yr := z.y;
 | 
						|
  Result.y[0] := scale * (t.y[0] - yr) + yr;
 | 
						|
  Result.y[1] := scale * (t.y[1] - yr) + yr;
 | 
						|
  Result.y[2] := scale * (t.y[2] - yr) + yr;
 | 
						|
  Result.x[0] := scale * (t.x[0] - xr) + xr;
 | 
						|
  Result.x[1] := scale * (t.x[1] - xr) + xr;
 | 
						|
  Result.x[2] := scale * (t.x[2] - xr) + xr;
 | 
						|
end;
 | 
						|
 | 
						|
function RotateTriangle(t: TTriangle; rad: double): TTriangle; //rad in Radians
 | 
						|
var
 | 
						|
  i: integer;
 | 
						|
begin
 | 
						|
  for i := 0 to 2 do
 | 
						|
  begin
 | 
						|
    Result.x[i] := t.x[i] * cos(rad) - t.y[i] * sin(rad);
 | 
						|
    Result.y[i] := t.x[i] * sin(rad) + t.y[i] * cos(rad);
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
function OffsetTriangle(t: TTriangle; range: double): TTriangle;
 | 
						|
var
 | 
						|
  i: integer;
 | 
						|
  r: double;
 | 
						|
begin
 | 
						|
  r := (random * 2 * range) - range;
 | 
						|
  for i := 0 to 2 do
 | 
						|
  begin
 | 
						|
    Result.x[i] := t.x[i] + r;
 | 
						|
    Result.y[i] := t.y[i] + r;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure ScaleAll;
 | 
						|
var
 | 
						|
  i, j: integer;
 | 
						|
begin
 | 
						|
  for i := 0 to 2 do
 | 
						|
  begin
 | 
						|
    MainTriangles[-1].y[i] := MainTriangles[-1].y[i] * 0.2;
 | 
						|
    MainTriangles[-1].x[i] := MainTriangles[-1].x[i] * 0.2;
 | 
						|
  end;
 | 
						|
  for j := 0 to Transforms - 1 do
 | 
						|
    for i := 0 to 2 do
 | 
						|
    begin
 | 
						|
      MainTriangles[j].y[i] := MainTriangles[j].y[i] * 0.2;
 | 
						|
      MainTriangles[j].x[i] := MainTriangles[j].x[i] * 0.2;
 | 
						|
    end;
 | 
						|
end;
 | 
						|
 | 
						|
function RotateTriangleCenter(t: TTriangle; rad: double): TTriangle;
 | 
						|
var
 | 
						|
  i: integer;
 | 
						|
  xr, yr: double;
 | 
						|
  z: TSPoint;
 | 
						|
begin
 | 
						|
  z := Centroid(t);
 | 
						|
  xr := z.x;
 | 
						|
  yr := z.y;
 | 
						|
  for i := 0 to 2 do
 | 
						|
  begin
 | 
						|
    Result.x[i] := xr + (t.x[i] - xr) * cos(rad) -
 | 
						|
      (t.y[i] - yr) * sin(rad);
 | 
						|
    Result.y[i] := yr + (t.x[i] - xr) * sin(rad) +
 | 
						|
      (t.y[i] - yr) * cos(rad);
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
function RotateTrianglePoint(t: TTriangle; x, y, rad: double): TTriangle;
 | 
						|
var
 | 
						|
  i: integer;
 | 
						|
  xr, yr: double;
 | 
						|
begin
 | 
						|
  xr := x;
 | 
						|
  yr := y;
 | 
						|
  for i := 0 to 2 do
 | 
						|
  begin
 | 
						|
    Result.x[i] := xr + (t.x[i] - xr) * cos(rad) -
 | 
						|
      (t.y[i] - yr) * sin(rad);
 | 
						|
    Result.y[i] := yr + (t.x[i] - xr) * sin(rad) +
 | 
						|
      (t.y[i] - yr) * cos(rad);
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
function ColorValToColor(c: TColorMap; index: double): TColor;
 | 
						|
var
 | 
						|
  i: integer;
 | 
						|
begin
 | 
						|
  i := Trunc(Index * 255);
 | 
						|
  result := c[i][2] shl 16 + c[i][1] shl 8 + c[i][0];
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.UpdateDisplay;
 | 
						|
var
 | 
						|
  i: integer;
 | 
						|
begin
 | 
						|
  cp.copy(MainCp);
 | 
						|
  AdjustScale(cp, PreviewImage.Width, PreviewImage.Height);
 | 
						|
  cp.cmap := MainCp.cmap;
 | 
						|
  cmap := MainCp.cmap;
 | 
						|
  cbTransforms.Clear;
 | 
						|
  for i := 0 to Transforms - 1 do
 | 
						|
    cbTransforms.Items.Add(IntToStr(i + 1));
 | 
						|
  AutoZoom;
 | 
						|
  ShowSelectedInfo;
 | 
						|
  DrawGraph;
 | 
						|
  DrawPreview;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.DrawPreview;
 | 
						|
begin
 | 
						|
  //Render.Stop;
 | 
						|
  cp.sample_density := PreviewDensity;
 | 
						|
  cp.spatial_oversample := defOversample;
 | 
						|
  cp.spatial_filter_radius := defFilterRadius;
 | 
						|
  if mnuResetLocation.checked then
 | 
						|
  begin
 | 
						|
    cp.zoom := 0;
 | 
						|
    cp.CalcBoundbox;
 | 
						|
  end
 | 
						|
  else
 | 
						|
  begin
 | 
						|
    cp.zoom := MainCp.zoom;
 | 
						|
    cp.center[0] := MainCp.Center[0];
 | 
						|
    cp.center[1] := MainCp.Center[1];
 | 
						|
  end;
 | 
						|
  cp.cmap := MainCp.cmap;
 | 
						|
  Render.Compatibility := compatibility;
 | 
						|
  Render.SetCP(cp);
 | 
						|
  Render.Render;
 | 
						|
  PreviewImage.Picture.Bitmap.Assign(Render.GetImage);
 | 
						|
  PreviewImage.refresh;
 | 
						|
end;
 | 
						|
 | 
						|
procedure ReadjustWeights(var cp: TControlPoint);
 | 
						|
{ Thanks to Rudy...code from Chaos}
 | 
						|
var
 | 
						|
  total, othertotals, excess: double;
 | 
						|
  t, i: integer;
 | 
						|
begin
 | 
						|
  t := NumXForms(cp);
 | 
						|
  { /* First determine the excess. */ }
 | 
						|
  total := 0.0;
 | 
						|
  othertotals := 0.0;
 | 
						|
  for i := 0 to T - 1 do
 | 
						|
    if cp.xform[i].density <> 0.0 then
 | 
						|
    begin
 | 
						|
      total := total + cp.xform[i].density;
 | 
						|
      if (i <> SelectedTriangle) then
 | 
						|
        othertotals := othertotals + cp.xform[i].density;
 | 
						|
    end;
 | 
						|
  excess := total - 1.0;
 | 
						|
  { /* Now we need to fix'em */ }
 | 
						|
  for i := 0 to T - 1 do
 | 
						|
    if (i <> SelectedTriangle) and (cp.xform[i].density <> 0) then
 | 
						|
      cp.xform[i].density := cp.xform[i].density -
 | 
						|
        cp.xform[i].density / othertotals * excess;
 | 
						|
end;
 | 
						|
 | 
						|
procedure ShowSelectedInfo;
 | 
						|
var
 | 
						|
  t: integer;
 | 
						|
  i: integer;
 | 
						|
  a, b, c, d, e, f: double;
 | 
						|
begin
 | 
						|
  t := SelectedTriangle;
 | 
						|
  if (t >= Transforms) then t := Transforms - 1;
 | 
						|
  //if EditForm.cbTransforms.ItemIndex <> t then EditForm.cbTransforms.ItemIndex := t;
 | 
						|
  EditForm.cbTransforms.ItemIndex := t;
 | 
						|
  //select combobox item
 | 
						|
  EditForm.txtAx.text := Format('%.6g', [MainTriangles[t].x[0]]);
 | 
						|
  EditForm.txtAy.text := Format('%.6g', [MainTriangles[t].y[0]]);
 | 
						|
  EditForm.txtBx.text := Format('%.6g', [MainTriangles[t].x[1]]);
 | 
						|
  EditForm.txtBy.text := Format('%.6g', [MainTriangles[t].y[1]]);
 | 
						|
  EditForm.txtCx.text := Format('%.6g', [MainTriangles[t].x[2]]);
 | 
						|
  EditForm.txtCy.text := Format('%.6g', [MainTriangles[t].y[2]]);
 | 
						|
  EditForm.lblTransform.Refresh;
 | 
						|
  EditForm.txtAx.Refresh;
 | 
						|
  EditForm.txtAy.Refresh;
 | 
						|
  EditForm.txtBx.Refresh;
 | 
						|
  EditForm.txtBy.Refresh;
 | 
						|
  EditForm.txtCx.Refresh;
 | 
						|
  EditForm.txtCy.Refresh;
 | 
						|
  a := EditForm.cp.xform[t].c[0][0];
 | 
						|
  b := EditForm.cp.xform[t].c[1][0];
 | 
						|
  c := EditForm.cp.xform[t].c[0][1];
 | 
						|
  d := EditForm.cp.xform[t].c[1][1];
 | 
						|
  e := EditForm.cp.xform[t].c[2][0];
 | 
						|
  f := EditForm.cp.xform[t].c[2][1];
 | 
						|
 | 
						|
  EditForm.txtA.text := Format('%.6g', [a]);
 | 
						|
  EditForm.txtB.text := Format('%.6g', [b]);
 | 
						|
  EditForm.txtC.text := Format('%.6g', [c]);
 | 
						|
  EditForm.txtD.text := Format('%.6g', [d]);
 | 
						|
  EditForm.txtE.text := Format('%.6g', [e]);
 | 
						|
  EditForm.txtF.text := Format('%.6g', [f]);
 | 
						|
 | 
						|
  EditForm.txtP.text := Format('%.6g', [EditForm.cp.xform[t].density]);
 | 
						|
  EditForm.txtSymmetry.text := Format('%.6g', [EditForm.cp.xform[t].symmetry]);
 | 
						|
  EditForm.txtA.Refresh;
 | 
						|
  EditForm.txtB.Refresh;
 | 
						|
  EditForm.txtC.Refresh;
 | 
						|
  EditForm.txtD.Refresh;
 | 
						|
  EditForm.txtE.Refresh;
 | 
						|
  EditForm.txtF.Refresh;
 | 
						|
  EditForm.txtP.Refresh;
 | 
						|
  EditForm.pnlXFormColor.Color := ColorValToColor(EditForm.cp.cmap, EditForm.cp.xform[t].color);
 | 
						|
  EditForm.txtXFormColor.Text := FloatToStr(EditForm.cp.xform[t].color);
 | 
						|
  EditForm.scrlXFormcolor.Position := Trunc(EditForm.cp.xform[t].color * 100);
 | 
						|
 | 
						|
  for i := 0 to NVars-1 do begin
 | 
						|
    EditForm.VEVars.Values[VarNames[i]] := Format('%.6g', [EditForm.cp.xform[SelectedTriangle].vars[i]]);
 | 
						|
  end;
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
procedure Scale(var fx, fy: double; x, y, Width, Height: integer);
 | 
						|
var
 | 
						|
  sc: double;
 | 
						|
begin
 | 
						|
  sc := 50 * GraphZoom;
 | 
						|
  fx := (x - (Width / 2)) / sc + gCenterX;
 | 
						|
  fy := -((y - (Height / 2)) / sc - gCentery);
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.AutoZoom;
 | 
						|
var
 | 
						|
  i, j: integer;
 | 
						|
  xminz, yminz, xmaxz, ymaxz: double;
 | 
						|
begin
 | 
						|
  xminz := 0;
 | 
						|
  yminz := 0;
 | 
						|
  xmaxz := 0;
 | 
						|
  ymaxz := 0;
 | 
						|
  for i := -1 to Transforms - 1 do
 | 
						|
  begin
 | 
						|
    for j := 0 to 2 do
 | 
						|
    begin
 | 
						|
      if MainTriangles[i].x[j] < xminz then xminz := MainTriangles[i].x[j];
 | 
						|
      if MainTriangles[i].y[j] < yminz then yminz := MainTriangles[i].y[j];
 | 
						|
      if MainTriangles[i].x[j] > xmaxz then xmaxz := MainTriangles[i].x[j];
 | 
						|
      if MainTriangles[i].y[j] > ymaxz then ymaxz := MainTriangles[i].y[j];
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
  gxlength := xmaxz - xminz;
 | 
						|
  gylength := ymaxz - yminz;
 | 
						|
  gCenterX := xminz + gxlength / 2;
 | 
						|
  gCentery := yminz + gylength / 2;
 | 
						|
  if gxlength >= gylength then
 | 
						|
  begin
 | 
						|
    GraphZoom := EditForm.GraphImage.Width / 60 / gxlength;
 | 
						|
  end
 | 
						|
  else
 | 
						|
  begin
 | 
						|
    GraphZoom := EditForm.GraphImage.Height / 60 / gylength;
 | 
						|
  end;
 | 
						|
  EditForm.StatusBar.Panels[2].Text := Format('Zoom: %f', [GraphZoom]);
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.UpdateFlameX;
 | 
						|
var
 | 
						|
  i: integer;
 | 
						|
begin
 | 
						|
  for i := 0 to transforms - 1 do
 | 
						|
  begin
 | 
						|
//    CP_compute(cp1, Triangles[i], Triangles[-1], i);
 | 
						|
    solve3(MainTriangles[-1].x[0], MainTriangles[-1].y[0], MainTriangles[i].x[0],
 | 
						|
      MainTriangles[-1].x[1], MainTriangles[-1].y[1], MainTriangles[i].x[1],
 | 
						|
      MainTriangles[-1].x[2], MainTriangles[-1].y[2], MainTriangles[i].x[2],
 | 
						|
      cp.xform[i].c[0][0], cp.xform[i].c[1][0], cp.xform[i].c[2][0]);
 | 
						|
 | 
						|
    solve3(MainTriangles[-1].x[0], MainTriangles[-1].y[0], MainTriangles[i].y[0],
 | 
						|
      MainTriangles[-1].x[1], MainTriangles[-1].y[1], MainTriangles[i].y[1],
 | 
						|
      MainTriangles[-1].x[2], MainTriangles[-1].y[2], MainTriangles[i].y[2],
 | 
						|
      cp.xform[i].c[0][1], cp.xform[i].c[1][1], cp.xform[i].c[2][1]);
 | 
						|
  end;
 | 
						|
 | 
						|
  GetXForms(cp, MainTriangles, transforms);
 | 
						|
  if not chkPreserve.checked then ComputeWeights(cp, MainTriangles, transforms);
 | 
						|
  DrawPreview;
 | 
						|
  ShowSelectedInfo;
 | 
						|
  DrawGraph;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.UpdateFlame(DrawMain: boolean);
 | 
						|
begin
 | 
						|
//;    MainForm.StopThread;
 | 
						|
  StatusBar.Panels[2].Text := Format('Zoom: %f', [GraphZoom]);
 | 
						|
  GetXForms(cp, MainTriangles, transforms);
 | 
						|
  if not chkPreserve.Checked then ComputeWeights(cp, MainTriangles, transforms);
 | 
						|
  DrawPreview;
 | 
						|
  ShowSelectedInfo;
 | 
						|
  DrawGraph;
 | 
						|
  if DrawMain then begin
 | 
						|
    MainForm.StopThread;
 | 
						|
    MainCp.Copy(cp);
 | 
						|
    MainCp.cmap := cmap;
 | 
						|
    if mnuResetLocation.checked then begin
 | 
						|
      MainCp.zoom := 0;
 | 
						|
      MainForm.center[0] := cp.center[0];
 | 
						|
      MainForm.center[1] := cp.center[1];
 | 
						|
    end;
 | 
						|
//    if AdjustForm.Visible then AdjustForm.UpdateDisplay;
 | 
						|
    if MutateForm.Visible then MutateForm.UpdateDisplay;
 | 
						|
    MainForm.RedrawTimer.enabled := true;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.DeleteTriangle(t: integer);
 | 
						|
var
 | 
						|
  i, j: integer;
 | 
						|
begin
 | 
						|
  if Transforms > 2 then
 | 
						|
  { Can't have less than 2 transofms}
 | 
						|
  begin
 | 
						|
    MainForm.UpdateUndo;
 | 
						|
    if t = (Transforms - 1) then
 | 
						|
    { Last triangle...just reduce number}
 | 
						|
    begin
 | 
						|
      Transforms := Transforms - 1;
 | 
						|
      SelectedTriangle := Transforms - 1;
 | 
						|
      cp.xform[transforms].density := 0;
 | 
						|
      cbTransforms.Clear;
 | 
						|
      UpdateFlame(True);
 | 
						|
    end
 | 
						|
    else
 | 
						|
    begin
 | 
						|
      for i := t to Transforms - 2 do
 | 
						|
      begin
 | 
						|
      { copy higher transforms down }
 | 
						|
        MainTriangles[i] := MainTriangles[i + 1];
 | 
						|
        cp.xform[i].density := cp.xform[i + 1].density;
 | 
						|
        cp.xform[i].color := cp.xform[i + 1].color;
 | 
						|
        cp.xform[i].symmetry := cp.xform[i + 1].symmetry;
 | 
						|
        for j := 0 to NVARS - 1 do
 | 
						|
          cp.xform[i].vars[j] := cp.xform[i + 1].vars[j];
 | 
						|
      end;
 | 
						|
      Transforms := Transforms - 1;
 | 
						|
      cp.xform[transforms].density := 0;
 | 
						|
      UpdateFlame(True);
 | 
						|
    end;
 | 
						|
    cbTransforms.clear;
 | 
						|
    for i := 0 to Transforms - 1 do
 | 
						|
      cbTransforms.Items.Add(IntToStr(i + 1));
 | 
						|
    cbTransforms.ItemIndex := SelectedTriangle;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
function InsideTriangle(x, y: double): integer;
 | 
						|
var
 | 
						|
  i, j, k: integer;
 | 
						|
  inside: boolean;
 | 
						|
begin
 | 
						|
{ is x, y inside a triangle }
 | 
						|
  Result := -1;
 | 
						|
  inside := False;
 | 
						|
  j := 2;
 | 
						|
  for k := 0 to Transforms - 1 do
 | 
						|
  begin
 | 
						|
    for i := 0 to 2 do
 | 
						|
    begin
 | 
						|
      if (((MainTriangles[k].y[i] <= y) and
 | 
						|
        (y < MainTriangles[k].y[j])) or
 | 
						|
        ((MainTriangles[k].y[j] <= y) and
 | 
						|
        (y < MainTriangles[k].y[i]))) and
 | 
						|
        (x < (MainTriangles[k].x[j] - MainTriangles[k].x[i]) *
 | 
						|
        (y - MainTriangles[k].y[i]) /
 | 
						|
        (MainTriangles[k].y[j] - MainTriangles[k].y[i]) +
 | 
						|
        MainTriangles[k].x[i]) then
 | 
						|
        Inside := not Inside;
 | 
						|
      j := i
 | 
						|
    end;
 | 
						|
    if inside then break;
 | 
						|
  end;
 | 
						|
  if inside then Result := k;
 | 
						|
end;
 | 
						|
 | 
						|
function InTriangle(fx, fy: double): integer;
 | 
						|
var
 | 
						|
  i, j: integer;
 | 
						|
  d: double;
 | 
						|
begin
 | 
						|
  Result := -2;
 | 
						|
  i := InsideTriangle(fx, fy);
 | 
						|
  if i > -1 then
 | 
						|
    Result := i
 | 
						|
  else
 | 
						|
    for i := 0 to Transforms - 1 do
 | 
						|
      for j := 0 to 2 do
 | 
						|
      begin
 | 
						|
        d := dist(fx, fy, MainTriangles[i].x[j], MainTriangles[i].y[j]);
 | 
						|
        if (d * GraphZoom * 50) < 4 then
 | 
						|
          Result := i
 | 
						|
      end;
 | 
						|
end;
 | 
						|
 | 
						|
function InsideSelected(x, y: double): boolean;
 | 
						|
var
 | 
						|
  i, j, k: integer;
 | 
						|
  inside: boolean;
 | 
						|
begin
 | 
						|
  inside := False;
 | 
						|
  j := 2;
 | 
						|
  k := SelectedTriangle;
 | 
						|
  for i := 0 to 2 do
 | 
						|
  begin
 | 
						|
    if (((MainTriangles[k].y[i] <= y) and
 | 
						|
      (y < MainTriangles[k].y[j])) or
 | 
						|
      ((MainTriangles[k].y[j] <= y) and
 | 
						|
      (y < MainTriangles[k].y[i]))) and
 | 
						|
      (x < (MainTriangles[k].x[j] - MainTriangles[k].x[i]) *
 | 
						|
      (y - MainTriangles[k].y[i]) /
 | 
						|
      (MainTriangles[k].y[j] - MainTriangles[k].y[i]) +
 | 
						|
      MainTriangles[k].x[i]) then inside := not inside;
 | 
						|
    j := i
 | 
						|
  end;
 | 
						|
  InsideSelected := inside;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.DrawGraph;
 | 
						|
var
 | 
						|
  i: integer;
 | 
						|
  ix, iy, sc: double;
 | 
						|
  ax, ay, bx, by, cx, cy: integer;
 | 
						|
  Width, Height: integer;
 | 
						|
  BitMap: TBitMap;
 | 
						|
begin
 | 
						|
  if SelectedTriangle >= Transforms then
 | 
						|
  begin
 | 
						|
    Dec(SelectedTriangle);
 | 
						|
    SelLocked := False;
 | 
						|
    EditForm.mnuLockSel.Checked := False;
 | 
						|
  end;
 | 
						|
  BitMap := TBitMap.Create;
 | 
						|
  try
 | 
						|
    Width := EditForm.GraphImage.Width;
 | 
						|
    Height := EditForm.GraphImage.Height;
 | 
						|
    BitMap.Width := Width;
 | 
						|
    BitMap.Height := Height;
 | 
						|
    ix := Width / 2;
 | 
						|
    iy := Height / 2;
 | 
						|
    sc := 50 * GraphZoom;
 | 
						|
    with Bitmap.canvas do
 | 
						|
    begin
 | 
						|
      if chkFlameBack.checked then
 | 
						|
        brush.Color := cp.background[2] shl 16 + cp.background[1] shl 8 + cp.background[0]
 | 
						|
      else
 | 
						|
        brush.Color := pnlBackColor.Color;
 | 
						|
      FillRect(rect(0, 0, Width, Height));
 | 
						|
      {Reference Triangle}
 | 
						|
      Pen.Width := 1;
 | 
						|
      Pen.Style := psDot;
 | 
						|
      Pen.color := pnlReference.Color;
 | 
						|
      MoveTo(integer(round(ix + MainTriangles[-1].x[0] * sc - gCenterX * sc)), integer(round(iy + (gCentery + -MainTriangles[-1].y[0]) * sc)));
 | 
						|
      LineTo(integer(round(ix + MainTriangles[-1].x[1] * sc - gCenterX * sc)), integer(round(iy + (gCentery + -MainTriangles[-1].y[1]) * sc)));
 | 
						|
      LineTo(integer(round(ix + MainTriangles[-1].x[2] * sc - gCenterX * sc)), integer(round(iy + (gCentery + -MainTriangles[-1].y[2]) * sc)));
 | 
						|
      LineTo(integer(round(ix + MainTriangles[-1].x[0] * sc - gCenterX * sc)), integer(round(iy + (gCentery + -MainTriangles[-1].y[0]) * sc)));
 | 
						|
      font.Color := pnlReference.Color;
 | 
						|
      TextOut(integer(round(ix + MainTriangles[-1].x[0] * sc - gCenterX * sc)), integer(round(iy + (gCentery + -MainTriangles[-1].y[0]) * sc)), 'A');
 | 
						|
      TextOut(integer(round(ix + MainTriangles[-1].x[1] * sc - gCenterX * sc)), integer(round(iy + (gCentery + -MainTriangles[-1].y[1]) * sc)), 'B');
 | 
						|
      TextOut(integer(round(ix + MainTriangles[-1].x[2] * sc - gCenterX * sc)), integer(round(iy + (gCentery + -MainTriangles[-1].y[2]) * sc)), 'C');
 | 
						|
      {Transforms}
 | 
						|
      for i := 0 to Transforms - 1 do
 | 
						|
      begin
 | 
						|
        ax := integer(round(ix + MainTriangles[i].x[0] * sc - gCenterX * sc));
 | 
						|
        ay := integer(round(iy + (gCentery + -MainTriangles[i].y[0]) * sc));
 | 
						|
        bx := integer(round(ix + MainTriangles[i].x[1] * sc - gCenterX * sc));
 | 
						|
        by := integer(round(iy + (gCentery + -MainTriangles[i].y[1]) * sc));
 | 
						|
        cx := integer(round(ix + MainTriangles[i].x[2] * sc - gCenterX * sc));
 | 
						|
        cy := integer(round(iy + (gCentery + -MainTriangles[i].y[2]) * sc));
 | 
						|
        if chkUseXFormColor.checked then
 | 
						|
          pen.color := ColorValToColor(MainCp.cmap, cp.xform[i].color)
 | 
						|
        else Pen.color := clr[i mod 12];
 | 
						|
        if i = SelectedTriangle then
 | 
						|
          Pen.Style := psSolid
 | 
						|
        else
 | 
						|
          Pen.Style := psDot;
 | 
						|
        MoveTo(ax, ay);
 | 
						|
        LineTo(bx, by);
 | 
						|
        LineTo(cx, cy);
 | 
						|
        LineTo(ax, ay);
 | 
						|
        Pen.Style := psSolid;
 | 
						|
        Ellipse(ax - 4, ay - 4, ax + 4, ay + 4);
 | 
						|
        Ellipse(bx - 4, by - 4, bx + 4, by + 4);
 | 
						|
        Ellipse(cx - 4, cy - 4, cx + 4, cy + 4);
 | 
						|
        Font.color := Pen.color;
 | 
						|
        TextOut(ax, ay, 'A');
 | 
						|
        TextOut(bx, by, 'B');
 | 
						|
        TextOut(cx, cy, 'C');
 | 
						|
      end;
 | 
						|
    end;
 | 
						|
    EditForm.GraphImage.Picture.Graphic := Bitmap;
 | 
						|
    EditForm.GraphImage.Refresh;
 | 
						|
  finally
 | 
						|
    BitMap.Free;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.FormCreate(Sender: TObject);
 | 
						|
var
 | 
						|
  i: integer;
 | 
						|
begin
 | 
						|
  for i:= 0 to NVars-1 do begin
 | 
						|
    VEVars.InsertRow(Varnames[i], '0', True);
 | 
						|
  end;
 | 
						|
 | 
						|
  bm := TBitmap.Create;
 | 
						|
  GraphZoom := 1;
 | 
						|
  clr[-1] := clGray;
 | 
						|
  clr[0] := clYellow1;
 | 
						|
  clr[1] := clPlum2;
 | 
						|
  clr[2] := clRed;
 | 
						|
  clr[3] := clLime;
 | 
						|
  clr[4] := clAqua;
 | 
						|
  clr[11] := clBlue;
 | 
						|
  clr[6] := clMaroon;
 | 
						|
  clr[7] := clNavy;
 | 
						|
  clr[8] := clOlive;
 | 
						|
  clr[9] := clPurple;
 | 
						|
  clr[10] := clTeal;
 | 
						|
  clr[5] := clGreen;
 | 
						|
  case EditPrevQual of
 | 
						|
    0: begin
 | 
						|
        mnuLowQuality.Checked := true;
 | 
						|
        PreviewDensity := prevLowQuality;
 | 
						|
      end;
 | 
						|
    1: begin
 | 
						|
        mnuMediumQuality.Checked := true;
 | 
						|
        PreviewDensity := prevMediumQuality;
 | 
						|
      end;
 | 
						|
    2: begin
 | 
						|
        mnuHighQuality.Checked := true;
 | 
						|
        PreviewDensity := prevHighQuality;
 | 
						|
      end;
 | 
						|
  end;
 | 
						|
  cp := TControlPoint.Create;
 | 
						|
  Render := TRenderer.Create;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.GraphImageMouseMove(Sender: TObject; Shift: TShiftState; X,
 | 
						|
  Y: integer);
 | 
						|
var
 | 
						|
  vx, vy, fx, fy: double;
 | 
						|
begin
 | 
						|
  Scale(fx, fy, x, y, EditForm.GraphImage.Width, EditForm.GraphImage.Height);
 | 
						|
  if inTriangle(fx, fy) >= 0 then
 | 
						|
    GraphImage.Cursor := crHandPoint
 | 
						|
  else
 | 
						|
    GraphImage.Cursor := crArrow;
 | 
						|
  StatusBar.Panels[0].Text := Format('X: %f', [fx]);
 | 
						|
  StatusBar.Panels[1].Text := Format('Y: %f', [fy]);
 | 
						|
  if CornerCaught then
 | 
						|
  begin
 | 
						|
    { Drag a corner }
 | 
						|
    MainTriangles[SelectedTriangle].x[SelectedCorner] := fx;
 | 
						|
    MainTriangles[SelectedTriangle].y[SelectedCorner] := fy;
 | 
						|
    HasChanged := True;
 | 
						|
    UpdateFlameX;
 | 
						|
//    UpdateFlame(False);
 | 
						|
  end
 | 
						|
  else if TriangleCaught then
 | 
						|
  begin
 | 
						|
    { Drag a whole triangle }
 | 
						|
    vx := oldx - fx;
 | 
						|
    vy := oldy - fy;
 | 
						|
    MainTriangles[SelectedTriangle].x[0] := OldTriangle.x[0] - vx;
 | 
						|
    MainTriangles[SelectedTriangle].y[0] := OldTriangle.y[0] - vy;
 | 
						|
    MainTriangles[SelectedTriangle].x[1] := OldTriangle.x[1] - vx;
 | 
						|
    MainTriangles[SelectedTriangle].y[1] := OldTriangle.y[1] - vy;
 | 
						|
    MainTriangles[SelectedTriangle].x[2] := OldTriangle.x[2] - vx;
 | 
						|
    MainTriangles[SelectedTriangle].y[2] := OldTriangle.y[2] - vy;
 | 
						|
    HasChanged := True;
 | 
						|
    UpdateFlameX;
 | 
						|
 | 
						|
//    UpdateFlame(False);
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.GraphImageMouseDown(Sender: TObject; Button: TMouseButton;
 | 
						|
  Shift: TShiftState; X, Y: integer);
 | 
						|
var
 | 
						|
  d, fx, fy: double;
 | 
						|
  i, j: integer;
 | 
						|
begin
 | 
						|
  intoldx := x;
 | 
						|
  intoldy := y;
 | 
						|
  CornerCaught := False;
 | 
						|
  TriangleCaught := False;
 | 
						|
  Scale(fx, fy, x, y, EditForm.GraphImage.Width, EditForm.GraphImage.Height);
 | 
						|
  {Has user grabbed a corner?}
 | 
						|
  if Button = mbLeft then
 | 
						|
  begin
 | 
						|
    if SelLocked then
 | 
						|
      { Only change the locked triangle}
 | 
						|
    begin
 | 
						|
      for j := 0 to 2 do
 | 
						|
      begin
 | 
						|
        d := dist(fx, fy, MainTriangles[SelectedTriangle].x[j], MainTriangles[SelectedTriangle].y[j]);
 | 
						|
        if (d * GraphZoom * 50) < 4 then
 | 
						|
        begin
 | 
						|
          SelectedCorner := j;
 | 
						|
          MainForm.UpdateUndo;
 | 
						|
          CornerCaught := True;
 | 
						|
          oldx := fx;
 | 
						|
          oldy := fy;
 | 
						|
          Break;
 | 
						|
        end;
 | 
						|
      end;
 | 
						|
    end
 | 
						|
    else
 | 
						|
      { Find a corner and select triangle }
 | 
						|
      for i := 0 to Transforms - 1 do
 | 
						|
        for j := 0 to 2 do
 | 
						|
        begin
 | 
						|
          d := dist(fx, fy, MainTriangles[i].x[j], MainTriangles[i].y[j]);
 | 
						|
          if (d * GraphZoom * 50) < 4 then
 | 
						|
          begin
 | 
						|
            SelectedTriangle := i;
 | 
						|
            SelectedCorner := j;
 | 
						|
            MainForm.UpdateUndo;
 | 
						|
            CornerCaught := True;
 | 
						|
            oldx := fx;
 | 
						|
            oldy := fy;
 | 
						|
            Break;
 | 
						|
          end;
 | 
						|
        end;
 | 
						|
    if CornerCaught then
 | 
						|
    begin
 | 
						|
      DrawPreview;
 | 
						|
      ShowSelectedInfo;
 | 
						|
      DrawGraph;
 | 
						|
    end
 | 
						|
    else
 | 
						|
    begin
 | 
						|
      if SelLocked then
 | 
						|
      begin
 | 
						|
        { Only move locked triangle }
 | 
						|
        if InsideSelected(fx, fy) then
 | 
						|
        begin
 | 
						|
          OldTriangle := MainTriangles[SelectedTriangle];
 | 
						|
          MainForm.UpdateUndo;
 | 
						|
          TriangleCaught := True;
 | 
						|
          oldx := fx;
 | 
						|
          oldy := fy;
 | 
						|
          DrawPreview;
 | 
						|
          ShowSelectedInfo;
 | 
						|
          DrawGraph;
 | 
						|
        end;
 | 
						|
      end
 | 
						|
      else
 | 
						|
      begin
 | 
						|
        { Mouse inside a triangle?}
 | 
						|
        i := InsideTriangle(fx, fy);
 | 
						|
        if i > -1 then
 | 
						|
        begin
 | 
						|
          SelectedTriangle := i;
 | 
						|
          OldTriangle := MainTriangles[i];
 | 
						|
          MainForm.UpdateUndo;
 | 
						|
          TriangleCaught := True;
 | 
						|
          oldx := fx;
 | 
						|
          oldy := fy;
 | 
						|
          DrawPreview;
 | 
						|
          ShowSelectedInfo;
 | 
						|
          DrawGraph;
 | 
						|
        end;
 | 
						|
      end;
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.GraphImageMouseUp(Sender: TObject; Button: TMouseButton;
 | 
						|
  Shift: TShiftState; X, Y: integer);
 | 
						|
var
 | 
						|
  fx, fy: double;
 | 
						|
  i: integer;
 | 
						|
begin
 | 
						|
  Scale(fx, fy, x, y, EditForm.GraphImage.Width, EditForm.GraphImage.Height);
 | 
						|
  { Mouse inside a triangle?}
 | 
						|
  i := InsideTriangle(fx, fy);
 | 
						|
  if i = -1 then
 | 
						|
  begin
 | 
						|
    if Button = mbLeft then
 | 
						|
      if Shift = [ssCtrl] then
 | 
						|
      begin
 | 
						|
        AutoZoom;
 | 
						|
        ShowSelectedInfo;
 | 
						|
        DrawGraph;
 | 
						|
      end
 | 
						|
  end
 | 
						|
  else
 | 
						|
  begin
 | 
						|
    if SelLocked and (i <> SelectedTriangle) then
 | 
						|
    begin
 | 
						|
    end
 | 
						|
    else if Button = mbLeft then
 | 
						|
      if Shift = [ssAlt] then
 | 
						|
      begin
 | 
						|
        MainTriangles[i] := RotateTriangleCenter(MainTriangles[i], -(PI / 20));
 | 
						|
        HasChanged := True;
 | 
						|
        UpdateFlame(False);
 | 
						|
      end
 | 
						|
      else if Shift = [ssCtrl, ssAlt] then
 | 
						|
      begin
 | 
						|
        MainTriangles[i] := RotateTriangleCenter(MainTriangles[i], PI / 20);
 | 
						|
        HasChanged := True;
 | 
						|
        UpdateFlame(False);
 | 
						|
      end
 | 
						|
      else if Shift = [ssShift] then
 | 
						|
      begin
 | 
						|
        MainTriangles[i] := ScaleTriangleCenter(MainTriangles[i], 1.1);
 | 
						|
        HasChanged := True;
 | 
						|
        UpdateFlame(False);
 | 
						|
      end
 | 
						|
      else if Shift = [ssCtrl, ssShift] then
 | 
						|
      begin
 | 
						|
        MainTriangles[i] := ScaleTriangleCenter(MainTriangles[i], 0.9);
 | 
						|
        HasChanged := True;
 | 
						|
        UpdateFlame(False);
 | 
						|
      end;
 | 
						|
  end;
 | 
						|
  CornerCaught := False;
 | 
						|
  TriangleCaught := False;
 | 
						|
  if HasChanged then
 | 
						|
  begin
 | 
						|
    UpdateFlame(true);
 | 
						|
  end;
 | 
						|
  HasChanged := False;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.FormShow(Sender: TObject);
 | 
						|
var
 | 
						|
  Registry: TRegistry;
 | 
						|
begin
 | 
						|
  Registry := TRegistry.Create;
 | 
						|
  try
 | 
						|
    Registry.RootKey := HKEY_CURRENT_USER;
 | 
						|
    if Registry.OpenKey('Software\' + APP_NAME + '\Forms\Editor', False) then
 | 
						|
    begin
 | 
						|
    { Size and position }
 | 
						|
      if Registry.ValueExists('Left') then
 | 
						|
        EditForm.Left := Registry.ReadInteger('Left');
 | 
						|
      if Registry.ValueExists('Top') then
 | 
						|
        EditForm.Top := Registry.ReadInteger('Top');
 | 
						|
      if Registry.ValueExists('Width') then
 | 
						|
        EditForm.Width := Registry.ReadInteger('Width');
 | 
						|
      if Registry.ValueExists('Height') then
 | 
						|
        EditForm.Height := Registry.ReadInteger('Height');
 | 
						|
     { Options }
 | 
						|
      if Registry.ValueExists('UseTransformColors') then
 | 
						|
      begin
 | 
						|
        UseTransformColors := Registry.ReadBool('UseTransformColors');
 | 
						|
      end
 | 
						|
      else
 | 
						|
      begin
 | 
						|
        UseTransformColors := False;
 | 
						|
      end;
 | 
						|
      if Registry.ValueExists('UseFlameBackground') then
 | 
						|
      begin
 | 
						|
        UseFlameBackground := Registry.ReadBool('UseFlameBackground');
 | 
						|
      end
 | 
						|
      else
 | 
						|
      begin
 | 
						|
        UseFlameBackground := False;
 | 
						|
      end;
 | 
						|
      if Registry.ValueExists('BackgroundColor') then
 | 
						|
      begin
 | 
						|
        BackgroundColor := Registry.ReadInteger('BackgroundColor');
 | 
						|
      end
 | 
						|
      else
 | 
						|
      begin
 | 
						|
        BackgroundColor := integer(clBlack);
 | 
						|
      end;
 | 
						|
      if Registry.ValueExists('ReferenceTriangleColor') then
 | 
						|
      begin
 | 
						|
        ReferenceTriangleColor := Registry.ReadInteger('ReferenceTriangleColor');
 | 
						|
      end
 | 
						|
      else
 | 
						|
      begin
 | 
						|
        ReferenceTriangleColor := integer(clGray);
 | 
						|
      end;
 | 
						|
    end
 | 
						|
    else begin
 | 
						|
      UseTransformColors := False;
 | 
						|
      UseFlameBackground := False;
 | 
						|
      BackgroundColor := integer(clBlack);
 | 
						|
      ReferenceTriangleColor := integer(clGray);
 | 
						|
    end;
 | 
						|
    Registry.CloseKey;
 | 
						|
  finally
 | 
						|
    Registry.Free;
 | 
						|
  end;
 | 
						|
  chkUseXFormColor.checked := UseTransformColors;
 | 
						|
  chkFlameBack.checked := UseFlameBackground;
 | 
						|
  pnlBackColor.Color := TColor(BackgroundColor);
 | 
						|
  GrphPnl.Color := TColor(BackgroundColor);
 | 
						|
  pnlReference.color := TColor(ReferenceTriangleColor);
 | 
						|
  UpdateDisplay;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.mnuDeleteClick(Sender: TObject);
 | 
						|
begin
 | 
						|
  if SelectedTriangle > -1 then DeleteTriangle(SelectedTriangle);
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.mnuAddClick(Sender: TObject);
 | 
						|
var
 | 
						|
  i: integer;
 | 
						|
begin
 | 
						|
  if Transforms < NXFORMS then
 | 
						|
  begin
 | 
						|
    MainForm.UpdateUndo;
 | 
						|
    Transforms := Transforms + 1;
 | 
						|
    MainTriangles[Transforms - 1] := MainTriangles[-1];
 | 
						|
    SelectedTriangle := Transforms - 1;
 | 
						|
    ComputeWeights(cp, MainTriangles, transforms);
 | 
						|
    cp.xform[Transforms - 1].vars[0] := 1;
 | 
						|
    for i := 1 to NVARS - 1 do
 | 
						|
      cp.xform[Transforms - 1].vars[i] := 0;
 | 
						|
    cbTransforms.clear;
 | 
						|
    for i := 0 to Transforms - 1 do
 | 
						|
      cbTransforms.Items.Add(IntToStr(i + 1));
 | 
						|
    UpdateFlame(True);
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.mnuDupClick(Sender: TObject);
 | 
						|
var
 | 
						|
  i: integer;
 | 
						|
begin
 | 
						|
  if Transforms < NXFORMS then
 | 
						|
  begin
 | 
						|
    MainForm.UpdateUndo;
 | 
						|
    Transforms := Transforms + 1;
 | 
						|
    MainTriangles[Transforms - 1] := MainTriangles[SelectedTriangle];
 | 
						|
    ComputeWeights(cp, MainTriangles, transforms);
 | 
						|
    for i := 0 to NVARS - 1 do
 | 
						|
      cp.xform[Transforms - 1].vars[i] := cp.xform[SelectedTriangle].vars[i];
 | 
						|
    SelectedTriangle := Transforms - 1;
 | 
						|
    cbTransforms.clear;
 | 
						|
    for i := 0 to Transforms - 1 do
 | 
						|
      cbTransforms.Items.Add(IntToStr(i + 1));
 | 
						|
    UpdateFlame(True);
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.mnuAutoZoomClick(Sender: TObject);
 | 
						|
begin
 | 
						|
  AutoZoom;
 | 
						|
  DrawGraph;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.mnuLockClick(Sender: TObject);
 | 
						|
begin
 | 
						|
  EditForm.mnuLockSel.Checked := not EditForm.mnuLockSel.Checked;
 | 
						|
  SelLocked := EditForm.mnuLockSel.Checked;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.mnuXFlipClick(Sender: TObject);
 | 
						|
begin
 | 
						|
  MainTriangles[SelectedTriangle] := FlipTriangleHorizontal(MainTriangles[SelectedTriangle]);
 | 
						|
  UpdateFlame(True);
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.mnuYFlipClick(Sender: TObject);
 | 
						|
begin
 | 
						|
  MainTriangles[SelectedTriangle] := FlipTriangleVertical(MainTriangles[SelectedTriangle]);
 | 
						|
  UpdateFlame(True);
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.btnCloseClick(Sender: TObject);
 | 
						|
begin
 | 
						|
  EditForm.Close;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.FormResize(Sender: TObject);
 | 
						|
begin
 | 
						|
  Autozoom;
 | 
						|
  DrawGraph;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.CornerEditExit(Sender: TObject);
 | 
						|
var
 | 
						|
  Allow: boolean;
 | 
						|
  OldText: string;
 | 
						|
  Val: string;
 | 
						|
begin
 | 
						|
  Allow := True;
 | 
						|
  if Sender = txtAx then
 | 
						|
    Val := Format('%.6f', [MainTriangles[SelectedTriangle].x[0]])
 | 
						|
  else if Sender = txtAy then
 | 
						|
    Val := Format('%.6f', [MainTriangles[SelectedTriangle].y[0]])
 | 
						|
  else if Sender = txtBx then
 | 
						|
    Val := Format('%.6f', [MainTriangles[SelectedTriangle].x[1]])
 | 
						|
  else if Sender = txtBy then
 | 
						|
    Val := Format('%.6f', [MainTriangles[SelectedTriangle].y[1]])
 | 
						|
  else if Sender = txtCx then
 | 
						|
    Val := Format('%.6f', [MainTriangles[SelectedTriangle].x[2]])
 | 
						|
  else if Sender = txtCy then
 | 
						|
    Val := Format('%.6f', [MainTriangles[SelectedTriangle].y[2]])
 | 
						|
  else if Sender = txtP then ;
 | 
						|
  val := Format('%.6f', [cp.xform[SelectedTriangle].density]);
 | 
						|
  OldText := Val;
 | 
						|
  { Test that it's a valid floating point number }
 | 
						|
  try
 | 
						|
    StrToFloat(TEdit(Sender).Text);
 | 
						|
  except on Exception do
 | 
						|
    begin
 | 
						|
      { It's not, so we restore the old value }
 | 
						|
      TEdit(Sender).Text := OldText;
 | 
						|
      Allow := False;
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
  { If it's not the same as the old value and it was valid }
 | 
						|
  if (val <> TEdit(Sender).Text) and Allow then
 | 
						|
  begin
 | 
						|
    if Sender = txtAx then
 | 
						|
      MainTriangles[SelectedTriangle].x[0] := StrToFloat(TEdit(Sender).Text)
 | 
						|
    else if Sender = txtAy then
 | 
						|
      MainTriangles[SelectedTriangle].y[0] := StrToFloat(TEdit(Sender).Text)
 | 
						|
    else if Sender = txtBx then
 | 
						|
      MainTriangles[SelectedTriangle].x[1] := StrToFloat(TEdit(Sender).Text)
 | 
						|
    else if Sender = txtBy then
 | 
						|
      MainTriangles[SelectedTriangle].y[1] := StrToFloat(TEdit(Sender).Text)
 | 
						|
    else if Sender = txtCx then
 | 
						|
      MainTriangles[SelectedTriangle].x[2] := StrToFloat(TEdit(Sender).Text)
 | 
						|
    else if Sender = txtCy then
 | 
						|
      MainTriangles[SelectedTriangle].y[2] := StrToFloat(TEdit(Sender).Text)
 | 
						|
    else if Sender = txtP then
 | 
						|
    begin
 | 
						|
      cp.xform[SelectedTriangle].density := StrToFloat(TEdit(Sender).Text);
 | 
						|
      ReadjustWeights(cp);
 | 
						|
      TEdit(Sender).Text := Format('%.6g', [cp.xform[SelectedTriangle].density]);
 | 
						|
    end;
 | 
						|
    MainForm.UpdateUndo;
 | 
						|
    UpdateFlame(True);
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.CornerEditKeyPress(Sender: TObject; var Key: Char);
 | 
						|
var
 | 
						|
  Allow: boolean;
 | 
						|
  OldText: string;
 | 
						|
  Val: string;
 | 
						|
begin
 | 
						|
  if key = #13 then
 | 
						|
  begin
 | 
						|
    Allow := True;
 | 
						|
    if Sender = txtAx then
 | 
						|
      Val := Format('%.6f', [MainTriangles[SelectedTriangle].x[0]])
 | 
						|
    else if Sender = txtAy then
 | 
						|
      Val := Format('%.6f', [MainTriangles[SelectedTriangle].y[0]])
 | 
						|
    else if Sender = txtBx then
 | 
						|
      Val := Format('%.6f', [MainTriangles[SelectedTriangle].x[1]])
 | 
						|
    else if Sender = txtBy then
 | 
						|
      Val := Format('%.6f', [MainTriangles[SelectedTriangle].y[1]])
 | 
						|
    else if Sender = txtCx then
 | 
						|
      Val := Format('%.6f', [MainTriangles[SelectedTriangle].x[2]])
 | 
						|
    else if Sender = txtCy then
 | 
						|
      Val := Format('%.6f', [MainTriangles[SelectedTriangle].y[2]])
 | 
						|
    else if Sender = txtP then ;
 | 
						|
    val := Format('%.6f', [cp.xform[SelectedTriangle].density]);
 | 
						|
    OldText := Val;
 | 
						|
    { Stop the beep }
 | 
						|
    Key := #0;
 | 
						|
    { Test that it's a valid floating point number }
 | 
						|
    try
 | 
						|
      StrToFloat(TEdit(Sender).Text);
 | 
						|
    except on Exception do
 | 
						|
      begin
 | 
						|
        { It's not, so we restore the old value }
 | 
						|
        TEdit(Sender).Text := OldText;
 | 
						|
        Allow := False;
 | 
						|
      end;
 | 
						|
    end;
 | 
						|
    { If it's not the same as the old value and it was valid }
 | 
						|
    if (val <> TEdit(Sender).Text) and Allow then
 | 
						|
    begin
 | 
						|
      if Sender = txtAx then
 | 
						|
        MainTriangles[SelectedTriangle].x[0] := StrToFloat(TEdit(Sender).Text)
 | 
						|
      else if Sender = txtAy then
 | 
						|
        MainTriangles[SelectedTriangle].y[0] := StrToFloat(TEdit(Sender).Text)
 | 
						|
      else if Sender = txtBx then
 | 
						|
        MainTriangles[SelectedTriangle].x[1] := StrToFloat(TEdit(Sender).Text)
 | 
						|
      else if Sender = txtBy then
 | 
						|
        MainTriangles[SelectedTriangle].y[1] := StrToFloat(TEdit(Sender).Text)
 | 
						|
      else if Sender = txtCx then
 | 
						|
        MainTriangles[SelectedTriangle].x[2] := StrToFloat(TEdit(Sender).Text)
 | 
						|
      else if Sender = txtCy then
 | 
						|
        MainTriangles[SelectedTriangle].y[2] := StrToFloat(TEdit(Sender).Text)
 | 
						|
      else if Sender = txtP then
 | 
						|
      begin
 | 
						|
        cp.xform[SelectedTriangle].density := StrToFloat(TEdit(Sender).Text);
 | 
						|
        ReadjustWeights(cp);
 | 
						|
        TEdit(Sender).Text := Format('%.6g', [cp.xform[SelectedTriangle].density]);
 | 
						|
      end;
 | 
						|
      MainForm.UpdateUndo;
 | 
						|
      UpdateFlame(True);
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
{ ************************* Probability input ******************************** }
 | 
						|
 | 
						|
procedure TEditForm.txtPKeyPress(Sender: TObject; var Key: Char);
 | 
						|
var
 | 
						|
  Allow: boolean;
 | 
						|
  NewVal, OldVal: double;
 | 
						|
begin
 | 
						|
  if key = #13 then
 | 
						|
  begin
 | 
						|
    { Stop the beep }
 | 
						|
    Key := #0;
 | 
						|
    Allow := True;
 | 
						|
    OldVal := Round6(cp.xform[SelectedTriangle].density);
 | 
						|
    { Test that it's a valid floating point number }
 | 
						|
    try
 | 
						|
      StrToFloat(TEdit(Sender).Text);
 | 
						|
    except on Exception do
 | 
						|
      begin
 | 
						|
        { It's not, so we restore the old value }
 | 
						|
        TEdit(Sender).Text := Format('%.6g', [OldVal]);
 | 
						|
        Allow := False;
 | 
						|
      end;
 | 
						|
    end;
 | 
						|
    NewVal := Round6(StrToFloat(TEdit(Sender).Text));
 | 
						|
    if NewVal < 0 then NewVal := 0;
 | 
						|
    if NewVal > 0.99 then NewVal := 0.99;
 | 
						|
    { If it's not the same as the old value and it was valid }
 | 
						|
    TEdit(Sender).Text := Format('%.6g', [NewVal]);
 | 
						|
    if (OldVal <> NewVal) and Allow then
 | 
						|
    begin
 | 
						|
      MainForm.UpdateUndo;
 | 
						|
      cp.xform[SelectedTriangle].density := NewVal;
 | 
						|
      ReadjustWeights(cp);
 | 
						|
      UpdateFlame(True);
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.txtPExit(Sender: TObject);
 | 
						|
var
 | 
						|
  Allow: boolean;
 | 
						|
  NewVal, OldVal: double;
 | 
						|
begin
 | 
						|
  Allow := True;
 | 
						|
  OldVal := Round6(cp.xform[SelectedTriangle].density);
 | 
						|
    { Test that it's a valid floating point number }
 | 
						|
  try
 | 
						|
    StrToFloat(TEdit(Sender).Text);
 | 
						|
  except on Exception do
 | 
						|
    begin
 | 
						|
        { It's not, so we restore the old value }
 | 
						|
      TEdit(Sender).Text := Format('%.6g', [OldVal]);
 | 
						|
      Allow := False;
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
  NewVal := Round6(StrToFloat(TEdit(Sender).Text));
 | 
						|
  if NewVal < 0 then NewVal := 0;
 | 
						|
  if NewVal > 0.99 then NewVal := 0.99;
 | 
						|
    { If it's not the same as the old value and it was valid }
 | 
						|
  TEdit(Sender).Text := Format('%.6g', [NewVal]);
 | 
						|
  if (OldVal <> NewVal) and Allow then
 | 
						|
  begin
 | 
						|
    MainForm.UpdateUndo;
 | 
						|
    cp.xform[SelectedTriangle].density := NewVal;
 | 
						|
    ReadjustWeights(cp);
 | 
						|
    UpdateFlame(True);
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
{ **************************************************************************** }
 | 
						|
 | 
						|
procedure TEditForm.FormClose(Sender: TObject; var Action: TCloseAction);
 | 
						|
var
 | 
						|
  Registry: TRegistry;
 | 
						|
begin
 | 
						|
  { Write position to registry }
 | 
						|
  Registry := TRegistry.Create;
 | 
						|
  try
 | 
						|
    Registry.RootKey := HKEY_CURRENT_USER;
 | 
						|
    { Defaults }
 | 
						|
    if Registry.OpenKey('\Software\' + APP_NAME + '\Forms\Editor', True) then
 | 
						|
    begin
 | 
						|
      { Options }
 | 
						|
      Registry.WriteBool('UseTransformColors', UseTransformColors);
 | 
						|
      Registry.WriteBool('UseFlameBackground', UseFlameBackground);
 | 
						|
      Registry.WriteInteger('BackgroundColor', BackgroundColor);
 | 
						|
      Registry.WriteInteger('ReferenceTriangleColor', ReferenceTriangleColor);
 | 
						|
      { Size and position }
 | 
						|
      if EditForm.WindowState <> wsMaximized then begin
 | 
						|
        Registry.WriteInteger('Top', EditForm.Top);
 | 
						|
        Registry.WriteInteger('Left', EditForm.Left);
 | 
						|
        Registry.WriteInteger('Width', EditForm.Width);
 | 
						|
        Registry.WriteInteger('Height', EditForm.Height);
 | 
						|
      end;
 | 
						|
    end;
 | 
						|
  finally
 | 
						|
    Registry.Free;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.mnuUndoClick(Sender: TObject);
 | 
						|
begin
 | 
						|
  MainForm.Undo;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.mnuRedoClick(Sender: TObject);
 | 
						|
begin
 | 
						|
  MainForm.Redo;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.FormDestroy(Sender: TObject);
 | 
						|
begin
 | 
						|
  bm.free;
 | 
						|
  cp.free;
 | 
						|
  Render.free;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.mnuLowQualityClick(Sender: TObject);
 | 
						|
begin
 | 
						|
  mnuLowQuality.Checked := True;
 | 
						|
  PreviewDensity := prevLowQuality;
 | 
						|
  EditPrevQual := 0;
 | 
						|
  DrawPreview;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.mnuHighQualityClick(Sender: TObject);
 | 
						|
begin
 | 
						|
  mnuHighQuality.Checked := True;
 | 
						|
  PreviewDensity := prevHighQuality;
 | 
						|
  EditPrevQual := 2;
 | 
						|
  DrawPreview;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.mnuMediumQualityClick(Sender: TObject);
 | 
						|
begin
 | 
						|
  mnuMediumQuality.Checked := True;
 | 
						|
  PreviewDensity := prevMediumQuality;
 | 
						|
  EditPrevQual := 1;
 | 
						|
  DrawPreview;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.mnuResetLocationClick(Sender: TObject);
 | 
						|
begin
 | 
						|
  mnuResetLocation.Checked := not mnuResetLocation.Checked;
 | 
						|
  if not mnuResetLocation.checked then
 | 
						|
  begin
 | 
						|
    cp.width := MainCp.width;
 | 
						|
    cp.height := MainCp.height;
 | 
						|
    cp.pixels_per_unit := MainCp.pixels_per_unit;
 | 
						|
    AdjustScale(cp, PreviewImage.width, PreviewImage.Height);
 | 
						|
    cp.zoom := MainCp.zoom;
 | 
						|
    cp.center[0] := MainCp.center[0];
 | 
						|
    cp.center[1] := MainCp.center[1];
 | 
						|
  end;
 | 
						|
  DrawPreview;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.mnuVerticalFlipAllClick(Sender: TObject);
 | 
						|
var
 | 
						|
  i: integer;
 | 
						|
begin
 | 
						|
  MainForm.UpdateUndo;
 | 
						|
  for i := -1 to Transforms - 1 do
 | 
						|
  begin
 | 
						|
    MainTriangles[i] := FlipTriangleVertical(MainTriangles[i]);
 | 
						|
  end;
 | 
						|
  AutoZoom;
 | 
						|
  UpdateFlame(True);
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.mnuHorizintalFlipAllClick(Sender: TObject);
 | 
						|
var
 | 
						|
  i: integer;
 | 
						|
begin
 | 
						|
  MainForm.UpdateUndo;
 | 
						|
  for i := -1 to Transforms - 1 do
 | 
						|
  begin
 | 
						|
    MainTriangles[i] := FlipTriangleHorizontal(MainTriangles[i]);
 | 
						|
  end;
 | 
						|
  AutoZoom;
 | 
						|
  UpdateFlame(True);
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.mnuFlipVerticalClick(Sender: TObject);
 | 
						|
begin
 | 
						|
  MainForm.UpdateUndo;
 | 
						|
  MainTriangles[SelectedTriangle] := FlipTriangleVertical(MainTriangles[SelectedTriangle]);
 | 
						|
  AutoZoom;
 | 
						|
  UpdateFlame(True);
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.mnuFlipHorizontalClick(Sender: TObject);
 | 
						|
begin
 | 
						|
  MainForm.UpdateUndo;
 | 
						|
  MainTriangles[SelectedTriangle] := FlipTriangleHorizontal(MainTriangles[SelectedTriangle]);
 | 
						|
  AutoZoom;
 | 
						|
  UpdateFlame(True);
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.GraphImageDblClick(Sender: TObject);
 | 
						|
begin
 | 
						|
  AutoZoom;
 | 
						|
  DrawGraph;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.cbTransformsChange(Sender: TObject);
 | 
						|
begin
 | 
						|
  if SelectedTriangle <> cbTransforms.ItemIndex then SelectedTriangle := cbTransforms.ItemIndex;
 | 
						|
  ShowSelectedInfo;
 | 
						|
  DrawGraph;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.CoefKeyPress(Sender: TObject; var Key: Char);
 | 
						|
var
 | 
						|
  Allow: boolean;
 | 
						|
  i: integer;
 | 
						|
  OldVal, NewVal: double;
 | 
						|
begin
 | 
						|
  i := 0; OldVal := 0;
 | 
						|
  if key = #13 then
 | 
						|
  begin
 | 
						|
    key := #0;
 | 
						|
    Allow := True;
 | 
						|
    if Sender = txtA then
 | 
						|
      i := 0
 | 
						|
    else if Sender = txtB then
 | 
						|
      i := 1
 | 
						|
    else if Sender = txtC then
 | 
						|
      i := 2
 | 
						|
    else if Sender = txtD then
 | 
						|
      i := 3
 | 
						|
    else if Sender = txtE then
 | 
						|
      i := 4
 | 
						|
    else if Sender = txtF then
 | 
						|
      i := 5;
 | 
						|
    case i of
 | 
						|
      0: OldVal := Round6(cp.xform[SelectedTriangle].c[0][0]); //a
 | 
						|
      1: OldVal := Round6(cp.xform[SelectedTriangle].c[1][0]); //b
 | 
						|
      2: OldVal := Round6(cp.xform[SelectedTriangle].c[0][1]); //c
 | 
						|
      3: OldVal := Round6(cp.xform[SelectedTriangle].c[1][1]); //d
 | 
						|
      4: OldVal := Round6(cp.xform[SelectedTriangle].c[2][0]); //e
 | 
						|
      5: OldVal := Round6(cp.xform[SelectedTriangle].c[2][1]); //f
 | 
						|
    end;
 | 
						|
//  OldText := Val;
 | 
						|
    { Test that it's a valid floating point number }
 | 
						|
    try
 | 
						|
      StrToFloat(TEdit(Sender).Text);
 | 
						|
    except on Exception do
 | 
						|
      begin
 | 
						|
        { It's not, so we restore the old value }
 | 
						|
        TEdit(Sender).Text := Format('%.6g', [OldVal]);
 | 
						|
        Allow := False;
 | 
						|
      end;
 | 
						|
    end;
 | 
						|
    NewVal := Round6(StrToFloat(TEdit(Sender).Text));
 | 
						|
    TEdit(Sender).Text := Format('%.6g', [NewVal]);
 | 
						|
 | 
						|
    { If it's not the same as the old value and it was valid }
 | 
						|
    if (NewVal <> OldVal) and Allow then
 | 
						|
    begin
 | 
						|
      MainForm.UpdateUndo;
 | 
						|
      case i of
 | 
						|
        0: cp.xform[SelectedTriangle].c[0][0] := NewVal; //a
 | 
						|
        1: cp.xform[SelectedTriangle].c[1][0] := NewVal; //b
 | 
						|
        2: cp.xform[SelectedTriangle].c[0][1] := NewVal; //c
 | 
						|
        3: cp.xform[SelectedTriangle].c[1][1] := NewVal; //d
 | 
						|
        4: cp.xform[SelectedTriangle].c[2][0] := NewVal; //e
 | 
						|
        5: cp.xform[SelectedTriangle].c[2][1] := NewVal; //f
 | 
						|
      end;
 | 
						|
      MainForm.TrianglesFromCP(cp, MainTriangles);
 | 
						|
      ShowSelectedInfo;
 | 
						|
      UpdateFlame(true);
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.CoefExit(Sender: TObject);
 | 
						|
var
 | 
						|
  Allow: boolean;
 | 
						|
  i: integer;
 | 
						|
  NewVal, OldVal: double;
 | 
						|
begin
 | 
						|
  i := 0; OldVal := 0;
 | 
						|
  Allow := True;
 | 
						|
  if Sender = txtA then
 | 
						|
    i := 0
 | 
						|
  else if Sender = txtB then
 | 
						|
    i := 1
 | 
						|
  else if Sender = txtC then
 | 
						|
    i := 2
 | 
						|
  else if Sender = txtD then
 | 
						|
    i := 3
 | 
						|
  else if Sender = txtE then
 | 
						|
    i := 4
 | 
						|
  else if Sender = txtF then
 | 
						|
    i := 5;
 | 
						|
  case i of
 | 
						|
    0: OldVal := Round6(cp.xform[SelectedTriangle].c[0][0]); //a
 | 
						|
    1: OldVal := Round6(cp.xform[SelectedTriangle].c[1][0]); //b
 | 
						|
    2: OldVal := Round6(cp.xform[SelectedTriangle].c[0][1]); //c
 | 
						|
    3: OldVal := Round6(cp.xform[SelectedTriangle].c[1][1]); //d
 | 
						|
    4: OldVal := Round6(cp.xform[SelectedTriangle].c[2][0]); //e
 | 
						|
    5: OldVal := Round6(cp.xform[SelectedTriangle].c[2][1]); //f
 | 
						|
  end;
 | 
						|
//  OldText := Val;
 | 
						|
    { Test that it's a valid floating point number }
 | 
						|
  try
 | 
						|
    StrToFloat(TEdit(Sender).Text);
 | 
						|
  except on Exception do
 | 
						|
    begin
 | 
						|
        { It's not, so we restore the old value }
 | 
						|
      TEdit(Sender).Text := Format('%.6g', [OldVal]);
 | 
						|
      Allow := False;
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
  NewVal := Round6(StrToFloat(TEdit(Sender).Text));
 | 
						|
  TEdit(Sender).Text := Format('%.6g', [NewVal]);
 | 
						|
 | 
						|
    { If it's not the same as the old value and it was valid }
 | 
						|
  if (NewVal <> OldVal) and Allow then
 | 
						|
  begin
 | 
						|
    MainForm.UpdateUndo;
 | 
						|
    case i of
 | 
						|
      0: cp.xform[SelectedTriangle].c[0][0] := NewVal; //a
 | 
						|
      1: cp.xform[SelectedTriangle].c[1][0] := NewVal; //b
 | 
						|
      2: cp.xform[SelectedTriangle].c[0][1] := NewVal; //c
 | 
						|
      3: cp.xform[SelectedTriangle].c[1][1] := NewVal; //d
 | 
						|
      4: cp.xform[SelectedTriangle].c[2][0] := NewVal; //e
 | 
						|
      5: cp.xform[SelectedTriangle].c[2][1] := NewVal; //f
 | 
						|
    end;
 | 
						|
    MainForm.TrianglesFromCP(cp, MainTriangles);
 | 
						|
    ShowSelectedInfo;
 | 
						|
    UpdateFlame(true);
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.scrlXFormColorScroll(Sender: TObject;
 | 
						|
  ScrollCode: TScrollCode; var ScrollPos: Integer);
 | 
						|
begin
 | 
						|
  if ScrollCode = scEndScroll then UpdateFlame(True);
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.scrlXFormColorChange(Sender: TObject);
 | 
						|
begin
 | 
						|
  cp.xform[SelectedTriangle].color := (scrlXFormColor.Position) / 100;
 | 
						|
  txtXFormColor.Text := FloatToStr(cp.xform[SelectedTriangle].color);
 | 
						|
  pnlXFormColor.color := ColorValToColor(MainCp.cmap, cp.xform[SelectedTriangle].color);
 | 
						|
  DrawGraph;
 | 
						|
  DrawPreview;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.chkUseXFormColorClick(Sender: TObject);
 | 
						|
begin
 | 
						|
  UseTransformColors := chkUseXFormColor.checked;
 | 
						|
  DrawGraph;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.chkFlameBackClick(Sender: TObject);
 | 
						|
begin
 | 
						|
  UseFlameBackground := chkFlameBack.checked;
 | 
						|
  DrawGraph;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.pnlBackColorClick(Sender: TObject);
 | 
						|
begin
 | 
						|
  AdjustForm.ColorDialog.Color := pnlBackColor.Color;
 | 
						|
  if AdjustForm.ColorDialog.Execute then
 | 
						|
  begin
 | 
						|
    pnlBackColor.Color := AdjustForm.ColorDialog.Color;
 | 
						|
    BackgroundColor := Integer(pnlBackColor.color);
 | 
						|
    GrphPnl.Color := BackgroundColor;
 | 
						|
    DrawGraph;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.pnlReferenceClick(Sender: TObject);
 | 
						|
begin
 | 
						|
  AdjustForm.ColorDialog.Color := pnlReference.Color;
 | 
						|
  if AdjustForm.ColorDialog.Execute then
 | 
						|
  begin
 | 
						|
    pnlReference.Color := AdjustForm.ColorDialog.Color;
 | 
						|
    ReferenceTriangleColor := Integer(pnlReference.color);
 | 
						|
    DrawGraph;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.txtXFormColorExit(Sender: TObject);
 | 
						|
var
 | 
						|
  v: double;
 | 
						|
begin
 | 
						|
  try
 | 
						|
    v := StrToFloat(txtXFormColor.Text);
 | 
						|
  except on EConvertError do
 | 
						|
    begin
 | 
						|
      txtXformColor.text := FLoattoStr(cp.xform[SelectedTriangle].color);
 | 
						|
      exit;
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
  if v > 1 then v := 1;
 | 
						|
  if v < 0 then v := 0;
 | 
						|
  if v <> cp.xform[SelectedTriangle].color then
 | 
						|
  begin
 | 
						|
    scrlXFormColor.Position := round(v * 100);
 | 
						|
    UpdateFlame(true);
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.txtXFormColorKeyPress(Sender: TObject; var Key: Char);
 | 
						|
var
 | 
						|
  v: double;
 | 
						|
begin
 | 
						|
  if key = #13 then
 | 
						|
  begin
 | 
						|
    key := #0;
 | 
						|
    try
 | 
						|
      v := StrToFloat(txtXFormColor.Text);
 | 
						|
    except on EConvertError do
 | 
						|
      begin
 | 
						|
        txtXformColor.text := FLoattoStr(cp.xform[SelectedTriangle].color);
 | 
						|
        exit;
 | 
						|
      end;
 | 
						|
    end;
 | 
						|
    if v > 1 then v := 1;
 | 
						|
    if v < 0 then v := 0;
 | 
						|
    if v <> cp.xform[SelectedTriangle].color then
 | 
						|
    begin
 | 
						|
      scrlXFormColor.Position := round(v * 100);
 | 
						|
      UpdateFlame(true);
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.txtSymmetryExit(Sender: TObject);
 | 
						|
var
 | 
						|
  Allow: boolean;
 | 
						|
  NewVal, OldVal: double;
 | 
						|
begin
 | 
						|
  Allow := True;
 | 
						|
  OldVal := Round6(cp.xform[SelectedTriangle].symmetry);
 | 
						|
    { Test that it's a valid floating point number }
 | 
						|
  try
 | 
						|
    StrToFloat(TEdit(Sender).Text);
 | 
						|
  except on Exception do
 | 
						|
    begin
 | 
						|
        { It's not, so we restore the old value }
 | 
						|
      TEdit(Sender).Text := Format('%.6g', [OldVal]);
 | 
						|
      Allow := False;
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
  NewVal := Round6(StrToFloat(TEdit(Sender).Text));
 | 
						|
  if NewVal < 0 then NewVal := 0;
 | 
						|
  if NewVal > 1 then NewVal := 1;
 | 
						|
    { If it's not the same as the old value and it was valid }
 | 
						|
  TEdit(Sender).Text := Format('%.6g', [NewVal]);
 | 
						|
  if (OldVal <> NewVal) and Allow then
 | 
						|
  begin
 | 
						|
    MainForm.UpdateUndo;
 | 
						|
    cp.xform[SelectedTriangle].symmetry := NewVal;
 | 
						|
    UpdateFlame(True);
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.txtSymmetryKeyPress(Sender: TObject; var Key: Char);
 | 
						|
var
 | 
						|
  Allow: boolean;
 | 
						|
  NewVal, OldVal: double;
 | 
						|
begin
 | 
						|
  if key = #13 then
 | 
						|
  begin
 | 
						|
    { Stop the beep }
 | 
						|
    Key := #0;
 | 
						|
    Allow := True;
 | 
						|
    OldVal := Round6(cp.xform[SelectedTriangle].symmetry);
 | 
						|
    { Test that it's a valid floating point number }
 | 
						|
    try
 | 
						|
      StrToFloat(TEdit(Sender).Text);
 | 
						|
    except on Exception do
 | 
						|
      begin
 | 
						|
        { It's not, so we restore the old value }
 | 
						|
        TEdit(Sender).Text := Format('%.6g', [OldVal]);
 | 
						|
        Allow := False;
 | 
						|
      end;
 | 
						|
    end;
 | 
						|
    NewVal := Round6(StrToFloat(TEdit(Sender).Text));
 | 
						|
    if NewVal < 0 then NewVal := 0;
 | 
						|
    if NewVal > 1 then NewVal := 1;
 | 
						|
    { If it's not the same as the old value and it was valid }
 | 
						|
    TEdit(Sender).Text := Format('%.6g', [NewVal]);
 | 
						|
    if (OldVal <> NewVal) and Allow then
 | 
						|
    begin
 | 
						|
      MainForm.UpdateUndo;
 | 
						|
      cp.xform[SelectedTriangle].symmetry := NewVal;
 | 
						|
      UpdateFlame(True);
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.VEVarsKeyPress(Sender: TObject; var Key: Char);
 | 
						|
var
 | 
						|
  Allow: boolean;
 | 
						|
  i: integer;
 | 
						|
  NewVal, OldVal: double;
 | 
						|
begin
 | 
						|
  if key = #13 then
 | 
						|
  begin
 | 
						|
    key := #0;
 | 
						|
    Allow := True;
 | 
						|
 | 
						|
    i := EditForm.VEVars.Row - 1;
 | 
						|
 | 
						|
    OldVal := Round6(cp.xform[SelectedTriangle].vars[i]);
 | 
						|
  { Test that it's a valid floating point number }
 | 
						|
    try
 | 
						|
      StrToFloat(VEVars.Values[VarNames[i]]);
 | 
						|
    except on Exception do
 | 
						|
      begin
 | 
						|
      { It's not, so we restore the old value }
 | 
						|
        VEVars.Values[VarNames[i]] := Format('%.6g', [OldVal]);
 | 
						|
        Allow := False;
 | 
						|
      end;
 | 
						|
    end;
 | 
						|
    NewVal := Round6(StrToFloat(VEVars.Values[VarNames[i]]));
 | 
						|
//    if NewVal < 0 then NewVal := 0;
 | 
						|
    VEVars.Values[VarNames[i]] := Format('%.6g', [NewVal]);
 | 
						|
 | 
						|
  { If it's not the same as the old value and it was valid }
 | 
						|
    if (NewVal <> OldVal) and Allow then
 | 
						|
    begin
 | 
						|
      MainForm.UpdateUndo;
 | 
						|
      EditedVariation := i;
 | 
						|
      cp.xform[SelectedTriangle].vars[i] := NewVal;
 | 
						|
//      VarNormalize(cp);
 | 
						|
      VEVars.Values[VarNames[i]] := Format('%.6g', [cp.xform[SelectedTriangle].vars[i]]);
 | 
						|
      ShowSelectedInfo;
 | 
						|
      UpdateFlame(True);
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.VEVarsExit(Sender: TObject);
 | 
						|
var
 | 
						|
  Allow: boolean;
 | 
						|
  i: integer;
 | 
						|
  NewVal, OldVal: double;
 | 
						|
begin
 | 
						|
  Allow := True;
 | 
						|
 | 
						|
  i := EditForm.VEVars.Row - 1;
 | 
						|
 | 
						|
  OldVal := Round6(cp.xform[SelectedTriangle].vars[i]);
 | 
						|
{ Test that it's a valid floating point number }
 | 
						|
  try
 | 
						|
    StrToFloat(VEVars.Values[VarNames[i]]);
 | 
						|
  except on Exception do
 | 
						|
    begin
 | 
						|
    { It's not, so we restore the old value }
 | 
						|
      VEVars.Values[VarNames[i]] := Format('%.6g', [OldVal]);
 | 
						|
      Allow := False;
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
  NewVal := Round6(StrToFloat(VEVars.Values[VarNames[i]]));
 | 
						|
//    if NewVal < 0 then NewVal := 0;
 | 
						|
  VEVars.Values[VarNames[i]] := Format('%.6g', [NewVal]);
 | 
						|
 | 
						|
{ If it's not the same as the old value and it was valid }
 | 
						|
  if (NewVal <> OldVal) and Allow then
 | 
						|
  begin
 | 
						|
    MainForm.UpdateUndo;
 | 
						|
    EditedVariation := i;
 | 
						|
    cp.xform[SelectedTriangle].vars[i] := NewVal;
 | 
						|
//      VarNormalize(cp);
 | 
						|
    VEVars.Values[VarNames[i]] := Format('%.6g', [cp.xform[SelectedTriangle].vars[i]]);
 | 
						|
    ShowSelectedInfo;
 | 
						|
    UpdateFlame(True);
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TEditForm.VEVarsValidate(Sender: TObject; ACol, ARow: Integer; const KeyName, KeyValue: String);
 | 
						|
var
 | 
						|
  Allow: boolean;
 | 
						|
  i: integer;
 | 
						|
  NewVal, OldVal: double;
 | 
						|
begin
 | 
						|
  Allow := True;
 | 
						|
 | 
						|
  i := EditForm.VEVars.Row - 1;
 | 
						|
 | 
						|
  OldVal := Round6(cp.xform[SelectedTriangle].vars[i]);
 | 
						|
{ Test that it's a valid floating point number }
 | 
						|
  try
 | 
						|
    StrToFloat(VEVars.Values[VarNames[i]]);
 | 
						|
  except on Exception do
 | 
						|
    begin
 | 
						|
    { It's not, so we restore the old value }
 | 
						|
      VEVars.Values[VarNames[i]] := Format('%.6g', [OldVal]);
 | 
						|
      Allow := False;
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
  NewVal := Round6(StrToFloat(VEVars.Values[VarNames[i]]));
 | 
						|
//    if NewVal < 0 then NewVal := 0;
 | 
						|
  VEVars.Values[VarNames[i]] := Format('%.6g', [NewVal]);
 | 
						|
 | 
						|
{ If it's not the same as the old value and it was valid }
 | 
						|
  if (NewVal <> OldVal) and Allow then
 | 
						|
  begin
 | 
						|
    MainForm.UpdateUndo;
 | 
						|
    EditedVariation := i;
 | 
						|
    cp.xform[SelectedTriangle].vars[i] := NewVal;
 | 
						|
//      VarNormalize(cp);
 | 
						|
    VEVars.Values[VarNames[i]] := Format('%.6g', [cp.xform[SelectedTriangle].vars[i]]);
 | 
						|
    ShowSelectedInfo;
 | 
						|
    UpdateFlame(True);
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
end.
 | 
						|
 |