Exemple #1
0
        private static void ChaosGameThread(object P)
        {
            object[]         Parameters = (object[])P;
            ManualResetEvent Done       = (ManualResetEvent)Parameters[0];
            int       GameNr            = (int)Parameters[1];
            Variables v = (Variables)Parameters[2];

            FlameFunction[] Functions   = (FlameFunction[])Parameters[3];
            double[]        SumWeights  = (double[])Parameters[4];
            FlameState      P2          = (FlameState)Parameters[5];
            ScriptNode      Node        = (ScriptNode)Parameters[6];
            bool            Preview     = (bool)Parameters[7];
            double          Gamma       = (double)Parameters[8];
            double          LightFactor = (double)Parameters[9];

            try
            {
                RunChaosGame(v, Functions, SumWeights, P2, Preview, Gamma, LightFactor, Node, GameNr == 0);
            }
            catch (ThreadAbortException)
            {
                Thread.ResetAbort();
            }
            catch (Exception)
            {
                // Ignore.
            }
            finally
            {
                Done.Set();
            }
        }
Exemple #2
0
        internal void Add(FlameState State)
        {
            int  f1, f2;
            long f;
            int  i;

            for (i = 0; i < this.size; i++)
            {
                f2 = State.frequency[i];
                if (f2 == 0)
                {
                    continue;
                }

                f1 = this.frequency[i];

                if (f1 == 0)
                {
                    this.frequency[i] = f2;
                    this.reds[i]      = State.reds[i];
                    this.greens[i]    = State.greens[i];
                    this.blues[i]     = State.blues[i];
                }
                else
                {
                    f  = f1;
                    f += f2;

                    if (f > int.MaxValue)
                    {
                        this.frequency[i] = int.MaxValue;
                    }
                    else
                    {
                        this.frequency[i] = (int)f;
                    }

                    this.reds[i]   = (f1 * this.reds[i] + f2 * State.reds[i]) / f;
                    this.greens[i] = (f1 * this.greens[i] + f2 * State.greens[i]) / f;
                    this.blues[i]  = (f1 * this.blues[i] + f2 * State.blues[i]) / f;
                }
            }
        }
Exemple #3
0
        internal bool Operate(FlameState point, Variables Variables)
        {
            double x = point.x;
            double y = point.y;

            double x2 = this.homogeneousTransform[0] * x +
                        this.homogeneousTransform[1] * y +
                        this.homogeneousTransform[2];

            double y2 = this.homogeneousTransform[3] * x +
                        this.homogeneousTransform[4] * y +
                        this.homogeneousTransform[5];

            if (this.hasProjection)
            {
                double p = this.homogeneousTransform[6] * x +
                           this.homogeneousTransform[7] * y +
                           this.homogeneousTransform[6];

                if (p == 0)
                {
                    return(false);
                }

                x2 /= p;
                y2 /= p;
            }

            if (this.hasVariations)
            {
                double x3 = 0;
                double y3 = 0;
                double w;
                int    i;

                if (this.nrVariations > 0)
                {
                    for (i = 0; i < this.nrVariations; i++)
                    {
                        x = x2;
                        y = y2;

                        this.variations[i].Operate(ref x, ref y);
                        w = this.variationWeights[i];

                        x3 += w * x;
                        y3 += w * y;
                    }
                }

                if (this.nrVariations2 > 0)
                {
                    for (i = 0; i < this.nrVariations2; i++)
                    {
                        w = this.variation2Weights[i];

                        if (this.variation2IsReal[i])
                        {
                            this.xv.Value = x2;
                            this.yv.Value = y2;

                            IElement Result = this.variations2[i].Evaluate(this.doubleParameters, Variables);

                            if (!(Result is IVector V) || V.Dimension != 2)
                            {
                                throw new ScriptRuntimeException("Real-valued lambda expressions must return a vector containing 2 real-valued numbers.", this.node);
                            }

                            x3 += w * Expression.ToDouble(V.GetElement(0).AssociatedObjectValue);
                            y3 += w * Expression.ToDouble(V.GetElement(1).AssociatedObjectValue);
                        }
                        else
                        {
                            this.zv.Value = new Complex(x2, y2);
                            Complex z = Expression.ToComplex(this.variations2[i].Evaluate(this.complexParameters, Variables).AssociatedObjectValue);

                            if (z == null)
                            {
                                throw new ScriptRuntimeException("Expected imaginary value as a result.", this.node);
                            }

                            x3 += w * z.Real;
                            y3 += w * z.Imaginary;
                        }
                    }
                }

                point.x = x3;
                point.y = y3;
            }
            else
            {
                point.x = x2;
                point.y = y2;
            }

            if (!this.isTransparent)
            {
                switch (point.ColorMode)
                {
                case ColorMode.Rgba:
                    point.red   = (point.red + this.red) * 0.5;
                    point.green = (point.green + this.green) * 0.5;
                    point.blue  = (point.blue + this.blue) * 0.5;
                    break;

                case ColorMode.Hsl:
                    double d;

                    if (this.red < point.red)                               // H
                    {
                        d = point.red - this.red;
                        if (d < 0.5)
                        {
                            point.red -= d * 0.5;
                        }
                        else
                        {
                            d          = 1 - d;
                            point.red += d * 0.5;
                            if (point.red > 1)
                            {
                                point.red -= 1;
                            }
                        }
                    }
                    else
                    {
                        d = this.red - point.red;
                        if (d < 0.5)
                        {
                            point.red += d * 0.5;
                        }
                        else
                        {
                            d          = 1 - d;
                            point.red -= d * 0.5;
                            if (point.red < 1)
                            {
                                point.red += 1;
                            }
                        }
                    }

                    point.green = (point.green + this.green) * 0.5;         // S
                    point.blue  = (point.blue + this.blue) * 0.5;           // L
                    break;
                }
            }

            return(true);
        }
