Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
NewtonTopographyFractal.cs
1using System;
2using System.Numerics;
3using System.Text;
4using SkiaSharp;
9
11{
42 {
48 : base(new ScriptNode[] { z, dr, R, c, Palette, DimX, DimY },
49 new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar,
50 ArgumentType.Normal, ArgumentType.Vector, ArgumentType.Scalar, ArgumentType.Scalar},
52 {
53 }
54
60 : base(new ScriptNode[] { z, dr, R, c, Palette, DimX },
61 new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar,
62 ArgumentType.Normal, ArgumentType.Vector, ArgumentType.Scalar},
64 {
65 }
66
72 : base(new ScriptNode[] { z, dr, R, c, Palette },
73 new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar,
74 ArgumentType.Normal, ArgumentType.Vector },
76 {
77 }
78
84 : base(new ScriptNode[] { z, dr, R, c },
85 new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar,
86 ArgumentType.Normal },
88 {
89 }
90
94 public override string[] DefaultArgumentNames
95 {
96 get
97 {
98 return new string[] { "z", "dr", "R", "c", "Palette", "DimX", "DimY" };
99 }
100 }
101
106 {
107 string ColorExpression = null;
108 SKColor[] Palette;
109 double[] Coefficients = null;
110 Complex[] CoefficientsZ = null;
111 ILambdaExpression f = null;
112 ScriptNode fDef = null;
113 double rc, ic;
114 double dr;
115 Complex R;
116 int dimx, dimy;
117 int c = Arguments.Length;
118 int i = 0;
119 object Obj;
120
121 Obj = Arguments[i++].AssociatedObjectValue;
122 if (Obj is Complex z)
123 {
124 rc = z.Real;
125 ic = z.Imaginary;
126 }
127 else
128 {
129 rc = Expression.ToDouble(Obj);
130 ic = Expression.ToDouble(Arguments[i++].AssociatedObjectValue);
131 }
132
133 if (i >= c)
134 throw new ScriptRuntimeException("Insufficient parameters in call to NewtonTopographyFractal().", this);
135
136 dr = Expression.ToDouble(Arguments[i++].AssociatedObjectValue);
137
138 if (i < c && ((Obj = Arguments[i].AssociatedObjectValue) is double || Obj is Complex))
139 {
140 R = Expression.ToComplex(Obj);
141 i++;
142 }
143 else
144 {
145 R = Complex.One;
146
147 if (i < c && this.Arguments[i] is null)
148 i++;
149 }
150
151 if (i < c)
152 {
153 if (Arguments[i] is DoubleVector)
154 Coefficients = (double[])Arguments[i++].AssociatedObjectValue;
155 else if (Arguments[i] is ComplexVector)
156 CoefficientsZ = (Complex[])Arguments[i++].AssociatedObjectValue;
157 /*else if (Parameters[i] is RealPolynomial)
158 Coefficients = ((RealPolynomial)Arguments[i++].AssociatedObjectValue).Coefficients;
159 else if (Parameters[i] is ComplexPolynomial)
160 CoefficientsZ = ((ComplexPolynomial)Arguments[i++].AssociatedObjectValue).Coefficients;*/
161 else if (Arguments[i] is IVector)
162 {
163 IVector Vector = (IVector)Arguments[i++];
164 int j, d = Vector.Dimension;
165
166 CoefficientsZ = new Complex[d];
167 for (j = 0; j < d; j++)
168 CoefficientsZ[j] = Expression.ToComplex(Vector.GetElement(j).AssociatedObjectValue);
169 }
170 else if (Arguments[i].AssociatedObjectValue is ILambdaExpression)
171 {
173 if (f.NrArguments != 1)
174 throw new ScriptRuntimeException("Lambda expression in calls to NewtonTopographyFractal() must be of one variable.", this);
175
176 fDef = this.Arguments[i++];
177 }
178 else
179 {
180 throw new ScriptRuntimeException("Parameter " + (i + 1).ToString() +
181 " in call to NewtonTopographyFractal has to be a vector of numbers, containing coefficients " +
182 "of the polynomial to use. Now it was of type " + Arguments[i].GetType().FullName,
183 this);
184 }
185 }
186 else
187 throw new ScriptRuntimeException("Missing coefficients or lambda expression.", this);
188
189 if (i < c && !(this.Arguments[i] is null) && Arguments[i] is ObjectVector)
190 {
191 ColorExpression = this.Arguments[i].SubExpression;
193 }
194 else
195 {
196 Palette = ColorModels.RandomLinearAnalogousHSL.CreatePalette(128, 4, out int Seed, this, Variables);
197 ColorExpression = "RandomLinearAnalogousHSL(128,4," + Seed.ToString() + ")";
198
199 if (i < c && this.Arguments[i] is null)
200 i++;
201 }
202
203 if (i < c)
204 dimx = (int)Expression.ToDouble(Arguments[i++].AssociatedObjectValue);
205 else
206 dimx = 320;
207
208 if (i < c)
209 dimy = (int)Expression.ToDouble(Arguments[i++].AssociatedObjectValue);
210 else
211 dimy = 200;
212
213 if (i < c)
214 {
215 throw new ScriptRuntimeException("Parameter mismatch in call to NewtonTopographyFractal(r,c,dr,Coefficients[,Palette][,dimx[,dimy]]).",
216 this);
217 }
218
219 if (dimx <= 0 || dimx > 5000 || dimy <= 0 || dimy > 5000)
220 throw new ScriptRuntimeException("Image size must be within 1x1 to 5000x5000", this);
221
222 if (!(f is null))
223 {
224 return CalcNewtonTopography(rc, ic, dr, R, f, Variables, Palette, dimx, dimy, this, this.FractalZoomScript,
225 new object[] { Palette, dimx, dimy, R, fDef, ColorExpression });
226 }
227 else if (!(CoefficientsZ is null))
228 {
229 return CalcNewtonTopography(Variables, rc, ic, dr, R, CoefficientsZ, Palette, dimx, dimy, this, this.FractalZoomScript,
230 new object[] { Palette, dimx, dimy, R, CoefficientsZ, ColorExpression });
231 }
232 else
233 {
234 return CalcNewtonTopography(Variables, rc, ic, dr, R, Coefficients, Palette, dimx, dimy, this, this.FractalZoomScript,
235 new object[] { Palette, dimx, dimy, R, Coefficients, ColorExpression });
236 }
237 }
238
239 private string FractalZoomScript(double r, double i, double Size, object State)
240 {
241 object[] Parameters = (object[])State;
242 int DimX = (int)Parameters[1];
243 int DimY = (int)Parameters[2];
244 Complex R = (Complex)Parameters[3];
245 double[] Coefficients = Parameters[4] as double[];
246 string ColorExpression = (string)Parameters[5];
247
248 StringBuilder sb = new StringBuilder();
249
250 sb.Append("NewtonTopographyFractal((");
251 sb.Append(Expression.ToString(r));
252 sb.Append(',');
253 sb.Append(Expression.ToString(i));
254 sb.Append("),");
255 sb.Append(Expression.ToString(Size / 4));
256 sb.Append(',');
257 sb.Append(Expression.ToString(R));
258 sb.Append(',');
259
260 if (Parameters[4] is ScriptNode fDef)
261 sb.Append(fDef.SubExpression);
262 else if (Parameters[4] is Complex[] CoefficientsZ)
263 sb.Append(Expression.ToString(CoefficientsZ));
264 else
265 sb.Append(Expression.ToString(Coefficients));
266
267 if (!string.IsNullOrEmpty(ColorExpression))
268 {
269 sb.Append(',');
270 sb.Append(ColorExpression);
271 }
272
273 sb.Append(',');
274 sb.Append(DimX.ToString());
275 sb.Append(',');
276 sb.Append(DimY.ToString());
277 sb.Append(')');
278
279 return sb.ToString();
280 }
281
285 public static FractalGraph CalcNewtonTopography(Variables Variables, double rCenter, double iCenter, double rDelta, Complex R,
286 double[] Coefficients, SKColor[] Palette, int Width, int Height, ScriptNode Node, FractalZoomScript FractalZoomScript, object State)
287 {
288 double RRe = R.Real;
289 double RIm = R.Imaginary;
290 double r0, i0, r1, i1;
291 double dr, di;
292 double r, i;
293 double zr, zi, zr2, zi2, zr3, zi3, zr4, zi4;
294 double aspect;
295 double Temp;
296 int x, y;
297 int n, N;
298 int Degree = Coefficients.Length - 1;
299
300 N = Palette.Length;
301
302 if (Degree < 2)
303 {
304 Array.Resize(ref Coefficients, 3);
305 while (Degree < 2)
306 Coefficients[++Degree] = 0;
307 }
308
309 if (Width <= 2 || Height <= 2)
310 throw new ScriptRuntimeException("Width and Height has to be greater than 2.", Node);
311
312 double[] Prim = new double[Degree];
313 for (x = 1; x <= Degree; x++)
314 Prim[x - 1] = x * Coefficients[x];
315
316 Array.Reverse(Prim);
317 Coefficients = (double[])Coefficients.Clone();
318 Array.Reverse(Coefficients);
319
320 int Size = Width * Height;
321 double Conv = 1e-10;
322 double Div = 1e10;
323 int[] ColorIndex = new int[Size];
324 int Index = 0;
325
326 rDelta *= 0.5;
327 r0 = rCenter - rDelta;
328 r1 = rCenter + rDelta;
329
330 aspect = ((double)Width) / Height;
331
332 i0 = iCenter - rDelta / aspect;
333 i1 = iCenter + rDelta / aspect;
334
335 dr = (r1 - r0) / Width;
336 di = (i1 - i0) / Height;
337
338 for (y = 0, i = i0; y < Height; y++, i += di)
339 {
340 for (x = 0, r = r0; x < Width; x++, r += dr)
341 {
342 zr = r;
343 zi = i;
344
345 n = 0;
346 do
347 {
348 // f:
349 zr2 = zi2 = 0;
350 foreach (double C in Coefficients)
351 {
352 Temp = zr2 * zr - zi2 * zi + C;
353 zi2 = zr2 * zi + zi2 * zr;
354 zr2 = Temp;
355 }
356
357 // f':
358 zr3 = zi3 = 0;
359 foreach (double C in Prim)
360 {
361 Temp = zr3 * zr - zi3 * zi + C;
362 zi3 = zr3 * zi + zi3 * zr;
363 zr3 = Temp;
364 }
365
366 // f/f':
367
368 Temp = 1.0 / (zr3 * zr3 + zi3 * zi3);
369 zr4 = (zr2 * zr3 + zi2 * zi3) * Temp;
370 zi4 = (zi2 * zr3 - zr2 * zi3) * Temp;
371
372 // R*f/f'
373 Temp = zr4 * RRe - zi4 * RIm;
374 zi4 = zr4 * RIm + zi4 * RRe;
375 zr4 = Temp;
376
377 zr -= zr4;
378 zi -= zi4;
379
380 Temp = Math.Sqrt(zr4 * zr4 + zi4 * zi4);
381 }
382 while ((Temp > Conv) && (Temp < Div) && (n++ < N));
383
384 if (Temp < Conv && n < N)
385 ColorIndex[Index++] = n;
386 else
387 ColorIndex[Index++] = N;
388 }
389 }
390
391 ColorIndex = FractalGraph.FindBoundaries(ColorIndex, Width, Height);
392
393 return new FractalGraph(Variables, FractalGraph.ToPixels(ColorIndex, Width, Height, Palette),
394 r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State);
395 }
396
400 public static FractalGraph CalcNewtonTopography(Variables Variables, double rCenter, double iCenter, double rDelta, Complex R,
401 Complex[] Coefficients, SKColor[] Palette, int Width, int Height, ScriptNode Node, FractalZoomScript FractalZoomScript,
402 object State)
403 {
404 double RRe = R.Real;
405 double RIm = R.Imaginary;
406 double r0, i0, r1, i1;
407 double dr, di;
408 double r, i;
409 double zr, zi, zr2, zi2, zr3, zi3, zr4, zi4;
410 double aspect;
411 double Temp;
412 int x, y;
413 int n, N;
414 int Degree = Coefficients.Length - 1;
415
416 N = Palette.Length;
417
418 if (Degree < 2)
419 {
420 Array.Resize(ref Coefficients, 3);
421 while (Degree < 2)
422 Coefficients[++Degree] = Complex.Zero;
423 }
424
425 if (Width <= 2 || Height <= 2)
426 throw new ScriptRuntimeException("Width and Height has to be greater than 2.", Node);
427
428 Complex[] Prim = new Complex[Degree];
429 for (x = 1; x <= Degree; x++)
430 Prim[x - 1] = x * Coefficients[x];
431
432 Array.Reverse(Prim);
433 Coefficients = (Complex[])Coefficients.Clone();
434 Array.Reverse(Coefficients);
435
436 int j, c = Prim.Length;
437 double[] ReC = new double[c + 1];
438 double[] ImC = new double[c + 1];
439 double[] RePrim = new double[c];
440 double[] ImPrim = new double[c];
441 Complex z;
442
443 for (j = 0; j < c; j++)
444 {
445 z = Coefficients[j];
446 ReC[j] = z.Real;
447 ImC[j] = z.Imaginary;
448
449 z = Prim[j];
450 RePrim[j] = z.Real;
451 ImPrim[j] = z.Imaginary;
452 }
453
454 z = Coefficients[j];
455 ReC[j] = z.Real;
456 ImC[j] = z.Imaginary;
457
458 int Size = Width * Height;
459 double Conv = 1e-10;
460 double Div = 1e10;
461 int[] ColorIndex = new int[Size];
462 int Index = 0;
463
464 rDelta *= 0.5;
465 r0 = rCenter - rDelta;
466 r1 = rCenter + rDelta;
467
468 aspect = ((double)Width) / Height;
469
470 i0 = iCenter - rDelta / aspect;
471 i1 = iCenter + rDelta / aspect;
472
473 dr = (r1 - r0) / Width;
474 di = (i1 - i0) / Height;
475
476 for (y = 0, i = i0; y < Height; y++, i += di)
477 {
478 for (x = 0, r = r0; x < Width; x++, r += dr)
479 {
480 zr = r;
481 zi = i;
482
483 n = 0;
484 do
485 {
486 // f:
487 zr2 = zi2 = 0;
488 for (j = 0; j <= c; j++)
489 {
490 Temp = zr2 * zr - zi2 * zi + ReC[j];
491 zi2 = zr2 * zi + zi2 * zr + ImC[j];
492 zr2 = Temp;
493 }
494
495 // f':
496 zr3 = zi3 = 0;
497 for (j = 0; j < c; j++)
498 {
499 Temp = zr3 * zr - zi3 * zi + RePrim[j];
500 zi3 = zr3 * zi + zi3 * zr + ImPrim[j];
501 zr3 = Temp;
502 }
503
504 // f/f':
505
506 Temp = 1.0 / (zr3 * zr3 + zi3 * zi3);
507 zr4 = (zr2 * zr3 + zi2 * zi3) * Temp;
508 zi4 = (zi2 * zr3 - zr2 * zi3) * Temp;
509
510 // R*f/f'
511 Temp = zr4 * RRe - zi4 * RIm;
512 zi4 = zr4 * RIm + zi4 * RRe;
513 zr4 = Temp;
514
515 zr -= zr4;
516 zi -= zi4;
517
518 Temp = Math.Sqrt(zr4 * zr4 + zi4 * zi4);
519 }
520 while ((Temp > Conv) && (Temp < Div) && (n++ < N));
521
522 if (Temp < Conv && n < N)
523 ColorIndex[Index++] = n;
524 else
525 ColorIndex[Index++] = N;
526 }
527 }
528
529 ColorIndex = FractalGraph.FindBoundaries(ColorIndex, Width, Height);
530
531 return new FractalGraph(Variables, FractalGraph.ToPixels(ColorIndex, Width, Height, Palette),
532 r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State);
533 }
534
538 public static FractalGraph CalcNewtonTopography(double rCenter, double iCenter, double rDelta, Complex R,
539 ILambdaExpression f, Variables Variables, SKColor[] Palette, int Width, int Height,
540 ScriptNode Node, FractalZoomScript FractalZoomScript, object State)
541 {
542 double RRe = R.Real;
543 double RIm = R.Imaginary;
544 double r0, i0, r1, i1;
545 double dr, di;
546 double r, i;
547 double aspect;
548 int x, y;
549 int n, N;
550
551 N = Palette.Length;
552
553 if (Width <= 2 || Height <= 2)
554 throw new ScriptRuntimeException("Width and Height has to be greater than 2.", Node);
555
556 Variables v = new Variables();
557 Variables.CopyTo(v);
558
559 if (!(f is IDifferentiable Differentiable) ||
560 !(Differentiable.Differentiate(Differentiable.DefaultVariableName, v) is ILambdaExpression fPrim))
561 {
562 throw new ScriptRuntimeException("Lambda expression not differentiable.", Node);
563 }
564
565 int Size = Width * Height;
566 double Conv = 1e-10;
567 double Div = 1e10;
568 int[] ColorIndex = new int[Size];
569 int Index = 0;
570
571 Complex[] Row;
572 Complex[] Row2;
573 Complex[] Row3;
574 int[] Offset;
575 IElement[] P = new IElement[1];
576 int j, c, x2;
577 IElement Obj, Obj2;
578 double Mod;
579 Complex z;
580
581 rDelta *= 0.5;
582 r0 = rCenter - rDelta;
583 r1 = rCenter + rDelta;
584
585 aspect = ((double)Width) / Height;
586
587 i0 = iCenter - rDelta / aspect;
588 i1 = iCenter + rDelta / aspect;
589
590 dr = (r1 - r0) / Width;
591 di = (i1 - i0) / Height;
592
593 for (y = 0, i = i0; y < Height; y++, i += di)
594 {
595 Row = new Complex[Width];
596 Offset = new int[Width];
597
598 c = Width;
599 for (x = 0, x2 = y * Width, r = r0; x < Width; x++, r += dr, x2++)
600 {
601 Row[x] = new Complex(r, i);
602 Offset[x] = x2;
603 }
604
605 n = 0;
606 while (n < N && c > 0)
607 {
608 n++;
609 P[0] = new ComplexVector(Row);
610 Obj = f.Evaluate(P, v);
611 Obj2 = fPrim.Evaluate(P, v);
612 Row2 = Obj.AssociatedObjectValue as Complex[];
613 Row3 = Obj2.AssociatedObjectValue as Complex[];
614
615 if (Row2 is null || Row3 is null)
616 {
617 throw new ScriptRuntimeException("Lambda expression (and its first derivative) must be able to accept complex vectors, " +
618 "and return complex vectors of equal length. Type returned: " +
619 Obj.GetType().FullName + " and " + Obj2.GetType().FullName, Node);
620 }
621 else if (Row2.Length != c || Row3.Length != c)
622 {
623 throw new ScriptRuntimeException("Lambda expression (and its first derivative) must be able to accept complex vectors, " +
624 "and return complex vectors of equal length. Length returned: " +
625 Row2.Length.ToString() + " and " + Row3.Length.ToString() +
626 ". Expected: " + c.ToString(), Node);
627 }
628
629 for (x = x2 = 0; x < c; x++)
630 {
631 j = Offset[x];
632 z = R * Row2[x] / Row3[x];
633 Row[x] -= z;
634
635 Mod = z.Magnitude;
636
637 if (Mod > Conv && Mod < Div)
638 {
639 if (x != x2)
640 Offset[x2] = j;
641
642 x2++;
643 }
644 else
645 {
646 if (n >= N)
647 ColorIndex[Index++] = N;
648 else
649 ColorIndex[j++] = n;
650 }
651 }
652
653 if (x2 < x)
654 {
655 Array.Resize(ref Row, x2);
656 Array.Resize(ref Offset, x2);
657 c = x2;
658 }
659 }
660 }
661
662 ColorIndex = FractalGraph.FindBoundaries(ColorIndex, Width, Height);
663
664 return new FractalGraph(Variables, FractalGraph.ToPixels(ColorIndex, Width, Height, Palette),
665 r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State);
666 }
667
671 public override string FunctionName => nameof(NewtonTopographyFractal);
672 }
673}
Class managing a script expression.
Definition: Expression.cs:39
static Complex ToComplex(object Object)
Converts an object to a complex value.
Definition: Expression.cs:4942
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 Newton Fractal Image, and extracts the topography lines from it.
static FractalGraph CalcNewtonTopography(Variables Variables, double rCenter, double iCenter, double rDelta, Complex R, Complex[] Coefficients, SKColor[] Palette, int Width, int Height, ScriptNode Node, FractalZoomScript FractalZoomScript, object State)
TODO
NewtonTopographyFractal(ScriptNode z, ScriptNode dr, ScriptNode R, ScriptNode c, ScriptNode Palette, ScriptNode DimX, int Start, int Length, Expression Expression)
TODO
NewtonTopographyFractal(ScriptNode z, ScriptNode dr, ScriptNode R, ScriptNode c, ScriptNode Palette, ScriptNode DimX, ScriptNode DimY, int Start, int Length, Expression Expression)
TODO
override IElement Evaluate(IElement[] Arguments, Variables Variables)
TODO
NewtonTopographyFractal(ScriptNode z, ScriptNode dr, ScriptNode R, ScriptNode c, int Start, int Length, Expression Expression)
TODO
static FractalGraph CalcNewtonTopography(double rCenter, double iCenter, double rDelta, Complex R, ILambdaExpression f, Variables Variables, SKColor[] Palette, int Width, int Height, ScriptNode Node, FractalZoomScript FractalZoomScript, object State)
TODO
NewtonTopographyFractal(ScriptNode z, ScriptNode dr, ScriptNode R, ScriptNode c, ScriptNode Palette, int Start, int Length, Expression Expression)
TODO
static FractalGraph CalcNewtonTopography(Variables Variables, double rCenter, double iCenter, double rDelta, Complex R, double[] Coefficients, SKColor[] Palette, int Width, int Height, ScriptNode Node, FractalZoomScript FractalZoomScript, object State)
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
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
override string ToString()
Definition: ScriptNode.cs:359
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 CopyTo(Variables Variables)
Copies available variables to another variable collection.
Definition: Variables.cs:400
Basic interface for all types of elements.
Definition: IElement.cs:20
object AssociatedObjectValue
Associated object value.
Definition: IElement.cs:33
Basic interface for vectors.
Definition: IVector.cs:9
int Dimension
Dimension of vector.
Definition: IVector.cs:14
IElement GetElement(int Index)
Gets an element of the vector.
Base interface for lambda expressions.
Base interface for lambda expressions.
IElement Evaluate(IElement[] Arguments, Variables Variables)
Evaluates the lambda expression.
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