public static FractalGraph CalcNewton(double rCenter, double iCenter, double rDelta, Complex R,
                                              Complex[] Coefficients, SKColor[] Palette, int Width, int Height, ScriptNode Node,
                                              FractalZoomScript FractalZoomScript, object State)
        {
            byte[]  reds;
            byte[]  greens;
            byte[]  blues;
            double  RRe = R.Real;
            double  RIm = R.Imaginary;
            double  r0, i0, r1, i1;
            double  dr, di;
            double  r, i;
            double  zr, zi, zr2, zi2, zr3, zi3, zr4, zi4;
            double  aspect;
            double  Temp;
            int     x, y;
            int     n, N;
            int     index;
            int     Degree = Coefficients.Length - 1;
            SKColor cl;

            N      = Palette.Length;
            reds   = new byte[N];
            greens = new byte[N];
            blues  = new byte[N];

            for (x = 0; x < N; x++)
            {
                cl        = Palette[x];
                reds[x]   = cl.Red;
                greens[x] = cl.Green;
                blues[x]  = cl.Blue;
            }

            if (Degree < 2)
            {
                Array.Resize <Complex>(ref Coefficients, 3);
                while (Degree < 2)
                {
                    Coefficients[++Degree] = Complex.Zero;
                }
            }

            Complex[] Prim = new Complex[Degree];
            for (x = 1; x <= Degree; x++)
            {
                Prim[x - 1] = x * Coefficients[x];
            }

            Array.Reverse(Prim);
            Coefficients = (Complex[])Coefficients.Clone();
            Array.Reverse(Coefficients);

            int j, c = Prim.Length;

            double[] ReC    = new double[c + 1];
            double[] ImC    = new double[c + 1];
            double[] RePrim = new double[c];
            double[] ImPrim = new double[c];
            Complex  z;

            for (j = 0; j < c; j++)
            {
                z      = Coefficients[j];
                ReC[j] = z.Real;
                ImC[j] = z.Imaginary;

                z         = Prim[j];
                RePrim[j] = z.Real;
                ImPrim[j] = z.Imaginary;
            }

            z      = Coefficients[j];
            ReC[j] = z.Real;
            ImC[j] = z.Imaginary;

            int    size = Width * Height * 4;
            double Conv = 1e-10;
            double Div  = 1e10;

            byte[] rgb = new byte[size];

            rDelta *= 0.5;
            r0      = rCenter - rDelta;
            r1      = rCenter + rDelta;

            aspect = ((double)Width) / Height;

            i0 = iCenter - rDelta / aspect;
            i1 = iCenter + rDelta / aspect;

            dr = (r1 - r0) / Width;
            di = (i1 - i0) / Height;

            for (y = 0, i = i0, index = 0; y < Height; y++, i += di)
            {
                for (x = 0, r = r0; x < Width; x++, r += dr)
                {
                    zr = r;
                    zi = i;

                    n = 0;
                    do
                    {
                        // f:
                        zr2 = zi2 = 0;
                        for (j = 0; j <= c; j++)
                        {
                            Temp = zr2 * zr - zi2 * zi + ReC[j];
                            zi2  = zr2 * zi + zi2 * zr + ImC[j];
                            zr2  = Temp;
                        }

                        // f':
                        zr3 = zi3 = 0;
                        for (j = 0; j < c; j++)
                        {
                            Temp = zr3 * zr - zi3 * zi + RePrim[j];
                            zi3  = zr3 * zi + zi3 * zr + ImPrim[j];
                            zr3  = Temp;
                        }

                        // f/f':

                        Temp = 1.0 / (zr3 * zr3 + zi3 * zi3);
                        zr4  = (zr2 * zr3 + zi2 * zi3) * Temp;
                        zi4  = (zi2 * zr3 - zr2 * zi3) * Temp;

                        // R*f/f'
                        Temp = zr4 * RRe - zi4 * RIm;
                        zi4  = zr4 * RIm + zi4 * RRe;
                        zr4  = Temp;

                        zr -= zr4;
                        zi -= zi4;

                        Temp = Math.Sqrt(zr4 * zr4 + zi4 * zi4);
                    }while ((Temp > Conv) && (Temp < Div) && (n++ < N));

                    if (Temp < Conv && n < N)
                    {
                        rgb[index++] = blues[n];
                        rgb[index++] = greens[n];
                        rgb[index++] = reds[n];
                    }
                    else
                    {
                        rgb[index++] = 0;
                        rgb[index++] = 0;
                        rgb[index++] = 0;
                    }

                    rgb[index++] = 255;
                }
            }

            using (SKData Data = SKData.Create(new MemoryStream(rgb)))
            {
                SKImage Bitmap = SKImage.FromPixelData(new SKImageInfo(Width, Height, SKColorType.Bgra8888), Data, Width * 4);
                return(new FractalGraph(Bitmap, r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State));
            }
        }
        public static FractalGraph CalcNewton(double rCenter, double iCenter, double rDelta, Complex R,
                                              ILambdaExpression f, ScriptNode fDef, Variables Variables, SKColor[] Palette,
                                              int Width, int Height, ScriptNode Node, FractalZoomScript FractalZoomScript,
                                              object State)
        {
            byte[]  reds;
            byte[]  greens;
            byte[]  blues;
            double  RRe = R.Real;
            double  RIm = R.Imaginary;
            double  r0, i0, r1, i1;
            double  dr, di;
            double  r, i;
            double  aspect;
            int     x, y;
            int     n, N;
            SKColor cl;
            Complex z;

            N      = Palette.Length;
            reds   = new byte[N];
            greens = new byte[N];
            blues  = new byte[N];

            for (x = 0; x < N; x++)
            {
                cl        = Palette[x];
                reds[x]   = cl.Red;
                greens[x] = cl.Green;
                blues[x]  = cl.Blue;
            }

            Variables v = new Variables();

            Variables.CopyTo(v);

            if (!(f is IDifferentiable Differentiable) ||
                !(Differentiable.Differentiate(Differentiable.DefaultVariableName, v) is ILambdaExpression fPrim))
            {
                throw new ScriptRuntimeException("Lambda expression not differentiable.", Node);
            }

            int    size = Width * Height * 4;
            double Conv = 1e-10;
            double Div  = 1e10;

            byte[] rgb = new byte[size];

            Complex[]  Row;
            Complex[]  Row2;
            Complex[]  Row3;
            int[]      Offset;
            IElement[] P = new IElement[1];
            int        j, c, x2;
            IElement   Obj, Obj2;
            double     Mod;

            rDelta *= 0.5;
            r0      = rCenter - rDelta;
            r1      = rCenter + rDelta;

            aspect = ((double)Width) / Height;

            i0 = iCenter - rDelta / aspect;
            i1 = iCenter + rDelta / aspect;

            dr = (r1 - r0) / Width;
            di = (i1 - i0) / Height;

            for (y = 0, i = i0; y < Height; y++, i += di)
            {
                Row    = new Complex[Width];
                Offset = new int[Width];

                c = Width;
                for (x = 0, x2 = y * Width * 4, r = r0; x < Width; x++, r += dr, x2 += 4)
                {
                    Row[x]    = new Complex(r, i);
                    Offset[x] = x2;
                }

                n = 0;
                while (n < N && c > 0)
                {
                    n++;
                    P[0] = Expression.Encapsulate(Row);
                    Obj  = f.Evaluate(P, v);
                    Obj2 = fPrim.Evaluate(P, v);
                    Row2 = Obj.AssociatedObjectValue as Complex[];
                    Row3 = Obj2.AssociatedObjectValue as Complex[];

                    if (Row2 == null || Row3 == null)
                    {
                        throw new ScriptRuntimeException("Lambda expression (and its first derivative) must be able to accept complex vectors, " +
                                                         "and return complex vectors of equal length. Type returned: " +
                                                         Obj.GetType().FullName + " and " + Obj2.GetType().FullName, Node);
                    }
                    else if (Row2.Length != c || Row3.Length != c)
                    {
                        throw new ScriptRuntimeException("Lambda expression (and its first derivative) must be able to accept complex vectors, " +
                                                         "and return complex vectors of equal length. Length returned: " +
                                                         Row2.Length.ToString() + " and " + Row3.Length.ToString() +
                                                         ". Expected: " + c.ToString(), Node);
                    }

                    for (x = x2 = 0; x < c; x++)
                    {
                        j       = Offset[x];
                        z       = R * Row2[x] / Row3[x];
                        Row[x] -= z;

                        Mod = z.Magnitude;

                        if (Mod > Conv && Mod < Div)
                        {
                            if (x != x2)
                            {
                                Offset[x2] = j;
                            }

                            x2++;
                        }
                        else
                        {
                            if (n >= N)
                            {
                                rgb[j++] = 0;
                                rgb[j++] = 0;
                                rgb[j++] = 0;
                            }
                            else
                            {
                                rgb[j++] = blues[n];
                                rgb[j++] = greens[n];
                                rgb[j++] = reds[n];
                            }

                            rgb[j++] = 255;
                        }
                    }

                    if (x2 < x)
                    {
                        Array.Resize <Complex>(ref Row, x2);
                        Array.Resize <int>(ref Offset, x2);
                        c = x2;
                    }
                }
            }

            using (SKData Data = SKData.Create(new MemoryStream(rgb)))
            {
                SKImage Bitmap = SKImage.FromPixelData(new SKImageInfo(Width, Height, SKColorType.Bgra8888), Data, Width * 4);
                return(new FractalGraph(Bitmap, r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State));
            }
        }
