5using System.Threading.Tasks;
35 : base(new
ScriptNode[] { xc, yc, dr, N, FlameFunctions, Preview, Parallel, DimX, DimY, SuperSampling,
36 Gamma, Vibrancy, Seed },
50 : base(new
ScriptNode[] { xc, yc, dr, N, FlameFunctions, Preview, Parallel, DimX, DimY, SuperSampling,
65 : base(new
ScriptNode[] { xc, yc, dr, N, FlameFunctions, Preview, Parallel, DimX, DimY, SuperSampling,
80 : base(new
ScriptNode[] { xc, yc, dr, N, FlameFunctions, Preview, Parallel, DimX, DimY, SuperSampling },
94 : base(new
ScriptNode[] { xc, yc, dr, N, FlameFunctions, Preview, Parallel, DimX, DimY },
107 : base(new
ScriptNode[] { xc, yc, dr, N, FlameFunctions, Preview, Parallel, DimX },
110 ArgumentType.Scalar },
120 : base(new
ScriptNode[] { xc, yc, dr, N, FlameFunctions, Preview, Parallel },
132 : base(new
ScriptNode[] { xc, yc, dr, N, FlameFunctions, Preview },
144 : base(new
ScriptNode[] { xc, yc, dr, N, FlameFunctions },
160 "xc",
"yc",
"dr",
"N",
"FlameFunctions",
"Preview",
"Parallel",
161 "DimX",
"DimY",
"SuperSampling",
"Gamma",
"Vibrancy",
"Seed"
178 return new string[] {
"FlameFractal" };
217 object Obj =
Arguments[i].AssociatedObjectValue;
218 string FunctionsExpression = this.Arguments[i++].SubExpression;
220 if (!(Obj is Array FlameArray))
221 throw new ScriptRuntimeException(
"The fifth parameter to FlameFractalRgba must be an array, containing flame definitions.",
this);
230 foreach (
object FlameItem
in FlameArray)
235 FlameFunctions.Add(CurrentFunction);
237 else if (FlameItem is SKColor || FlameItem is
string)
239 if (CurrentFunction is
null)
241 M =
new DoubleMatrix(
new double[,] { { 1, 0 }, { 0, 1 } });
243 FlameFunctions.Add(CurrentFunction);
247 CurrentFunction =
null;
251 if (CurrentFunction is
null)
253 M =
new DoubleMatrix(
new double[,] { { 1, 0 }, { 0, 1 } });
255 FlameFunctions.Add(CurrentFunction);
258 CurrentFunction.Add(FlameVariation);
262 if (CurrentFunction is
null)
264 M =
new DoubleMatrix(
new double[,] { { 1, 0 }, { 0, 1 } });
266 FlameFunctions.Add(CurrentFunction);
269 CurrentFunction.Add(LambdaExpression);
271 else if (!(FlameItem is
null))
277 if (CurrentFunction is
null)
279 M =
new DoubleMatrix(
new double[,] { { 1, 0 }, { 0, 1 } });
281 FlameFunctions.Add(CurrentFunction);
284 CurrentFunction.SetWeight(Weight);
293 if (i < c &&
Arguments[i].AssociatedObjectValue is
bool Preview)
298 if (i < c &&
Arguments[i].AssociatedObjectValue is
bool Parallel)
342 throw new ScriptRuntimeException(
"Parameter mismatch in call to FlameFractalRgba(xc,yc,dr,N,FlameFunctions[,Preview[,Parallel[,dimx[,dimy[,SuperSampling[,Gamma[,Vibrancy[,Seed]]]]]]]]).",
346 if (dimx <= 0 || dimx > 5000 || dimy <= 0 || dimy > 5000)
360 return await
CalcFlame(xc, yc, dr, N, Functions, dimx, dimy, Seed, SuperSampling, Gamma,
361 Vibrancy, Preview, Parallel,
Variables,
this, this.FractalZoomScript,
362 new object[] { dimx, dimy, N, FunctionsExpression, Seed, SuperSampling, Gamma,
363 Vibrancy, Preview, Parallel });
366 private readonly
static Random gen =
new Random();
368 private string FractalZoomScript(
double r,
double i,
double Size,
object State)
370 object[] Parameters = (
object[])State;
371 int DimX = (int)Parameters[0];
372 int DimY = (int)Parameters[1];
373 long N = (long)Parameters[2];
374 string FunctionsExpression = (string)Parameters[3];
375 int Seed = (int)Parameters[4];
376 int SuperSampling = (int)Parameters[5];
377 double Gamma = (double)Parameters[6];
378 double Vibrancy = (double)Parameters[7];
379 bool Preview = (bool)Parameters[8];
380 bool Parallel = (bool)Parameters[9];
382 StringBuilder sb =
new StringBuilder();
384 sb.Append(
"FlameFractalRgba(");
391 sb.Append(N.ToString());
393 sb.Append(FunctionsExpression);
399 sb.Append(DimX.ToString());
401 sb.Append(DimY.ToString());
403 sb.Append(SuperSampling.ToString());
409 sb.Append(Seed.ToString());
412 return sb.ToString();
421 double TotWeight = 0;
423 int i, c = Functions.Length;
424 Random Gen =
new Random(Seed);
429 double[] SumWeights =
new double[c];
432 for (i = 0; i < c; i++)
441 SumWeights[i] = TotWeight;
447 for (i = 0; i < c; i++)
448 SumWeights[i] /= TotWeight;
450 double AspectRatio = ((double)Width) / Height;
452 double xMin, xMax, yMin, yMax;
455 FlameState P =
new FlameState(Gen, -1, 1, -1, 1, Width, Height, 1, N, ColorMode.Rgba, Node);
459 for (i = 0; i < 20; i++)
461 Weight = Gen.NextDouble();
463 while (j < c - 1 && SumWeights[j] <= Weight)
467 if (!f.Operate(P, v))
479 Weight = Gen.NextDouble();
481 while (j < c - 1 && SumWeights[j] <= Weight)
485 if (!f.Operate(P, v))
502 xMin = Math.Floor(xMin / d) * d;
503 xMax = Math.Ceiling(xMax / d) * d;
506 yMin = Math.Floor(yMin / d) * d;
507 yMax = Math.Ceiling(yMax / d) * d;
509 xCenter = (xMax + xMin) * 0.5;
510 yCenter = (yMax + yMin) * 0.5;
512 rDelta = xMax - xMin;
513 d = (yMax - yMin) * AspectRatio;
521 public static async Task<FractalGraph>
CalcFlame(
double xCenter,
double yCenter,
double rDelta,
long N,
522 FlameFunction[] Functions,
int Width,
int Height,
int Seed,
int SuperSampling,
double Gamma,
524 FractalZoomScript FractalZoomScript,
object State)
526 double TotWeight = 0;
528 int i, c = Functions.Length;
529 Random Gen =
new Random(Seed);
534 if (SuperSampling < 1)
540 Array.Sort(Functions, (f1, f2) =>
542 double d = f2.Weight - f1.
Weight;
551 double[] SumWeights =
new double[c];
554 for (i = 0; i < c; i++)
563 SumWeights[i] = TotWeight;
569 for (i = 0; i < c; i++)
570 SumWeights[i] /= TotWeight;
572 double AspectRatio = ((double)Width) / Height;
573 double xMin, xMax, yMin, yMax;
575 xMin = xCenter - rDelta / 2;
576 xMax = xMin + rDelta;
577 yMin = yCenter - rDelta / (2 * AspectRatio);
578 yMax = yMin + rDelta / AspectRatio;
580 int NrGames = Parallel ? Environment.ProcessorCount : 1;
584 FlameState P =
new FlameState(Gen, xMin, xMax, yMin, yMax, Width, Height, SuperSampling, N, ColorMode.Rgba, Node);
588 await RunChaosGame(v, Functions, SumWeights, P, Preview, Gamma, Vibrancy, Node);
590 return new FractalGraph(
Variables, P.RenderBitmapRgba(Gamma, Vibrancy,
false, SKColors.White), xMin, yMin, xMax, yMax, rDelta,
595 FlameState[] P =
new FlameState[NrGames];
596 WaitHandle[] Done =
new WaitHandle[NrGames];
597 Thread[] T =
new Thread[NrGames];
601 for (i = 0; i < NrGames; i++)
603 Done[i] =
new ManualResetEvent(
false);
604 P[i] =
new FlameState(Gen, xMin, xMax, yMin, yMax, Width, Height, SuperSampling,
605 i < NrGames - 1 ? N / NrGames : N - (N / NrGames) * (NrGames - 1),
606 ColorMode.Rgba, Node);
611 T[i] =
new Thread(
new ParameterizedThreadStart(ChaosGameThread))
613 Name =
"FlameFractal thread #" + (i + 1).
ToString(),
614 Priority = ThreadPriority.BelowNormal
617 T[i].Start(
new object[] { Done[i], i, v, Functions, SumWeights, P[i],
618 Node, i == 0 && Preview, Gamma, Vibrancy });
621 WaitHandle.WaitAll(Done);
623 for (i = 1; i < NrGames; i++)
626 return new FractalGraph(
Variables, P[0].RenderBitmapRgba(Gamma, Vibrancy,
false, SKColors.White), xMin, yMin, xMax, yMax, rDelta,
629 catch (ThreadAbortException)
631 for (i = 0; i < NrGames; i++)
638 if (Done[i] is
null || !Done[i].WaitOne(0))
651 for (i = 0; i < NrGames; i++)
666 private static void ChaosGameThread(
object P)
668 object[] Parameters = (
object[])P;
669 ManualResetEvent Done = (ManualResetEvent)Parameters[0];
673 double[] SumWeights = (
double[])Parameters[4];
674 FlameState P2 = (FlameState)Parameters[5];
676 bool Preview = (bool)Parameters[7];
677 double Gamma=(double)Parameters[8];
678 double Vibrancy=(double)Parameters[9];
682 RunChaosGame(v, Functions, SumWeights, P2, Preview, Gamma, Vibrancy, Node).Wait();
684 catch (ThreadAbortException)
698 private static async Task RunChaosGame(
Variables v, FlameFunction[] Functions,
699 double[] SumWeights, FlameState P,
bool Preview,
double Gamma,
double Vibrancy,
702 Random Gen =
new Random();
706 int c = Functions.Length;
708 for (i = 0; i < 20; i++)
710 Weight = Gen.NextDouble();
712 while (j < c - 1 && SumWeights[j] <= Weight)
716 if (!f.Operate(P, v))
725 DateTime
Start = DateTime.Now;
726 DateTime NextPreview =
Start.AddSeconds(1);
727 DateTime PrevPreview =
Start;
731 int NextPreviewDeciSeconds = 10;
732 int NrIterationsPerPreview = 4096;
733 int Pos = NrIterationsPerPreview;
735 long PrevNrIterations = 0;
736 long NrIterationsSinceLast;
738 double IterationsPerSeconds;
744 Pos = NrIterationsPerPreview;
746 if (Temp > NextPreview)
748 NextPreview = Temp.AddSeconds(NextPreviewDeciSeconds * 0.1);
749 if (NextPreviewDeciSeconds < 50)
750 NextPreviewDeciSeconds++;
756 Temp2 = DateTime.Now;
758 double d = (Temp2 - Temp).TotalSeconds;
759 double d2 = (Temp - PrevPreview).TotalSeconds;
763 NrIterationsPerPreview <<= 1;
764 if (NrIterationsPerPreview < 0)
765 NrIterationsPerPreview =
int.MaxValue;
769 NrIterations = P.N0 - P.N;
770 NrIterationsSinceLast = NrIterations - PrevNrIterations;
771 IterationsPerSeconds = NrIterationsSinceLast / (Temp - PrevPreview).TotalSeconds;
772 PercentDone = (100 * (1.0 - ((double)P.N) / P.N0));
773 TimeLeft =
new TimeSpan((
long)((Temp -
Start).Ticks * 100 / PercentDone));
774 await v.
Status(Node.
Expression, P.N.
ToString() +
" iterations left, " + NrIterations.ToString() +
" iterations done, " + IterationsPerSeconds.ToString(
"F0") +
" iterations/s, " + PercentDone.ToString(
"F1") +
"% done, Time Left: " + TimeLeft.ToString() +
".");
775 PrevNrIterations = NrIterations;
780 Weight = Gen.NextDouble();
782 while (j < c - 1 && SumWeights[j] <= Weight)
786 if (!f.Operate(P, v))
789 while (P.IncHistogram());
797 Weight = Gen.NextDouble();
799 while (j < c - 1 && SumWeights[j] <= Weight)
803 if (!f.Operate(P, v))
806 while (P.IncHistogram());
A chunked list is a linked list of chunks of objects of type T .
Script runtime exception.
Class managing a script expression.
static double ToDouble(object Object)
Converts an object to a double value.
static string ToString(double Value)
Converts a value to a string, that can be parsed as part of an expression.
Exception thrown if an image with invalid size is requested.
Defines a clickable fractal graph in the complex plane.
Calculates a flame fractal in RGBA space. Intensity is calculated along the A-axis....
override bool IsAsynchronous
If the node (or its decendants) include asynchronous evaluation. Asynchronous nodes should be evaluat...
static async Task< FractalGraph > CalcFlame(double xCenter, double yCenter, double rDelta, long N, FlameFunction[] Functions, int Width, int Height, int Seed, int SuperSampling, double Gamma, double Vibrancy, bool Preview, bool Parallel, Variables Variables, ScriptNode Node, FractalZoomScript FractalZoomScript, object State)
TODO
override IElement Evaluate(IElement[] Arguments, Variables Variables)
TODO
FlameFractalRgba(ScriptNode xc, ScriptNode yc, ScriptNode dr, ScriptNode N, ScriptNode FlameFunctions, ScriptNode Preview, int Start, int Length, Expression Expression)
TODO
static void EstimateSize(out double xCenter, out double yCenter, out double rDelta, FlameFunction[] Functions, int Width, int Height, int Seed, long N, Variables Variables, ScriptNode Node)
TODO
FlameFractalRgba(ScriptNode xc, ScriptNode yc, ScriptNode dr, ScriptNode N, ScriptNode FlameFunctions, ScriptNode Preview, ScriptNode Parallel, ScriptNode DimX, ScriptNode DimY, ScriptNode SuperSampling, int Start, int Length, Expression Expression)
TODO
FlameFractalRgba(ScriptNode xc, ScriptNode yc, ScriptNode dr, ScriptNode N, ScriptNode FlameFunctions, ScriptNode Preview, ScriptNode Parallel, int Start, int Length, Expression Expression)
TODO
override string FunctionName
TODO
FlameFractalRgba(ScriptNode xc, ScriptNode yc, ScriptNode dr, ScriptNode N, ScriptNode FlameFunctions, int Start, int Length, Expression Expression)
TODO
override string[] DefaultArgumentNames
TODO
override string[] Aliases
TODO
FlameFractalRgba(ScriptNode xc, ScriptNode yc, ScriptNode dr, ScriptNode N, ScriptNode FlameFunctions, ScriptNode Preview, ScriptNode Parallel, ScriptNode DimX, ScriptNode DimY, ScriptNode SuperSampling, ScriptNode Gamma, ScriptNode Vibrancy, ScriptNode Seed, int Start, int Length, Expression Expression)
TODO
FlameFractalRgba(ScriptNode xc, ScriptNode yc, ScriptNode dr, ScriptNode N, ScriptNode FlameFunctions, ScriptNode Preview, ScriptNode Parallel, ScriptNode DimX, int Start, int Length, Expression Expression)
TODO
FlameFractalRgba(ScriptNode xc, ScriptNode yc, ScriptNode dr, ScriptNode N, ScriptNode FlameFunctions, ScriptNode Preview, ScriptNode Parallel, ScriptNode DimX, ScriptNode DimY, ScriptNode SuperSampling, ScriptNode Gamma, int Start, int Length, Expression Expression)
TODO
FlameFractalRgba(ScriptNode xc, ScriptNode yc, ScriptNode dr, ScriptNode N, ScriptNode FlameFunctions, ScriptNode Preview, ScriptNode Parallel, ScriptNode DimX, ScriptNode DimY, int Start, int Length, Expression Expression)
TODO
FlameFractalRgba(ScriptNode xc, ScriptNode yc, ScriptNode dr, ScriptNode N, ScriptNode FlameFunctions, ScriptNode Preview, ScriptNode Parallel, ScriptNode DimX, ScriptNode DimY, ScriptNode SuperSampling, ScriptNode Gamma, ScriptNode Vibrancy, int Start, int Length, Expression Expression)
TODO
override async Task< IElement > EvaluateAsync(IElement[] Arguments, Variables Variables)
TODO
Handles bitmap-based graphs.
static double GetStepSize(double Min, double Max, int ApproxNrLabels)
Gets a human readable step size for an interval, given its limits and desired number of steps.
static SKColor ToColor(object Object)
Converts an object to a color.
Base class for multivariate funcions.
ScriptNode[] Arguments
Function arguments.
Base class for all nodes in a parsed script tree.
int Length
Length of expression covered by node.
override string ToString()
Expression Expression
Expression of which the node is a part.
int Start
Start position in script expression.
TextWriter ConsoleOut
Console out interface. Can be used by functions and script to output data to the console.
async Task Status(Expression Expression, string Result)
Reports current status of execution.
bool HandlesPreview
If previews are desired.
bool HandlesStatus
If status messages are desired.
void CopyTo(Variables Variables)
Copies available variables to another variable collection.
async Task Preview(Expression Expression, IElement Result)
Reports a preview of the final result.
Basic interface for all types of elements.
Base interface for lambda expressions.
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.