Exemple #4
0
        private static void RunChaosGame(Variables v, FlameFunction[] Functions,
                                         double[] SumWeights, FlameState P, bool Preview, double Gamma, double LightFactor,
                                         ScriptNode Node, bool ShowStatus)
        {
            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.RenderBitmapHsl(Gamma, LightFactor, true, SKColors.Black)));

                                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());
            }
        }
Exemple #5
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 LightFactor, 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.Hsl, Node);
                Variables  v = new Variables();
                Variables.CopyTo(v);

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

                return(new FractalGraph(P.RenderBitmapHsl(Gamma, LightFactor, false, SKColors.Black), 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.Hsl, 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, LightFactor });
                    }

                    WaitHandle.WaitAll(Done);

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

                    return(new FractalGraph(P[0].RenderBitmapHsl(Gamma, LightFactor, false, SKColors.Black), 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
                        }
                    }
                }
            }
        }
        public 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)
        {
            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);
            }

            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;
            int    j;
            double xMin, xMax, yMin, yMax;
            double d;

            FlameState P = new FlameState(Gen, -1, 1, -1, 1, Width, Height, 1, N, ColorMode.Rgba, Node);
            Variables  v = new Variables();

            Variables.CopyTo(v);

            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))
                {
                    N = 0;
                    break;
                }
            }

            xMin = xMax = P.x;
            yMin = yMax = P.y;

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

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

                d = P.x;
                if (d < xMin)
                {
                    xMin = d;
                }
                else if (d > xMax)
                {
                    xMax = d;
                }

                d = P.y;
                if (d < yMin)
                {
                    yMin = d;
                }
                else if (d > yMax)
                {
                    yMax = d;
                }
            }

            d    = Graph.GetStepSize(xMin, xMax, 10);
            xMin = Math.Floor(xMin / d) * d;
            xMax = Math.Ceiling(xMax / d) * d;

            d    = Graph.GetStepSize(yMin, yMax, 10);
            yMin = Math.Floor(yMin / d) * d;
            yMax = Math.Ceiling(yMax / d) * d;

            xCenter = (xMax + xMin) * 0.5;
            yCenter = (yMax + yMin) * 0.5;

            rDelta = xMax - xMin;
            d      = (yMax - yMin) * AspectRatio;
            if (d > rDelta)
            {
                rDelta = d;
            }
        }