Exemple #3
0
        public static FractalGraph CalcHalley(double rCenter, double iCenter, double rDelta, Complex R,
                                              double[] Coefficients, SKColor[] Palette, int Width, int Height, ScriptNode Node,
                                              FractalZoomScript FractalZoomScript, object State)
        {
            byte[]  reds;
            byte[]  greens;
            byte[]  blues;
            double  RRe = R.Real;
            double  RIm = R.Imaginary;
            double  r0, i0, r1, i1;
            double  dr, di;
            double  r, i;
            double  zr, zi, zr2, zi2, zr3, zi3, zr4, zi4, zr5, zi5, zr6, zi6;
            double  aspect;
            double  Temp;
            int     x, y;
            int     n, N;
            int     index;
            int     Degree = Coefficients.Length - 1;
            SKColor cl;

            N      = Palette.Length;
            reds   = new byte[N];
            greens = new byte[N];
            blues  = new byte[N];

            for (x = 0; x < N; x++)
            {
                cl        = Palette[x];
                reds[x]   = cl.Red;
                greens[x] = cl.Green;
                blues[x]  = cl.Blue;
            }

            if (Degree < 3)
            {
                Array.Resize <double>(ref Coefficients, 4);
                while (Degree < 3)
                {
                    Coefficients[++Degree] = 0;
                }
            }

            double[] Prim = new double[Degree];
            for (x = 1; x <= Degree; x++)
            {
                Prim[x - 1] = x * Coefficients[x];
            }

            double[] Bis = new double[Degree - 1];
            for (x = 1; x < Degree; x++)
            {
                Bis[x - 1] = x * Prim[x];
            }

            Array.Reverse(Bis);
            Array.Reverse(Prim);
            Coefficients = (double[])Coefficients.Clone();
            Array.Reverse(Coefficients);

            int    size = Width * Height * 4;
            double Conv = 1e-10;
            double Div  = 1e10;

            byte[] rgb = new byte[size];

            rDelta *= 0.5;
            r0      = rCenter - rDelta;
            r1      = rCenter + rDelta;

            aspect = ((double)Width) / Height;

            i0 = iCenter - rDelta / aspect;
            i1 = iCenter + rDelta / aspect;

            dr = (r1 - r0) / Width;
            di = (i1 - i0) / Height;

            for (y = 0, i = i0, index = 0; y < Height; y++, i += di)
            {
                for (x = 0, r = r0; x < Width; x++, r += dr)
                {
                    zr = r;
                    zi = i;

                    n = 0;
                    do
                    {
                        // f:
                        zr2 = zi2 = 0;
                        foreach (double C in Coefficients)
                        {
                            Temp = zr2 * zr - zi2 * zi + C;
                            zi2  = zr2 * zi + zi2 * zr;
                            zr2  = Temp;
                        }

                        // f':
                        zr3 = zi3 = 0;
                        foreach (double C in Prim)
                        {
                            Temp = zr3 * zr - zi3 * zi + C;
                            zi3  = zr3 * zi + zi3 * zr;
                            zr3  = Temp;
                        }

                        // f":
                        zr4 = zi4 = 0;
                        foreach (double C in Bis)
                        {
                            Temp = zr4 * zr - zi4 * zi + C;
                            zi4  = zr4 * zi + zi4 * zr;
                            zr4  = Temp;
                        }

                        // 2*f*f'

                        zr5 = 2 * (zr2 * zr3 - zi2 * zi3);
                        zi5 = 2 * (zr2 * zi3 + zi2 * zr3);

                        // 2f'^2-f*f"

                        zr6 = 2 * (zr3 * zr3 - zi3 * zi3) - (zr2 * zr4 - zi2 * zi4);
                        zi6 = 4 * zr3 * zi3 - (zr2 * zi4 + zr4 * zi2);

                        // R*2*f*f'/2f'^2-f*f"

                        Temp = 1.0 / (zr6 * zr6 + zi6 * zi6);
                        zr4  = (zr5 * zr6 + zi5 * zi6) * Temp;
                        zi4  = (zi5 * zr6 - zr5 * zi6) * Temp;

                        // R*2*f*f'/(2f'^2-f*f")
                        Temp = zr4 * RRe - zi4 * RIm;
                        zi4  = zr4 * RIm + zi4 * RRe;
                        zr4  = Temp;

                        zr -= zr4;
                        zi -= zi4;

                        Temp = Math.Sqrt(zr4 * zr4 + zi4 * zi4);
                    }while ((Temp > Conv) && (Temp < Div) && (n++ < N));

                    if (Temp < Conv && n < N)
                    {
                        rgb[index++] = blues[n];
                        rgb[index++] = greens[n];
                        rgb[index++] = reds[n];
                    }
                    else
                    {
                        rgb[index++] = 0;
                        rgb[index++] = 0;
                        rgb[index++] = 0;
                    }

                    rgb[index++] = 255;
                }
            }

            using (SKData Data = SKData.Create(new MemoryStream(rgb)))
            {
                SKImage Bitmap = SKImage.FromPixelData(new SKImageInfo(Width, Height, SKColorType.Bgra8888), Data, Width * 4);
                return(new FractalGraph(Bitmap, r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State));
            }
        }
Exemple #4
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 FractalGraph CalcNewtonSmooth(double rCenter, double iCenter, double rDelta, Complex R,
                                                    ILambdaExpression f, ScriptNode fDef, Variables Variables, SKColor[] Palette, int Width, int Height,
                                                    ScriptNode Node, FractalZoomScript FractalZoomScript, object State)
        {
            double RRe = R.Real;
            double RIm = R.Imaginary;
            double r0, i0, r1, i1;
            double dr, di;
            double r, i;
            double aspect;
            int    x, y;
            int    n, N;

            N = Palette.Length;

            if (Width <= 2 || Height <= 2)
            {
                throw new ScriptRuntimeException("Width and Height has to be greater than 2.", Node);
            }

            Variables v = new Variables();

            Variables.CopyTo(v);

            if (!(f is IDifferentiable Differentiable) ||
                !(Differentiable.Differentiate(Differentiable.DefaultVariableName, v) is ILambdaExpression fPrim))
            {
                throw new ScriptRuntimeException("Lambda expression not differentiable.", Node);
            }

            int    Size = Width * Height;
            double Conv = 1e-10;
            double Div  = 1e10;

            double[] ColorIndex = new double[Size];
            int      Index      = 0;

            Complex[]  Row;
            Complex[]  Row2;
            Complex[]  Row3;
            int[]      Offset;
            IElement[] P = new IElement[1];
            int        j, c, x2;
            IElement   Obj, Obj2;
            double     Mod;
            Complex    z;

            rDelta *= 0.5;
            r0      = rCenter - rDelta;
            r1      = rCenter + rDelta;

            aspect = ((double)Width) / Height;

            i0 = iCenter - rDelta / aspect;
            i1 = iCenter + rDelta / aspect;

            dr = (r1 - r0) / Width;
            di = (i1 - i0) / Height;

            for (y = 0, i = i0; y < Height; y++, i += di)
            {
                Row    = new Complex[Width];
                Offset = new int[Width];

                c = Width;
                for (x = 0, x2 = y * Width, r = r0; x < Width; x++, r += dr, x2++)
                {
                    Row[x]    = new Complex(r, i);
                    Offset[x] = x2;
                }

                n = 0;
                while (n < N && c > 0)
                {
                    n++;
                    P[0] = Expression.Encapsulate(Row);
                    Obj  = f.Evaluate(P, v);
                    Obj2 = fPrim.Evaluate(P, v);
                    Row2 = Obj.AssociatedObjectValue as Complex[];
                    Row3 = Obj2.AssociatedObjectValue as Complex[];

                    if (Row2 == null || Row3 == null)
                    {
                        throw new ScriptRuntimeException("Lambda expression (and its first derivative) must be able to accept complex vectors, " +
                                                         "and return complex vectors of equal length. Type returned: " +
                                                         Obj.GetType().FullName + " and " + Obj2.GetType().FullName, Node);
                    }
                    else if (Row2.Length != c || Row3.Length != c)
                    {
                        throw new ScriptRuntimeException("Lambda expression (and its first derivative) must be able to accept complex vectors, " +
                                                         "and return complex vectors of equal length. Length returned: " +
                                                         Row2.Length.ToString() + " and " + Row3.Length.ToString() +
                                                         ". Expected: " + c.ToString(), Node);
                    }

                    for (x = x2 = 0; x < c; x++)
                    {
                        j       = Offset[x];
                        z       = R * Row2[x] / Row3[x];
                        Row[x] -= z;

                        Mod = z.Magnitude;

                        if (Mod > Conv && Mod < Div)
                        {
                            if (x != x2)
                            {
                                Offset[x2] = j;
                            }

                            x2++;
                        }
                        else
                        {
                            if (n >= N)
                            {
                                ColorIndex[Index++] = N;
                            }
                            else
                            {
                                ColorIndex[j++] = n;
                            }
                        }
                    }

                    if (x2 < x)
                    {
                        Array.Resize <Complex>(ref Row, x2);
                        Array.Resize <int>(ref Offset, x2);
                        c = x2;
                    }
                }
            }

            Node.Expression.Preview(new GraphBitmap(FractalGraph.ToBitmap(ColorIndex, Width, Height, Palette)));

            double[] Boundary = FractalGraph.FindBoundaries(ColorIndex, Width, Height);
            FractalGraph.Smooth(ColorIndex, Boundary, Width, Height, N, Palette, Node, Variables);

            return(new FractalGraph(FractalGraph.ToBitmap(ColorIndex, Width, Height, Palette),
                                    r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State));
        }
Exemple #6
0
        public static FractalGraph CalcMandelbrot(double rCenter, double iCenter, double rDelta,
                                                  SKColor[] Palette, int Width, int Height, ScriptNode Node,
                                                  FractalZoomScript FractalZoomScript, object State)
        {
            double r0, i0, r1, i1;
            double dr, di;
            double r, i;
            double zr, zi, zrt, zr2, zi2;
            double aspect;
            int    x, y;
            int    n, N;

            N = Palette.Length;

            int Size = Width * Height;

            int[] ColorIndex = new int[Size];
            int   Index      = 0;

            rDelta *= 0.5;
            r0      = rCenter - rDelta;
            r1      = rCenter + rDelta;

            aspect = ((double)Width) / Height;

            i0 = iCenter - rDelta / aspect;
            i1 = iCenter + rDelta / aspect;

            dr = (r1 - r0) / Width;
            di = (i1 - i0) / Height;

            for (y = 0, i = i0; y < Height; y++, i += di)
            {
                for (x = 0, r = r0; x < Width; x++, r += dr)
                {
                    zr = r;
                    zi = i;

                    n   = 0;
                    zr2 = zr * zr;
                    zi2 = zi * zi;

                    while (zr2 + zi2 < 9 && n < N)
                    {
                        n++;
                        zrt = zr2 - zi2 + r;
                        zi  = 2 * zr * zi + i;
                        zr  = zrt;

                        zr2 = zr * zr;
                        zi2 = zi * zi;
                    }

                    if (n >= N)
                    {
                        ColorIndex[Index++] = N;
                    }
                    else
                    {
                        ColorIndex[Index++] = n;
                    }
                }
            }

            ColorIndex = FractalGraph.FindBoundaries(ColorIndex, Width, Height);

            return(new FractalGraph(FractalGraph.ToBitmap(ColorIndex, Width, Height, Palette),
                                    r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State));
        }
