1 /**
2  * Mandelbulber v2, a 3D fractal generator  _%}}i*<.         ______
3  * Copyright (C) 2020 Mandelbulber Team   _>]|=||i=i<,      / ____/ __    __
4  *                                        \><||i|=>>%)     / /   __/ /___/ /_
5  * This file is part of Mandelbulber.     )<=i=]=|=i<>    / /__ /_  __/_  __/
6  * The project is licensed under GPLv3,   -<>>=|><|||`    \____/ /_/   /_/
7  * see also COPYING file in this folder.    ~+{i%+++
8  *
9  * poly fold atan2
10  * @reference
11  * https://fractalforums.org/fragmentarium/17/polyfoldsym-pre-transform/2684
12  */
13 
14 #include "all_fractal_definitions.h"
15 
cFractalTransfPolyFoldAtan2()16 cFractalTransfPolyFoldAtan2::cFractalTransfPolyFoldAtan2() : cAbstractFractal()
17 {
18 	nameInComboBox = "T>Poly Fold Atan2";
19 	internalName = "transf_poly_fold_atan2";
20 	internalID = fractal::transfPolyFoldAtan2;
21 	DEType = analyticDEType;
22 	DEFunctionType = withoutDEFunction;
23 	cpixelAddition = cpixelDisabledByDefault;
24 	defaultBailout = 100.0;
25 	DEAnalyticFunction = analyticFunctionNone;
26 	coloringFunction = coloringFunctionDefault;
27 }
28 
FormulaCode(CVector4 & z,const sFractal * fractal,sExtendedAux & aux)29 void cFractalTransfPolyFoldAtan2::FormulaCode(
30 	CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
31 {
32 	CVector4 oldZ = z;
33 	// pre abs
34 	if (fractal->transformCommon.functionEnabledx) z.x = fabs(z.x);
35 	if (fractal->transformCommon.functionEnabledyFalse) z.y = fabs(z.y);
36 	if (fractal->transformCommon.functionEnabledzFalse) z.z = fabs(z.z);
37 
38 	if (fractal->transformCommon.functionEnabledCx)
39 	{
40 		if (fractal->transformCommon.functionEnabledAxFalse && z.y < 0.0) z.x = -z.x;
41 		double psi = M_PI / fractal->transformCommon.int8X;
42 		psi = fabs(fmod(atan2(z.y, z.x) + psi, 2.0 * psi) - psi);
43 		double len = sqrt(z.x * z.x + z.y * z.y);
44 		z.x = cos(psi) * len;
45 		z.y = sin(psi) * len;
46 	}
47 
48 	if (fractal->transformCommon.functionEnabledCyFalse)
49 	{
50 		if (fractal->transformCommon.functionEnabledAyFalse && z.z < 0.0) z.y = -z.y;
51 		double psi = M_PI / fractal->transformCommon.int8Y;
52 		psi = fabs(fmod(atan2(z.z, z.y) + psi, 2.0 * psi) - psi);
53 		double len = sqrt(z.y * z.y + z.z * z.z);
54 		z.y = cos(psi) * len;
55 		z.z = sin(psi) * len;
56 	}
57 
58 	if (fractal->transformCommon.functionEnabledCzFalse)
59 	{
60 		if (fractal->transformCommon.functionEnabledAzFalse && z.x < 0.0) z.z = -z.z;
61 		double psi = M_PI / fractal->transformCommon.int8Z;
62 		psi = fabs(fmod(atan2(z.x, z.z) + psi, 2.0 * psi) - psi);
63 		double len = sqrt(z.z * z.z + z.x * z.x);
64 		z.z = cos(psi) * len;
65 		z.x = sin(psi) * len;
66 	}
67 
68 	// addition constant
69 	z += fractal->transformCommon.additionConstant000;
70 
71 	// rotation
72 	if (fractal->transformCommon.rotation2EnabledFalse)
73 	{
74 		z = fractal->transformCommon.rotationMatrix.RotateVector(z);
75 	}
76 
77 	// DE tweaks
78 	if (fractal->analyticDE.enabled)
79 	{
80 		if (!fractal->analyticDE.enabledFalse)
81 			aux.DE = aux.DE * fractal->analyticDE.scale1 + fractal->analyticDE.offset0;
82 		else
83 		{
84 			double avgScale = z.Length() / oldZ.Length();
85 			aux.DE = aux.DE * avgScale * fractal->analyticDE.scale1 + fractal->analyticDE.offset0;
86 		}
87 	}
88 }
89