Пример #1
0
        /// <summary>
        /// Evaluates the operator on scalar operands.
        /// </summary>
        /// <param name="Operand">Operand.</param>
        /// <param name="Variables">Variables collection.</param>
        /// <returns>Result</returns>
        public override IElement EvaluateScalar(IElement Operand, Variables Variables)
        {
            if (!(Operand.AssociatedObjectValue is ILambdaExpression Lambda))
            {
                throw new ScriptRuntimeException("Expected a lambda expression.", this);
            }

            int c = this.arguments.Length;

            if (c != Lambda.NrArguments)
            {
                throw new ScriptRuntimeException("Expected " + Lambda.NrArguments.ToString() + " arguments.", this);
            }

            IElement[] Arg = new IElement[c];
            ScriptNode Node;
            int        i;

            for (i = 0; i < c; i++)
            {
                Node = this.arguments[i];
                if (Node == null)
                {
                    Arg[i] = ObjectValue.Null;
                }
                else
                {
                    Arg[i] = Node.Evaluate(Variables);
                }
            }

            return(Lambda.Evaluate(Arg, Variables));
        }
Пример #2
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));
            }
        }
Пример #3
0
        public void Evaluate()
        {
            var text = lambda.Evaluate(Arguments).Text;

            State.Print(text);
        }