Exemple #7
0
        public static FractalGraph CalcNewton(double rCenter, double iCenter, double rDelta, Complex R,
                                              ILambdaExpression f, ScriptNode fDef, Variables Variables, int N, int Width, int Height,
                                              ScriptNode Node, FractalZoomScript FractalZoomScript, object State)
        {
            double        RRe             = R.Real;
            double        RIm             = R.Imaginary;
            List <double> AttractorsR     = new List <double>();
            List <double> AttractorsI     = new List <double>();
            List <int>    AttractorColors = new List <int>();

            double[] AttractorsR2 = new double[0];
            double[] AttractorsI2 = new double[0];
            int[]    AttractorsColors2 = new int[0];
            double   r0, i0, r1, i1;
            double   dr, di;
            double   r, i;
            double   zr, zi;
            double   aspect;
            int      x, y, b, c, d;
            int      NrAttractors = 0;
            int      n;
            int      index;

            Variables v = new Variables();

            Variables.CopyTo(v);

            if (!(f is IDifferentiable Differentiable) ||
                !(Differentiable.Differentiate(Differentiable.DefaultVariableName, v) is ILambdaExpression fPrim))
            {
                throw new ScriptRuntimeException("Lambda expression not differentiable.", Node);
            }

            int    size  = Width * Height * 4;
            double Conv  = 1e-10;
            double Div   = 1e10;
            double Conv2 = Conv * 2;

            byte[] rgb = new byte[size];

            Complex[]  Row;
            Complex[]  Row2;
            Complex[]  Row3;
            int[]      Offset;
            IElement[] P = new IElement[1];
            int        j, x2;
            IElement   Obj, Obj2;
            double     Mod;
            Complex    z;

            rDelta *= 0.5;
            r0      = rCenter - rDelta;
            r1      = rCenter + rDelta;

            aspect = ((double)Width) / Height;

            i0 = iCenter - rDelta / aspect;
            i1 = iCenter + rDelta / aspect;

            dr = (r1 - r0) / Width;
            di = (i1 - i0) / Height;

            for (y = 0, i = i0, index = 0; y < Height; y++, i += di)
            {
                Row    = new Complex[Width];
                Offset = new int[Width];

                c = Width;
                for (x = 0, x2 = y * Width * 4, r = r0; x < Width; x++, r += dr, x2 += 4)
                {
                    Row[x]    = new Complex(r, i);
                    Offset[x] = x2;
                }

                n = 0;
                while (n < N && c > 0)
                {
                    n++;
                    P[0] = Expression.Encapsulate(Row);
                    Obj  = f.Evaluate(P, v);
                    Obj2 = fPrim.Evaluate(P, v);
                    Row2 = Obj.AssociatedObjectValue as Complex[];
                    Row3 = Obj2.AssociatedObjectValue as Complex[];

                    if (Row2 == null || Row3 == null)
                    {
                        throw new ScriptRuntimeException("Lambda expression (and its first derivative) must be able to accept complex vectors, " +
                                                         "and return complex vectors of equal length. Type returned: " +
                                                         Obj.GetType().FullName + " and " + Obj2.GetType().FullName, Node);
                    }
                    else if (Row2.Length != c || Row3.Length != c)
                    {
                        throw new ScriptRuntimeException("Lambda expression (and its first derivative) must be able to accept complex vectors, " +
                                                         "and return complex vectors of equal length. Length returned: " +
                                                         Row2.Length.ToString() + " and " + Row3.Length.ToString() +
                                                         ". Expected: " + c.ToString(), Node);
                    }

                    for (x = x2 = 0; x < c; x++)
                    {
                        j       = Offset[x];
                        z       = R * Row2[x] / Row3[x];
                        Row[x] -= z;

                        Mod = z.Magnitude;

                        if (Mod > Conv && Mod < Div)
                        {
                            if (x != x2)
                            {
                                Offset[x2] = j;
                            }

                            x2++;
                        }
                        else
                        {
                            if (n >= N)
                            {
                                rgb[j++] = 0;
                                rgb[j++] = 0;
                                rgb[j++] = 0;
                            }
                            else
                            {
                                zr = z.Real;
                                zi = z.Imaginary;

                                for (b = 0; b < NrAttractors; b++)
                                {
                                    if (Math.Abs(AttractorsR2[b] - zr) < Conv2 &&
                                        Math.Abs(AttractorsI2[b] - zi) < Conv2)
                                    {
                                        break;
                                    }
                                }

                                if (b == NrAttractors)
                                {
                                    AttractorsR.Add(zr);
                                    AttractorsI.Add(zi);

                                    int p1 = ~((b % 6) + 1);
                                    int p2 = ((b / 6) % 7);

                                    int Red   = (p1 & 1) != 0 ? 255 : 0;
                                    int Green = (p1 & 2) != 0 ? 255 : 0;
                                    int Blue  = (p1 & 4) != 0 ? 255 : 0;

                                    if ((p2 & 1) != 0)
                                    {
                                        Red >>= 1;
                                    }

                                    if ((p2 & 2) != 0)
                                    {
                                        Green >>= 1;
                                    }

                                    if ((p2 & 4) != 0)
                                    {
                                        Blue >>= 1;
                                    }

                                    Blue <<= 8;
                                    Blue  |= Green;
                                    Blue <<= 8;
                                    Blue  |= Red;

                                    AttractorColors.Add(Blue);

                                    AttractorsR2      = AttractorsR.ToArray();
                                    AttractorsI2      = AttractorsI.ToArray();
                                    AttractorsColors2 = AttractorColors.ToArray();

                                    NrAttractors++;
                                }

                                b = AttractorColors[b];

                                d            = (byte)b;
                                rgb[index++] = (byte)((d * (N - n + 1)) / N);
                                b          >>= 8;
                                d            = (byte)b;
                                rgb[index++] = (byte)((d * (N - n + 1)) / N);
                                b          >>= 8;
                                d            = (byte)b;
                                rgb[index++] = (byte)((d * (N - n + 1)) / N);
                            }

                            rgb[j++] = 255;
                        }
                    }

                    if (x2 < x)
                    {
                        Array.Resize <Complex>(ref Row, x2);
                        Array.Resize <int>(ref Offset, x2);
                        c = x2;
                    }
                }
            }

            using (SKData Data = SKData.Create(new MemoryStream(rgb)))
            {
                SKImage Bitmap = SKImage.FromPixelData(new SKImageInfo(Width, Height, SKColorType.Bgra8888), Data, Width * 4);
                return(new FractalGraph(Bitmap, r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State));
            }
        }
