Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
MandelbrotSmoothGradientFractal.cs
1using System;
2using System.Numerics;
3using System.Text;
4using System.Threading.Tasks;
5using SkiaSharp;
12
14{
28 {
34 : base(new ScriptNode[] { z, f, dr, Palette, DimX, DimY },
35 new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar,
37 {
38 }
39
45 : base(new ScriptNode[] { z, f, dr, Palette, DimX },
46 new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar,
48 {
49 }
50
55 : base(new ScriptNode[] { z, f, dr, Palette },
56 new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar,
58 {
59 }
60
65 : base(new ScriptNode[] { z, f, dr },
66 new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar }, Start, Length, Expression)
67 {
68 }
69
73 public override string[] DefaultArgumentNames
74 {
75 get
76 {
77 return new string[] { "z", "f", "dr", "Palette", "DimX", "DimY" };
78 }
79 }
80
85 public override bool IsAsynchronous => true;
86
91 {
92 return this.EvaluateAsync(Arguments, Variables).Result;
93 }
94
98 public override async Task<IElement> EvaluateAsync(IElement[] Arguments, Variables Variables)
99 {
100 string ColorExpression = null;
101 SKColor[] Palette;
102 double rc, ic;
103 double dr;
104 int dimx, dimy;
105 int i, c;
106 object Obj;
107 ScriptNode fDef = null;
108 c = Arguments.Length;
109 i = 0;
110
111 Obj = Arguments[i++].AssociatedObjectValue;
112 if (Obj is Complex z)
113 {
114 rc = z.Real;
115 ic = z.Imaginary;
116 }
117 else
118 {
119 rc = Expression.ToDouble(Obj);
120 ic = Expression.ToDouble(Arguments[i++].AssociatedObjectValue);
121 }
122
123 if (i >= c)
124 throw new ScriptRuntimeException("Insufficient parameters in call to MandelbrotTopographyFractal().", this);
125
126 Obj = Arguments[i].AssociatedObjectValue;
127 if (Obj is ILambdaExpression f)
128 {
129 fDef = this.Arguments[i++];
130
131 if (f.NrArguments != 2)
132 throw new ScriptRuntimeException("Lambda expression in calls to MandelbrotTopographyFractal() must be of two variables (z,c).", this);
133 }
134 else
135 {
136 f = null;
137 fDef = null;
138
139 if (Obj is null)
140 i++;
141 }
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 MandelbrotSmoothGradientFractal(r,c,dr[,Palette][,dimx[,dimy]]).",
172 this);
173 }
174
175 if (dimx <= 0 || dimx > 5000 || dimy <= 0 || dimy > 5000)
176 throw new FractalImageSizeScriptException(this);
177
178 if (!(f is null))
179 {
180 return await 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 await CalcMandelbrot(rc, ic, dr, Palette, dimx, dimy, this, Variables, 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("MandelbrotSmoothGradientFractal((");
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 async Task<FractalGraph> CalcMandelbrot(double rCenter, double iCenter, double rDelta,
231 SKColor[] Palette, int Width, int Height, ScriptNode Node, Variables Variables,
232 FractalZoomScript FractalZoomScript, object State)
233 {
234 double r0, i0, r1, i1;
235 double dr, di;
236 double r, i;
237 double zr, zi, zrt, zr2, zi2;
238 double aspect;
239 int x, y;
240 int n, N;
241
242 N = Palette.Length;
243
244 int Size = Width * Height;
245 double[] ColorIndex = new double[Size];
246 int Index = 0;
247
248 rDelta *= 0.5;
249 r0 = rCenter - rDelta;
250 r1 = rCenter + rDelta;
251
252 aspect = ((double)Width) / Height;
253
254 i0 = iCenter - rDelta / aspect;
255 i1 = iCenter + rDelta / aspect;
256
257 dr = (r1 - r0) / Width;
258 di = (i1 - i0) / Height;
259
260 for (y = 0, i = i0; y < Height; y++, i += di)
261 {
262 for (x = 0, r = r0; x < Width; x++, r += dr)
263 {
264 zr = r;
265 zi = i;
266
267 n = 0;
268 zr2 = zr * zr;
269 zi2 = zi * zi;
270
271 while (zr2 + zi2 < 9 && n < N)
272 {
273 n++;
274 zrt = zr2 - zi2 + r;
275 zi = 2 * zr * zi + i;
276 zr = zrt;
277
278 zr2 = zr * zr;
279 zi2 = zi * zi;
280 }
281
282 if (n >= N)
283 ColorIndex[Index++] = N;
284 else
285 ColorIndex[Index++] = n;
286 }
287 }
288
289 await Variables.Preview(Node.Expression, new GraphBitmap(Variables, FractalGraph.ToPixels(ColorIndex, Width, Height, Palette)));
290
291 double[] Boundary = FractalGraph.FindBoundaries(ColorIndex, Width, Height);
292 await FractalGraph.Smooth(ColorIndex, Boundary, Width, Height, N, Palette, Node, Variables);
293 FractalGraph.Diff(ColorIndex, Width, Height, out double[] dx, out double[] dy);
294 FractalGraph.Angle(ColorIndex, Width, Height, N, dx, dy);
295
296 return new FractalGraph(Variables, FractalGraph.ToPixels(ColorIndex, Width, Height, Palette),
297 r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State);
298 }
299
303 public static async Task<FractalGraph> CalcMandelbrot(double rCenter, double iCenter, double rDelta,
304 ILambdaExpression f, Variables Variables, SKColor[] Palette, int Width, int Height,
305 ScriptNode Node, FractalZoomScript FractalZoomScript, object State)
306 {
307 double r0, i0, r1, i1;
308 double dr, di;
309 double r, i, Mod;
310 double aspect;
311 int x, x2, y;
312 int n, N;
313
314 N = Palette.Length;
315
316 int Size = Width * Height;
317 double[] ColorIndex = new double[Size];
318
319 Complex z;
320 IElement[] P = new IElement[2];
321 int j, c;
322 IElement Obj;
323
324 rDelta *= 0.5;
325 r0 = rCenter - rDelta;
326 r1 = rCenter + rDelta;
327
328 aspect = ((double)Width) / Height;
329
330 i0 = iCenter - rDelta / aspect;
331 i1 = iCenter + rDelta / aspect;
332
333 dr = (r1 - r0) / Width;
334 di = (i1 - i0) / Height;
335
336 for (y = 0, i = i0; y < Height; y++, i += di)
337 {
338 Complex[] Row = new Complex[Width];
339 Complex[] Row0 = new Complex[Width];
340 int[] Offset = new int[Width];
341
342 c = Width;
343 for (x = 0, x2 = y * Width, r = r0; x < Width; x++, r += dr, x2++)
344 {
345 Row[x] = Row0[x] = new Complex(r, i);
346 Offset[x] = x2;
347 }
348
349 Variables v = new Variables();
350 Variables.CopyTo(v);
351
352 n = 0;
353 while (n < N && c > 0)
354 {
355 n++;
356 P[0] = new ComplexVector(Row);
357 P[1] = Expression.Encapsulate(Row0);
358 Obj = f.Evaluate(P, v);
359 Row = Obj.AssociatedObjectValue as Complex[];
360
361 if (Row is null)
362 throw new LambdaTypeScriptException(Obj.GetType(), Node);
363 else if (Row.Length != c)
364 throw new LambdaLengthScriptException(Row.Length, c, Node);
365
366 for (x = x2 = 0; x < c; x++)
367 {
368 z = Row[x];
369 j = Offset[x];
370
371 Mod = z.Magnitude;
372
373 if (Mod < 3)
374 {
375 if (x != x2)
376 {
377 Row[x2] = z;
378 Row0[x2] = Row0[x];
379 Offset[x2] = j;
380 }
381
382 x2++;
383 }
384 else
385 {
386 if (n >= N)
387 ColorIndex[j++] = N;
388 else
389 ColorIndex[j++] = n;
390 }
391 }
392
393 if (x2 < x)
394 {
395 Array.Resize(ref Row, x2);
396 Array.Resize(ref Row0, x2);
397 Array.Resize(ref Offset, x2);
398 c = x2;
399 }
400 }
401
402 if (c > 0)
403 {
404 for (x = 0; x < c; x++)
405 {
406 j = Offset[x];
407 ColorIndex[j] = N;
408 }
409 }
410
411 }
412
413 await Variables.Preview(Node.Expression, new GraphBitmap(Variables, FractalGraph.ToPixels(ColorIndex, Width, Height, Palette)));
414
415 double[] Boundary = FractalGraph.FindBoundaries(ColorIndex, Width, Height);
416 await FractalGraph.Smooth(ColorIndex, Boundary, Width, Height, N, Palette, Node, Variables);
417 FractalGraph.Diff(ColorIndex, Width, Height, out double[] dx, out double[] dy);
418 FractalGraph.Angle(ColorIndex, Width, Height, N, dx, dy);
419
420 return new FractalGraph(Variables, FractalGraph.ToPixels(ColorIndex, Width, Height, Palette),
421 r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State);
422 }
423
427 public override string FunctionName => nameof(MandelbrotSmoothGradientFractal);
428
429 }
430}
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
Calculates a Mandelbrot Smooth Fractal Image, where coloring is done in accordance with the ange of t...
MandelbrotSmoothGradientFractal(ScriptNode z, ScriptNode f, ScriptNode dr, ScriptNode Palette, int Start, int Length, Expression Expression)
TODO
MandelbrotSmoothGradientFractal(ScriptNode z, ScriptNode f, ScriptNode dr, ScriptNode Palette, ScriptNode DimX, int Start, int Length, Expression Expression)
TODO
MandelbrotSmoothGradientFractal(ScriptNode z, ScriptNode f, ScriptNode dr, int Start, int Length, Expression Expression)
TODO
override bool IsAsynchronous
If the node (or its decendants) include asynchronous evaluation. Asynchronous nodes should be evaluat...
static async Task< 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
override async Task< IElement > EvaluateAsync(IElement[] Arguments, Variables Variables)
TODO
static async Task< FractalGraph > CalcMandelbrot(double rCenter, double iCenter, double rDelta, SKColor[] Palette, int Width, int Height, ScriptNode Node, Variables Variables, FractalZoomScript FractalZoomScript, object State)
TODO
override IElement Evaluate(IElement[] Arguments, Variables Variables)
TODO
MandelbrotSmoothGradientFractal(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 async Task Smooth(double[] ColorIndex, double[] Boundary, int Width, int Height, int N, SKColor[] Palette, ScriptNode Node, Variables Variables)
TODO
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 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
Handles bitmap-based graphs.
Definition: GraphBitmap.cs:13
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
async Task Preview(Expression Expression, IElement Result)
Reports a preview of the final result.
Definition: Variables.cs:407
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