Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
FlameFunction.cs
1using System.Collections.Generic;
2using System.Numerics;
3using SkiaSharp;
9
11{
15 public class FlameFunction
16 {
17 private readonly DoubleNumber xv, yv;
18 private readonly ComplexNumber zv;
19 private readonly IElement[] complexParameters;
20 private readonly IElement[] doubleParameters;
21 private readonly double[] homogeneousTransform;
22 private readonly ScriptNode node;
23 private IFlameVariation[] variations;
24 private ILambdaExpression[] variations2;
25 private double[] variationWeights;
26 private double[] variation2Weights;
27 private bool[] variation2IsReal;
28 private readonly List<IFlameVariation> variationsList = new List<IFlameVariation>();
29 private readonly List<ILambdaExpression> variations2List = new List<ILambdaExpression>();
30 private readonly List<double> variationsWeightList = new List<double>();
31 private readonly List<double> variations2WeightList = new List<double>();
32 private readonly List<bool> isReal = new List<bool>();
33 private SKColor color = SKColors.Red;
34 private double weight = 1.0;
35 private int nrVariations = 0;
36 private int nrVariations2 = 0;
37 private object lastVariation = null;
38 private double red = 1.0;
39 private double green = 0.0;
40 private double blue = 0.0;
41 private readonly bool hasProjection;
42 private bool hasVariations;
43 private bool isTransparent = false;
44
49 {
50 double[,] E = M.Values;
51
52 this.homogeneousTransform = new double[9];
53 this.node = Node;
54 this.xv = new DoubleNumber(0);
55 this.yv = new DoubleNumber(0);
56 this.zv = new ComplexNumber(0);
57 this.doubleParameters = new IElement[] { xv, yv };
58 this.complexParameters = new IElement[] { zv };
59
60 if (M.Columns == 2 && M.Rows == 2)
61 {
62 this.homogeneousTransform[0] = (double)E[0, 0];
63 this.homogeneousTransform[1] = (double)E[0, 1];
64 this.homogeneousTransform[2] = 0;
65 this.homogeneousTransform[3] = (double)E[1, 0];
66 this.homogeneousTransform[4] = (double)E[1, 1];
67 this.homogeneousTransform[5] = 0;
68 this.homogeneousTransform[6] = 0;
69 this.homogeneousTransform[7] = 0;
70 this.homogeneousTransform[8] = 1;
71 this.hasProjection = false;
72 }
73 else if (M.Columns == 3 && M.Rows == 3)
74 {
75 this.homogeneousTransform[0] = (double)E[0, 0];
76 this.homogeneousTransform[1] = (double)E[0, 1];
77 this.homogeneousTransform[2] = (double)E[0, 2];
78 this.homogeneousTransform[3] = (double)E[1, 0];
79 this.homogeneousTransform[4] = (double)E[1, 1];
80 this.homogeneousTransform[5] = (double)E[1, 2];
81 this.homogeneousTransform[6] = (double)E[2, 0];
82 this.homogeneousTransform[7] = (double)E[2, 1];
83 this.homogeneousTransform[8] = (double)E[2, 2];
84
85 this.hasProjection = this.homogeneousTransform[6] != 0 ||
86 this.homogeneousTransform[7] != 0 ||
87 this.homogeneousTransform[8] != 1;
88 }
89 else
90 throw new ScriptRuntimeException("Linear transformation must be a 2D or homogeneous 2D transformation.", Node);
91 }
92
96 public void Add(IFlameVariation Variation)
97 {
98 this.variationsList.Add(Variation);
99 this.variationsWeightList.Add(1);
100 this.lastVariation = Variation;
101 }
102
106 public void Add(ILambdaExpression Variation)
107 {
108 switch (Variation.NrArguments)
109 {
110 case 1:
111 this.isReal.Add(false);
112 break;
113
114 case 2:
115 this.isReal.Add(true);
116 break;
117
118 default:
119 throw new ScriptRuntimeException("Only lambda expressions taking 2 real-valued parmeters or 1 complex-valued parameter are allowed.", this.node);
120 }
121
122 this.variations2List.Add(Variation);
123 this.variations2WeightList.Add(1);
124 this.lastVariation = Variation;
125 }
126
130 public void SetWeight(double Weight)
131 {
132 if (this.lastVariation is IFlameVariation)
133 this.variationsWeightList[this.variationsWeightList.Count - 1] = Weight;
134
135 else if (this.lastVariation is ILambdaExpression)
136 this.variations2WeightList[this.variations2WeightList.Count - 1] = Weight;
137
138 else
139 this.weight = Weight;
140 }
141
145 public void SetColor(SKColor Color)
146 {
147 this.color = Color;
148 this.red = this.color.Red / 255.0;
149 this.green = this.color.Green / 255.0;
150 this.blue = this.color.Blue / 255.0;
151 this.isTransparent = (this.color.Alpha == 0);
152 }
153
157 public void SetColorHsl(double H, double S, double L)
158 {
159 this.color = SKColors.Black;
160 this.red = H / 360.0;
161 this.green = S / 100.0;
162 this.blue = L / 100.0;
163 this.isTransparent = false;
164 }
165
166 internal void DefinitionDone()
167 {
168 this.variations = this.variationsList.ToArray();
169 this.variationWeights = this.variationsWeightList.ToArray();
170 this.nrVariations = this.variations.Length;
171
172 this.variations2 = this.variations2List.ToArray();
173 this.variation2Weights = this.variations2WeightList.ToArray();
174 this.nrVariations2 = this.variation2Weights.Length;
175 this.variation2IsReal = this.isReal.ToArray();
176
177 this.hasVariations = this.nrVariations > 0 || this.nrVariations2 > 0;
178
179 int c = this.variations.Length;
180 int i;
181
182 for (i = 0; i < c; i++)
183 this.variations[i].Initialize(this.homogeneousTransform, this.variationWeights[i]);
184 }
185
189 public double Weight => this.weight;
190
191 internal bool Operate(FlameState point, Variables Variables)
192 {
193 double x = point.x;
194 double y = point.y;
195
196 double x2 = this.homogeneousTransform[0] * x +
197 this.homogeneousTransform[1] * y +
198 this.homogeneousTransform[2];
199
200 double y2 = this.homogeneousTransform[3] * x +
201 this.homogeneousTransform[4] * y +
202 this.homogeneousTransform[5];
203
204 if (this.hasProjection)
205 {
206 double p = this.homogeneousTransform[6] * x +
207 this.homogeneousTransform[7] * y +
208 this.homogeneousTransform[6];
209
210 if (p == 0)
211 return false;
212
213 x2 /= p;
214 y2 /= p;
215 }
216
217 if (this.hasVariations)
218 {
219 double x3 = 0;
220 double y3 = 0;
221 double w;
222 int i;
223
224 if (this.nrVariations > 0)
225 {
226 for (i = 0; i < this.nrVariations; i++)
227 {
228 x = x2;
229 y = y2;
230
231 this.variations[i].Operate(ref x, ref y);
232 w = this.variationWeights[i];
233
234 x3 += w * x;
235 y3 += w * y;
236 }
237 }
238
239 if (this.nrVariations2 > 0)
240 {
241 for (i = 0; i < this.nrVariations2; i++)
242 {
243 w = this.variation2Weights[i];
244
245 if (this.variation2IsReal[i])
246 {
247 this.xv.Value = x2;
248 this.yv.Value = y2;
249
250 IElement Result = this.variations2[i].Evaluate(this.doubleParameters, Variables);
251
252 if (!(Result is IVector V) || V.Dimension != 2)
253 throw new ScriptRuntimeException("Real-valued lambda expressions must return a vector containing 2 real-valued numbers.", this.node);
254
255 x3 += w * Expression.ToDouble(V.GetElement(0).AssociatedObjectValue);
256 y3 += w * Expression.ToDouble(V.GetElement(1).AssociatedObjectValue);
257 }
258 else
259 {
260 this.zv.Value = new Complex(x2, y2);
261 Complex z = Expression.ToComplex(this.variations2[i].Evaluate(this.complexParameters, Variables).AssociatedObjectValue);
262
263 x3 += w * z.Real;
264 y3 += w * z.Imaginary;
265 }
266 }
267 }
268
269 point.x = x3;
270 point.y = y3;
271 }
272 else
273 {
274 point.x = x2;
275 point.y = y2;
276 }
277
278 if (!this.isTransparent)
279 {
280 switch (point.ColorMode)
281 {
282 case ColorMode.Rgba:
283 point.red = (point.red + this.red) * 0.5;
284 point.green = (point.green + this.green) * 0.5;
285 point.blue = (point.blue + this.blue) * 0.5;
286 break;
287
288 case ColorMode.Hsl:
289 double d;
290
291 if (this.red < point.red) // H
292 {
293 d = point.red - this.red;
294 if (d < 0.5)
295 point.red -= d * 0.5;
296 else
297 {
298 d = 1 - d;
299 point.red += d * 0.5;
300 if (point.red > 1)
301 point.red -= 1;
302 }
303 }
304 else
305 {
306 d = this.red - point.red;
307 if (d < 0.5)
308 point.red += d * 0.5;
309 else
310 {
311 d = 1 - d;
312 point.red -= d * 0.5;
313 if (point.red < 1)
314 point.red += 1;
315 }
316 }
317
318 point.green = (point.green + this.green) * 0.5; // S
319 point.blue = (point.blue + this.blue) * 0.5; // L
320 break;
321 }
322 }
323
324 return true;
325 }
326
327 }
328}
Class managing a script expression.
Definition: Expression.cs:39
static Complex ToComplex(object Object)
Converts an object to a complex value.
Definition: Expression.cs:4942
static double ToDouble(object Object)
Converts an object to a double value.
Definition: Expression.cs:4824
void Add(ILambdaExpression Variation)
TODO
FlameFunction(DoubleMatrix M, ScriptNode Node)
TODO
void Add(IFlameVariation Variation)
TODO
void SetColorHsl(double H, double S, double L)
TODO
Base class for all nodes in a parsed script tree.
Definition: ScriptNode.cs:69
double[,] Values
Matrix element values.
Definition: DoubleMatrix.cs:56
Collection of variables.
Definition: Variables.cs:25
Basic interface for all types of elements.
Definition: IElement.cs:20
Basic interface for vectors.
Definition: IVector.cs:9
void Operate(ref double x, ref double y)
TODO
Base interface for lambda expressions.
IElement Evaluate(IElement[] Arguments, Variables Variables)
Evaluates the lambda expression.