Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
FractalGraph.cs
1using System;
2using System.Threading.Tasks;
3using SkiaSharp;
7
9{
17 public delegate string FractalZoomScript(double r, double i, double Size, object State);
18
23 {
24 //private const double LimitPercentChange = 0.0025;
25 private const double LimitPercentChange = 0.00025;
26
27 private readonly FractalZoomScript fractalZoomScript;
28 private readonly ScriptNode node;
29 private readonly double r0, i0, r1, i1, size;
30 private readonly object state;
31 private readonly int width;
32 private readonly int height;
33 private readonly bool invertY;
34
38 public FractalGraph()
39 : base(new Variables())
40 {
41 }
42
48 : base(Variables)
49 {
50 }
51
66 public FractalGraph(Variables Variables, PixelInformation Pixels, double r0, double i0, double r1, double i1, double Size,
67 bool InvertY, ScriptNode Node, FractalZoomScript FractalZoomScript, object State)
68 : base(Variables, Pixels)
69 {
70 this.r0 = r0;
71 this.i0 = i0;
72 this.r1 = r1;
73 this.i1 = i1;
74 this.state = State;
75 this.size = Size;
76 this.invertY = InvertY;
77 this.width = Pixels.Width;
78 this.height = Pixels.Height;
79 this.node = Node;
80 this.fractalZoomScript = FractalZoomScript;
81 }
82
86 public ScriptNode Node => this.node;
87
91 public override string GetBitmapClickScript(double X, double Y, object[] States)
92 {
93 double r = X * (this.r1 - this.r0) / this.width + this.r0;
94 double i;
95
96 if (this.invertY)
97 i = this.i0 - Y * (this.i0 - this.i1) / this.height;
98 else
99 i = this.i1 - Y * (this.i1 - this.i0) / this.height;
100
101 if (this.fractalZoomScript is null)
102 return "[" + Expression.ToString(r) + ";" + Expression.ToString(i) + "]";
103
104 return this.fractalZoomScript(r, i, this.size, this.state);
105 }
106
110 public static SKColor[] ToPalette(ObjectVector Vector)
111 {
112 int i, c = Vector.Dimension;
113 SKColor[] Palette = new SKColor[c];
114
115 for (i = 0; i < c; i++)
116 Palette[i] = Graph.ToColor(Vector.GetElement(i).AssociatedObjectValue);
117
118 return Palette;
119 }
120
124 public static async Task Smooth(double[] ColorIndex, double[] Boundary, int Width, int Height, int N,
125 SKColor[] Palette, ScriptNode Node, Variables Variables)
126 {
127 // Passing ColorIndex through the heat equation of 2 spatial dimensions,
128 // maintaining the boundary values fixed in each step.
129 //
130 // du ( d2u d2u )
131 // -- = a * | --- + --- |
132 // dt ( dx2 dy2 )
133 //
134 // the following difference equations will be used to estimate the derivatives:
135 //
136 // f(x+h)-2f(x)+f(x-h)
137 // f"(x) = ------------------- + O(h^2)
138 // h^2
139 //
140 // at the edges, we let f"(x)=0.
141
142 int Size = Width * Height;
143 double[] Delta = new double[Size];
144 double uxx, uyy;
145 double d;
146 int Iterations = 0;
147 int Index;
148 int x, y;
149 int DynamicPixels = Size;
150 double Sum = Size;
151 bool DoPreview = Variables.HandlesPreview;
152 DateTime LastPreview = DateTime.Now;
153 DateTime TP;
154
155 for (Index = 0; Index < Size; Index++)
156 {
157 if (Boundary[Index] >= 0 || ColorIndex[Index] >= N)
158 DynamicPixels--;
159 }
160
161 DateTime Start = DateTime.Now;
162 TimeSpan Limit = new TimeSpan(1, 0, 0);
163
164 while (100 * Sum / DynamicPixels > LimitPercentChange && Iterations < 50000 && (DateTime.Now - Start) < Limit)
165 {
166 Sum = 0;
167
168 for (y = Index = 0; y < Height; y++)
169 {
170 for (x = 0; x < Width; x++)
171 {
172 d = Boundary[Index];
173 if (d >= 0)
174 {
175 Delta[Index++] = 0;
176 continue;
177 }
178
179 d = 2 * ColorIndex[Index];
180 if (x == 0 || x == Width - 1)
181 uxx = 0;
182 else
183 uxx = ColorIndex[Index - 1] - d + ColorIndex[Index + 1];
184
185 if (y == 0 || y == Height - 1)
186 uyy = 0;
187 else
188 uyy = ColorIndex[Index - Width] - d + ColorIndex[Index + Width];
189
190 d = 0.2 * (uxx + uyy);
191 Delta[Index++] = d;
192 Sum += Math.Abs(d);
193 }
194 }
195
196 for (Index = 0; Index < Size; Index++)
197 ColorIndex[Index] += Delta[Index];
198
199 Iterations++;
200
201 TP = DateTime.Now;
202 if ((TP - LastPreview).TotalSeconds > 5)
203 {
204 if (!(Node is null))
205 {
206 LastPreview = TP;
207
208 if (DoPreview)
209 await Variables.Preview(Node.Expression, new GraphBitmap(Variables, ToPixels(ColorIndex, Width, Height, Palette)));
210
211 await Variables.Status(Node.Expression, "Smoothing. Change: " + (100 * Sum / DynamicPixels).ToString("F3") + "%, Limit: " + LimitPercentChange.ToString("F3") + "%, Iterations: " + Iterations.ToString());
212 }
213 }
214 }
215
216 Variables.ConsoleOut?.Write("Iterations: " + Iterations.ToString());
217 await Variables.Status(Node.Expression, string.Empty);
218 }
219
223 public static async Task Smooth(double[] R, double[] G, double[] B, double[] A,
224 double[] BoundaryR, double[] BoundaryG, double[] BoundaryB, double[] BoundaryA,
225 int Width, int Height, ScriptNode Node, Variables Variables)
226 {
227 // Passing color components through the heat equation of 2 spatial dimensions,
228 // maintaining the boundary values fixed in each step.
229 //
230 // du ( d2u d2u )
231 // -- = a * | --- + --- |
232 // dt ( dx2 dy2 )
233 //
234 // the following difference equations will be used to estimate the derivatives:
235 //
236 // f(x+h)-2f(x)+f(x-h)
237 // f"(x) = ------------------- + O(h^2)
238 // h^2
239 //
240 // at the edges, we let f"(x)=0.
241
242 int Size = Width * Height;
243 double[] DeltaR = new double[Size];
244 double[] DeltaG = new double[Size];
245 double[] DeltaB = new double[Size];
246 double[] DeltaA = new double[Size];
247 double uxx, uyy;
248 double d;
249 int Iterations = 0;
250 int Index;
251 int x, y;
252 int DynamicPixels = Size;
253 double Sum = Size;
254 bool DoPreview = Variables.HandlesPreview;
255 DateTime LastPreview = DateTime.Now;
256 DateTime TP;
257
258 for (Index = 0; Index < Size; Index++)
259 {
260 if (BoundaryR[Index] >= 0)
261 DynamicPixels--;
262 }
263
264 DateTime Start = DateTime.Now;
265 TimeSpan Limit = new TimeSpan(1, 0, 0);
266
267 while (100 * Sum / DynamicPixels > LimitPercentChange && Iterations < 50000 && (DateTime.Now - Start) < Limit)
268 {
269 Sum = 0;
270
271 for (y = Index = 0; y < Height; y++)
272 {
273 for (x = 0; x < Width; x++)
274 {
275 if (BoundaryR[Index] >= 0 || BoundaryG[Index] >= 0 || BoundaryB[Index] >= 0 || BoundaryA[Index] >= 0)
276 {
277 DeltaR[Index] = 0;
278 DeltaG[Index] = 0;
279 DeltaB[Index] = 0;
280 DeltaA[Index++] = 0;
281 continue;
282 }
283
284 d = 2 * R[Index];
285 if (x == 0 || x == Width - 1)
286 uxx = 0;
287 else
288 uxx = R[Index - 1] - d + R[Index + 1];
289
290 if (y == 0 || y == Height - 1)
291 uyy = 0;
292 else
293 uyy = R[Index - Width] - d + R[Index + Width];
294
295 d = 0.2 * (uxx + uyy);
296 DeltaR[Index] = d;
297 Sum += Math.Abs(d);
298
299 d = 2 * G[Index];
300 if (x == 0 || x == Width - 1)
301 uxx = 0;
302 else
303 uxx = G[Index - 1] - d + G[Index + 1];
304
305 if (y == 0 || y == Height - 1)
306 uyy = 0;
307 else
308 uyy = G[Index - Width] - d + G[Index + Width];
309
310 d = 0.2 * (uxx + uyy);
311 DeltaG[Index] = d;
312 Sum += Math.Abs(d);
313
314 d = 2 * B[Index];
315 if (x == 0 || x == Width - 1)
316 uxx = 0;
317 else
318 uxx = B[Index - 1] - d + B[Index + 1];
319
320 if (y == 0 || y == Height - 1)
321 uyy = 0;
322 else
323 uyy = B[Index - Width] - d + B[Index + Width];
324
325 d = 0.2 * (uxx + uyy);
326 DeltaB[Index] = d;
327 Sum += Math.Abs(d);
328
329 d = 2 * A[Index];
330 if (x == 0 || x == Width - 1)
331 uxx = 0;
332 else
333 uxx = A[Index - 1] - d + A[Index + 1];
334
335 if (y == 0 || y == Height - 1)
336 uyy = 0;
337 else
338 uyy = A[Index - Width] - d + A[Index + Width];
339
340 d = 0.2 * (uxx + uyy);
341 DeltaA[Index] = d;
342 Sum += Math.Abs(d);
343
344 Index++;
345 }
346 }
347
348 for (Index = 0; Index < Size; Index++)
349 {
350 R[Index] += DeltaR[Index];
351 G[Index] += DeltaG[Index];
352 B[Index] += DeltaB[Index];
353 A[Index] += DeltaA[Index];
354 }
355
356 Iterations++;
357
358 TP = DateTime.Now;
359 if ((TP - LastPreview).TotalSeconds > 5)
360 {
361 if (!(Node is null))
362 {
363 LastPreview = TP;
364
365 if (DoPreview)
366 await Variables.Preview(Node.Expression, new GraphBitmap(Variables, ToPixels(R, G, B, A, Width, Height)));
367
368 await Variables.Status(Node.Expression, "Smoothing. Change: " + (100 * Sum / DynamicPixels).ToString("F3") + "%, Limit: " + LimitPercentChange.ToString("F3") + "%, Iterations: " + Iterations.ToString());
369 }
370 }
371 }
372
373 Variables.ConsoleOut?.Write("Iterations: " + Iterations.ToString());
374 await Variables.Status(Node.Expression, string.Empty);
375 }
376
380 public static double[] FindBoundaries(double[] ColorIndex, int Width, int Height)
381 {
382 // Finding boundary values:
383
384 double[] Boundary = (double[])ColorIndex.Clone();
385 double d, d2;
386 int Index;
387 int x, y;
388
389 Index = 0;
390
391 d = ColorIndex[0];
392
393 d2 = ColorIndex[1];
394 if (d <= d2 && d > d2 - 2)
395 {
396 d2 = ColorIndex[Width];
397 if (d <= d2 && d > d2 - 2)
398 Boundary[0] = -1;
399 }
400
401 Index++;
402
403 for (x = 2; x < Width; x++, Index++)
404 {
405 d = ColorIndex[Index];
406
407 d2 = ColorIndex[Index + 1];
408 if (d > d2 || d <= d2 - 2)
409 continue;
410
411 d2 = ColorIndex[Index - 1];
412 if (d > d2 || d <= d2 - 2)
413 continue;
414
415 d2 = ColorIndex[Index + Width];
416 if (d > d2 || d <= d2 - 2)
417 continue;
418
419 Boundary[Index] = -1;
420 }
421
422 d2 = ColorIndex[Index];
423 if (d <= d2 && d > d2 - 2)
424 {
425 d2 = ColorIndex[Index - 1];
426 if (d <= d2 && d > d2 - 2)
427 {
428 d2 = ColorIndex[Index + Width];
429 if (d <= d2 && d > d2 - 2)
430 Boundary[Index] = -1;
431 }
432 }
433
434 Index++;
435
436 for (y = 2; y < Height; y++)
437 {
438 d = ColorIndex[Index];
439
440 d2 = ColorIndex[Index + 1];
441 if (d <= d2 && d > d2 - 2)
442 {
443 d2 = ColorIndex[Index - Width];
444 if (d <= d2 && d > d2 - 2)
445 {
446 d2 = ColorIndex[Index + Width];
447 if (d <= d2 && d > d2 - 2)
448 Boundary[Index] = -1;
449 }
450 }
451
452 Index++;
453
454 for (x = 2; x < Width; x++, Index++)
455 {
456 d = ColorIndex[Index];
457
458 d2 = ColorIndex[Index + 1];
459 if (d > d2 || d <= d2 - 2)
460 continue;
461
462 d2 = ColorIndex[Index - 1];
463 if (d > d2 || d <= d2 - 2)
464 continue;
465
466 d2 = ColorIndex[Index + Width];
467 if (d > d2 || d <= d2 - 2)
468 continue;
469
470 d2 = ColorIndex[Index - Width];
471 if (d > d2 || d <= d2 - 2)
472 continue;
473
474 Boundary[Index] = -1;
475 }
476
477 d = ColorIndex[Index];
478
479 d2 = ColorIndex[Index - 1];
480 if (d <= d2 && d > d2 - 2)
481 {
482 d2 = ColorIndex[Index - Width];
483 if (d <= d2 && d > d2 - 2)
484 {
485 d2 = ColorIndex[Index + Width];
486 if (d <= d2 && d > d2 - 2)
487 Boundary[Index] = -1;
488 }
489 }
490
491 Index++;
492 }
493
494 d = ColorIndex[Index];
495
496 d2 = ColorIndex[Index + 1];
497 if (d <= d2 && d > d2 - 2)
498 {
499 d2 = ColorIndex[Index - Width];
500 if (d <= d2 && d > d2 - 2)
501 Boundary[Index] = -1;
502 }
503
504 Index++;
505
506 for (x = 2; x < Width; x++, Index++)
507 {
508 d = ColorIndex[Index];
509
510 d2 = ColorIndex[Index + 1];
511 if (d > d2 || d <= d2 - 2)
512 continue;
513
514 d2 = ColorIndex[Index - 1];
515 if (d > d2 || d <= d2 - 2)
516 continue;
517
518 d2 = ColorIndex[Index - Width];
519 if (d > d2 || d <= d2 - 2)
520 continue;
521
522 Boundary[Index] = -1;
523 }
524
525 d = ColorIndex[Index];
526
527 d2 = ColorIndex[Index - 1];
528 if (d <= d2 && d > d2 - 2)
529 {
530 d2 = ColorIndex[Index - Width];
531 if (d <= d2 && d > d2 - 2)
532 Boundary[Index] = -1;
533 }
534
535 return Boundary;
536 }
537
541 public static int[] FindBoundaries(int[] ColorIndex, int Width, int Height)
542 {
543 // Finding boundary values:
544
545 int[] Boundary = (int[])ColorIndex.Clone();
546 int Index;
547 int d, d2;
548 int x, y;
549
550 Index = 0;
551
552 d = ColorIndex[0];
553
554 d2 = ColorIndex[1];
555 if (d <= d2 && d > d2 - 2)
556 {
557 d2 = ColorIndex[Width];
558 if (d <= d2 && d > d2 - 2)
559 Boundary[0] = -1;
560 }
561
562 Index++;
563
564 for (x = 2; x < Width; x++, Index++)
565 {
566 d = ColorIndex[Index];
567
568 d2 = ColorIndex[Index + 1];
569 if (d > d2 || d <= d2 - 2)
570 continue;
571
572 d2 = ColorIndex[Index - 1];
573 if (d > d2 || d <= d2 - 2)
574 continue;
575
576 d2 = ColorIndex[Index + Width];
577 if (d > d2 || d <= d2 - 2)
578 continue;
579
580 Boundary[Index] = -1;
581 }
582
583 d2 = ColorIndex[Index];
584 if (d <= d2 && d > d2 - 2)
585 {
586 d2 = ColorIndex[Index - 1];
587 if (d <= d2 && d > d2 - 2)
588 {
589 d2 = ColorIndex[Index + Width];
590 if (d <= d2 && d > d2 - 2)
591 Boundary[Index] = -1;
592 }
593 }
594
595 Index++;
596
597 for (y = 2; y < Height; y++)
598 {
599 d = ColorIndex[Index];
600
601 d2 = ColorIndex[Index + 1];
602 if (d <= d2 && d > d2 - 2)
603 {
604 d2 = ColorIndex[Index - Width];
605 if (d <= d2 && d > d2 - 2)
606 {
607 d2 = ColorIndex[Index + Width];
608 if (d <= d2 && d > d2 - 2)
609 Boundary[Index] = -1;
610 }
611 }
612
613 Index++;
614
615 for (x = 2; x < Width; x++, Index++)
616 {
617 d = ColorIndex[Index];
618
619 d2 = ColorIndex[Index + 1];
620 if (d > d2 || d <= d2 - 2)
621 continue;
622
623 d2 = ColorIndex[Index - 1];
624 if (d > d2 || d <= d2 - 2)
625 continue;
626
627 d2 = ColorIndex[Index + Width];
628 if (d > d2 || d <= d2 - 2)
629 continue;
630
631 d2 = ColorIndex[Index - Width];
632 if (d > d2 || d <= d2 - 2)
633 continue;
634
635 Boundary[Index] = -1;
636 }
637
638 d = ColorIndex[Index];
639
640 d2 = ColorIndex[Index - 1];
641 if (d <= d2 && d > d2 - 2)
642 {
643 d2 = ColorIndex[Index - Width];
644 if (d <= d2 && d > d2 - 2)
645 {
646 d2 = ColorIndex[Index + Width];
647 if (d <= d2 && d > d2 - 2)
648 Boundary[Index] = -1;
649 }
650 }
651
652 Index++;
653 }
654
655 d = ColorIndex[Index];
656
657 d2 = ColorIndex[Index + 1];
658 if (d <= d2 && d > d2 - 2)
659 {
660 d2 = ColorIndex[Index - Width];
661 if (d <= d2 && d > d2 - 2)
662 Boundary[Index] = -1;
663 }
664
665 Index++;
666
667 for (x = 2; x < Width; x++, Index++)
668 {
669 d = ColorIndex[Index];
670
671 d2 = ColorIndex[Index + 1];
672 if (d > d2 || d <= d2 - 2)
673 continue;
674
675 d2 = ColorIndex[Index - 1];
676 if (d > d2 || d <= d2 - 2)
677 continue;
678
679 d2 = ColorIndex[Index - Width];
680 if (d > d2 || d <= d2 - 2)
681 continue;
682
683 Boundary[Index] = -1;
684 }
685
686 d = ColorIndex[Index];
687
688 d2 = ColorIndex[Index - 1];
689 if (d <= d2 && d > d2 - 2)
690 {
691 d2 = ColorIndex[Index - Width];
692 if (d <= d2 && d > d2 - 2)
693 Boundary[0] = -1;
694 }
695
696 return Boundary;
697 }
698
702 public static (double[], double[], double[], double[]) FindBoundaries(double[] R, double[] G, double[] B, double[] A, int Width, int Height)
703 {
704 // Finding boundary values:
705
706 double[] BoundaryR = (double[])R.Clone();
707 double[] BoundaryG = (double[])G.Clone();
708 double[] BoundaryB = (double[])B.Clone();
709 double[] BoundaryA = (double[])A.Clone();
710 double dR, dR2;
711 double dG, dG2;
712 double dB, dB2;
713 double dA, dA2;
714 int Index;
715 int x, y;
716
717 Index = 0;
718
719 dR = R[0];
720 dG = G[0];
721 dB = B[0];
722 dA = A[0];
723
724 dR2 = R[1];
725 dG2 = G[1];
726 dB2 = B[1];
727 dA2 = A[1];
728
729 if (dR <= dR2 && dR > dR2 - 2 &&
730 dG <= dG2 && dG > dG2 - 2 &&
731 dB <= dB2 && dB > dB2 - 2 &&
732 dA <= dA2 && dA > dA2 - 2)
733 {
734 dR2 = R[Width];
735 dG2 = G[Width];
736 dB2 = B[Width];
737 dA2 = A[Width];
738
739 if (dR <= dR2 && dR > dR2 - 2 &&
740 dG <= dG2 && dG > dG2 - 2 &&
741 dB <= dB2 && dB > dB2 - 2 &&
742 dA <= dA2 && dA > dA2 - 2)
743 {
744 BoundaryR[0] = -1;
745 BoundaryG[0] = -1;
746 BoundaryB[0] = -1;
747 BoundaryA[0] = -1;
748 }
749 }
750
751 Index++;
752
753 for (x = 2; x < Width; x++, Index++)
754 {
755 dR = R[Index];
756 dG = G[Index];
757 dB = B[Index];
758 dA = A[Index];
759
760 dR2 = R[Index + 1];
761 dG2 = G[Index + 1];
762 dB2 = B[Index + 1];
763 dA2 = A[Index + 1];
764
765 if (dR > dR2 || dR <= dR2 - 2 &&
766 dG > dG2 || dG <= dG2 - 2 &&
767 dB > dB2 || dB <= dB2 - 2 &&
768 dA > dA2 || dA <= dA2 - 2)
769 {
770 continue;
771 }
772
773 dR2 = R[Index - 1];
774 dG2 = G[Index - 1];
775 dB2 = B[Index - 1];
776 dA2 = A[Index - 1];
777
778 if (dR > dR2 || dR <= dR2 - 2 &&
779 dG > dG2 || dG <= dG2 - 2 &&
780 dB > dB2 || dB <= dB2 - 2 &&
781 dA > dA2 || dA <= dA2 - 2)
782 {
783 continue;
784 }
785
786 dR2 = R[Index + Width];
787 dG2 = G[Index + Width];
788 dB2 = B[Index + Width];
789 dA2 = A[Index + Width];
790
791 if (dR > dR2 || dR <= dR2 - 2 &&
792 dG > dG2 || dG <= dG2 - 2 &&
793 dB > dB2 || dB <= dB2 - 2 &&
794 dA > dA2 || dA <= dA2 - 2)
795 {
796 continue;
797 }
798
799 BoundaryR[Index] = -1;
800 BoundaryG[Index] = -1;
801 BoundaryB[Index] = -1;
802 BoundaryA[Index] = -1;
803 }
804
805 dR2 = R[Index];
806 dG2 = G[Index];
807 dB2 = B[Index];
808 dA2 = A[Index];
809
810 if (dR <= dR2 && dR > dR2 - 2 &&
811 dG <= dG2 && dG > dG2 - 2 &&
812 dB <= dB2 && dB > dB2 - 2 &&
813 dA <= dA2 && dA > dA2 - 2)
814 {
815 dR2 = R[Index - 1];
816 dG2 = G[Index - 1];
817 dB2 = B[Index - 1];
818 dA2 = A[Index - 1];
819
820 if (dR <= dR2 && dR > dR2 - 2 &&
821 dG <= dG2 && dG > dG2 - 2 &&
822 dB <= dB2 && dB > dB2 - 2 &&
823 dA <= dA2 && dA > dA2 - 2)
824 {
825 dR2 = R[Index + Width];
826 dG2 = G[Index + Width];
827 dB2 = B[Index + Width];
828 dA2 = A[Index + Width];
829
830 if (dR <= dR2 && dR > dR2 - 2 &&
831 dG <= dG2 && dG > dG2 - 2 &&
832 dB <= dB2 && dB > dB2 - 2 &&
833 dA <= dA2 && dA > dA2 - 2)
834 {
835 BoundaryR[Index] = -1;
836 BoundaryG[Index] = -1;
837 BoundaryB[Index] = -1;
838 BoundaryA[Index] = -1;
839 }
840 }
841 }
842
843 Index++;
844
845 for (y = 2; y < Height; y++)
846 {
847 dR = R[Index];
848 dG = G[Index];
849 dB = B[Index];
850 dA = A[Index];
851
852 dR2 = R[Index + 1];
853 dG2 = G[Index + 1];
854 dB2 = B[Index + 1];
855 dA2 = A[Index + 1];
856
857 if (dR <= dR2 && dR > dR2 - 2 &&
858 dG <= dG2 && dG > dG2 - 2 &&
859 dB <= dB2 && dB > dB2 - 2 &&
860 dA <= dA2 && dA > dA2 - 2)
861 {
862 dR2 = R[Index - Width];
863 dG2 = G[Index - Width];
864 dB2 = B[Index - Width];
865 dA2 = A[Index - Width];
866
867 if (dR <= dR2 && dR > dR2 - 2 &&
868 dG <= dG2 && dG > dG2 - 2 &&
869 dB <= dB2 && dB > dB2 - 2 &&
870 dA <= dA2 && dA > dA2 - 2)
871 {
872 dR2 = R[Index + Width];
873 dG2 = G[Index + Width];
874 dB2 = B[Index + Width];
875 dA2 = A[Index + Width];
876
877 if (dR <= dR2 && dR > dR2 - 2 &&
878 dG <= dG2 && dG > dG2 - 2 &&
879 dB <= dB2 && dB > dB2 - 2 &&
880 dA <= dA2 && dA > dA2 - 2)
881 {
882 BoundaryR[Index] = -1;
883 BoundaryG[Index] = -1;
884 BoundaryB[Index] = -1;
885 BoundaryA[Index] = -1;
886 }
887 }
888 }
889
890 Index++;
891
892 for (x = 2; x < Width; x++, Index++)
893 {
894 dR = R[Index];
895 dG = G[Index];
896 dB = B[Index];
897 dA = A[Index];
898
899 dR2 = R[Index + 1];
900 dG2 = G[Index + 1];
901 dB2 = B[Index + 1];
902 dA2 = A[Index + 1];
903
904 if (dR > dR2 || dR <= dR2 - 2 &&
905 dG > dG2 || dG <= dG2 - 2 &&
906 dB > dB2 || dB <= dB2 - 2 &&
907 dA > dA2 || dA <= dA2 - 2)
908 {
909 continue;
910 }
911
912 dR2 = R[Index - 1];
913 dG2 = G[Index - 1];
914 dB2 = B[Index - 1];
915 dA2 = A[Index - 1];
916
917 if (dR > dR2 || dR <= dR2 - 2 &&
918 dG > dG2 || dG <= dG2 - 2 &&
919 dB > dB2 || dB <= dB2 - 2 &&
920 dA > dA2 || dA <= dA2 - 2)
921 {
922 continue;
923 }
924
925 dR2 = R[Index + Width];
926 dG2 = G[Index + Width];
927 dB2 = B[Index + Width];
928 dA2 = A[Index + Width];
929
930 if (dR > dR2 || dR <= dR2 - 2 &&
931 dG > dG2 || dG <= dG2 - 2 &&
932 dB > dB2 || dB <= dB2 - 2 &&
933 dA > dA2 || dA <= dA2 - 2)
934 {
935 continue;
936 }
937
938 dR2 = R[Index - Width];
939 dG2 = G[Index - Width];
940 dB2 = B[Index - Width];
941 dA2 = A[Index - Width];
942
943 if (dR > dR2 || dR <= dR2 - 2 &&
944 dG > dG2 || dG <= dG2 - 2 &&
945 dB > dB2 || dB <= dB2 - 2 &&
946 dA > dA2 || dA <= dA2 - 2)
947 {
948 continue;
949 }
950
951 BoundaryR[Index] = -1;
952 BoundaryG[Index] = -1;
953 BoundaryB[Index] = -1;
954 BoundaryA[Index] = -1;
955 }
956
957 dR = R[Index];
958 dG = G[Index];
959 dB = B[Index];
960 dA = A[Index];
961
962 dR2 = R[Index - 1];
963 dG2 = G[Index - 1];
964 dB2 = B[Index - 1];
965 dA2 = A[Index - 1];
966
967 if (dR <= dR2 && dR > dR2 - 2 &&
968 dG <= dG2 && dG > dG2 - 2 &&
969 dB <= dB2 && dB > dB2 - 2 &&
970 dA <= dA2 && dA > dA2 - 2)
971 {
972 dR2 = R[Index - Width];
973 dG2 = G[Index - Width];
974 dB2 = B[Index - Width];
975 dA2 = A[Index - Width];
976
977 if (dR <= dR2 && dR > dR2 - 2 &&
978 dG <= dG2 && dG > dG2 - 2 &&
979 dB <= dB2 && dB > dB2 - 2 &&
980 dA <= dA2 && dA > dA2 - 2)
981 {
982 dR2 = R[Index + Width];
983 dG2 = G[Index + Width];
984 dB2 = B[Index + Width];
985 dA2 = A[Index + Width];
986
987 if (dR <= dR2 && dR > dR2 - 2 &&
988 dG <= dG2 && dG > dG2 - 2 &&
989 dB <= dB2 && dB > dB2 - 2 &&
990 dA <= dA2 && dA > dA2 - 2)
991 {
992 BoundaryR[Index] = -1;
993 BoundaryG[Index] = -1;
994 BoundaryB[Index] = -1;
995 BoundaryA[Index] = -1;
996 }
997 }
998 }
999
1000 Index++;
1001 }
1002
1003 dR = R[Index];
1004 dG = G[Index];
1005 dB = B[Index];
1006 dA = A[Index];
1007
1008 dR2 = R[Index + 1];
1009 dG2 = G[Index + 1];
1010 dB2 = B[Index + 1];
1011 dA2 = A[Index + 1];
1012
1013 if (dR <= dR2 && dR > dR2 - 2 &&
1014 dG <= dG2 && dG > dG2 - 2 &&
1015 dB <= dB2 && dB > dB2 - 2 &&
1016 dA <= dA2 && dA > dA2 - 2)
1017 {
1018 dR2 = R[Index - Width];
1019 dG2 = G[Index - Width];
1020 dB2 = B[Index - Width];
1021 dA2 = A[Index - Width];
1022
1023 if (dR <= dR2 && dR > dR2 - 2 &&
1024 dG <= dG2 && dG > dG2 - 2 &&
1025 dB <= dB2 && dB > dB2 - 2 &&
1026 dA <= dA2 && dA > dA2 - 2)
1027 {
1028 BoundaryR[Index] = -1;
1029 BoundaryG[Index] = -1;
1030 BoundaryB[Index] = -1;
1031 BoundaryA[Index] = -1;
1032 }
1033 }
1034
1035 Index++;
1036
1037 for (x = 2; x < Width; x++, Index++)
1038 {
1039 dR = R[Index];
1040 dG = G[Index];
1041 dB = B[Index];
1042 dA = A[Index];
1043
1044 dR2 = R[Index + 1];
1045 dG2 = G[Index + 1];
1046 dB2 = B[Index + 1];
1047 dA2 = A[Index + 1];
1048
1049 if (dR > dR2 || dR <= dR2 - 2 &&
1050 dG > dG2 || dG <= dG2 - 2 &&
1051 dB > dB2 || dB <= dB2 - 2 &&
1052 dA > dA2 || dA <= dA2 - 2)
1053 {
1054 continue;
1055 }
1056
1057 dR2 = R[Index - 1];
1058 dG2 = G[Index - 1];
1059 dB2 = B[Index - 1];
1060 dA2 = A[Index - 1];
1061
1062 if (dR > dR2 || dR <= dR2 - 2 &&
1063 dG > dG2 || dG <= dG2 - 2 &&
1064 dB > dB2 || dB <= dB2 - 2 &&
1065 dA > dA2 || dA <= dA2 - 2)
1066 {
1067 continue;
1068 }
1069
1070 dR2 = R[Index - Width];
1071 dG2 = G[Index - Width];
1072 dB2 = B[Index - Width];
1073 dA2 = A[Index - Width];
1074
1075 if (dR > dR2 || dR <= dR2 - 2 &&
1076 dG > dG2 || dG <= dG2 - 2 &&
1077 dB > dB2 || dB <= dB2 - 2 &&
1078 dA > dA2 || dA <= dA2 - 2)
1079 {
1080 continue;
1081 }
1082
1083 BoundaryR[Index] = -1;
1084 BoundaryG[Index] = -1;
1085 BoundaryB[Index] = -1;
1086 BoundaryA[Index] = -1;
1087 }
1088
1089 dR = R[Index];
1090 dG = G[Index];
1091 dB = B[Index];
1092 dA = A[Index];
1093
1094 dR2 = R[Index - 1];
1095 dG2 = G[Index - 1];
1096 dB2 = B[Index - 1];
1097 dA2 = A[Index - 1];
1098
1099 if (dR <= dR2 && dR > dR2 - 2 &&
1100 dG <= dG2 && dG > dG2 - 2 &&
1101 dB <= dB2 && dB > dB2 - 2 &&
1102 dA <= dA2 && dA > dA2 - 2)
1103 {
1104 dR2 = R[Index - Width];
1105 dG2 = G[Index - Width];
1106 dB2 = B[Index - Width];
1107 dA2 = A[Index - Width];
1108
1109 if (dR <= dR2 && dR > dR2 - 2 &&
1110 dG <= dG2 && dG > dG2 - 2 &&
1111 dB <= dB2 && dB > dB2 - 2 &&
1112 dA <= dA2 && dA > dA2 - 2)
1113 {
1114 BoundaryR[Index] = -1;
1115 BoundaryG[Index] = -1;
1116 BoundaryB[Index] = -1;
1117 BoundaryA[Index] = -1;
1118 }
1119 }
1120
1121 return (BoundaryR, BoundaryG, BoundaryB, BoundaryA);
1122 }
1123
1127 public static PixelInformation ToPixels(double[] ColorIndex, int Width, int Height, SKColor[] Palette)
1128 {
1129 int N = Palette.Length;
1130 int Size = Width * Height;
1131 int Size4 = Size * 4;
1132 byte[] rgb = new byte[Size4];
1133 byte[] reds;
1134 byte[] greens;
1135 byte[] blues;
1136 double d;
1137 SKColor cl;
1138 int Index2;
1139 int ci;
1140 int Component;
1141 int Index;
1142 int x;
1143
1144 reds = new byte[N];
1145 greens = new byte[N];
1146 blues = new byte[N];
1147
1148 for (x = 0; x < N; x++)
1149 {
1150 cl = Palette[x];
1151 reds[x] = cl.Red;
1152 greens[x] = cl.Green;
1153 blues[x] = cl.Blue;
1154 }
1155
1156 for (Index = Index2 = 0; Index < Size; Index++)
1157 {
1158 d = ColorIndex[Index];
1159
1160 ci = (int)d;
1161 if (ci < 0 || ci >= N)
1162 {
1163 rgb[Index2++] = 0;
1164 rgb[Index2++] = 0;
1165 rgb[Index2++] = 0;
1166 rgb[Index2++] = 255;
1167 }
1168 else if (ci == N - 1)
1169 {
1170 rgb[Index2++] = blues[ci];
1171 rgb[Index2++] = greens[ci];
1172 rgb[Index2++] = reds[ci];
1173 rgb[Index2++] = 255;
1174 }
1175 else
1176 {
1177 d -= ci;
1178
1179 Component = (int)(blues[ci + 1] * d + blues[ci] * (1 - d) + 0.5);
1180 if (Component > 255)
1181 rgb[Index2++] = 255;
1182 else
1183 rgb[Index2++] = (byte)Component;
1184
1185 Component = (int)(greens[ci + 1] * d + greens[ci] * (1 - d) + 0.5);
1186 if (Component > 255)
1187 rgb[Index2++] = 255;
1188 else
1189 rgb[Index2++] = (byte)Component;
1190
1191 Component = (int)(reds[ci + 1] * d + reds[ci] * (1 - d) + 0.5);
1192 if (Component > 255)
1193 rgb[Index2++] = 255;
1194 else
1195 rgb[Index2++] = (byte)Component;
1196
1197 rgb[Index2++] = 255;
1198 }
1199 }
1200
1201 return PixelInformation.FromRaw(SKColorType.Bgra8888, rgb, Width, Height, Width << 2);
1202 }
1203
1207 public static PixelInformation ToPixels(int[] ColorIndex, int Width, int Height, SKColor[] Palette)
1208 {
1209 int N = Palette.Length;
1210 byte[] reds = new byte[N];
1211 byte[] greens = new byte[N];
1212 byte[] blues = new byte[N];
1213 SKColor cl;
1214 int x;
1215
1216 for (x = 0; x < N; x++)
1217 {
1218 cl = Palette[x];
1219 reds[x] = cl.Red;
1220 greens[x] = cl.Green;
1221 blues[x] = cl.Blue;
1222 }
1223
1224 int Size = Width * Height;
1225 int Size4 = Size * 4;
1226 byte[] rgb = new byte[Size4];
1227 int Index, Index2;
1228 int d;
1229
1230 for (Index = Index2 = 0; Index < Size; Index++)
1231 {
1232 d = ColorIndex[Index];
1233
1234 if (d < 0 || d >= N)
1235 {
1236 rgb[Index2++] = 0;
1237 rgb[Index2++] = 0;
1238 rgb[Index2++] = 0;
1239 rgb[Index2++] = 255;
1240 }
1241 else
1242 {
1243 rgb[Index2++] = blues[d];
1244 rgb[Index2++] = greens[d];
1245 rgb[Index2++] = reds[d];
1246 rgb[Index2++] = 255;
1247 }
1248 }
1249
1250 return PixelInformation.FromRaw(SKColorType.Bgra8888, rgb, Width, Height, Width << 2);
1251 }
1252
1256 public static PixelInformation ToPixels(double[] R, double[] G, double[] B, double[] A, int Width, int Height)
1257 {
1258 int Size = Width * Height;
1259 int Size4 = Size * 4;
1260 byte[] rgb = new byte[Size4];
1261 int Index2;
1262 int ci;
1263 int Index;
1264
1265 for (Index = Index2 = 0; Index < Size; Index++)
1266 {
1267 ci = (int)(B[Index] + 0.5);
1268 rgb[Index2++] = (byte)(ci < 0 ? 0 : ci > 255 ? 255 : ci);
1269
1270 ci = (int)(G[Index] + 0.5);
1271 rgb[Index2++] = (byte)(ci < 0 ? 0 : ci > 255 ? 255 : ci);
1272
1273 ci = (int)(R[Index] + 0.5);
1274 rgb[Index2++] = (byte)(ci < 0 ? 0 : ci > 255 ? 255 : ci);
1275
1276 ci = (int)(A[Index] + 0.5);
1277 rgb[Index2++] = (byte)(ci < 0 ? 0 : ci > 255 ? 255 : ci);
1278 }
1279
1280 return PixelInformation.FromRaw(SKColorType.Bgra8888, rgb, Width, Height, Width << 2);
1281 }
1282
1286 public static void Diff(double[] ColorIndex, int Width, int Height, out double[] dx, out double[] dy)
1287 {
1288 int Size = Width * Height;
1289 int Widthm1 = Width - 1;
1290 int Heightm1 = Height - 1;
1291 int i, x, y;
1292
1293 dx = new double[Size];
1294 dy = new double[Size];
1295
1296 dx[0] = ColorIndex[1] - ColorIndex[0];
1297 dy[0] = ColorIndex[Height] - ColorIndex[0];
1298
1299 for (i = x = 1; x < Widthm1; x++, i++)
1300 {
1301 dx[i] = (ColorIndex[i + 1] - ColorIndex[i - 1]) * 0.5;
1302 dy[i] = ColorIndex[i + Width] - ColorIndex[i];
1303 }
1304
1305 dx[i] = ColorIndex[i] - ColorIndex[i - 1];
1306 dy[i] = ColorIndex[i + Width] - ColorIndex[i];
1307 i++;
1308
1309 for (y = 1; y < Heightm1; y++)
1310 {
1311 dx[i] = ColorIndex[i + 1] - ColorIndex[i];
1312 dy[i] = (ColorIndex[i + Width] - ColorIndex[i - Width]) * 0.5;
1313 i++;
1314
1315 for (x = 1; x < Widthm1; x++, i++)
1316 {
1317 dx[i] = (ColorIndex[i + 1] - ColorIndex[i - 1]) * 0.5;
1318 dy[i] = (ColorIndex[i + Width] - ColorIndex[i - Width]) * 0.5;
1319 }
1320
1321 dx[i] = ColorIndex[i] - ColorIndex[i - 1];
1322 dy[i] = (ColorIndex[i + Width] - ColorIndex[i - Width]) * 0.5;
1323 i++;
1324 }
1325
1326 dx[i] = ColorIndex[i + 1] - ColorIndex[i];
1327 dy[i] = ColorIndex[i] - ColorIndex[i - Width];
1328 i++;
1329
1330 for (x = 1; x < Widthm1; x++, i++)
1331 {
1332 dx[i] = (ColorIndex[i + 1] - ColorIndex[i - 1]) * 0.5;
1333 dy[i] = ColorIndex[i] - ColorIndex[i - Width];
1334 }
1335
1336 dx[i] = ColorIndex[i] - ColorIndex[i - 1];
1337 dy[i] = ColorIndex[i] - ColorIndex[i - Width];
1338 }
1339
1343 public static void Abs(double[] ColorIndex, int Width, int Height, double[] dx, double[] dy)
1344 {
1345 int i, c = Width * Height;
1346 double x, y;
1347
1348 for (i = 0; i < c; i++)
1349 {
1350 x = dx[i];
1351 y = dy[i];
1352
1353 ColorIndex[i] = Math.Sqrt(x * x + y * y);
1354 }
1355 }
1356
1360 public static void Angle(double[] ColorIndex, int Width, int Height, int N, double[] dx, double[] dy)
1361 {
1362 int i, c = Width * Height;
1363 double x, y, Scale = N / (2.0 * Math.PI);
1364
1365 for (i = 0; i < c; i++)
1366 {
1367 x = dx[i];
1368 y = dy[i];
1369
1370 if (x == 0 && y == 0)
1371 ColorIndex[i] = 0;
1372 else
1373 ColorIndex[i] = (Math.Atan2(y, x) + Math.PI) * Scale;
1374 }
1375 }
1376
1377 }
1378}
Class managing a script expression.
Definition: Expression.cs:41
static string ToString(double Value)
Converts a value to a string, that can be parsed as part of an expression.
Definition: Expression.cs:4760
Defines a clickable fractal graph in the complex plane.
Definition: FractalGraph.cs:23
override string GetBitmapClickScript(double X, double Y, object[] States)
Graph.GetBitmapClickScript
Definition: FractalGraph.cs:91
static void Abs(double[] ColorIndex, int Width, int Height, double[] dx, double[] dy)
TODO
static PixelInformation ToPixels(int[] ColorIndex, int Width, int Height, SKColor[] Palette)
TODO
static int[] FindBoundaries(int[] ColorIndex, int Width, int Height)
TODO
static async Task Smooth(double[] ColorIndex, double[] Boundary, int Width, int Height, int N, SKColor[] Palette, ScriptNode Node, Variables Variables)
TODO
FractalGraph(Variables Variables)
Defines a clickable fractal graph in the complex plane.
Definition: FractalGraph.cs:47
static void Diff(double[] ColorIndex, int Width, int Height, out double[] dx, out double[] dy)
TODO
static PixelInformation ToPixels(double[] ColorIndex, int Width, int Height, SKColor[] Palette)
TODO
static PixelInformation ToPixels(double[] R, double[] G, double[] B, double[] A, int Width, int Height)
TODO
ScriptNode Node
Node generating the graph.
Definition: FractalGraph.cs:86
static async Task Smooth(double[] R, double[] G, double[] B, double[] A, double[] BoundaryR, double[] BoundaryG, double[] BoundaryB, double[] BoundaryA, int Width, int Height, ScriptNode Node, Variables Variables)
TODO
FractalGraph()
Defines a clickable fractal graph in the complex plane.
Definition: FractalGraph.cs:38
static SKColor[] ToPalette(ObjectVector Vector)
TODO
static double[] FindBoundaries(double[] ColorIndex, int Width, int Height)
TODO
static void Angle(double[] ColorIndex, int Width, int Height, int N, double[] dx, double[] dy)
TODO
FractalGraph(Variables Variables, PixelInformation Pixels, double r0, double i0, double r1, double i1, double Size, bool InvertY, ScriptNode Node, FractalZoomScript FractalZoomScript, object State)
Defines a clickable fractal graph in the complex plane.
Definition: FractalGraph.cs:66
Handles bitmap-based graphs.
Definition: GraphBitmap.cs:13
Base class for graphs.
Definition: Graph.cs:88
static SKPoint[] Scale(IVector VectorX, IVector VectorY, IElement MinX, IElement MaxX, IElement MinY, IElement MaxY, double OffsetX, double OffsetY, double Width, double Height, Dictionary< string, double > XLabelPositions, Dictionary< string, double > YLabelPositions)
Scales two vectors of equal size to points in a rectangular area.
Definition: Graph.cs:513
static SKColor ToColor(object Object)
Converts an object to a color.
Definition: Graph.cs:844
Contains pixel information
static PixelInformation FromRaw(SKColorType ColorType, byte[] Binary, int Width, int Height, int BytesPerRow)
Gets the pixel information object from raw pixel data.
Base class for all nodes in a parsed script tree.
Definition: ScriptNode.cs:69
Expression Expression
Expression of which the node is a part.
Definition: ScriptNode.cs:177
override int Dimension
Dimension of vector.
override IElement GetElement(int Index)
Gets an element of the vector.
Collection of variables.
Definition: Variables.cs:25
TextWriter ConsoleOut
Console out interface. Can be used by functions and script to output data to the console.
Definition: Variables.cs:223
async Task Status(Expression Expression, string Result)
Reports current status of execution.
Definition: Variables.cs:424
bool HandlesPreview
If previews are desired.
Definition: Variables.cs:389
async Task Preview(Expression Expression, IElement Result)
Reports a preview of the final result.
Definition: Variables.cs:407
delegate string FractalZoomScript(double r, double i, double Size, object State)
Generates new script when zoomed.