Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
NovaMandelbrotSmoothFractal.cs
1using System;
2using System.Numerics;
3using System.Text;
4using System.Threading.Tasks;
5using SkiaSharp;
12
14{
22 {
27 ScriptNode Palette, ScriptNode DimX, ScriptNode DimY, int Start, int Length, Expression Expression)
28 : base(new ScriptNode[] { r, i, dr, R, p, Palette, DimX, DimY },
29 new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar,
30 ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Vector, ArgumentType.Scalar,
31 ArgumentType.Scalar},
33 {
34 }
35
40 ScriptNode Palette, ScriptNode DimX, int Start, int Length, Expression Expression)
41 : base(new ScriptNode[] { r, i, dr, R, p, Palette, DimX },
42 new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar,
43 ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Vector, ArgumentType.Scalar },
45 {
46 }
47
52 ScriptNode Palette, int Start, int Length, Expression Expression)
53 : base(new ScriptNode[] { r, i, dr, R, p, Palette },
54 new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar,
55 ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Vector },
57 {
58 }
59
65 : base(new ScriptNode[] { r, i, dr, R, p },
66 new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar,
67 ArgumentType.Scalar, ArgumentType.Scalar },
69 {
70 }
71
75 public override string[] DefaultArgumentNames
76 {
77 get
78 {
79 return new string[] { "r", "i", "dr", "R", "p", "Palette", "DimX", "DimY" };
80 }
81 }
82
87 public override bool IsAsynchronous => true;
88
93 {
94 return this.EvaluateAsync(Arguments, Variables).Result;
95 }
96
100 public override async Task<IElement> EvaluateAsync(IElement[] Arguments, Variables Variables)
101 {
102 string ColorExpression = null;
103 SKColor[] Palette;
104 object Obj;
105 double rc, ic;
106 double dr;
107 double Rr, Ri, pr, pi;
108 int dimx, dimy;
109 int i, c;
110
111 rc = Expression.ToDouble(Arguments[0].AssociatedObjectValue);
112 ic = Expression.ToDouble(Arguments[1].AssociatedObjectValue);
113 dr = Expression.ToDouble(Arguments[2].AssociatedObjectValue);
114
115 if ((Obj = Arguments[3].AssociatedObjectValue) is Complex)
116 {
117 Complex z = (Complex)Obj;
118 Rr = z.Real;
119 Ri = z.Imaginary;
120 }
121 else
122 {
123 Rr = Expression.ToDouble(Arguments[3].AssociatedObjectValue);
124 Ri = 0;
125 }
126
127 if ((Obj = Arguments[4].AssociatedObjectValue) is Complex)
128 {
129 Complex z = (Complex)Obj;
130 pr = z.Real;
131 pi = z.Imaginary;
132 }
133 else
134 {
135 pr = Expression.ToDouble(Arguments[4].AssociatedObjectValue);
136 pi = 0;
137 }
138
139 c = Arguments.Length;
140 i = 5;
141
142 if (i < c && !(this.Arguments[i] is null) && Arguments[i] is ObjectVector)
143 {
144 ColorExpression = this.Arguments[i].SubExpression;
146 }
147 else
148 {
149 Palette = ColorModels.RandomLinearAnalogousHSL.CreatePalette(1024, 16, out int Seed, this, Variables);
150 ColorExpression = "RandomLinearAnalogousHSL(1024,16," + Seed.ToString() + ")";
151
152 if (i < c && this.Arguments[i] is null)
153 i++;
154 }
155
156 if (i < c)
157 dimx = (int)Expression.ToDouble(Arguments[i++].AssociatedObjectValue);
158 else
159 dimx = 320;
160
161 if (i < c)
162 dimy = (int)Expression.ToDouble(Arguments[i++].AssociatedObjectValue);
163 else
164 dimy = 200;
165
166 if (i < c)
167 {
168 throw new ScriptRuntimeException("Parameter mismatch in call to NovaMandelbrotSmoothFractal(r,c,dr,Coefficients[,Palette][,dimx[,dimy]]).",
169 this);
170 }
171
172 if (dimx <= 0 || dimx > 5000 || dimy <= 0 || dimy > 5000)
173 throw new FractalImageSizeScriptException(this);
174
175 return await CalcNovaMandelbrot(rc, ic, dr, Rr, Ri, pr, pi, Palette, dimx, dimy,
176 this, Variables, this.FractalZoomScript,
177 new object[] { Palette, dimx, dimy, Rr, Ri, pr, pi, ColorExpression });
178 }
179
180 private string FractalZoomScript(double r, double i, double Size, object State)
181 {
182 object[] Parameters = (object[])State;
183 int DimX = (int)Parameters[1];
184 int DimY = (int)Parameters[2];
185 double Rr = (double)Parameters[3];
186 double Ri = (double)Parameters[4];
187 double pr = (double)Parameters[5];
188 double pi = (double)Parameters[6];
189 string ColorExpression = (string)Parameters[7];
190
191 StringBuilder sb = new StringBuilder();
192
193 sb.Append("NovaMandelbrotSmoothFractal(");
194 sb.Append(Expression.ToString(r));
195 sb.Append(',');
196 sb.Append(Expression.ToString(i));
197 sb.Append(',');
198 sb.Append(Expression.ToString(Size / 4));
199 sb.Append(',');
200 sb.Append(Expression.ToString(Rr));
201
202 if (Ri != 0)
203 {
204 sb.Append('+');
205 sb.Append(Expression.ToString(Ri));
206 sb.Append("*i");
207 }
208
209 sb.Append(',');
210 sb.Append(Expression.ToString(pr));
211
212 if (pi != 0)
213 {
214 sb.Append('+');
215 sb.Append(Expression.ToString(pi));
216 sb.Append("*i");
217 }
218
219 if (!string.IsNullOrEmpty(ColorExpression))
220 {
221 sb.Append(',');
222 sb.Append(ColorExpression);
223 }
224
225 sb.Append(',');
226 sb.Append(DimX.ToString());
227 sb.Append(',');
228 sb.Append(DimY.ToString());
229 sb.Append(')');
230
231 return sb.ToString();
232 }
233
237 public static async Task<FractalGraph> CalcNovaMandelbrot(double rCenter, double iCenter, double rDelta, double Rr, double Ri,
238 double pr, double pi, SKColor[] Palette, int Width, int Height, ScriptNode Node, Variables Variables,
239 FractalZoomScript FractalZoomScript, object State)
240 {
241 double r0, i0, r1, i1;
242 double dr, di;
243 double r, i;
244 double zr, zi, zr2, zi2, zr3, zi3, zr4, zi4;
245 double aspect;
246 double Temp;
247 int x, y;
248 int n, N;
249 int index;
250 double lnz;
251 double argz;
252 double amp;
253 double phi;
254
255 N = Palette.Length;
256
257 int size = Width * Height;
258 double[] ColorIndex = new double[size];
259 double Conv = 1e-10;
260 double Div = 1e10;
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 do
283 {
284 // f: z->z^p-1 = exp(p*ln(z))-1
285 // exp(a+ib)=exp(a)*(cos(b)+i*sin(b))
286 // ln(z)=ln|z|+i*arg(z)
287 // exp(p*ln(z))-1 =
288 // = exp((pr+i*pi)*(ln|z|+i*arg(z)))-1 =
289 // = exp(pr*ln|z|-pi*arg(z)+i*(pi*ln|z|+pr*arg(z)))-1 =
290 // = exp(pr*ln|z|-pi*arg(z))*(cos(pi*ln|z|+pr*arg(z))+i*sin(pi*ln|z|+pr*arg(z)))-1
291
292 lnz = Math.Log(Math.Sqrt(zr * zr + zi * zi));
293 argz = Math.Atan2(zi, zr);
294 amp = Math.Exp(pr * lnz - pi * argz);
295 phi = pi * lnz + pr * argz;
296
297 zr2 = amp * Math.Cos(phi) - 1;
298 zi2 = amp * Math.Sin(phi);
299
300 // f': z->p*z^(p-1) = p*exp((p-1)*ln(z)) =
301 // = (pr+i*pi)*exp((pr-1+i*pi)*(ln|z|+i*arg(z))) =
302 // = (pr+i*pi)*exp((pr-1)*ln|z|-pi*arg(z)+i*(pi*ln|z|+(pr-1)*arg(z))) =
303 // = (pr+i*pi)*exp((pr-1)*ln|z|-pi*arg(z))(sin(pi*ln|z|+(pr-1)*arg(z))+i*cos(pi*ln|z|+(pr-1)*arg(z))) =
304
305 amp = Math.Exp((pr - 1) * lnz - pi * argz);
306 phi = pi * lnz + (pr - 1) * argz;
307
308 zr3 = amp * Math.Cos(phi);
309 zi3 = amp * Math.Sin(phi);
310
311 Temp = pr * zr3 - pi * zi3;
312 zi3 = pr * zi3 + pi * zr3;
313 zr3 = Temp;
314
315 // f/f':
316
317 Temp = 1.0 / (zr3 * zr3 + zi3 * zi3);
318 zr4 = (zr2 * zr3 + zi2 * zi3) * Temp;
319 zi4 = (zi2 * zr3 - zr2 * zi3) * Temp;
320
321 Temp = Rr * zr4 - Ri * zi4;
322 zi4 = Ri * zr4 + Rr * zi4 + i;
323 zr4 = Temp + r;
324
325 zr -= zr4;
326 zi -= zi4;
327
328 Temp = Math.Sqrt(zr4 * zr4 + zi4 * zi4);
329 }
330 while ((Temp > Conv) && (Temp < Div) && (n++ < N));
331
332 if (Temp < Conv && n < N)
333 ColorIndex[index++] = n;
334 else
335 ColorIndex[index++] = N;
336 }
337 }
338
339 await Variables.Preview(Node.Expression, new GraphBitmap(Variables, FractalGraph.ToPixels(ColorIndex, Width, Height, Palette)));
340
341 double[] Boundary = FractalGraph.FindBoundaries(ColorIndex, Width, Height);
342 await FractalGraph.Smooth(ColorIndex, Boundary, Width, Height, N, Palette, Node, Variables);
343
344 return new FractalGraph(Variables, FractalGraph.ToPixels(ColorIndex, Width, Height, Palette),
345 r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State);
346 }
347
351 public override string FunctionName => nameof(NovaMandelbrotSmoothFractal);
352 }
353}
Class managing a script expression.
Definition: Expression.cs:41
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 Nova Mandelbrot Fractal Image (by Paul Derbyshire)
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
override async Task< IElement > EvaluateAsync(IElement[] Arguments, Variables Variables)
TODO
NovaMandelbrotSmoothFractal(ScriptNode r, ScriptNode i, ScriptNode dr, ScriptNode R, ScriptNode p, ScriptNode Palette, ScriptNode DimX, int Start, int Length, Expression Expression)
TODO
NovaMandelbrotSmoothFractal(ScriptNode r, ScriptNode i, ScriptNode dr, ScriptNode R, ScriptNode p, ScriptNode Palette, ScriptNode DimX, ScriptNode DimY, int Start, int Length, Expression Expression)
TODO
NovaMandelbrotSmoothFractal(ScriptNode r, ScriptNode i, ScriptNode dr, ScriptNode R, ScriptNode p, ScriptNode Palette, int Start, int Length, Expression Expression)
TODO
static async Task< FractalGraph > CalcNovaMandelbrot(double rCenter, double iCenter, double rDelta, double Rr, double Ri, double pr, double pi, SKColor[] Palette, int Width, int Height, ScriptNode Node, Variables Variables, FractalZoomScript FractalZoomScript, object State)
TODO
NovaMandelbrotSmoothFractal(ScriptNode r, ScriptNode i, ScriptNode dr, ScriptNode R, ScriptNode p, int Start, int Length, Expression Expression)
TODO
Exception thrown if an image with invalid size is requested.
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
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
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
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