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