{ Apophysis AV "Phoenix Edition" Copyright (C) 2021 Alice V. Koryagina } unit varTriangleCrop; interface uses BaseVariation, XFormMan; type TVariationTriangleCrop = class(TBaseVariation) private alpha, beta, Cx, Cy, Ax, Ay: double; mode, zero: byte; function IsP_Inside(Cx, Cy, Px, Py: double): boolean; procedure CalcPre; procedure CalcPost; public constructor Create; class function GetName: string; override; class function GetInstance: TBaseVariation; override; function GetNrVariables: integer; override; function GetVariableNameAt(const Index: integer): string; override; function SetVariable(const Name: string; var value: double): boolean; override; function GetVariable(const Name: string; var value: double): boolean; override; function ResetVariable(const Name: string): boolean; override; procedure Prepare; override; procedure CalcFunction; override; procedure GetCalcFunction(var f: TCalcFunction); override; end; implementation uses Math; { TVariationTriangleCrop } /////////////////////////////////////////////////////////////////////////////// procedure TVariationTriangleCrop.Prepare; var side, gamma, sa, ca: double; begin gamma := (180 - alpha - beta) * pi / 180; side := sin(beta * pi / 180) / sin(gamma); SinCos(alpha * pi / 180, sa, ca); Cx := side * ca; Cy := -side * sa; end; procedure TVariationTriangleCrop.GetCalcFunction(var f: TCalcFunction); begin case mode of 0: f := CalcPre; 1: f := CalcFunction; else f := CalcPost; end; end; function TVariationTriangleCrop.IsP_Inside(Cx, Cy, Px, Py: double): boolean; var m, n : double; begin Result := False; m := Py / Cy; if (m >= 0) and (m <= 1) then begin n := Px - m * Cx; if (n >= 0) and ((m + n) <= 1) then Result := True; end; end; procedure TVariationTriangleCrop.CalcPre; var x, y, k: double; begin x := FTx^ - Ax; y := FTy^ + Ay; if not IsP_Inside(Cx, Cy, x, y) then begin if (zero = 1) then begin x := 0; y := 0; // put the point into origin end else begin // put it on triangle's edge k := random; if (random(2) = 1) then begin x := k * Cx + random(2)*(1 - k); y := k * Cy; end else begin x := random(2)* k; y := 0; end; end; end; FTx^ := vvar * x + Ax; FTy^ := vvar * y - Ay; end; procedure TVariationTriangleCrop.CalcFunction; var x, y, k: double; begin x := FTx^ - Ax; y := FTy^ + Ay; if not IsP_Inside(Cx, Cy, x, y) then begin if (zero = 1) then begin x := 0; y := 0; // put the point into origin end else begin // put it on triangle's edge k := random; if (random(2) = 1) then begin x := k * Cx + random(2)*(1 - k); y := k * Cy; end else begin x := random(2)* k; y := 0; end; end; end; FPx^ := FPx^ + vvar * x + Ax; FPy^ := FPy^ + vvar * y - Ay; end; procedure TVariationTriangleCrop.CalcPost; var x, y, k: double; begin x := FPx^ - Ax; y := FPy^ + Ay; if not IsP_Inside(Cx, Cy, x, y) then begin if (zero = 1) then begin x := 0; y := 0; // put the point into origin end else begin // put it on triangle's edge k := random; if (random(2) = 1) then begin x := k * Cx + random(2)*(1 - k); y := k * Cy; end else begin x := random(2)* k; y := 0; end; end; end; FPx^ := vvar * x + Ax; FPy^ := vvar * y - Ay; end; /////////////////////////////////////////////////////////////////////////////// constructor TVariationTriangleCrop.Create; begin alpha := 60; beta := 60; mode := 1; zero := 0; Ax := 0; Ay := 0; end; /////////////////////////////////////////////////////////////////////////////// class function TVariationTriangleCrop.GetInstance: TBaseVariation; begin Result := TVariationTriangleCrop.Create; end; /////////////////////////////////////////////////////////////////////////////// class function TVariationTriangleCrop.GetName: string; begin Result := 'trianglecrop'; end; /////////////////////////////////////////////////////////////////////////////// function TVariationTriangleCrop.GetVariableNameAt(const Index: integer): string; begin case Index Of 0: Result := 'trianglecrop_alpha'; 1: Result := 'trianglecrop_beta'; 2: Result := 'trianglecrop_Ax'; 3: Result := 'trianglecrop_Ay'; 4: Result := 'trianglecrop_zero_edges'; 5: Result := 'trianglecrop_mode'; else Result := ''; end end; /////////////////////////////////////////////////////////////////////////////// function TVariationTriangleCrop.SetVariable(const Name: string; var value: double): boolean; begin Result := False; if Name = 'trianglecrop_alpha' then begin if (value < 1) then Value := 1; if (value > (179 - beta)) then Value := 179 - beta; alpha := Value; Result := True; end else if Name = 'trianglecrop_beta' then begin if (value < 1) then Value := 1; if (value > (179 - alpha)) then Value := 179 - alpha; beta := Value; Result := True; end else if Name = 'trianglecrop_mode' then begin if (value < 0) then Value := 0; if (value > 2) then Value := 2; mode := Round(Value); Result := True; end else if Name = 'trianglecrop_zero_edges' then begin if (value < 0) then Value := 0; if (value > 1) then Value := 1; zero := Round(Value); Result := True; end else if Name = 'trianglecrop_Ax' then begin Ax := Value; Result := True; end else if Name = 'trianglecrop_Ay' then begin Ay := Value; Result := True; end; end; function TVariationTriangleCrop.ResetVariable(const Name: string): boolean; begin Result := False; if Name = 'trianglecrop_alpha' then begin alpha:= 60; Result := True; end else if Name = 'trianglecrop_beta' then begin beta := 60; Result := True; end else if Name = 'trianglecrop_mode' then begin mode := 1; Result := True; end else if Name = 'trianglecrop_zero_edges' then begin zero := IfThen(zero = 1, 0, 1); Result := True; end else if Name = 'trianglecrop_Ax' then begin Ax := 0; Result := True; end else if Name = 'trianglecrop_Ay' then begin Ay := 0; Result := True; end; end; /////////////////////////////////////////////////////////////////////////////// function TVariationTriangleCrop.GetNrVariables: integer; begin Result := 6; end; /////////////////////////////////////////////////////////////////////////////// function TVariationTriangleCrop.GetVariable(const Name: string; var value: double): boolean; begin Result := False; if Name = 'trianglecrop_alpha' then begin Value := alpha; Result := True; end else if Name = 'trianglecrop_beta' then begin Value := beta; Result := True; end else if Name = 'trianglecrop_mode' then begin Value := mode; Result := True; end else if Name = 'trianglecrop_zero_edges' then begin Value := zero; Result := True; end else if Name = 'trianglecrop_Ax' then begin Value := Ax; Result := True; end else if Name = 'trianglecrop_Ay' then begin Value := Ay; Result := True; end; end; /////////////////////////////////////////////////////////////////////////////// initialization RegisterVariation(TVariationClassLoader.Create(TVariationTriangleCrop), false, false); end.