Exemple #8
0
        public static FractalGraph CalcJulia(double rCenter, double iCenter, ILambdaExpression f,
                                             ScriptNode fDef, double rDelta, SKColor[] Palette, int Width, int Height,
                                             ScriptNode Node, Variables Variables,
                                             FractalZoomScript FractalZoomScript, object State)
        {
            byte[]  reds;
            byte[]  greens;
            byte[]  blues;
            double  r0, i0, r1, i1;
            double  dr, di;
            double  r, i, Mod;
            double  aspect;
            int     x, x2, y;
            int     n, N;
            SKColor cl;

            N      = Palette.Length;
            reds   = new byte[N];
            greens = new byte[N];
            blues  = new byte[N];

            for (x = 0; x < N; x++)
            {
                cl        = Palette[x];
                reds[x]   = cl.Red;
                greens[x] = cl.Green;
                blues[x]  = cl.Blue;
            }

            int size = Width * Height * 4;

            byte[]  rgb = new byte[size];
            Complex z;

            IElement[] P = new IElement[1];
            int        j, c;
            IElement   Obj;

            rDelta *= 0.5;
            r0      = rCenter - rDelta;
            r1      = rCenter + rDelta;

            aspect = ((double)Width) / Height;

            i0 = iCenter - rDelta / aspect;
            i1 = iCenter + rDelta / aspect;

            dr = (r1 - r0) / Width;
            di = (i1 - i0) / Height;

            for (y = 0, i = i0; y < Height; y++, i += di)
            {
                Complex[] Row    = new Complex[Width];
                int[]     Offset = new int[Width];

                c = Width;
                for (x = 0, x2 = y * Width * 4, r = r0; x < Width; x++, r += dr, x2 += 4)
                {
                    Row[x]    = new Complex(r, i);
                    Offset[x] = x2;
                }

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

                n = 0;
                while (n < N && c > 0)
                {
                    n++;
                    P[0] = Expression.Encapsulate(Row);
                    Obj  = f.Evaluate(P, v);
                    Row  = Obj.AssociatedObjectValue as Complex[];

                    if (Row == null)
                    {
                        throw new ScriptRuntimeException("Lambda expression must be able to accept complex vectors, " +
                                                         "and return complex vectors of equal length. Type returned: " +
                                                         Obj.GetType().FullName, Node);
                    }
                    else if (Row.Length != c)
                    {
                        throw new ScriptRuntimeException("Lambda expression must be able to accept complex vectors, " +
                                                         "and return complex vectors of equal length. Length returned: " +
                                                         Row.Length.ToString() + ". Expected: " + c.ToString(), Node);
                    }

                    for (x = x2 = 0; x < c; x++)
                    {
                        z = Row[x];
                        j = Offset[x];

                        Mod = z.Magnitude;

                        if (Mod < 3)
                        {
                            if (x != x2)
                            {
                                Row[x2]    = z;
                                Offset[x2] = j;
                            }

                            x2++;
                        }
                        else
                        {
                            if (n >= N)
                            {
                                rgb[j++] = 0;
                                rgb[j++] = 0;
                                rgb[j++] = 0;
                            }
                            else
                            {
                                rgb[j++] = blues[n];
                                rgb[j++] = greens[n];
                                rgb[j++] = reds[n];
                            }

                            rgb[j++] = 255;
                        }
                    }

                    if (x2 < x)
                    {
                        Array.Resize <Complex>(ref Row, x2);
                        Array.Resize <int>(ref Offset, x2);
                        c = x2;
                    }
                }

                if (c > 0)
                {
                    for (x = 0; x < c; x++)
                    {
                        j = Offset[x];

                        rgb[j++] = 0;
                        rgb[j++] = 0;
                        rgb[j++] = 0;
                        rgb[j++] = 255;
                    }
                }
            }

            using (SKData Data = SKData.Create(new MemoryStream(rgb)))
            {
                SKImage Bitmap = SKImage.FromPixelData(new SKImageInfo(Width, Height, SKColorType.Bgra8888), Data, Width * 4);
                return(new FractalGraph(Bitmap, r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State));
            }
        }
        public static FractalGraph CalcHalley(double rCenter, double iCenter, double rDelta, Complex R,
                                              ILambdaExpression f, ScriptNode fDef, Variables Variables, SKColor[] Palette, int Width, int Height,
                                              ScriptNode Node, FractalZoomScript FractalZoomScript, object State)
        {
            byte[]  reds;
            byte[]  greens;
            byte[]  blues;
            double  RRe = R.Real;
            double  RIm = R.Imaginary;
            double  r0, i0, r1, i1;
            double  dr, di;
            double  r, i;
            double  aspect;
            int     x, y;
            int     n, N;
            SKColor cl;

            N      = Palette.Length;
            reds   = new byte[N];
            greens = new byte[N];
            blues  = new byte[N];

            for (x = 0; x < N; x++)
            {
                cl        = Palette[x];
                reds[x]   = cl.Red;
                greens[x] = cl.Green;
                blues[x]  = cl.Blue;
            }

            Variables v = new Variables();

            Variables.CopyTo(v);

            string ParameterName;

            if (!(f is IDifferentiable Differentiable) ||
                !(Differentiable.Differentiate(ParameterName = Differentiable.DefaultVariableName, v) is ILambdaExpression fPrim))
            {
                throw new ScriptRuntimeException("Lambda expression not differentiable.", Node);
            }

            if (!(fPrim is IDifferentiable Differentiable2) ||
                !(Differentiable2.Differentiate(ParameterName, v) is ILambdaExpression fBis))
            {
                throw new ScriptRuntimeException("Lambda expression not twice differentiable.", Node);
            }

            int    size = Width * Height * 4;
            double Conv = 1e-10;
            double Div  = 1e10;

            byte[] rgb = new byte[size];

            Complex[]  Row;
            Complex[]  Row2;
            Complex[]  Row3;
            Complex[]  Row4;
            int[]      Offset;
            IElement[] P = new IElement[1];
            int        j, c, x2;
            IElement   Obj, Obj2, Obj3;
            double     Mod;
            Complex    z, z2, z3;
            Complex    R2 = R * 2;

            rDelta *= 0.5;
            r0      = rCenter - rDelta;
            r1      = rCenter + rDelta;

            aspect = ((double)Width) / Height;

            i0 = iCenter - rDelta / aspect;
            i1 = iCenter + rDelta / aspect;

            dr = (r1 - r0) / Width;
            di = (i1 - i0) / Height;

            for (y = 0, i = i0; y < Height; y++, i += di)
            {
                Row    = new Complex[Width];
                Offset = new int[Width];

                c = Width;
                for (x = 0, x2 = y * Width * 4, r = r0; x < Width; x++, r += dr, x2 += 4)
                {
                    Row[x]    = new Complex(r, i);
                    Offset[x] = x2;
                }

                n = 0;
                while (n < N && c > 0)
                {
                    n++;
                    P[0] = Expression.Encapsulate(Row);
                    Obj  = f.Evaluate(P, v);
                    Obj2 = fPrim.Evaluate(P, v);
                    Obj3 = fBis.Evaluate(P, v);
                    Row2 = Obj.AssociatedObjectValue as Complex[];
                    Row3 = Obj2.AssociatedObjectValue as Complex[];
                    Row4 = Obj3.AssociatedObjectValue as Complex[];

                    if (Row2 is null || Row3 is null || Row4 is null)
                    {
                        throw new ScriptRuntimeException("Lambda expression (and its first and second derivative) must be able to accept complex vectors, " +
                                                         "and return complex vectors of equal length. Type returned: " +
                                                         Obj.GetType().FullName + ", " + Obj2.GetType().FullName + " and " + Obj3.GetType().FullName,
                                                         Node);
                    }
Exemple #10
0
        public static FractalGraph CalcNewton(double rCenter, double iCenter, double rDelta, Complex R,
                                              Complex[] Coefficients, int N, int Width, int Height, ScriptNode Node,
                                              FractalZoomScript FractalZoomScript, object State)
        {
            double        RRe             = R.Real;
            double        RIm             = R.Imaginary;
            List <double> AttractorsR     = new List <double>();
            List <double> AttractorsI     = new List <double>();
            List <int>    AttractorColors = new List <int>();

            double[] AttractorsR2 = new double[0];
            double[] AttractorsI2 = new double[0];
            int[]    AttractorsColors2 = new int[0];
            double   r0, i0, r1, i1;
            double   dr, di;
            double   r, i;
            double   zr, zi, zr2, zi2, zr3, zi3, zr4, zi4;
            double   aspect;
            double   Temp;
            int      x, y, b, c = 0, d;
            int      n;
            int      index;
            int      Degree = Coefficients.Length - 1;

            if (Degree < 2)
            {
                Array.Resize <Complex>(ref Coefficients, 3);
                while (Degree < 2)
                {
                    Coefficients[++Degree] = Complex.Zero;
                }
            }

            Complex[] Prim = new Complex[Degree];
            for (x = 1; x <= Degree; x++)
            {
                Prim[x - 1] = x * Coefficients[x];
            }

            Array.Reverse(Prim);
            Coefficients = (Complex[])Coefficients.Clone();
            Array.Reverse(Coefficients);

            int j, e = Prim.Length;

            double[] ReC    = new double[e + 1];
            double[] ImC    = new double[e + 1];
            double[] RePrim = new double[e];
            double[] ImPrim = new double[e];
            Complex  z;

            for (j = 0; j < e; j++)
            {
                z      = Coefficients[j];
                ReC[j] = z.Real;
                ImC[j] = z.Imaginary;

                z         = Prim[j];
                RePrim[j] = z.Real;
                ImPrim[j] = z.Imaginary;
            }

            z      = Coefficients[j];
            ReC[j] = z.Real;
            ImC[j] = z.Imaginary;

            int    size  = Width * Height * 4;
            double Conv  = 1e-10;
            double Div   = 1e10;
            double Conv2 = Conv * 2;

            byte[] rgb = new byte[size];

            rDelta *= 0.5;
            r0      = rCenter - rDelta;
            r1      = rCenter + rDelta;

            aspect = ((double)Width) / Height;

            i0 = iCenter - rDelta / aspect;
            i1 = iCenter + rDelta / aspect;

            dr = (r1 - r0) / Width;
            di = (i1 - i0) / Height;

            for (y = 0, i = i0, index = 0; y < Height; y++, i += di)
            {
                for (x = 0, r = r0; x < Width; x++, r += dr)
                {
                    zr = r;
                    zi = i;

                    n = 0;
                    do
                    {
                        // f:
                        zr2 = zi2 = 0;
                        for (j = 0; j <= e; j++)
                        {
                            Temp = zr2 * zr - zi2 * zi + ReC[j];
                            zi2  = zr2 * zi + zi2 * zr + ImC[j];
                            zr2  = Temp;
                        }

                        // f':
                        zr3 = zi3 = 0;
                        for (j = 0; j < e; j++)
                        {
                            Temp = zr3 * zr - zi3 * zi + RePrim[j];
                            zi3  = zr3 * zi + zi3 * zr + ImPrim[j];
                            zr3  = Temp;
                        }

                        // f/f':

                        Temp = 1.0 / (zr3 * zr3 + zi3 * zi3);
                        zr4  = (zr2 * zr3 + zi2 * zi3) * Temp;
                        zi4  = (zi2 * zr3 - zr2 * zi3) * Temp;

                        // R*f/f'
                        Temp = zr4 * RRe - zi4 * RIm;
                        zi4  = zr4 * RIm + zi4 * RRe;
                        zr4  = Temp;

                        zr -= zr4;
                        zi -= zi4;

                        Temp = Math.Sqrt(zr4 * zr4 + zi4 * zi4);
                    }while ((Temp > Conv) && (Temp < Div) && (n++ < N));

                    if (Temp < Conv && n < N)
                    {
                        for (b = 0; b < c; b++)
                        {
                            if (Math.Abs(AttractorsR2[b] - zr) < Conv2 &&
                                Math.Abs(AttractorsI2[b] - zi) < Conv2)
                            {
                                break;
                            }
                        }

                        if (b == c)
                        {
                            AttractorsR.Add(zr);
                            AttractorsI.Add(zi);

                            int p1 = ~((b % 6) + 1);
                            int p2 = ((b / 6) % 7);

                            int Red   = (p1 & 1) != 0 ? 255 : 0;
                            int Green = (p1 & 2) != 0 ? 255 : 0;
                            int Blue  = (p1 & 4) != 0 ? 255 : 0;

                            if ((p2 & 1) != 0)
                            {
                                Red >>= 1;
                            }

                            if ((p2 & 2) != 0)
                            {
                                Green >>= 1;
                            }

                            if ((p2 & 4) != 0)
                            {
                                Blue >>= 1;
                            }

                            Blue <<= 8;
                            Blue  |= Green;
                            Blue <<= 8;
                            Blue  |= Red;

                            AttractorColors.Add(Blue);

                            AttractorsR2      = AttractorsR.ToArray();
                            AttractorsI2      = AttractorsI.ToArray();
                            AttractorsColors2 = AttractorColors.ToArray();

                            c++;
                        }

                        b = AttractorColors[b];

                        d            = (byte)b;
                        rgb[index++] = (byte)((d * (N - n + 1)) / N);
                        b          >>= 8;
                        d            = (byte)b;
                        rgb[index++] = (byte)((d * (N - n + 1)) / N);
                        b          >>= 8;
                        d            = (byte)b;
                        rgb[index++] = (byte)((d * (N - n + 1)) / N);
                    }
                    else
                    {
                        rgb[index++] = 0;
                        rgb[index++] = 0;
                        rgb[index++] = 0;
                    }

                    rgb[index++] = 255;
                }
            }

            using (SKData Data = SKData.Create(new MemoryStream(rgb)))
            {
                SKImage Bitmap = SKImage.FromPixelData(new SKImageInfo(Width, Height, SKColorType.Bgra8888), Data, Width * 4);
                return(new FractalGraph(Bitmap, r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State));
            }
        }
        public static FractalGraph CalcNewtonSmooth(double rCenter, double iCenter, double rDelta, Complex R,
                                                    ILambdaExpression f, ScriptNode fDef, Variables Variables, SKColor[] Palette, int Width, int Height,
                                                    ScriptNode Node, FractalZoomScript FractalZoomScript, object State)
        {
            double RRe = R.Real;
            double RIm = R.Imaginary;
            double r0, i0, r1, i1;
            double dr, di;
            double r, i;
            double aspect;
            int    x, y;
            int    n, N;

            N = Palette.Length;

            if (Width <= 2 || Height <= 2)
            {
                throw new ScriptRuntimeException("Width and Height has to be greater than 2.", Node);
            }

            Variables v = new Variables();

            Variables.CopyTo(v);

            if (!(f is IDifferentiable Differentiable) ||
                !(Differentiable.Differentiate(Differentiable.DefaultVariableName, v) is ILambdaExpression fPrim))
            {
                throw new ScriptRuntimeException("Lambda expression not differentiable.", Node);
            }

            int    Size = Width * Height;
            double Conv = 1e-10;
            double Div  = 1e10;

            double[] ColorIndex = new double[Size];
            int      Index      = 0;

            Complex[]  Row;
            Complex[]  Row2;
            Complex[]  Row3;
            int[]      Offset;
            IElement[] P = new IElement[1];
            int        j, c, x2;
            IElement   Obj, Obj2;
            double     Mod;
            Complex    z;

            rDelta *= 0.5;
            r0      = rCenter - rDelta;
            r1      = rCenter + rDelta;

            aspect = ((double)Width) / Height;

            i0 = iCenter - rDelta / aspect;
            i1 = iCenter + rDelta / aspect;

            dr = (r1 - r0) / Width;
            di = (i1 - i0) / Height;

            for (y = 0, i = i0; y < Height; y++, i += di)
            {
                Row    = new Complex[Width];
                Offset = new int[Width];

                c = Width;
                for (x = 0, x2 = y * Width, r = r0; x < Width; x++, r += dr, x2++)
                {
                    Row[x]    = new Complex(r, i);
                    Offset[x] = x2;
                }

                n = 0;
                while (n < N && c > 0)
                {
                    n++;
                    P[0] = Expression.Encapsulate(Row);
                    Obj  = f.Evaluate(P, v);
                    Obj2 = fPrim.Evaluate(P, v);
                    Row2 = Obj.AssociatedObjectValue as Complex[];
                    Row3 = Obj2.AssociatedObjectValue as Complex[];

                    if (Row2 is null || Row3 is null)
                    {
                        throw new ScriptRuntimeException("Lambda expression (and its first derivative) must be able to accept complex vectors, " +
                                                         "and return complex vectors of equal length. Type returned: " +
                                                         Obj.GetType().FullName + " and " + Obj2.GetType().FullName, Node);
                    }
Exemple #12
0
        public static FractalGraph CalcIfs(double xCenter, double yCenter, double rDelta, long N,
                                           ILambdaExpression[] Functions, double[] Weights, SKColor[] Colors, int Width, int Height, int Seed,
                                           ScriptNode Node, Variables Variables, FractalZoomScript FractalZoomScript, object State)
        {
            ILambdaExpression Lambda;
            double            TotWeight = 0;
            double            Weight;

            bool[]  Real;
            byte[]  Reds;
            byte[]  Greens;
            byte[]  Blues;
            SKColor cl;
            int     i, c = Functions.Length;
            Random  Gen = new Random(Seed);

            if (c < 2)
            {
                throw new ScriptRuntimeException("At least two transformations need to be provided.", Node);
            }

            if (Weights.Length != c)
            {
                throw new ArgumentException("Weights must be of equal length as Functions.", "Weights");
            }

            if (Colors.Length != c)
            {
                throw new ArgumentException("Colors must be of equal length as Functions.", "Colors");
            }

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

                Weights[i] += TotWeight;
                TotWeight  += Weight;
            }

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

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

            Real   = new bool[c];
            Reds   = new byte[c];
            Greens = new byte[c];
            Blues  = new byte[c];

            for (i = 0; i < c; i++)
            {
                cl        = Colors[i];
                Reds[i]   = cl.Red;
                Greens[i] = cl.Green;
                Blues[i]  = cl.Blue;

                Lambda = Functions[i];

                switch (Lambda.NrArguments)
                {
                case 1:
                    Real[i] = false;
                    break;

                case 2:
                    Real[i] = true;
                    break;

                default:
                    throw new ScriptRuntimeException("Lambda expressions in calls to IfsFractal() must be either real-values (taking two parameters) or complex valued (taking one parameter).", Node);
                }
            }

            int size = Width * Height * 4;

            byte[] rgb = new byte[size];

            double        AspectRatio = ((double)Width) / Height;
            double        x           = Gen.NextDouble();
            double        y           = Gen.NextDouble();
            int           j;
            double        xMin, xMax, yMin, yMax;
            double        sx, sy;
            DoubleNumber  xv = new DoubleNumber(0);
            DoubleNumber  yv = new DoubleNumber(0);
            ComplexNumber zv = new ComplexNumber(0);

            IElement[] RealParameters    = new IElement[] { xv, yv };
            IElement[] ComplexParameters = new IElement[] { zv };
            Variables  v = new Variables();
            int        xi, yi;

            Variables.CopyTo(v);

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

            sx = Width / (xMax - xMin);
            sy = Height / (yMax - yMin);

            Complex z;

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

                Lambda = Functions[j];

                if (Real[j])
                {
                    xv.Value = x;
                    yv.Value = y;

                    if (!(Lambda.Evaluate(RealParameters, v) is IVector Result) || Result.Dimension != 2)
                    {
                        throw new ScriptRuntimeException("Expected 2-dimensional numeric vector as a result.", Node);
                    }

                    x = Expression.ToDouble(Result.GetElement(0).AssociatedObjectValue);
                    y = Expression.ToDouble(Result.GetElement(1).AssociatedObjectValue);
                }
                else
                {
                    zv.Value = new Complex(x, y);
                    z        = Expression.ToComplex(Lambda.Evaluate(ComplexParameters, v).AssociatedObjectValue);

                    x = z.Real;
                    y = z.Imaginary;
                }
            }

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

                Lambda = Functions[j];

                if (Real[j])
                {
                    xv.Value = x;
                    yv.Value = y;

                    if (!(Lambda.Evaluate(RealParameters, v) is IVector Result) || Result.Dimension != 2)
                    {
                        throw new ScriptRuntimeException("Expected 2-dimensional numeric vector as a result.", Node);
                    }

                    x = Expression.ToDouble(Result.GetElement(0).AssociatedObjectValue);
                    y = Expression.ToDouble(Result.GetElement(1).AssociatedObjectValue);
                }
                else
                {
                    zv.Value = new Complex(x, y);
                    z        = Expression.ToComplex(Lambda.Evaluate(ComplexParameters, v).AssociatedObjectValue);

                    x = z.Real;
                    y = z.Imaginary;
                }

                if (x < xMin || x > xMax || y < yMin || y > yMax)
                {
                    continue;
                }

                xi = (int)((x - xMin) * sx + 0.5);
                yi = Height - 1 - (int)((y - yMin) * sy + 0.5);

                if (xi < 0 || xi >= Width || yi < 0 || yi >= Height)
                {
                    continue;
                }

                i = (yi * Width + xi) << 2;

                if (rgb[i + 3] == 0)
                {
                    rgb[i++] = Blues[j];
                    rgb[i++] = Greens[j];
                    rgb[i++] = Reds[j];
                    rgb[i]   = 0xff;
                }
                else
                {
                    rgb[i] = (byte)((rgb[i] + Blues[j]) >> 1);
                    i++;
                    rgb[i] = (byte)((rgb[i] + Greens[j]) >> 1);
                    i++;
                    rgb[i] = (byte)((rgb[i] + Reds[j]) >> 1);
                }
            }

            using (SKData Data = SKData.Create(new MemoryStream(rgb)))
            {
                SKImage Bitmap = SKImage.FromPixelData(new SKImageInfo(Width, Height, SKColorType.Bgra8888), Data, Width * 4);
                return(new FractalGraph(Bitmap, xMin, yMin, xMax, yMax, rDelta, false, Node, FractalZoomScript, State));
            }
        }
Exemple #13
0
        public static FractalGraph CalcIfs(double xCenter, double yCenter, double rDelta, long N,
                                           DoubleMatrix[] Functions, double[] Weights, SKColor[] Colors, int Width, int Height, int Seed,
                                           ScriptNode Node, FractalZoomScript FractalZoomScript, object State)
        {
            DoubleMatrix M;

            double[,] E;
            double[][] Coefficients;
            double     TotWeight = 0;
            double     Weight;
            SKColor    cl;

            byte[] Reds;
            byte[] Greens;
            byte[] Blues;
            int    i, c = Functions.Length;
            Random Gen = new Random(Seed);

            if (c < 2)
            {
                throw new ScriptRuntimeException("At least two transformations need to be provided.", Node);
            }

            if (Weights.Length != c)
            {
                throw new ArgumentException("Weights must be of equal length as Functions.", "Weights");
            }

            if (Colors.Length != c)
            {
                throw new ArgumentException("Colors must be of equal length as Functions.", "Colors");
            }

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

                Weights[i] += TotWeight;
                TotWeight  += Weight;
            }

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

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

            Coefficients = new double[c][];
            Reds         = new byte[c];
            Greens       = new byte[c];
            Blues        = new byte[c];

            for (i = 0; i < c; i++)
            {
                cl        = Colors[i];
                Reds[i]   = cl.Red;
                Greens[i] = cl.Green;
                Blues[i]  = cl.Blue;

                M = Functions[i];
                E = M.Values;

                if (M.Columns == 2 && M.Rows == 2)
                {
                    Coefficients[i] = new double[]
                    {
                        (double)E[0, 0], (double)E[0, 1], 0,
                        (double)E[1, 0], (double)E[1, 1], 0,
                        0, 0, 1
                    };
                }
                else if (M.Columns == 3 && M.Rows == 3)
                {
                    Coefficients[i] = new double[]
                    {
                        (double)E[0, 0], (double)E[0, 1], (double)E[0, 2],
                        (double)E[1, 0], (double)E[1, 1], (double)E[1, 2],
                        (double)E[2, 0], (double)E[2, 1], (double)E[2, 2]
                    };
                }
                else
                {
                    throw new ScriptRuntimeException("Matrix not a linear 2D-transformation or a homogenous 2D-transformation.", Node);
                }
            }

            int size = Width * Height * 4;

            byte[] rgb = new byte[size];

            double AspectRatio = ((double)Width) / Height;
            double x = Gen.NextDouble();
            double y = Gen.NextDouble();
            double p = 1;
            double x2, y2, p2;

            double[] C;
            int      j;
            double   xMin, xMax, yMin, yMax;
            double   sx, sy;
            int      xi, yi;

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

            sx = Width / (xMax - xMin);
            sy = Height / (yMax - yMin);

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

                C = Coefficients[j];

                x2 = C[0] * x + C[1] * y + C[2] * p;
                y2 = C[3] * x + C[4] * y + C[5] * p;
                p2 = C[6] * x + C[7] * y + C[8] * p;

                x = x2;
                y = y2;
                p = p2;
            }

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

                C = Coefficients[j];

                x2 = C[0] * x + C[1] * y + C[2] * p;
                y2 = C[3] * x + C[4] * y + C[5] * p;
                p2 = C[6] * x + C[7] * y + C[8] * p;

                x = x2;
                y = y2;
                p = p2;

                if (p == 0)
                {
                    break;
                }

                if (x < xMin || x > xMax || y < yMin || y > yMax)
                {
                    continue;
                }

                xi = (int)((x / p - xMin) * sx + 0.5);
                yi = Height - 1 - (int)((y / p - yMin) * sy + 0.5);

                if (xi < 0 || xi >= Width || yi < 0 || yi >= Height)
                {
                    continue;
                }

                i = (yi * Width + xi) << 2;

                if (rgb[i + 3] == 0)
                {
                    rgb[i++] = Blues[j];
                    rgb[i++] = Greens[j];
                    rgb[i++] = Reds[j];
                    rgb[i]   = 0xff;
                }
                else
                {
                    rgb[i] = (byte)((rgb[i] + Blues[j]) >> 1);
                    i++;
                    rgb[i] = (byte)((rgb[i] + Greens[j]) >> 1);
                    i++;
                    rgb[i] = (byte)((rgb[i] + Reds[j]) >> 1);
                }
            }

            using (SKData Data = SKData.Create(new MemoryStream(rgb)))
            {
                SKImage Bitmap = SKImage.FromPixelData(new SKImageInfo(Width, Height, SKColorType.Bgra8888), Data, Width * 4);
                return(new FractalGraph(Bitmap, xMin, yMin, xMax, yMax, rDelta, false, Node, FractalZoomScript, State));
            }
        }
