/// <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)); }
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)); } }
public void Evaluate() { var text = lambda.Evaluate(Arguments).Text; State.Print(text); }