示例#1
0
        private static void RunChaosGame(Variables v, FlameFunction[] Functions,
                                         double[] SumWeights, FlameState P, bool Preview, double Gamma, double Vibrancy,
                                         ScriptNode Node)
        {
            Random        Gen = new Random();
            FlameFunction f;
            double        Weight;
            int           i, j;
            int           c = Functions.Length;

            for (i = 0; i < 20; i++)
            {
                Weight = Gen.NextDouble();
                j      = 0;
                while (j < c - 1 && SumWeights[j] <= Weight)
                {
                    j++;
                }

                f = Functions[j];
                if (!f.Operate(P, v))
                {
                    P.N = 0;
                    break;
                }
            }

            if (Preview || Node.Expression.HandlesStatus)
            {
                System.DateTime Start       = System.DateTime.Now;
                System.DateTime NextPreview = Start.AddSeconds(1);
                System.DateTime PrevPreview = Start;
                System.DateTime Temp;
                System.DateTime Temp2;
                TimeSpan        TimeLeft;
                int             NextPreviewDeciSeconds = 10;
                int             NrIterationsPerPreview = 4096;
                int             Pos = NrIterationsPerPreview;
                long            NrIterations;
                long            PrevNrIterations = 0;
                long            NrIterationsSinceLast;
                double          PercentDone;
                double          IterationsPerSeconds;

                do
                {
                    if (Pos-- <= 0)
                    {
                        Pos  = NrIterationsPerPreview;
                        Temp = System.DateTime.Now;
                        if (Temp > NextPreview)
                        {
                            NextPreview = Temp.AddSeconds(NextPreviewDeciSeconds * 0.1);
                            if (NextPreviewDeciSeconds < 50)
                            {
                                NextPreviewDeciSeconds++;
                            }

                            if (Preview)
                            {
                                Node.Expression.Preview(new GraphBitmap(P.RenderBitmapRgba(Gamma, Vibrancy, true, SKColors.White)));

                                Temp2 = System.DateTime.Now;

                                double d  = (Temp2 - Temp).TotalSeconds;
                                double d2 = (Temp - PrevPreview).TotalSeconds;

                                if (d / d2 > 0.1)
                                {
                                    NrIterationsPerPreview <<= 1;
                                    if (NrIterationsPerPreview < 0)
                                    {
                                        NrIterationsPerPreview = int.MaxValue;
                                    }
                                }
                            }

                            NrIterations          = P.N0 - P.N;
                            NrIterationsSinceLast = NrIterations - PrevNrIterations;
                            IterationsPerSeconds  = NrIterationsSinceLast / (Temp - PrevPreview).TotalSeconds;
                            PercentDone           = (100 * (1.0 - ((double)P.N) / P.N0));
                            TimeLeft = new TimeSpan((long)((Temp - Start).Ticks * 100 / PercentDone));
                            Node.Expression.Status(P.N.ToString() + " iterations left, " + NrIterations.ToString() + " iterations done, " + IterationsPerSeconds.ToString("F0") + " iterations/s, " + PercentDone.ToString("F1") + "% done, Time Left: " + TimeLeft.ToString() + ".");
                            PrevNrIterations = NrIterations;
                            PrevPreview      = Temp;
                        }
                    }

                    Weight = Gen.NextDouble();
                    j      = 0;
                    while (j < c - 1 && SumWeights[j] <= Weight)
                    {
                        j++;
                    }

                    f = Functions[j];
                    if (!f.Operate(P, v))
                    {
                        break;
                    }
                }while (P.IncHistogram());

                Node.Expression.Status(string.Empty);
            }
            else
            {
                do
                {
                    Weight = Gen.NextDouble();
                    j      = 0;
                    while (j < c - 1 && SumWeights[j] <= Weight)
                    {
                        j++;
                    }

                    f = Functions[j];
                    if (!f.Operate(P, v))
                    {
                        break;
                    }
                }while (P.IncHistogram());
            }
        }
