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