Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
NovaJuliaSmoothFractal.cs
1using System;
2using System.Numerics;
3using System.Text;
4using SkiaSharp;
10
12{
20 {
25 ScriptNode R, ScriptNode p, ScriptNode Palette, ScriptNode DimX, ScriptNode DimY,
27 : base(new ScriptNode[] { r, i, r0, i0, dr, R, p, Palette, DimX, DimY },
28 new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar,
29 ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar,
30 ArgumentType.Vector, ArgumentType.Scalar, ArgumentType.Scalar},
32 {
33 }
34
39 ScriptNode R, ScriptNode p, ScriptNode Palette, ScriptNode DimX, int Start, int Length,
41 : base(new ScriptNode[] { r, i, r0, i0, dr, R, p, Palette, DimX },
42 new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar,
43 ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar,
44 ArgumentType.Vector, ArgumentType.Scalar },
46 {
47 }
48
54 : base(new ScriptNode[] { r, i, r0, i0, dr, R, p, Palette },
55 new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar,
56 ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar,
57 ArgumentType.Vector },
59 {
60 }
61
67 : base(new ScriptNode[] { r, i, r0, i0, dr, R, p },
68 new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar,
69 ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar },
71 {
72 }
73
77 public override string[] DefaultArgumentNames
78 {
79 get
80 {
81 return new string[] { "r", "i", "r0", "i0", "dr", "R", "p", "Palette", "DimX", "DimY" };
82 }
83 }
84
89 {
90 string ColorExpression = null;
91 SKColor[] Palette;
92 object Obj;
93 double rc, ic;
94 double r0, i0;
95 double dr;
96 double Rr, Ri, pr, pi;
97 int dimx, dimy;
98 int i, c;
99
100 rc = Expression.ToDouble(Arguments[0].AssociatedObjectValue);
101 ic = Expression.ToDouble(Arguments[1].AssociatedObjectValue);
102 r0 = Expression.ToDouble(Arguments[2].AssociatedObjectValue);
103 i0 = Expression.ToDouble(Arguments[3].AssociatedObjectValue);
104 dr = Expression.ToDouble(Arguments[4].AssociatedObjectValue);
105
106 if ((Obj = Arguments[5].AssociatedObjectValue) is Complex)
107 {
108 Complex z = (Complex)Obj;
109 Rr = z.Real;
110 Ri = z.Imaginary;
111 }
112 else
113 {
114 Rr = Expression.ToDouble(Arguments[5].AssociatedObjectValue);
115 Ri = 0;
116 }
117
118 if ((Obj = Arguments[6].AssociatedObjectValue) is Complex)
119 {
120 Complex z = (Complex)Obj;
121 pr = z.Real;
122 pi = z.Imaginary;
123 }
124 else
125 {
126 pr = Expression.ToDouble(Arguments[6].AssociatedObjectValue);
127 pi = 0;
128 }
129
130 c = Arguments.Length;
131 i = 7;
132
133 if (i < c && !(this.Arguments[i] is null) && Arguments[i] is ObjectVector)
134 {
135 ColorExpression = this.Arguments[i].SubExpression;
137 }
138 else
139 {
140 Palette = ColorModels.RandomLinearAnalogousHSL.CreatePalette(1024, 16, out int Seed, this, Variables);
141 ColorExpression = "RandomLinearAnalogousHSL(1024,16," + Seed.ToString() + ")";
142
143 if (i < c && this.Arguments[i] is null)
144 i++;
145 }
146
147 if (i < c)
148 dimx = (int)Expression.ToDouble(Arguments[i++].AssociatedObjectValue);
149 else
150 dimx = 320;
151
152 if (i < c)
153 dimy = (int)Expression.ToDouble(Arguments[i++].AssociatedObjectValue);
154 else
155 dimy = 200;
156
157 if (i < c)
158 {
159 throw new ScriptRuntimeException("Parameter mismatch in call to NovaJuliaSmoothFractal(r,c,r0,i0,dr,Coefficients[,Palette][,dimx[,dimy]]).",
160 this);
161 }
162
163 if (dimx <= 0 || dimx > 5000 || dimy <= 0 || dimy > 5000)
164 throw new ScriptRuntimeException("Image size must be within 1x1 to 5000x5000", this);
165
166 return CalcNovaJulia(rc, ic, r0, i0, dr, Rr, Ri, pr, pi, Palette, dimx, dimy,
167 this, Variables, this.FractalZoomScript,
168 new object[] { Palette, dimx, dimy, r0, i0, Rr, Ri, pr, pi, ColorExpression });
169 }
170
171 private string FractalZoomScript(double r, double i, double Size, object State)
172 {
173 object[] Parameters = (object[])State;
174 int DimX = (int)Parameters[1];
175 int DimY = (int)Parameters[2];
176 double r0 = (double)Parameters[3];
177 double i0 = (double)Parameters[4];
178 double Rr = (double)Parameters[5];
179 double Ri = (double)Parameters[6];
180 double pr = (double)Parameters[7];
181 double pi = (double)Parameters[8];
182 string ColorExpression = (string)Parameters[9];
183
184 StringBuilder sb = new StringBuilder();
185
186 sb.Append("NovaJuliaSmoothFractal(");
187 sb.Append(Expression.ToString(r));
188 sb.Append(',');
189 sb.Append(Expression.ToString(i));
190 sb.Append(',');
191 sb.Append(Expression.ToString(r0));
192 sb.Append(',');
193 sb.Append(Expression.ToString(i0));
194 sb.Append(',');
195 sb.Append(Expression.ToString(Size / 4));
196 sb.Append(',');
197 sb.Append(Expression.ToString(Rr));
198
199 if (Ri != 0)
200 {
201 sb.Append('+');
202 sb.Append(Expression.ToString(Ri));
203 sb.Append("*i");
204 }
205
206 sb.Append(',');
207 sb.Append(Expression.ToString(pr));
208
209 if (pi != 0)
210 {
211 sb.Append('+');
212 sb.Append(Expression.ToString(pi));
213 sb.Append("*i");
214 }
215
216 if (!string.IsNullOrEmpty(ColorExpression))
217 {
218 sb.Append(',');
219 sb.Append(ColorExpression);
220 }
221
222 sb.Append(',');
223 sb.Append(DimX.ToString());
224 sb.Append(',');
225 sb.Append(DimY.ToString());
226 sb.Append(')');
227
228 return sb.ToString();
229 }
230
234 public static FractalGraph CalcNovaJulia(double rCenter, double iCenter, double R0, double I0,
235 double rDelta, double Rr, double Ri, double pr, double pi, SKColor[] Palette,
236 int Width, int Height, ScriptNode Node, Variables Variables,
237 FractalZoomScript FractalZoomScript, object State)
238 {
239 double r0, i0, r1, i1;
240 double dr, di;
241 double r, i;
242 double zr, zi, zr2, zi2, zr3, zi3, zr4, zi4;
243 double aspect;
244 double Temp;
245 int x, y;
246 int n, N;
247 int index;
248 double lnz;
249 double argz;
250 double amp;
251 double phi;
252
253 N = Palette.Length;
254
255 int Size = Width * Height;
256 double[] ColorIndex = new double[Size];
257 double Conv = 1e-10;
258 double Div = 1e10;
259
260 rDelta *= 0.5;
261 r0 = rCenter - rDelta;
262 r1 = rCenter + rDelta;
263
264 aspect = ((double)Width) / Height;
265
266 i0 = iCenter - rDelta / aspect;
267 i1 = iCenter + rDelta / aspect;
268
269 dr = (r1 - r0) / Width;
270 di = (i1 - i0) / Height;
271
272 for (y = 0, i = i0, index = 0; y < Height; y++, i += di)
273 {
274 for (x = 0, r = r0; x < Width; x++, r += dr)
275 {
276 zr = r;
277 zi = i;
278
279 n = 0;
280 do
281 {
282 // f: z->z^p-1 = exp(p*ln(z))-1
283 // exp(a+ib)=exp(a)*(cos(b)+i*sin(b))
284 // ln(z)=ln|z|+i*arg(z)
285 // exp(p*ln(z))-1 =
286 // = exp((pr+i*pi)*(ln|z|+i*arg(z)))-1 =
287 // = exp(pr*ln|z|-pi*arg(z)+i*(pi*ln|z|+pr*arg(z)))-1 =
288 // = exp(pr*ln|z|-pi*arg(z))*(cos(pi*ln|z|+pr*arg(z))+i*sin(pi*ln|z|+pr*arg(z)))-1
289
290 lnz = Math.Log(Math.Sqrt(zr * zr + zi * zi));
291 argz = Math.Atan2(zi, zr);
292 amp = Math.Exp(pr * lnz - pi * argz);
293 phi = pi * lnz + pr * argz;
294
295 zr2 = amp * Math.Cos(phi) - 1;
296 zi2 = amp * Math.Sin(phi);
297
298 // f': z->p*z^(p-1) = p*exp((p-1)*ln(z)) =
299 // = (pr+i*pi)*exp((pr-1+i*pi)*(ln|z|+i*arg(z))) =
300 // = (pr+i*pi)*exp((pr-1)*ln|z|-pi*arg(z)+i*(pi*ln|z|+(pr-1)*arg(z))) =
301 // = (pr+i*pi)*exp((pr-1)*ln|z|-pi*arg(z))(sin(pi*ln|z|+(pr-1)*arg(z))+i*cos(pi*ln|z|+(pr-1)*arg(z))) =
302
303 amp = Math.Exp((pr - 1) * lnz - pi * argz);
304 phi = pi * lnz + (pr - 1) * argz;
305
306 zr3 = amp * Math.Cos(phi);
307 zi3 = amp * Math.Sin(phi);
308
309 Temp = pr * zr3 - pi * zi3;
310 zi3 = pr * zi3 + pi * zr3;
311 zr3 = Temp;
312
313 // f/f':
314
315 Temp = 1.0 / (zr3 * zr3 + zi3 * zi3);
316 zr4 = (zr2 * zr3 + zi2 * zi3) * Temp;
317 zi4 = (zi2 * zr3 - zr2 * zi3) * Temp;
318
319 Temp = Rr * zr4 - Ri * zi4;
320 zi4 = Ri * zr4 + Rr * zi4 + I0;
321 zr4 = Temp + R0;
322
323 zr -= zr4;
324 zi -= zi4;
325
326 Temp = Math.Sqrt(zr4 * zr4 + zi4 * zi4);
327 }
328 while ((Temp > Conv) && (Temp < Div) && (n++ < N));
329
330 if (Temp < Conv && n < N)
331 ColorIndex[index++] = n;
332 else
333 ColorIndex[index++] = N;
334 }
335 }
336
337 Variables.Preview(Node.Expression, new GraphBitmap(Variables, FractalGraph.ToPixels(ColorIndex, Width, Height, Palette)));
338
339 double[] Boundary = FractalGraph.FindBoundaries(ColorIndex, Width, Height);
340 FractalGraph.Smooth(ColorIndex, Boundary, Width, Height, N, Palette, Node, Variables);
341
342 return new FractalGraph(Variables, FractalGraph.ToPixels(ColorIndex, Width, Height, Palette),
343 r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State);
344 }
345
349 public override string FunctionName => nameof(NovaJuliaSmoothFractal);
350 }
351}
Class managing a script expression.
Definition: Expression.cs:39
static double ToDouble(object Object)
Converts an object to a double value.
Definition: Expression.cs:4824
static string ToString(double Value)
Converts a value to a string, that can be parsed as part of an expression.
Definition: Expression.cs:4496
Calculates a Nova Julia Smooth Fractal Image (by Paul Derbyshire)
override IElement Evaluate(IElement[] Arguments, Variables Variables)
TODO
NovaJuliaSmoothFractal(ScriptNode r, ScriptNode i, ScriptNode r0, ScriptNode i0, ScriptNode dr, ScriptNode R, ScriptNode p, int Start, int Length, Expression Expression)
TODO
static FractalGraph CalcNovaJulia(double rCenter, double iCenter, double R0, double I0, double rDelta, double Rr, double Ri, double pr, double pi, SKColor[] Palette, int Width, int Height, ScriptNode Node, Variables Variables, FractalZoomScript FractalZoomScript, object State)
TODO
NovaJuliaSmoothFractal(ScriptNode r, ScriptNode i, ScriptNode r0, ScriptNode i0, ScriptNode dr, ScriptNode R, ScriptNode p, ScriptNode Palette, int Start, int Length, Expression Expression)
TODO
NovaJuliaSmoothFractal(ScriptNode r, ScriptNode i, ScriptNode r0, ScriptNode i0, ScriptNode dr, ScriptNode R, ScriptNode p, ScriptNode Palette, ScriptNode DimX, ScriptNode DimY, int Start, int Length, Expression Expression)
TODO
NovaJuliaSmoothFractal(ScriptNode r, ScriptNode i, ScriptNode r0, ScriptNode i0, ScriptNode dr, ScriptNode R, ScriptNode p, ScriptNode Palette, ScriptNode DimX, int Start, int Length, Expression Expression)
TODO
Defines a clickable fractal graph in the complex plane.
Definition: FractalGraph.cs:22
static PixelInformation ToPixels(double[] ColorIndex, int Width, int Height, SKColor[] Palette)
TODO
static SKColor[] ToPalette(ObjectVector Vector)
TODO
static double[] FindBoundaries(double[] ColorIndex, int Width, int Height)
TODO
static void Smooth(double[] ColorIndex, double[] Boundary, int Width, int Height, int N, SKColor[] Palette, ScriptNode Node, Variables Variables)
TODO
Handles bitmap-based graphs.
Definition: GraphBitmap.cs:13
Base class for multivariate funcions.
ScriptNode[] Arguments
Function arguments.
Base class for all nodes in a parsed script tree.
Definition: ScriptNode.cs:69
int Length
Length of expression covered by node.
Definition: ScriptNode.cs:101
Expression Expression
Expression of which the node is a part.
Definition: ScriptNode.cs:177
int Start
Start position in script expression.
Definition: ScriptNode.cs:92
Collection of variables.
Definition: Variables.cs:25
void Preview(Expression Expression, IElement Result)
Reports a preview of the final result.
Definition: Variables.cs:455
Basic interface for all types of elements.
Definition: IElement.cs:20
delegate string FractalZoomScript(double r, double i, double Size, object State)
Generates new script when zoomed.
ArgumentType
Type of parameter used in a function definition or a lambda definition.
Definition: IFunction.cs:9