Exemple #14
0
        public static FractalGraph CalcNovaMandelbrot(double rCenter, double iCenter, double rDelta, double Rr, double Ri,
                                                      double pr, double pi, SKColor[] Palette, int Width, int Height, ScriptNode Node,
                                                      FractalZoomScript FractalZoomScript, object State)
        {
            byte[]  reds;
            byte[]  greens;
            byte[]  blues;
            double  r0, i0, r1, i1;
            double  dr, di;
            double  r, i;
            double  zr, zi, zr2, zi2, zr3, zi3, zr4, zi4;
            double  aspect;
            double  Temp;
            int     x, y;
            int     n, N;
            int     index;
            SKColor cl;
            double  lnz;
            double  argz;
            double  amp;
            double  phi;

            N      = Palette.Length;
            reds   = new byte[N];
            greens = new byte[N];
            blues  = new byte[N];

            for (x = 0; x < N; x++)
            {
                cl        = Palette[x];
                reds[x]   = cl.Red;
                greens[x] = cl.Green;
                blues[x]  = cl.Blue;
            }

            int    size = Width * Height * 4;
            double Conv = 1e-10;
            double Div  = 1e10;

            byte[] rgb = new byte[size];

            rDelta *= 0.5;
            r0      = rCenter - rDelta;
            r1      = rCenter + rDelta;

            aspect = ((double)Width) / Height;

            i0 = iCenter - rDelta / aspect;
            i1 = iCenter + rDelta / aspect;

            dr = (r1 - r0) / Width;
            di = (i1 - i0) / Height;

            for (y = 0, i = i0, index = 0; y < Height; y++, i += di)
            {
                for (x = 0, r = r0; x < Width; x++, r += dr)
                {
                    zr = r;
                    zi = i;

                    n = 0;
                    do
                    {
                        // f: z->z^p-1 = exp(p*ln(z))-1
                        // exp(a+ib)=exp(a)*(cos(b)+i*sin(b))
                        // ln(z)=ln|z|+i*arg(z)
                        // exp(p*ln(z))-1 =
                        // = exp((pr+i*pi)*(ln|z|+i*arg(z)))-1 =
                        // = exp(pr*ln|z|-pi*arg(z)+i*(pi*ln|z|+pr*arg(z)))-1 =
                        // = exp(pr*ln|z|-pi*arg(z))*(cos(pi*ln|z|+pr*arg(z))+i*sin(pi*ln|z|+pr*arg(z)))-1

                        lnz  = System.Math.Log(Math.Sqrt(zr * zr + zi * zi));
                        argz = System.Math.Atan2(zi, zr);
                        amp  = System.Math.Exp(pr * lnz - pi * argz);
                        phi  = pi * lnz + pr * argz;

                        zr2 = amp * System.Math.Cos(phi) - 1;
                        zi2 = amp * System.Math.Sin(phi);

                        // f': z->p*z^(p-1) = p*exp((p-1)*ln(z)) =
                        // = (pr+i*pi)*exp((pr-1+i*pi)*(ln|z|+i*arg(z))) =
                        // = (pr+i*pi)*exp((pr-1)*ln|z|-pi*arg(z)+i*(pi*ln|z|+(pr-1)*arg(z))) =
                        // = (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))) =

                        amp = System.Math.Exp((pr - 1) * lnz - pi * argz);
                        phi = pi * lnz + (pr - 1) * argz;

                        zr3 = amp * System.Math.Cos(phi);
                        zi3 = amp * System.Math.Sin(phi);

                        Temp = pr * zr3 - pi * zi3;
                        zi3  = pr * zi3 + pi * zr3;
                        zr3  = Temp;

                        // f/f':

                        Temp = 1.0 / (zr3 * zr3 + zi3 * zi3);
                        zr4  = (zr2 * zr3 + zi2 * zi3) * Temp;
                        zi4  = (zi2 * zr3 - zr2 * zi3) * Temp;

                        Temp = Rr * zr4 - Ri * zi4;
                        zi4  = Ri * zr4 + Rr * zi4 + i;
                        zr4  = Temp + r;

                        zr -= zr4;
                        zi -= zi4;

                        Temp = Math.Sqrt(zr4 * zr4 + zi4 * zi4);
                    }while ((Temp > Conv) && (Temp < Div) && (n++ < N));

                    if (Temp < Conv && n < N)
                    {
                        rgb[index++] = blues[n];
                        rgb[index++] = greens[n];
                        rgb[index++] = reds[n];
                    }
                    else
                    {
                        rgb[index++] = 0;
                        rgb[index++] = 0;
                        rgb[index++] = 0;
                    }

                    rgb[index++] = 255;
                }
            }

            using (SKData Data = SKData.Create(new MemoryStream(rgb)))
            {
                SKImage Bitmap = SKImage.FromPixelData(new SKImageInfo(Width, Height, SKColorType.Bgra8888), Data, Width * 4);
                return(new FractalGraph(Bitmap, r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State));
            }
        }
        public static FractalGraph CalcJulia(double rCenter, double iCenter, double R0, double I0, double rDelta,
                                             SKColor[] Palette, int Width, int Height, ScriptNode Node, Variables Variables,
                                             FractalZoomScript FractalZoomScript, object State)
        {
            double r0, i0, r1, i1;
            double dr, di;
            double r, i;
            double zr, zi, zrt, zr2, zi2;
            double aspect;
            int    x, y;
            int    n, N;
            int    index;

            N = Palette.Length;

            rDelta *= 0.5;
            r0      = rCenter - rDelta;
            r1      = rCenter + rDelta;

            aspect = ((double)Width) / Height;

            i0 = iCenter - rDelta / aspect;
            i1 = iCenter + rDelta / aspect;

            dr = (r1 - r0) / Width;
            di = (i1 - i0) / Height;

            int Size = Width * Height;

            double[] ColorIndex = new double[Size];

            for (y = 0, i = i0, index = 0; y < Height; y++, i += di)
            {
                for (x = 0, r = r0; x < Width; x++, r += dr)
                {
                    zr = r;
                    zi = i;

                    n   = 0;
                    zr2 = zr * zr;
                    zi2 = zi * zi;

                    while (zr2 + zi2 < 9 && n < N)
                    {
                        n++;
                        zrt = zr2 - zi2 + R0;
                        zi  = 2 * zr * zi + I0;
                        zr  = zrt;

                        zr2 = zr * zr;
                        zi2 = zi * zi;
                    }

                    if (n >= N)
                    {
                        ColorIndex[index++] = N;
                    }
                    else
                    {
                        ColorIndex[index++] = n;
                    }
                }
            }

            Node.Expression.Preview(new GraphBitmap(FractalGraph.ToBitmap(ColorIndex, Width, Height, Palette)));

            double[] Boundary = FractalGraph.FindBoundaries(ColorIndex, Width, Height);
            FractalGraph.Smooth(ColorIndex, Boundary, Width, Height, N, Palette, Node, Variables);

            return(new FractalGraph(FractalGraph.ToBitmap(ColorIndex, Width, Height, Palette),
                                    r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State));
        }
