Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
JuliaInternalFractal.cs
1using System;
2using System.Numerics;
3using System.Text;
4using SkiaSharp;
10
12{
37 {
43 : base(new ScriptNode[] { z, c, dr, Palette, DimX, DimY },
44 new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar,
46 {
47 }
48
54 : base(new ScriptNode[] { z, c, dr, Palette, DimX },
55 new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar,
57 {
58 }
59
64 : base(new ScriptNode[] { z, c, dr, Palette },
65 new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar,
67 {
68 }
69
74 : base(new ScriptNode[] { z, c, dr },
75 new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar }, Start, Length, Expression)
76 {
77 }
78
82 public override string[] DefaultArgumentNames
83 {
84 get
85 {
86 return new string[] { "z", "c", "dr", "Palette", "DimX", "DimY" };
87 }
88 }
89
94 {
95 string ColorExpression = null;
96 SKColor[] Palette;
97 double rc, ic;
98 double r0, i0;
99 double dr;
100 int dimx, dimy;
101 int i, c;
102 object Obj;
104 ScriptNode fDef = null;
105 c = Arguments.Length;
106 i = 0;
107
108 Obj = Arguments[i++].AssociatedObjectValue;
109 if (Obj is Complex z)
110 {
111 rc = z.Real;
112 ic = z.Imaginary;
113 }
114 else
115 {
116 rc = Expression.ToDouble(Obj);
117 ic = Expression.ToDouble(Arguments[i++].AssociatedObjectValue);
118 }
119
120 if (i >= c)
121 throw new ScriptRuntimeException("Insufficient parameters in call to JuliaInternalFractal().", this);
122
123 Obj = Arguments[i++].AssociatedObjectValue;
124 if (!((f = Obj as ILambdaExpression) is null))
125 {
126 if (f.NrArguments != 1)
127 throw new ScriptRuntimeException("Lambda expression in calls to JuliaInternalFractal() must be of one variable.", this);
128
129 r0 = 0;
130 i0 = 0;
131 fDef = this.Arguments[i - 1];
132 }
133 else if (Obj is Complex z2)
134 {
135 r0 = z2.Real;
136 i0 = z2.Imaginary;
137 }
138 else
139 {
140 if (i >= c)
141 throw new ScriptRuntimeException("Insufficient parameters in call to JuliaInternalFractal().", this);
142
143 r0 = Expression.ToDouble(Obj);
144 i0 = Expression.ToDouble(Arguments[i++].AssociatedObjectValue);
145 }
146
147 if (i >= c)
148 throw new ScriptRuntimeException("Insufficient parameters in call to JuliaInternalFractal().", this);
149
150 dr = Expression.ToDouble(Arguments[i++].AssociatedObjectValue);
151
152 if (i < c && !(this.Arguments[i] is null) && Arguments[i] is ObjectVector)
153 {
154 ColorExpression = this.Arguments[i].SubExpression;
156 }
157 else
158 {
159 Palette = ColorModels.RandomLinearAnalogousHSL.CreatePalette(16, 4, out int Seed, this, Variables);
160 ColorExpression = "RandomLinearAnalogousHSL(16,4," + Seed.ToString() + ")";
161
162 if (i < c && this.Arguments[i] is null)
163 i++;
164 }
165
166 if (i < c)
167 dimx = (int)Expression.ToDouble(Arguments[i++].AssociatedObjectValue);
168 else
169 dimx = 320;
170
171 if (i < c)
172 dimy = (int)Expression.ToDouble(Arguments[i++].AssociatedObjectValue);
173 else
174 dimy = 200;
175
176 if (i < c)
177 {
178 throw new ScriptRuntimeException("Parameter mismatch in call to JuliaInternalFractal(z,c|f,dr[,Palette][,dimx[,dimy]]).",
179 this);
180 }
181
182 if (dimx <= 0 || dimx > 5000 || dimy <= 0 || dimy > 5000)
183 throw new ScriptRuntimeException("Image size must be within 1x1 to 5000x5000", this);
184
185 if (!(f is null))
186 {
187 return CalcJulia(rc, ic, f, fDef, dr, Palette, dimx, dimy, this, Variables,
188 this.FractalZoomScript, new object[] { Palette, dimx, dimy, r0, i0, ColorExpression, fDef });
189 }
190 else
191 {
192 return CalcJulia(Variables, rc, ic, r0, i0, dr, Palette, dimx, dimy, this,
193 this.FractalZoomScript, new object[] { Palette, dimx, dimy, r0, i0, ColorExpression, fDef });
194 }
195 }
196
197 private string FractalZoomScript(double r, double i, double Size, object State)
198 {
199 object[] Parameters = (object[])State;
200 int DimX = (int)Parameters[1];
201 int DimY = (int)Parameters[2];
202 double r0 = (double)Parameters[3];
203 double i0 = (double)Parameters[4];
204 string ColorExpression = (string)Parameters[5];
205 ScriptNode f = (ScriptNode)Parameters[6];
206
207 StringBuilder sb = new StringBuilder();
208
209 sb.Append("JuliaInternalFractal((");
210 sb.Append(Expression.ToString(r));
211 sb.Append(',');
212 sb.Append(Expression.ToString(i));
213 sb.Append("),");
214
215 if (!(f is null))
216 sb.Append(f.SubExpression);
217 else
218 {
219 sb.Append('(');
220 sb.Append(Expression.ToString(r0));
221 sb.Append(',');
222 sb.Append(Expression.ToString(i0));
223 sb.Append(')');
224 }
225
226 sb.Append(',');
227 sb.Append(Expression.ToString(Size / 4));
228
229 if (!string.IsNullOrEmpty(ColorExpression))
230 {
231 sb.Append(',');
232 sb.Append(ColorExpression);
233 }
234
235 sb.Append(',');
236 sb.Append(DimX.ToString());
237 sb.Append(',');
238 sb.Append(DimY.ToString());
239 sb.Append(')');
240
241 return sb.ToString();
242 }
243
247 public static FractalGraph CalcJulia(Variables Variables, double rCenter, double iCenter, double R0, double I0, double rDelta,
248 SKColor[] Palette, int Width, int Height, ScriptNode Node, FractalZoomScript FractalZoomScript, object State)
249 {
250 byte[] reds;
251 byte[] greens;
252 byte[] blues;
253 double r0, i0, r1, i1;
254 double dr, di;
255 double r, i;
256 double zr, zi, zrt, zr2, zi2;
257 double aspect;
258 int x, y;
259 int n, N;
260 int index;
261 SKColor cl;
262
263 N = Palette.Length;
264 reds = new byte[N];
265 greens = new byte[N];
266 blues = new byte[N];
267
268 for (x = 0; x < N; x++)
269 {
270 cl = Palette[x];
271 reds[x] = cl.Red;
272 greens[x] = cl.Green;
273 blues[x] = cl.Blue;
274 }
275
276 int size = Width * Height * 4;
277 byte[] rgb = new byte[size];
278
279 rDelta *= 0.5;
280 r0 = rCenter - rDelta;
281 r1 = rCenter + rDelta;
282
283 aspect = ((double)Width) / Height;
284
285 i0 = iCenter - rDelta / aspect;
286 i1 = iCenter + rDelta / aspect;
287
288 dr = (r1 - r0) / Width;
289 di = (i1 - i0) / Height;
290
291 for (y = 0, i = i0, index = 0; y < Height; y++, i += di)
292 {
293 for (x = 0, r = r0; x < Width; x++, r += dr)
294 {
295 zr = r;
296 zi = i;
297
298 n = 0;
299 zr2 = zr * zr;
300 zi2 = zi * zi;
301
302 while (zr2 + zi2 < 9 && n < N)
303 {
304 n++;
305 zrt = zr2 - zi2 + R0;
306 zi = 2 * zr * zi + I0;
307 zr = zrt;
308
309 zr2 = zr * zr;
310 zi2 = zi * zi;
311 }
312
313 n = (int)(N * Math.Sqrt((zr2 + zi2) / 9) + 0.5);
314 if (n < N)
315 {
316 rgb[index++] = blues[n];
317 rgb[index++] = greens[n];
318 rgb[index++] = reds[n];
319 }
320 else
321 {
322 rgb[index++] = 0;
323 rgb[index++] = 0;
324 rgb[index++] = 0;
325 }
326
327 rgb[index++] = 255;
328 }
329 }
330
331 PixelInformation Pixels = new PixelInformationRaw(SKColorType.Bgra8888, rgb, Width, Height, Width << 2);
332 return new FractalGraph(Variables, Pixels, r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State);
333 }
334
338 public static FractalGraph CalcJulia(double rCenter, double iCenter, ILambdaExpression f, ScriptNode _,
339 double rDelta, SKColor[] Palette, int Width, int Height, ScriptNode Node, Variables Variables,
340 FractalZoomScript FractalZoomScript, object State)
341 {
342 byte[] reds;
343 byte[] greens;
344 byte[] blues;
345 double r0, i0, r1, i1;
346 double dr, di;
347 double r, i, Mod;
348 double aspect;
349 int x, x2, y;
350 int n, N;
351 SKColor cl;
352
353 N = Palette.Length;
354 reds = new byte[N];
355 greens = new byte[N];
356 blues = new byte[N];
357
358 for (x = 0; x < N; x++)
359 {
360 cl = Palette[x];
361 reds[x] = cl.Red;
362 greens[x] = cl.Green;
363 blues[x] = cl.Blue;
364 }
365
366 int size = Width * Height * 4;
367 byte[] rgb = new byte[size];
368 Complex z;
369 IElement[] P = new IElement[1];
370 int j, c;
371 IElement Obj;
372
373 rDelta *= 0.5;
374 r0 = rCenter - rDelta;
375 r1 = rCenter + rDelta;
376
377 int[] Counts = new int[N];
378
379 aspect = ((double)Width) / Height;
380
381 i0 = iCenter - rDelta / aspect;
382 i1 = iCenter + rDelta / aspect;
383
384 dr = (r1 - r0) / Width;
385 di = (i1 - i0) / Height;
386
387 for (y = 0, i = i0; y < Height; y++, i += di)
388 {
389 Complex[] Row = new Complex[Width];
390 int[] Offset = new int[Width];
391
392 c = Width;
393 for (x = 0, x2 = y * Width * 4, r = r0; x < Width; x++, r += dr, x2 += 4)
394 {
395 Row[x] = new Complex(r, i);
396 Offset[x] = x2;
397 }
398
399 Variables v = new Variables();
400 Variables.CopyTo(v);
401
402 n = 0;
403 while (n < N && c > 0)
404 {
405 n++;
406 P[0] = new ComplexVector(Row);
407 Obj = f.Evaluate(P, v);
408 Row = Obj.AssociatedObjectValue as Complex[];
409
410 if (Row is null)
411 {
412 throw new ScriptRuntimeException("Lambda expression must be able to accept complex vectors, " +
413 "and return complex vectors of equal length. Type returned: " +
414 Obj.GetType().FullName, Node);
415 }
416 else if (Row.Length != c)
417 {
418 throw new ScriptRuntimeException("Lambda expression must be able to accept complex vectors, " +
419 "and return complex vectors of equal length. Length returned: " +
420 Row.Length.ToString() + ". Expected: " + c.ToString(), Node);
421 }
422
423 for (x = x2 = 0; x < c; x++)
424 {
425 z = Row[x];
426 j = Offset[x];
427
428 Mod = z.Magnitude;
429
430 if (Mod < 3)
431 {
432 if (x != x2)
433 {
434 Row[x2] = z;
435 Offset[x2] = j;
436 }
437
438 x2++;
439 }
440 else
441 {
442 rgb[j++] = 0;
443 rgb[j++] = 0;
444 rgb[j++] = 0;
445 rgb[j++] = 255;
446 }
447 }
448
449 if (x2 < x)
450 {
451 Array.Resize(ref Row, x2);
452 Array.Resize(ref Offset, x2);
453 c = x2;
454 }
455 }
456
457 if (c > 0)
458 {
459 for (x = 0; x < c; x++)
460 {
461 z = Row[x];
462 j = Offset[x];
463
464 Mod = z.Magnitude;
465 n = (int)(N * Mod / 3 + 0.5);
466
467 if (n < N)
468 {
469 Counts[n]++;
470 rgb[j++] = blues[n];
471 rgb[j++] = greens[n];
472 rgb[j++] = reds[n];
473 }
474 else
475 {
476 rgb[j++] = 0;
477 rgb[j++] = 0;
478 rgb[j++] = 0;
479 }
480
481 rgb[j++] = 255;
482 }
483 }
484
485 }
486
487 Variables.ConsoleOut.WriteLine(Expression.ToString(Counts));
488
489 PixelInformation Pixels = new PixelInformationRaw(SKColorType.Bgra8888, rgb, Width, Height, Width << 2);
490 return new FractalGraph(Variables, Pixels, r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State);
491 }
492
496 public override string FunctionName => nameof(JuliaInternalFractal);
497 }
498}
Class managing a script expression.
Definition: Expression.cs:39
static double ToDouble(object Object)
Converts an object to a double value.
Definition: Expression.cs:4824
static string ToString(double Value)
Converts a value to a string, that can be parsed as part of an expression.
Definition: Expression.cs:4496
JuliaInternalFractal(ScriptNode z, ScriptNode c, ScriptNode dr, ScriptNode Palette, int Start, int Length, Expression Expression)
TODO
override IElement Evaluate(IElement[] Arguments, Variables Variables)
TODO
JuliaInternalFractal(ScriptNode z, ScriptNode c, ScriptNode dr, int Start, int Length, Expression Expression)
TODO
JuliaInternalFractal(ScriptNode z, ScriptNode c, ScriptNode dr, ScriptNode Palette, ScriptNode DimX, int Start, int Length, Expression Expression)
TODO
JuliaInternalFractal(ScriptNode z, ScriptNode c, ScriptNode dr, ScriptNode Palette, ScriptNode DimX, ScriptNode DimY, int Start, int Length, Expression Expression)
TODO
static FractalGraph CalcJulia(double rCenter, double iCenter, ILambdaExpression f, ScriptNode _, double rDelta, SKColor[] Palette, int Width, int Height, ScriptNode Node, Variables Variables, FractalZoomScript FractalZoomScript, object State)
TODO
static FractalGraph CalcJulia(Variables Variables, double rCenter, double iCenter, double R0, double I0, double rDelta, 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 SKColor[] ToPalette(ObjectVector Vector)
TODO
Contains pixel information
Contains pixel information in a raw unencoded format.
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
string SubExpression
Sub-expression defining the node.
Definition: ScriptNode.cs:183
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
TextWriter ConsoleOut
Console out interface. Can be used by functions and script to output data to the console.
Definition: Variables.cs:219
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
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