示例#2
0
        public 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)
        {
            double TotWeight = 0;
            double Weight;
            int    i, c = Functions.Length;
            Random Gen = new Random(Seed);

            if (c < 1)
            {
                throw new ScriptRuntimeException("At least one flame function needs to be provided.", Node);
            }

            if (SuperSampling < 1)
            {
                throw new ScriptRuntimeException("SuperSampling must be a postitive integer.", Node);
            }

            if (!Node.Expression.HandlesPreview)
            {
                Preview = false;
            }

            Array.Sort <FlameFunction>(Functions, (f1, f2) =>
            {
                double d = f2.Weight - f1.Weight;
                if (d < 0)
                {
                    return(-1);
                }
                else if (d > 0)
                {
                    return(1);
                }
                else
                {
                    return(0);
                }
            });

            double[]      SumWeights = new double[c];
            FlameFunction f;

            for (i = 0; i < c; i++)
            {
                f      = Functions[i];
                Weight = f.Weight;
                if (Weight < 0)
                {
                    throw new ScriptRuntimeException("Weights must be non-negative.", Node);
                }

                f.DefinitionDone();
                TotWeight    += Weight;
                SumWeights[i] = TotWeight;
            }

            if (TotWeight == 0)
            {
                throw new ScriptRuntimeException("The total weight of all functions must be postitive.", Node);
            }

            for (i = 0; i < c; i++)
            {
                SumWeights[i] /= TotWeight;
            }

            double AspectRatio = ((double)Width) / Height;
            double xMin, xMax, yMin, yMax;

            xMin = xCenter - rDelta / 2;
            xMax = xMin + rDelta;
            yMin = yCenter - rDelta / (2 * AspectRatio);
            yMax = yMin + rDelta / AspectRatio;

            int NrGames = Parallel ? System.Environment.ProcessorCount : 1;

            if (NrGames <= 1)
            {
                FlameState P = new FlameState(Gen, xMin, xMax, yMin, yMax, Width, Height, SuperSampling, N, ColorMode.Rgba, Node);
                Variables  v = new Variables();
                Variables.CopyTo(v);

                RunChaosGame(v, Functions, SumWeights, P, Preview, Gamma, Vibrancy, Node);

                return(new FractalGraph(P.RenderBitmapRgba(Gamma, Vibrancy, false, SKColors.White), xMin, yMin, xMax, yMax, rDelta,
                                        false, Node, FractalZoomScript, State));
            }
            else
            {
                FlameState[] P    = new FlameState[NrGames];
                WaitHandle[] Done = new WaitHandle[NrGames];
                Thread[]     T    = new Thread[NrGames];

                try
                {
                    for (i = 0; i < NrGames; i++)
                    {
                        Done[i] = new ManualResetEvent(false);
                        P[i]    = new FlameState(Gen, xMin, xMax, yMin, yMax, Width, Height, SuperSampling,
                                                 i < NrGames - 1 ? N / NrGames : N - (N / NrGames) * (NrGames - 1),
                                                 ColorMode.Rgba, Node);

                        Variables v = new Variables();
                        Variables.CopyTo(v);

                        T[i] = new Thread(new ParameterizedThreadStart(ChaosGameThread))
                        {
                            Name     = "FlameFractal thread #" + (i + 1).ToString(),
                            Priority = ThreadPriority.BelowNormal
                        };

                        T[i].Start(new object[] { Done[i], i, v, Functions, SumWeights, P[i],
                                                  Node, i == 0 ? Preview : false, Gamma, Vibrancy });
                    }

                    WaitHandle.WaitAll(Done);

                    for (i = 1; i < NrGames; i++)
                    {
                        P[0].Add(P[i]);
                    }

                    return(new FractalGraph(P[0].RenderBitmapRgba(Gamma, Vibrancy, false, SKColors.White), xMin, yMin, xMax, yMax, rDelta,
                                            false, Node, FractalZoomScript, State));
                }
                catch (ThreadAbortException)
                {
                    for (i = 0; i < NrGames; i++)
                    {
                        try
                        {
                            if (T[i] == null)
                            {
                                continue;
                            }

                            if (Done[i] == null || !Done[i].WaitOne(0))
                            {
                                T[i].Abort();
                            }
                        }
                        catch (Exception)
                        {
                            // Ignore
                        }
                    }

                    return(null);
                }
                finally
                {
                    for (i = 0; i < NrGames; i++)
                    {
                        try
                        {
                            if (Done[i] != null)
                            {
                                Done[i].Close();
                            }
                        }
                        catch (Exception)
                        {
                            // Ignore
                        }
                    }
                }
            }
        }