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