Exemple #16
0
        public static FractalGraph CalcJulia(double rCenter, double iCenter, double R0, double I0, double rDelta,
                                             SKColor[] Palette, int Width, int Height, ScriptNode Node,
                                             FractalZoomScript FractalZoomScript, object State)
        {
            byte[]  reds;
            byte[]  greens;
            byte[]  blues;
            double  r0, i0, r1, i1;
            double  dr, di;
            double  r, i;
            double  zr, zi, zrt, zr2, zi2;
            double  aspect;
            int     x, y;
            int     n, N;
            int     index;
            SKColor cl;

            N      = Palette.Length;
            reds   = new byte[N];
            greens = new byte[N];
            blues  = new byte[N];

            for (x = 0; x < N; x++)
            {
                cl        = Palette[x];
                reds[x]   = cl.Red;
                greens[x] = cl.Green;
                blues[x]  = cl.Blue;
            }

            int size = Width * Height * 4;

            byte[] rgb = new byte[size];

            rDelta *= 0.5;
            r0      = rCenter - rDelta;
            r1      = rCenter + rDelta;

            aspect = ((double)Width) / Height;

            i0 = iCenter - rDelta / aspect;
            i1 = iCenter + rDelta / aspect;

            dr = (r1 - r0) / Width;
            di = (i1 - i0) / Height;

            for (y = 0, i = i0, index = 0; y < Height; y++, i += di)
            {
                for (x = 0, r = r0; x < Width; x++, r += dr)
                {
                    zr = r;
                    zi = i;

                    n   = 0;
                    zr2 = zr * zr;
                    zi2 = zi * zi;

                    while (zr2 + zi2 < 9 && n < N)
                    {
                        n++;
                        zrt = zr2 - zi2 + R0;
                        zi  = 2 * zr * zi + I0;
                        zr  = zrt;

                        zr2 = zr * zr;
                        zi2 = zi * zi;
                    }

                    if (n >= N)
                    {
                        rgb[index++] = 0;
                        rgb[index++] = 0;
                        rgb[index++] = 0;
                    }
                    else
                    {
                        rgb[index++] = blues[n];
                        rgb[index++] = greens[n];
                        rgb[index++] = reds[n];
                    }

                    rgb[index++] = 255;
                }
            }

            using (SKData Data = SKData.Create(new MemoryStream(rgb)))
            {
                SKImage Bitmap = SKImage.FromPixelData(new SKImageInfo(Width, Height, SKColorType.Bgra8888), Data, Width * 4);
                return(new FractalGraph(Bitmap, r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State));
            }
        }
        public static FractalGraph CalcJulia(double rCenter, double iCenter, ILambdaExpression f,
                                             ScriptNode fDef, double rDelta, SKColor[] Palette, int Width, int Height, ScriptNode Node,
                                             Variables Variables, FractalZoomScript FractalZoomScript, object State)
        {
            double r0, i0, r1, i1;
            double dr, di;
            double r, i;
            double aspect;
            int    x, y;
            int    n, N;

            N = Palette.Length;

            rDelta *= 0.5;
            r0      = rCenter - rDelta;
            r1      = rCenter + rDelta;

            aspect = ((double)Width) / Height;

            i0 = iCenter - rDelta / aspect;
            i1 = iCenter + rDelta / aspect;

            dr = (r1 - r0) / Width;
            di = (i1 - i0) / Height;

            int Size = Width * Height;

            double[] ColorIndex = new double[Size];
            int      c, j, x2;
            Complex  z;

            IElement[] P = new IElement[1];
            IElement   Obj;
            double     Mod;

            for (y = 0, i = i0; y < Height; y++, i += di)
            {
                Complex[] Row    = new Complex[Width];
                int[]     Offset = new int[Width];

                c = Width;
                for (x = 0, x2 = y * Width, r = r0; x < Width; x++, r += dr, x2++)
                {
                    Row[x]    = new Complex(r, i);
                    Offset[x] = x2;
                }

                n = 0;
                while (n < N && c > 0)
                {
                    n++;
                    P[0] = Expression.Encapsulate(Row);
                    Obj  = f.Evaluate(P, Variables);
                    Row  = Obj.AssociatedObjectValue as Complex[];

                    if (Row == null)
                    {
                        throw new ScriptRuntimeException("Lambda expression must be able to accept complex vectors, " +
                                                         "and return complex vectors of equal length. Type returned: " +
                                                         Obj.GetType().FullName, Node);
                    }
                    else if (Row.Length != c)
                    {
                        throw new ScriptRuntimeException("Lambda expression must be able to accept complex vectors, " +
                                                         "and return complex vectors of equal length. Length returned: " +
                                                         Row.Length.ToString() + ". Expected: " + c.ToString(), Node);
                    }

                    for (x = x2 = 0; x < c; x++)
                    {
                        z = Row[x];
                        j = Offset[x];

                        Mod = z.Magnitude;

                        if (Mod < 3)
                        {
                            if (x != x2)
                            {
                                Row[x2]    = z;
                                Offset[x2] = j;
                            }

                            x2++;
                        }
                        else
                        {
                            ColorIndex[j++] = n;
                        }
                    }

                    if (x2 < x)
                    {
                        Array.Resize <Complex>(ref Row, x2);
                        Array.Resize <int>(ref Offset, x2);
                        c = x2;
                    }
                }

                if (c > 0)
                {
                    for (x = 0; x < c; x++)
                    {
                        j             = Offset[x];
                        ColorIndex[j] = N;
                    }
                }
            }

            Node.Expression.Preview(new GraphBitmap(FractalGraph.ToBitmap(ColorIndex, Width, Height, Palette)));

            double[] Boundary = FractalGraph.FindBoundaries(ColorIndex, Width, Height);
            FractalGraph.Smooth(ColorIndex, Boundary, Width, Height, N, Palette, Node, Variables);

            return(new FractalGraph(FractalGraph.ToBitmap(ColorIndex, Width, Height, Palette),
                                    r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State));
        }
        public static FractalGraph CalcNewtonSmooth(double rCenter, double iCenter, double rDelta, Complex R,
                                                    Complex[] Coefficients, SKColor[] Palette, int Width, int Height, ScriptNode Node, Variables Variables,
                                                    FractalZoomScript FractalZoomScript, object State)
        {
            double RRe = R.Real;
            double RIm = R.Imaginary;
            double r0, i0, r1, i1;
            double dr, di;
            double r, i;
            double zr, zi, zr2, zi2, zr3, zi3, zr4, zi4;
            double aspect;
            double Temp;
            int    x, y;
            int    n, N;
            int    Degree = Coefficients.Length - 1;

            N = Palette.Length;

            if (Degree < 2)
            {
                Array.Resize <Complex>(ref Coefficients, 3);
                while (Degree < 2)
                {
                    Coefficients[++Degree] = Complex.Zero;
                }
            }

            if (Width <= 2 || Height <= 2)
            {
                throw new ScriptRuntimeException("Width and Height has to be greater than 2.", Node);
            }

            Complex[] Prim = new Complex[Degree];
            for (x = 1; x <= Degree; x++)
            {
                Prim[x - 1] = x * Coefficients[x];
            }

            Array.Reverse(Prim);
            Coefficients = (Complex[])Coefficients.Clone();
            Array.Reverse(Coefficients);

            int j, c = Prim.Length;

            double[] ReC    = new double[c + 1];
            double[] ImC    = new double[c + 1];
            double[] RePrim = new double[c];
            double[] ImPrim = new double[c];
            Complex  z;

            for (j = 0; j < c; j++)
            {
                z      = Coefficients[j];
                ReC[j] = z.Real;
                ImC[j] = z.Imaginary;

                z         = Prim[j];
                RePrim[j] = z.Real;
                ImPrim[j] = z.Imaginary;
            }

            z      = Coefficients[j];
            ReC[j] = z.Real;
            ImC[j] = z.Imaginary;

            int    Size = Width * Height;
            double Conv = 1e-10;
            double Div  = 1e10;

            double[] ColorIndex = new double[Size];
            int      Index      = 0;

            rDelta *= 0.5;
            r0      = rCenter - rDelta;
            r1      = rCenter + rDelta;

            aspect = ((double)Width) / Height;

            i0 = iCenter - rDelta / aspect;
            i1 = iCenter + rDelta / aspect;

            dr = (r1 - r0) / Width;
            di = (i1 - i0) / Height;

            for (y = 0, i = i0; y < Height; y++, i += di)
            {
                for (x = 0, r = r0; x < Width; x++, r += dr)
                {
                    zr = r;
                    zi = i;

                    n = 0;
                    do
                    {
                        // f:
                        zr2 = zi2 = 0;
                        for (j = 0; j <= c; j++)
                        {
                            Temp = zr2 * zr - zi2 * zi + ReC[j];
                            zi2  = zr2 * zi + zi2 * zr + ImC[j];
                            zr2  = Temp;
                        }

                        // f':
                        zr3 = zi3 = 0;
                        for (j = 0; j < c; j++)
                        {
                            Temp = zr3 * zr - zi3 * zi + RePrim[j];
                            zi3  = zr3 * zi + zi3 * zr + ImPrim[j];
                            zr3  = Temp;
                        }

                        // f/f':

                        Temp = 1.0 / (zr3 * zr3 + zi3 * zi3);
                        zr4  = (zr2 * zr3 + zi2 * zi3) * Temp;
                        zi4  = (zi2 * zr3 - zr2 * zi3) * Temp;

                        // R*f/f'
                        Temp = zr4 * RRe - zi4 * RIm;
                        zi4  = zr4 * RIm + zi4 * RRe;
                        zr4  = Temp;

                        zr -= zr4;
                        zi -= zi4;

                        Temp = Math.Sqrt(zr4 * zr4 + zi4 * zi4);
                    }while ((Temp > Conv) && (Temp < Div) && (n++ < N));

                    if (Temp < Conv && n < N)
                    {
                        ColorIndex[Index++] = n;
                    }
                    else
                    {
                        ColorIndex[Index++] = N;
                    }
                }
            }

            Node.Expression.Preview(new GraphBitmap(FractalGraph.ToBitmap(ColorIndex, Width, Height, Palette)));

            double[] Boundary = FractalGraph.FindBoundaries(ColorIndex, Width, Height);
            FractalGraph.Smooth(ColorIndex, Boundary, Width, Height, N, Palette, Node, Variables);

            return(new FractalGraph(FractalGraph.ToBitmap(ColorIndex, Width, Height, Palette),
                                    r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State));
        }
