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