Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
MandelbrotSmoothFractal.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 MandelbrotSmoothFractal(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("MandelbrotSmoothFractal((");
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
294 return new FractalGraph(Variables, FractalGraph.ToPixels(ColorIndex, Width, Height, Palette),
295 r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State);
296 }
297
301 public static async Task<FractalGraph> CalcMandelbrot(double rCenter, double iCenter, double rDelta,
302 ILambdaExpression f, Variables Variables, SKColor[] Palette, int Width, int Height,
303 ScriptNode Node, FractalZoomScript FractalZoomScript, object State)
304 {
305 double r0, i0, r1, i1;
306 double dr, di;
307 double r, i, Mod;
308 double aspect;
309 int x, x2, y;
310 int n, N;
311
312 N = Palette.Length;
313
314 int Size = Width * Height;
315 double[] ColorIndex = new double[Size];
316
317 Complex z;
318 IElement[] P = new IElement[2];
319 int j, c;
320 IElement Obj;
321
322 rDelta *= 0.5;
323 r0 = rCenter - rDelta;
324 r1 = rCenter + rDelta;
325
326 aspect = ((double)Width) / Height;
327
328 i0 = iCenter - rDelta / aspect;
329 i1 = iCenter + rDelta / aspect;
330
331 dr = (r1 - r0) / Width;
332 di = (i1 - i0) / Height;
333
334 for (y = 0, i = i0; y < Height; y++, i += di)
335 {
336 Complex[] Row = new Complex[Width];
337 Complex[] Row0 = new Complex[Width];
338 int[] Offset = new int[Width];
339
340 c = Width;
341 for (x = 0, x2 = y * Width, r = r0; x < Width; x++, r += dr, x2++)
342 {
343 Row[x] = Row0[x] = new Complex(r, i);
344 Offset[x] = x2;
345 }
346
347 Variables v = new Variables();
348 Variables.CopyTo(v);
349
350 n = 0;
351 while (n < N && c > 0)
352 {
353 n++;
354 P[0] = new ComplexVector(Row);
355 P[1] = Expression.Encapsulate(Row0);
356 Obj = f.Evaluate(P, v);
357 Row = Obj.AssociatedObjectValue as Complex[];
358
359 if (Row is null)
360 throw new LambdaTypeScriptException(Obj.GetType(), Node);
361 else if (Row.Length != c)
362 throw new LambdaLengthScriptException(Row.Length, c, Node);
363
364 for (x = x2 = 0; x < c; x++)
365 {
366 z = Row[x];
367 j = Offset[x];
368
369 Mod = z.Magnitude;
370
371 if (Mod < 3)
372 {
373 if (x != x2)
374 {
375 Row[x2] = z;
376 Row0[x2] = Row0[x];
377 Offset[x2] = j;
378 }
379
380 x2++;
381 }
382 else
383 {
384 if (n >= N)
385 ColorIndex[j++] = N;
386 else
387 ColorIndex[j++] = n;
388 }
389 }
390
391 if (x2 < x)
392 {
393 Array.Resize(ref Row, x2);
394 Array.Resize(ref Row0, x2);
395 Array.Resize(ref Offset, x2);
396 c = x2;
397 }
398 }
399
400 if (c > 0)
401 {
402 for (x = 0; x < c; x++)
403 {
404 j = Offset[x];
405 ColorIndex[j] = N;
406 }
407 }
408
409 }
410
411 await Variables.Preview(Node.Expression, new GraphBitmap(Variables, FractalGraph.ToPixels(ColorIndex, Width, Height, Palette)));
412
413 double[] Boundary = FractalGraph.FindBoundaries(ColorIndex, Width, Height);
414 await FractalGraph.Smooth(ColorIndex, Boundary, Width, Height, N, Palette, Node, Variables);
415
416 return new FractalGraph(Variables, FractalGraph.ToPixels(ColorIndex, Width, Height, Palette),
417 r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State);
418 }
419
423 public override string FunctionName => nameof(MandelbrotSmoothFractal);
424
425 }
426}
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 bool IsAsynchronous
If the node (or its decendants) include asynchronous evaluation. Asynchronous nodes should be evaluat...
override IElement Evaluate(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
MandelbrotSmoothFractal(ScriptNode z, ScriptNode f, ScriptNode dr, ScriptNode Palette, ScriptNode DimX, int Start, int Length, Expression Expression)
TODO
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
MandelbrotSmoothFractal(ScriptNode z, ScriptNode f, ScriptNode dr, ScriptNode Palette, ScriptNode DimX, ScriptNode DimY, int Start, int Length, Expression Expression)
TODO
MandelbrotSmoothFractal(ScriptNode z, ScriptNode f, ScriptNode dr, ScriptNode Palette, int Start, int Length, Expression Expression)
TODO
MandelbrotSmoothFractal(ScriptNode z, ScriptNode f, ScriptNode dr, int Start, int Length, Expression Expression)
TODO
override async Task< IElement > EvaluateAsync(IElement[] Arguments, Variables Variables)
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 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
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