Apophysis-AV/Variations/varHyperboloid.pas

241 lines
6.2 KiB
ObjectPascal
Raw Normal View History

2022-03-08 12:25:51 -05:00
{ Apophysis AV "Phoenix Edition" Copyright (C) 2021 Alice V. Koryagina }
unit varHyperboloid;
interface
uses
BaseVariation, XFormMan;
type
TVariationHyperboloid = class(TBaseVariation)
private
kx, ky, kz, maxheight, h, hb: double;
vkx, vky, vkz: double;
limit, zero: byte;
procedure CalcCut;
procedure CalcCutBoarder;
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;
{ TVariationHyperboloid }
///////////////////////////////////////////////////////////////////////////////
procedure TVariationHyperboloid.Prepare;
begin
vkx := VVAR * kx;
vky := VVAR * ky;
vkz := VVAR * kz;
h := sqrt(1 + sqr(maxheight / ky));
hb := sqrt(sqr(h) - 1);
end;
procedure TVariationHyperboloid.GetCalcFunction(var f: TCalcFunction);
begin
if (limit = 0) then
f := CalcFunction
else if (zero = 0) then
f := CalcCutBoarder
else
f := CalcCut;
end;
procedure TVariationHyperboloid.CalcFunction;
var
sn, cn, sh, ch: double;
begin
SinCos(FTx^, sn, cn);
SinhCosh(FTy^, sh, ch);
FPx^ := FPx^ + vkx * ch * sn;
FPy^ := FPy^ + vky * sh;
FPz^ := FPz^ + vkz * ch * cn;
end;
procedure TVariationHyperboloid.CalcCut;
var
sn, cn, sh, ch: double;
begin
SinhCosh(FTy^, sh, ch);
if (ch <= h) then // cut the surface
begin
SinCos(FTx^, sn, cn);
FPx^ := FPx^ + vkx * ch * sn;
FPy^ := FPy^ + vky * sh;
FPz^ := FPz^ + vkz * ch * cn;
end;
end;
procedure TVariationHyperboloid.CalcCutBoarder;
var
sn, cn, sh, ch: double;
begin
SinCos(FTx^, sn, cn);
SinhCosh(FTy^, sh, ch);
if (ch <= h) then // cut the surface
begin
FPx^ := FPx^ + vkx * ch * sn;
FPy^ := FPy^ + vky * sh;
FPz^ := FPz^ + vkz * ch * cn;
end
else begin // place the point on it's boarder
FPx^ := FPx^ + vkx * h * sn;
FPy^ := FPy^ + vky * sign(sh) * hb;
FPz^ := FPz^ + vkz * h * cn;
end;
end;
///////////////////////////////////////////////////////////////////////////////
constructor TVariationHyperboloid.Create;
begin
kx := 1;
ky := 1;
kz := 1;
maxheight := RandomRange(3, 6);
limit := 1;
zero := 0;
end;
///////////////////////////////////////////////////////////////////////////////
class function TVariationHyperboloid.GetInstance: TBaseVariation;
begin
Result := TVariationHyperboloid.Create;
end;
///////////////////////////////////////////////////////////////////////////////
class function TVariationHyperboloid.GetName: string;
begin
Result := 'hourglass3D'; // AV: hyperbolic hyperboloid :)
end;
///////////////////////////////////////////////////////////////////////////////
function TVariationHyperboloid.GetVariableNameAt(const Index: integer): string;
begin
case Index Of
0: Result := 'hourglass3D_kx';
1: Result := 'hourglass3D_ky';
2: Result := 'hourglass3D_kz';
3: Result := 'hourglass3D_maxheight';
4: Result := 'hourglass3D_uselimit';
5: Result := 'hourglass3D_zero_edges';
else
Result := '';
end
end;
///////////////////////////////////////////////////////////////////////////////
function TVariationHyperboloid.SetVariable(const Name: string; var value: double): boolean;
begin
Result := False;
if Name = 'hourglass3D_kx' then begin
if (value < 1E-5) then Value := 1E-5;
kx := Value;
Result := True;
end else if Name = 'hourglass3D_ky' then begin
if (value < 1E-5) then Value := 1E-5;
ky := Value;
Result := True;
end else if Name = 'hourglass3D_kz' then begin
if (value < 1E-5) then Value := 1E-5;
kz := Value;
Result := True;
end else if Name = 'hourglass3D_maxheight' then begin
if (value < 0.1) then Value := 0.1;
maxheight := Value;
Result := True;
end else if Name = 'hourglass3D_uselimit' then begin
if (value < 0) then Value := 0;
if (value > 1) then Value := 1;
limit := Round(Value);
Result := True;
end else if Name = 'hourglass3D_zero_edges' then begin
if (value < 0) then Value := 0;
if (value > 1) then Value := 1;
zero := Round(Value);
Result := True;
end;
end;
function TVariationHyperboloid.ResetVariable(const Name: string): boolean;
begin
Result := False;
if Name = 'hourglass3D_kx' then begin
kx:= 1;
Result := True;
end else if Name = 'hourglass3D_ky' then begin
ky := 1;
Result := True;
end else if Name = 'hourglass3D_kz' then begin
kz := 1;
Result := True;
end else if Name = 'hourglass3D_maxheight' then begin
maxheight := 3;
Result := True;
end else if Name = 'hourglass3D_uselimit' then begin
limit := IfThen(limit = 0, 1, 0);
Result := True;
end else if Name = 'hourglass3D_zero_edges' then begin
zero := IfThen(zero = 0, 1, 0);
Result := True;
end;
end;
///////////////////////////////////////////////////////////////////////////////
function TVariationHyperboloid.GetNrVariables: integer;
begin
Result := 6;
end;
///////////////////////////////////////////////////////////////////////////////
function TVariationHyperboloid.GetVariable(const Name: string; var value: double): boolean;
begin
Result := False;
if Name = 'hourglass3D_kx' then begin
Value := kx;
Result := True;
end else if Name = 'hourglass3D_ky' then begin
Value := ky;
Result := True;
end else if Name = 'hourglass3D_kz' then begin
Value := kz;
Result := True;
end else if Name = 'hourglass3D_maxheight' then begin
Value := maxheight;
Result := True;
end else if Name = 'hourglass3D_uselimit' then begin
Value := limit;
Result := True;
end else if Name = 'hourglass3D_zero_edges' then begin
Value := zero;
Result := True;
end;
end;
///////////////////////////////////////////////////////////////////////////////
initialization
RegisterVariation(TVariationClassLoader.Create(TVariationHyperboloid), true, false);
end.