Exemple #19
0
        public static FractalGraph CalcHalley(double rCenter, double iCenter, double rDelta, Complex R,
                                              Complex[] Coefficients, SKColor[] Palette, int Width, int Height, ScriptNode Node,
                                              FractalZoomScript FractalZoomScript, object State)
        {
            double RRe = R.Real;
            double RIm = R.Imaginary;
            double r0, i0, r1, i1;
            double dr, di;
            double r, i;
            double zr, zi, zr2, zi2, zr3, zi3, zr4, zi4, zr5, zi5, zr6, zi6;
            double aspect;
            double Temp;
            int    x, y;
            int    n, N;
            int    index;
            int    Degree = Coefficients.Length - 1;

            N = Palette.Length;

            if (Degree < 3)
            {
                Array.Resize <Complex>(ref Coefficients, 4);
                while (Degree < 3)
                {
                    Coefficients[++Degree] = Complex.Zero;
                }
            }

            Complex[] Prim = new Complex[Degree];
            for (x = 1; x <= Degree; x++)
            {
                Prim[x - 1] = x * Coefficients[x];
            }

            Complex[] Bis = new Complex[Degree - 1];
            for (x = 1; x < Degree; x++)
            {
                Bis[x - 1] = x * Prim[x];
            }

            Array.Reverse(Bis);
            Array.Reverse(Prim);
            Coefficients = (Complex[])Coefficients.Clone();
            Array.Reverse(Coefficients);

            int j, c = Prim.Length;
            int c2 = c - 1;

            double[] ReC    = new double[c + 1];
            double[] ImC    = new double[c + 1];
            double[] RePrim = new double[c];
            double[] ImPrim = new double[c];
            double[] ReBis  = new double[c2];
            double[] ImBis  = new double[c2];
            Complex  z;

            for (j = 0; j < c; j++)
            {
                z      = Coefficients[j];
                ReC[j] = z.Real;
                ImC[j] = z.Imaginary;

                z         = Prim[j];
                RePrim[j] = z.Real;
                ImPrim[j] = z.Imaginary;

                if (j < c2)
                {
                    z        = Bis[j];
                    ReBis[j] = z.Real;
                    ImBis[j] = z.Imaginary;
                }
            }

            z      = Coefficients[j];
            ReC[j] = z.Real;
            ImC[j] = z.Imaginary;

            int size = Width * Height;

            int[]  ColorIndex = new int[size];
            double Conv       = 1e-10;
            double Div        = 1e10;

            rDelta *= 0.5;
            r0      = rCenter - rDelta;
            r1      = rCenter + rDelta;

            aspect = ((double)Width) / Height;

            i0 = iCenter - rDelta / aspect;
            i1 = iCenter + rDelta / aspect;

            dr = (r1 - r0) / Width;
            di = (i1 - i0) / Height;

            for (y = 0, i = i0, index = 0; y < Height; y++, i += di)
            {
                for (x = 0, r = r0; x < Width; x++, r += dr)
                {
                    zr = r;
                    zi = i;

                    n = 0;
                    do
                    {
                        // f:
                        zr2 = zi2 = 0;
                        for (j = 0; j <= c; j++)
                        {
                            Temp = zr2 * zr - zi2 * zi + ReC[j];
                            zi2  = zr2 * zi + zi2 * zr + ImC[j];
                            zr2  = Temp;
                        }

                        // f':
                        zr3 = zi3 = 0;
                        for (j = 0; j < c; j++)
                        {
                            Temp = zr3 * zr - zi3 * zi + RePrim[j];
                            zi3  = zr3 * zi + zi3 * zr + ImPrim[j];
                            zr3  = Temp;
                        }

                        // f":
                        zr4 = zi4 = 0;
                        for (j = 0; j < c2; j++)
                        {
                            Temp = zr4 * zr - zi4 * zi + ReBis[j];
                            zi4  = zr4 * zi + zi4 * zr + ImBis[j];
                            zr4  = Temp;
                        }

                        // 2*f*f'

                        zr5 = 2 * (zr2 * zr3 - zi2 * zi3);
                        zi5 = 2 * (zr2 * zi3 + zi2 * zr3);

                        // 2f'^2-f*f"

                        zr6 = 2 * (zr3 * zr3 - zi3 * zi3) - (zr2 * zr4 - zi2 * zi4);
                        zi6 = 4 * zr3 * zi3 - (zr2 * zi4 + zr4 * zi2);

                        // R*2*f*f'/2f'^2-f*f"

                        Temp = 1.0 / (zr6 * zr6 + zi6 * zi6);
                        zr4  = (zr5 * zr6 + zi5 * zi6) * Temp;
                        zi4  = (zi5 * zr6 - zr5 * zi6) * Temp;

                        // R*2*f*f'/(2f'^2-f*f")
                        Temp = zr4 * RRe - zi4 * RIm;
                        zi4  = zr4 * RIm + zi4 * RRe;
                        zr4  = Temp;

                        zr -= zr4;
                        zi -= zi4;

                        Temp = Math.Sqrt(zr4 * zr4 + zi4 * zi4);
                    }while ((Temp > Conv) && (Temp < Div) && (n++ < N));

                    if (Temp < Conv && n < N)
                    {
                        ColorIndex[index++] = n;
                    }
                    else
                    {
                        ColorIndex[index++] = N;
                    }
                }
            }

            ColorIndex = FractalGraph.FindBoundaries(ColorIndex, Width, Height);

            return(new FractalGraph(FractalGraph.ToBitmap(ColorIndex, Width, Height, Palette),
                                    r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State));
        }
