3using System.Collections.Generic;
33 : base(new
ScriptNode[] { xc, yc, dr, N, FlameFunctions, Preview, Parallel, DimX, DimY, SuperSampling,
34 Gamma, Vibrancy, Seed },
48 : base(new
ScriptNode[] { xc, yc, dr, N, FlameFunctions, Preview, Parallel, DimX, DimY, SuperSampling,
63 : base(new
ScriptNode[] { xc, yc, dr, N, FlameFunctions, Preview, Parallel, DimX, DimY, SuperSampling,
78 : base(new
ScriptNode[] { xc, yc, dr, N, FlameFunctions, Preview, Parallel, DimX, DimY, SuperSampling },
92 : base(new
ScriptNode[] { xc, yc, dr, N, FlameFunctions, Preview, Parallel, DimX, DimY },
105 : base(new
ScriptNode[] { xc, yc, dr, N, FlameFunctions, Preview, Parallel, DimX },
108 ArgumentType.Scalar },
118 : base(new
ScriptNode[] { xc, yc, dr, N, FlameFunctions, Preview, Parallel },
130 : base(new
ScriptNode[] { xc, yc, dr, N, FlameFunctions, Preview },
142 : base(new
ScriptNode[] { xc, yc, dr, N, FlameFunctions },
158 "xc",
"yc",
"dr",
"N",
"FlameFunctions",
"Preview",
"Parallel",
159 "DimX",
"DimY",
"SuperSampling",
"Gamma",
"Vibrancy",
"Seed"
176 return new string[] {
"FlameFractal" };
201 object Obj =
Arguments[i].AssociatedObjectValue;
202 string FunctionsExpression = this.Arguments[i++].SubExpression;
204 if (!(Obj is Array FlameArray))
205 throw new ScriptRuntimeException(
"The fifth parameter to FlameFractalRgba must be an array, containing flame definitions.",
this);
207 List<FlameFunction> FlameFunctions =
new List<FlameFunction>();
214 foreach (
object FlameItem
in FlameArray)
219 FlameFunctions.Add(CurrentFunction);
221 else if (FlameItem is SKColor || FlameItem is
string)
223 if (CurrentFunction is
null)
225 M =
new DoubleMatrix(
new double[,] { { 1, 0 }, { 0, 1 } });
227 FlameFunctions.Add(CurrentFunction);
231 CurrentFunction =
null;
235 if (CurrentFunction is
null)
237 M =
new DoubleMatrix(
new double[,] { { 1, 0 }, { 0, 1 } });
239 FlameFunctions.Add(CurrentFunction);
242 CurrentFunction.Add(FlameVariation);
246 if (CurrentFunction is
null)
248 M =
new DoubleMatrix(
new double[,] { { 1, 0 }, { 0, 1 } });
250 FlameFunctions.Add(CurrentFunction);
253 CurrentFunction.Add(LambdaExpression);
255 else if (!(FlameItem is
null))
261 if (CurrentFunction is
null)
263 M =
new DoubleMatrix(
new double[,] { { 1, 0 }, { 0, 1 } });
265 FlameFunctions.Add(CurrentFunction);
268 CurrentFunction.SetWeight(Weight);
277 if (i < c &&
Arguments[i].AssociatedObjectValue is
bool Preview)
282 if (i < c &&
Arguments[i].AssociatedObjectValue is
bool Parallel)
326 throw new ScriptRuntimeException(
"Parameter mismatch in call to FlameFractalRgba(xc,yc,dr,N,FlameFunctions[,Preview[,Parallel[,dimx[,dimy[,SuperSampling[,Gamma[,Vibrancy[,Seed]]]]]]]]).",
330 if (dimx <= 0 || dimx > 5000 || dimy <= 0 || dimy > 5000)
344 return CalcFlame(xc, yc, dr, N, Functions, dimx, dimy, Seed, SuperSampling, Gamma,
345 Vibrancy, Preview, Parallel,
Variables,
this, this.FractalZoomScript,
346 new object[] { dimx, dimy, N, FunctionsExpression, Seed, SuperSampling, Gamma,
347 Vibrancy, Preview, Parallel });
350 private readonly
static Random gen =
new Random();
352 private string FractalZoomScript(
double r,
double i,
double Size,
object State)
354 object[] Parameters = (
object[])State;
355 int DimX = (int)Parameters[0];
356 int DimY = (int)Parameters[1];
357 long N = (long)Parameters[2];
358 string FunctionsExpression = (string)Parameters[3];
359 int Seed = (int)Parameters[4];
360 int SuperSampling = (int)Parameters[5];
361 double Gamma = (double)Parameters[6];
362 double Vibrancy = (double)Parameters[7];
363 bool Preview = (bool)Parameters[8];
364 bool Parallel = (bool)Parameters[9];
366 StringBuilder sb =
new StringBuilder();
368 sb.Append(
"FlameFractalRgba(");
375 sb.Append(N.ToString());
377 sb.Append(FunctionsExpression);
383 sb.Append(DimX.ToString());
385 sb.Append(DimY.ToString());
387 sb.Append(SuperSampling.ToString());
393 sb.Append(Seed.ToString());
396 return sb.ToString();
405 double TotWeight = 0;
407 int i, c = Functions.Length;
408 Random Gen =
new Random(Seed);
413 double[] SumWeights =
new double[c];
416 for (i = 0; i < c; i++)
425 SumWeights[i] = TotWeight;
431 for (i = 0; i < c; i++)
432 SumWeights[i] /= TotWeight;
434 double AspectRatio = ((double)Width) / Height;
436 double xMin, xMax, yMin, yMax;
439 FlameState P =
new FlameState(Gen, -1, 1, -1, 1, Width, Height, 1, N, ColorMode.Rgba, Node);
443 for (i = 0; i < 20; i++)
445 Weight = Gen.NextDouble();
447 while (j < c - 1 && SumWeights[j] <= Weight)
451 if (!f.Operate(P, v))
463 Weight = Gen.NextDouble();
465 while (j < c - 1 && SumWeights[j] <= Weight)
469 if (!f.Operate(P, v))
486 xMin = Math.Floor(xMin / d) * d;
487 xMax = Math.Ceiling(xMax / d) * d;
490 yMin = Math.Floor(yMin / d) * d;
491 yMax = Math.Ceiling(yMax / d) * d;
493 xCenter = (xMax + xMin) * 0.5;
494 yCenter = (yMax + yMin) * 0.5;
496 rDelta = xMax - xMin;
497 d = (yMax - yMin) * AspectRatio;
506 FlameFunction[] Functions,
int Width,
int Height,
int Seed,
int SuperSampling,
double Gamma,
508 FractalZoomScript FractalZoomScript,
object State)
510 double TotWeight = 0;
512 int i, c = Functions.Length;
513 Random Gen =
new Random(Seed);
518 if (SuperSampling < 1)
524 Array.Sort(Functions, (f1, f2) =>
526 double d = f2.Weight - f1.
Weight;
535 double[] SumWeights =
new double[c];
538 for (i = 0; i < c; i++)
547 SumWeights[i] = TotWeight;
553 for (i = 0; i < c; i++)
554 SumWeights[i] /= TotWeight;
556 double AspectRatio = ((double)Width) / Height;
557 double xMin, xMax, yMin, yMax;
559 xMin = xCenter - rDelta / 2;
560 xMax = xMin + rDelta;
561 yMin = yCenter - rDelta / (2 * AspectRatio);
562 yMax = yMin + rDelta / AspectRatio;
564 int NrGames = Parallel ? Environment.ProcessorCount : 1;
568 FlameState P =
new FlameState(Gen, xMin, xMax, yMin, yMax, Width, Height, SuperSampling, N, ColorMode.Rgba, Node);
572 RunChaosGame(v, Functions, SumWeights, P, Preview, Gamma, Vibrancy, Node);
574 return new FractalGraph(
Variables, P.RenderBitmapRgba(Gamma, Vibrancy,
false, SKColors.White), xMin, yMin, xMax, yMax, rDelta,
579 FlameState[] P =
new FlameState[NrGames];
580 WaitHandle[] Done =
new WaitHandle[NrGames];
581 Thread[] T =
new Thread[NrGames];
585 for (i = 0; i < NrGames; i++)
587 Done[i] =
new ManualResetEvent(
false);
588 P[i] =
new FlameState(Gen, xMin, xMax, yMin, yMax, Width, Height, SuperSampling,
589 i < NrGames - 1 ? N / NrGames : N - (N / NrGames) * (NrGames - 1),
590 ColorMode.Rgba, Node);
595 T[i] =
new Thread(
new ParameterizedThreadStart(ChaosGameThread))
597 Name =
"FlameFractal thread #" + (i + 1).
ToString(),
598 Priority = ThreadPriority.BelowNormal
601 T[i].Start(
new object[] { Done[i], i, v, Functions, SumWeights, P[i],
602 Node, i == 0 && Preview, Gamma, Vibrancy });
605 WaitHandle.WaitAll(Done);
607 for (i = 1; i < NrGames; i++)
610 return new FractalGraph(
Variables, P[0].RenderBitmapRgba(Gamma, Vibrancy,
false, SKColors.White), xMin, yMin, xMax, yMax, rDelta,
613 catch (ThreadAbortException)
615 for (i = 0; i < NrGames; i++)
622 if (Done[i] is
null || !Done[i].WaitOne(0))
635 for (i = 0; i < NrGames; i++)
650 private static void ChaosGameThread(
object P)
652 object[] Parameters = (
object[])P;
653 ManualResetEvent Done = (ManualResetEvent)Parameters[0];
657 double[] SumWeights = (
double[])Parameters[4];
658 FlameState P2 = (FlameState)Parameters[5];
660 bool Preview = (bool)Parameters[7];
661 double Gamma=(double)Parameters[8];
662 double Vibrancy=(double)Parameters[9];
666 RunChaosGame(v, Functions, SumWeights, P2, Preview, Gamma, Vibrancy, Node);
668 catch (ThreadAbortException)
682 private static void RunChaosGame(
Variables v, FlameFunction[] Functions,
683 double[] SumWeights, FlameState P,
bool Preview,
double Gamma,
double Vibrancy,
686 Random Gen =
new Random();
690 int c = Functions.Length;
692 for (i = 0; i < 20; i++)
694 Weight = Gen.NextDouble();
696 while (j < c - 1 && SumWeights[j] <= Weight)
700 if (!f.Operate(P, v))
709 DateTime
Start = DateTime.Now;
710 DateTime NextPreview =
Start.AddSeconds(1);
711 DateTime PrevPreview =
Start;
715 int NextPreviewDeciSeconds = 10;
716 int NrIterationsPerPreview = 4096;
717 int Pos = NrIterationsPerPreview;
719 long PrevNrIterations = 0;
720 long NrIterationsSinceLast;
722 double IterationsPerSeconds;
728 Pos = NrIterationsPerPreview;
730 if (Temp > NextPreview)
732 NextPreview = Temp.AddSeconds(NextPreviewDeciSeconds * 0.1);
733 if (NextPreviewDeciSeconds < 50)
734 NextPreviewDeciSeconds++;
740 Temp2 = DateTime.Now;
742 double d = (Temp2 - Temp).TotalSeconds;
743 double d2 = (Temp - PrevPreview).TotalSeconds;
747 NrIterationsPerPreview <<= 1;
748 if (NrIterationsPerPreview < 0)
749 NrIterationsPerPreview =
int.MaxValue;
753 NrIterations = P.N0 - P.N;
754 NrIterationsSinceLast = NrIterations - PrevNrIterations;
755 IterationsPerSeconds = NrIterationsSinceLast / (Temp - PrevPreview).TotalSeconds;
756 PercentDone = (100 * (1.0 - ((double)P.N) / P.N0));
757 TimeLeft =
new TimeSpan((
long)((Temp -
Start).Ticks * 100 / PercentDone));
758 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() +
".");
759 PrevNrIterations = NrIterations;
764 Weight = Gen.NextDouble();
766 while (j < c - 1 && SumWeights[j] <= Weight)
770 if (!f.Operate(P, v))
773 while (P.IncHistogram());
781 Weight = Gen.NextDouble();
783 while (j < c - 1 && SumWeights[j] <= Weight)
787 if (!f.Operate(P, v))
790 while (P.IncHistogram());
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.
Defines a clickable fractal graph in the complex plane.
Calculates a flame fractal in RGBA space. Intensity is calculated along the A-axis....
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
static 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 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
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.
void Preview(Expression Expression, IElement Result)
Reports a preview of the final result.
bool HandlesPreview
If previews are desired.
bool HandlesStatus
If status messages are desired.
void Status(Expression Expression, string Result)
Reports current status of execution.
void CopyTo(Variables Variables)
Copies available variables to another variable collection.
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.