Exemple #20
0
        public static FractalGraph CalcNovaJulia(double rCenter, double iCenter, double R0, double I0,
                                                 double rDelta, double Rr, double Ri, double pr, double pi, SKColor[] Palette,
                                                 int Width, int Height, ScriptNode Node, Variables Variables,
                                                 FractalZoomScript FractalZoomScript, object State)
        {
            double r0, i0, r1, i1;
            double dr, di;
            double r, i;
            double zr, zi, zr2, zi2, zr3, zi3, zr4, zi4;
            double aspect;
            double Temp;
            int    x, y;
            int    n, N;
            int    index;
            double lnz;
            double argz;
            double amp;
            double phi;

            N = Palette.Length;

            int Size = Width * Height;

            double[] ColorIndex = new double[Size];
            double   Conv       = 1e-10;
            double   Div        = 1e10;

            rDelta *= 0.5;
            r0      = rCenter - rDelta;
            r1      = rCenter + rDelta;

            aspect = ((double)Width) / Height;

            i0 = iCenter - rDelta / aspect;
            i1 = iCenter + rDelta / aspect;

            dr = (r1 - r0) / Width;
            di = (i1 - i0) / Height;

            for (y = 0, i = i0, index = 0; y < Height; y++, i += di)
            {
                for (x = 0, r = r0; x < Width; x++, r += dr)
                {
                    zr = r;
                    zi = i;

                    n = 0;
                    do
                    {
                        // f: z->z^p-1 = exp(p*ln(z))-1
                        // exp(a+ib)=exp(a)*(cos(b)+i*sin(b))
                        // ln(z)=ln|z|+i*arg(z)
                        // exp(p*ln(z))-1 =
                        // = exp((pr+i*pi)*(ln|z|+i*arg(z)))-1 =
                        // = exp(pr*ln|z|-pi*arg(z)+i*(pi*ln|z|+pr*arg(z)))-1 =
                        // = exp(pr*ln|z|-pi*arg(z))*(cos(pi*ln|z|+pr*arg(z))+i*sin(pi*ln|z|+pr*arg(z)))-1

                        lnz  = System.Math.Log(Math.Sqrt(zr * zr + zi * zi));
                        argz = System.Math.Atan2(zi, zr);
                        amp  = System.Math.Exp(pr * lnz - pi * argz);
                        phi  = pi * lnz + pr * argz;

                        zr2 = amp * System.Math.Cos(phi) - 1;
                        zi2 = amp * System.Math.Sin(phi);

                        // f': z->p*z^(p-1) = p*exp((p-1)*ln(z)) =
                        // = (pr+i*pi)*exp((pr-1+i*pi)*(ln|z|+i*arg(z))) =
                        // = (pr+i*pi)*exp((pr-1)*ln|z|-pi*arg(z)+i*(pi*ln|z|+(pr-1)*arg(z))) =
                        // = (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))) =

                        amp = System.Math.Exp((pr - 1) * lnz - pi * argz);
                        phi = pi * lnz + (pr - 1) * argz;

                        zr3 = amp * System.Math.Cos(phi);
                        zi3 = amp * System.Math.Sin(phi);

                        Temp = pr * zr3 - pi * zi3;
                        zi3  = pr * zi3 + pi * zr3;
                        zr3  = Temp;

                        // f/f':

                        Temp = 1.0 / (zr3 * zr3 + zi3 * zi3);
                        zr4  = (zr2 * zr3 + zi2 * zi3) * Temp;
                        zi4  = (zi2 * zr3 - zr2 * zi3) * Temp;

                        Temp = Rr * zr4 - Ri * zi4;
                        zi4  = Ri * zr4 + Rr * zi4 + I0;
                        zr4  = Temp + R0;

                        zr -= zr4;
                        zi -= zi4;

                        Temp = Math.Sqrt(zr4 * zr4 + zi4 * zi4);
                    }while ((Temp > Conv) && (Temp < Div) && (n++ < N));

                    if (Temp < Conv && n < N)
                    {
                        ColorIndex[index++] = n;
                    }
                    else
                    {
                        ColorIndex[index++] = N;
                    }
                }
            }

            Node.Expression.Preview(new GraphBitmap(FractalGraph.ToBitmap(ColorIndex, Width, Height, Palette)));

            double[] Boundary = FractalGraph.FindBoundaries(ColorIndex, Width, Height);
            FractalGraph.Smooth(ColorIndex, Boundary, Width, Height, N, Palette, Node, Variables);

            return(new FractalGraph(FractalGraph.ToBitmap(ColorIndex, Width, Height, Palette),
                                    r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State));
        }
        public static FractalGraph CalcNewton(double rCenter, double iCenter, double rDelta, Complex R,
                                              ILambdaExpression f, ScriptNode fDef, Variables Variables, int N, int Width, int Height,
                                              ScriptNode Node, FractalZoomScript FractalZoomScript, object State)
        {
            double        RRe             = R.Real;
            double        RIm             = R.Imaginary;
            List <double> AttractorsR     = new List <double>();
            List <double> AttractorsI     = new List <double>();
            List <int>    AttractorColors = new List <int>();

            double[] AttractorsR2 = new double[0];
            double[] AttractorsI2 = new double[0];
            int[]    AttractorsColors2 = new int[0];
            double   r0, i0, r1, i1;
            double   dr, di;
            double   r, i;
            double   zr, zi;
            double   aspect;
            int      x, y, b, c, d;
            int      NrAttractors = 0;
            int      n;
            int      index;

            Variables v = new Variables();

            Variables.CopyTo(v);

            if (!(f is IDifferentiable Differentiable) ||
                !(Differentiable.Differentiate(Differentiable.DefaultVariableName, v) is ILambdaExpression fPrim))
            {
                throw new ScriptRuntimeException("Lambda expression not differentiable.", Node);
            }

            int    size  = Width * Height * 4;
            double Conv  = 1e-10;
            double Div   = 1e10;
            double Conv2 = Conv * 2;

            byte[] rgb = new byte[size];

            Complex[]  Row;
            Complex[]  Row2;
            Complex[]  Row3;
            int[]      Offset;
            IElement[] P = new IElement[1];
            int        j, x2;
            IElement   Obj, Obj2;
            double     Mod;
            Complex    z;

            rDelta *= 0.5;
            r0      = rCenter - rDelta;
            r1      = rCenter + rDelta;

            aspect = ((double)Width) / Height;

            i0 = iCenter - rDelta / aspect;
            i1 = iCenter + rDelta / aspect;

            dr = (r1 - r0) / Width;
            di = (i1 - i0) / Height;

            for (y = 0, i = i0, index = 0; y < Height; y++, i += di)
            {
                Row    = new Complex[Width];
                Offset = new int[Width];

                c = Width;
                for (x = 0, x2 = y * Width * 4, r = r0; x < Width; x++, r += dr, x2 += 4)
                {
                    Row[x]    = new Complex(r, i);
                    Offset[x] = x2;
                }

                n = 0;
                while (n < N && c > 0)
                {
                    n++;
                    P[0] = Expression.Encapsulate(Row);
                    Obj  = f.Evaluate(P, v);
                    Obj2 = fPrim.Evaluate(P, v);
                    Row2 = Obj.AssociatedObjectValue as Complex[];
                    Row3 = Obj2.AssociatedObjectValue as Complex[];

                    if (Row2 is null || Row3 is null)
                    {
                        throw new ScriptRuntimeException("Lambda expression (and its first derivative) must be able to accept complex vectors, " +
                                                         "and return complex vectors of equal length. Type returned: " +
                                                         Obj.GetType().FullName + " and " + Obj2.GetType().FullName, Node);
                    }