7using System.Threading.Tasks;
39 private Type axisTypeX;
40 private Type axisTypeY;
41 private Type axisTypeZ;
42 private string title =
string.Empty;
43 private string labelX =
string.Empty;
44 private string labelY =
string.Empty;
45 private string labelZ =
string.Empty;
46 private double angle = 20;
47 private double inclination = 30;
48 private int overSampling = 2;
49 private bool showXAxis =
true;
50 private bool showYAxis =
true;
51 private bool showZAxis =
true;
52 private bool showGrid =
true;
81 : base(
Variables, DefaultWidth, DefaultHeight)
116 if (c !=
Y.Columns || d !=
Y.Rows || c !=
Z.Columns || d !=
Z.Rows)
117 throw new ScriptException(
"X, Y and Z matrices must be of equal dimensions.");
120 throw new ScriptException(
"Normal matrix must be of equal dimensions as axes.");
126 if (this.minX is
null)
129 if (this.maxX is
null)
134 Zero = AG.AdditiveIdentity;
140 if (this.minY is
null)
143 if (this.maxY is
null)
148 Zero = AG2.AdditiveIdentity;
154 if (this.minZ is
null)
157 if (this.maxZ is
null)
162 Zero = AG3.AdditiveIdentity;
168 this.axisTypeX =
X.GetType();
169 this.axisTypeY =
Y.GetType();
170 this.axisTypeZ =
Z.GetType();
178 this.painters.Add(Painter);
214 set => this.minX = value;
223 set => this.maxX = value;
232 set => this.minY = value;
241 set => this.maxY = value;
250 set => this.minZ = value;
259 set => this.maxZ = value;
268 set => this.title = value;
277 set => this.labelX = value;
286 set => this.labelY = value;
295 set => this.labelZ = value;
303 get => this.showXAxis;
304 set => this.showXAxis = value;
312 get => this.showYAxis;
313 set => this.showYAxis = value;
321 get => this.showZAxis;
322 set => this.showZAxis = value;
330 get => this.showGrid;
331 set => this.showGrid = value;
340 set => this.angle = value;
348 get => this.inclination;
349 set => this.inclination = value;
357 get => this.overSampling;
361 throw new ArgumentException(
"Must be a positive integer.", nameof(this.
Oversampling));
363 this.overSampling = value;
384 return this.
AddRight(Element,
false);
394 return Element.AddRightElementWise(
this);
415 if (!this.x.HasFirstItem)
421 if (G.x.FirstItem is
null)
426 axisTypeX = this.axisTypeX,
427 axisTypeY = this.axisTypeY,
428 axisTypeZ = this.axisTypeZ,
430 labelX = this.labelX,
431 labelY = this.labelY,
432 labelZ = this.labelZ,
439 Result.normals.
AddRange(this.normals);
440 Result.painters.AddRange(this.painters);
441 Result.parameters.
AddRange(this.parameters);
445 if (M.GetType() !=
this.axisTypeX)
453 if (M.GetType() !=
this.axisTypeY)
461 if (M.GetType() !=
this.axisTypeZ)
467 Result.normals.AddRange(G.normals);
468 Result.painters.AddRange(G.painters);
469 Result.parameters.AddRange(G.parameters);
478 Result.showXAxis |= G.showXAxis;
479 Result.showYAxis |= G.showYAxis;
480 Result.showZAxis |= G.showZAxis;
492 this.minX.Equals(G.minX) &&
493 this.maxX.Equals(G.maxX) &&
494 this.minY.Equals(G.minY) &&
495 this.maxY.Equals(G.maxY) &&
496 this.minZ.Equals(G.minZ) &&
497 this.maxZ.Equals(G.maxZ) &&
498 this.axisTypeX.Equals(G.axisTypeX) &&
499 this.axisTypeY.Equals(G.axisTypeY) &&
500 this.axisTypeZ.Equals(G.axisTypeZ) &&
501 this.title.Equals(G.title) &&
502 this.labelX.Equals(G.labelX) &&
503 this.labelY.Equals(G.labelY) &&
504 this.labelZ.Equals(G.labelZ) &&
505 this.showXAxis.Equals(G.showXAxis) &&
506 this.showYAxis.Equals(G.showYAxis) &&
507 this.showZAxis.Equals(G.showZAxis) &&
508 this.showGrid.Equals(G.showGrid) &&
509 this.Equals(
this.x.GetEnumerator(), G.x.GetEnumerator()) &&
510 this.Equals(
this.y.GetEnumerator(), G.y.GetEnumerator()) &&
511 this.Equals(
this.z.GetEnumerator(), G.z.GetEnumerator()) &&
512 this.Equals(
this.normals?.GetEnumerator(), G.normals?.GetEnumerator()) &&
513 this.Equals(
this.parameters.GetEnumerator(), G.parameters.GetEnumerator()) &&
514 this.Equals(
this.painters.GetEnumerator(), G.painters.GetEnumerator()));
517 private bool Equals(IEnumerator e1, IEnumerator e2)
521 if ((e1 is
null) ^ (e2 is
null))
527 bool b1 = e1.MoveNext();
528 bool b2 = e2.MoveNext();
532 if (!e1.Current.Equals(e2.Current))
543 if (e1 is IDisposable Disposable1)
544 Disposable1.Dispose();
546 if (e2 is IDisposable Disposable2)
547 Disposable2.Dispose();
554 int Result = this.minX.GetHashCode();
555 Result ^= Result << 5 ^ this.maxX.GetHashCode();
556 Result ^= Result << 5 ^ this.minY.GetHashCode();
557 Result ^= Result << 5 ^ this.maxY.GetHashCode();
558 Result ^= Result << 5 ^ this.minZ.GetHashCode();
559 Result ^= Result << 5 ^ this.maxZ.GetHashCode();
560 Result ^= Result << 5 ^ this.axisTypeX.GetHashCode();
561 Result ^= Result << 5 ^ this.axisTypeY.GetHashCode();
562 Result ^= Result << 5 ^ this.axisTypeZ.GetHashCode();
563 Result ^= Result << 5 ^ this.title.GetHashCode();
564 Result ^= Result << 5 ^ this.labelX.GetHashCode();
565 Result ^= Result << 5 ^ this.labelY.GetHashCode();
566 Result ^= Result << 5 ^ this.labelZ.GetHashCode();
567 Result ^= Result << 5 ^ this.showXAxis.GetHashCode();
568 Result ^= Result << 5 ^ this.showYAxis.GetHashCode();
569 Result ^= Result << 5 ^ this.showZAxis.GetHashCode();
570 Result ^= Result << 5 ^ this.showGrid.GetHashCode();
573 Result ^= Result << 5 ^ E.GetHashCode();
576 Result ^= Result << 5 ^ E.GetHashCode();
579 Result ^= Result << 5 ^ E.GetHashCode();
581 if (!(this.normals is
null))
583 foreach (Vector4[,]
Normals in this.normals)
584 Result ^= Result << 5 ^
Normals.GetHashCode();
587 foreach (
object Obj
in this.parameters)
588 Result ^= Result << 5 ^ Obj.GetHashCode();
591 Result ^= Result << 5 ^ Painter.GetHashCode();
620 this.minX.AssociatedObjectValue is
double MinX &&
630 double SX = Width / (DX == 0 ? 1 : DX);
631 double SY = Height / (DY == 0 ? 1 : DY);
632 double SZ = Depth / (DZ == 0 ? 1 : DZ);
633 double MinScale = Math.Min(SX, Math.Min(SY, SZ));
637 int Height2 = (int)(Height * SX / SY + 0.5);
638 OffsetY += (Height - Height2) / 2;
641 int Depth2 = (int)(Depth * SX / SZ + 0.5);
642 OffsetZ += (Depth - Depth2) / 2;
645 else if (SY == MinScale)
647 int Width2 = (int)(Width * SY / SX + 0.5);
648 OffsetX += (Width - Width2) / 2;
651 int Depth2 = (int)(Depth * SY / SZ + 0.5);
652 OffsetZ += (Depth - Depth2) / 2;
657 int Width2 = (int)(Width * SZ / SX + 0.5);
658 OffsetX += (Width - Width2) / 2;
661 int Height2 = (int)(Height * SZ / SY + 0.5);
662 OffsetY += (Height - Height2) / 2;
668 OrigoX = (float)
Scale(
new ObjectVector(AgX.AdditiveIdentity), this.minX, this.maxX, OffsetX, Width,
null)[0];
673 OrigoY = (float)
Scale(
new ObjectVector(AgY.AdditiveIdentity), this.minY, this.maxY, OffsetY, Height,
null)[0];
678 OrigoZ = (float)
Scale(
new ObjectVector(AgZ.AdditiveIdentity), this.maxZ, this.minZ, OffsetZ, Depth,
null)[0];
682 float PlaneX = OrigoX ?? OffsetX;
683 float PlaneY = OrigoY ?? OffsetY;
684 float PlaneZ = OrigoZ ?? OffsetZ + Depth;
687 this.minY, this.maxY, this.minZ, this.maxZ, OffsetX, OffsetY, OffsetZ,
688 Width, Height, Depth, OrigoX, OrigoY, OrigoZ);
690 Dictionary<string, double> XLabelPositions = XLabelType == LabelType.String ?
new Dictionary<string, double>() :
null;
691 Dictionary<string, double> YLabelPositions = YLabelType == LabelType.String ?
new Dictionary<string, double>() :
null;
692 Dictionary<string, double> ZLabelPositions = ZLabelType == LabelType.String ?
new Dictionary<string, double>() :
null;
696 string[] XLabelStrings =
LabelStrings(XLabels, XLabelType);
697 string[] YLabelStrings =
LabelStrings(YLabels, YLabelType);
698 string[] ZLabelStrings =
LabelStrings(ZLabels, ZLabelType);
702 if (!(XLabelPositions is
null))
708 s = XLabelStrings[i];
709 XLabelPositions[s] = LabelXX[i++];
713 if (!(YLabelPositions is
null))
719 s = YLabelStrings[i];
720 YLabelPositions[s] = LabelYY[i++];
724 if (!(ZLabelPositions is
null))
730 s = ZLabelStrings[i];
731 ZLabelPositions[s] = LabelZZ[i++];
735 DrawingVolume.XLabelPositions = XLabelPositions;
736 DrawingVolume.YLabelPositions = YLabelPositions;
737 DrawingVolume.ZLabelPositions = ZLabelPositions;
742 Canvas.
RotateX(-(
float)this.inclination,
new Vector3(0, 0, 1500));
743 Canvas.
RotateY((
float)this.angle,
new Vector3(0, 0, 1500));
745 IEnumerator<IMatrix> ex = this.x.GetEnumerator();
746 IEnumerator<IMatrix> ey = this.y.GetEnumerator();
747 IEnumerator<IMatrix> ez = this.z.GetEnumerator();
748 IEnumerator<Vector4[,]> eN = this.normals.GetEnumerator();
749 IEnumerator<object[]> eParameters = this.parameters.GetEnumerator();
750 IEnumerator<IPainter3D> ePainters = this.painters.GetEnumerator();
753 Vector4[,] PrevPoints =
null;
754 Vector4[,] PrevNormals =
null;
755 object[] PrevParameters =
null;
760 while (ex.MoveNext() && ey.MoveNext() && ez.MoveNext() &&
761 eN.MoveNext() && eParameters.MoveNext() && ePainters.MoveNext())
766 if (!(PrevPainter is
null) && ePainters.Current.GetType() == PrevPainter.GetType())
767 ePainters.Current.DrawGraph(Canvas, Points,
Normals, eParameters.Current, PrevPoints, PrevNormals, PrevParameters,
DrawingVolume);
769 ePainters.Current.DrawGraph(Canvas, Points,
Normals, eParameters.Current,
null,
null,
null,
DrawingVolume);
773 PrevParameters = eParameters.Current;
774 PrevPainter = ePainters.Current;
783 eParameters.Dispose();
789 float TextSize0 = (
float)Settings.LabelFontSize * 5;
790 float TextSize = this.CalcTextSize(LabelXX, TextSize0);
798 s = XLabelStrings[i];
801 f = (float)LabelXX[i++];
807 this.DrawPlaneLine(Canvas,
808 new Vector4(f, PlaneY, OffsetZ, 1),
809 new Vector4(f, PlaneY, OffsetZ + Depth, 1),
812 this.DrawPlaneLine(Canvas,
813 new Vector4(f, OffsetY, PlaneZ, 1),
814 new Vector4(f, OffsetY + Height, PlaneZ, 1),
819 this.DrawPlaneLine(Canvas,
820 new Vector4(f, PlaneY, OffsetZ, 1),
821 new Vector4(f, PlaneY, OffsetZ + Depth, 1),
824 this.DrawPlaneLine(Canvas,
825 new Vector4(f, OffsetY, PlaneZ, 1),
826 new Vector4(f, OffsetY + Height, PlaneZ, 1),
833 Canvas.Translate(f, PlaneY, OffsetZ);
837 new Vector4(-5 * LabelMargin - Size.Width, LabelMargin - Size.Height / 2, 0, 1),
839 Canvas.ModelTransformation = M;
843 if (!
string.IsNullOrEmpty(this.labelX))
845 Size = Canvas.TextDimensions(this.labelX,
Settings.
FontName, TextSize0 * 1.25f);
847 Canvas.Translate(OffsetX + Width / 2, PlaneY, OffsetZ);
849 Canvas.Text(this.labelX,
850 new Vector4(-Size.Width / 2, -2 * Size.Height, 0, 1),
852 Canvas.ModelTransformation = M;
856 TextSize = this.CalcTextSize(LabelZZ, TextSize0);
860 s = ZLabelStrings[i];
863 f = (float)LabelZZ[i++];
869 this.DrawPlaneLine(Canvas,
870 new Vector4(OffsetX, PlaneY, f, 1),
871 new Vector4(OffsetX + Width, PlaneY, f, 1),
874 this.DrawPlaneLine(Canvas,
875 new Vector4(PlaneX, OffsetY, f, 1),
876 new Vector4(PlaneX, OffsetY + Height, f, 1),
881 this.DrawPlaneLine(Canvas,
882 new Vector4(OffsetX, PlaneY, f, 1),
883 new Vector4(OffsetX + Width, PlaneY, f, 1),
886 this.DrawPlaneLine(Canvas,
887 new Vector4(PlaneX, OffsetY, f, 1),
888 new Vector4(PlaneX, OffsetY + Height, f, 1),
895 Canvas.Translate(OffsetX + Width, PlaneY, f);
898 new Vector4(5 * LabelMargin, LabelMargin - Size.Height / 2, 0, 1),
900 Canvas.ModelTransformation = M;
904 if (!
string.IsNullOrEmpty(this.labelZ))
906 Size = Canvas.TextDimensions(this.labelZ,
Settings.
FontName, TextSize0 * 1.25f);
908 Canvas.Translate(OffsetX + Width, PlaneY, OffsetZ + Depth / 2);
911 Canvas.Text(this.labelZ,
912 new Vector4(-Size.Width / 2, -2 * Size.Height, 0, 1),
914 Canvas.ModelTransformation = M;
918 TextSize = this.CalcTextSize(LabelYY, TextSize0);
922 s = YLabelStrings[i];
925 f = (float)LabelYY[i++];
931 this.DrawPlaneLine(Canvas,
932 new Vector4(PlaneX, f, OffsetZ, 1),
933 new Vector4(PlaneX, f, OffsetZ + Depth, 1),
936 this.DrawPlaneLine(Canvas,
937 new Vector4(OffsetX, f, PlaneZ, 1),
938 new Vector4(OffsetX + Width, f, PlaneZ, 1),
943 this.DrawPlaneLine(Canvas,
944 new Vector4(PlaneX, f, OffsetZ, 1),
945 new Vector4(PlaneX, f, OffsetZ + Depth, 1),
948 this.DrawPlaneLine(Canvas,
949 new Vector4(OffsetX, f, PlaneZ, 1),
950 new Vector4(OffsetX + Width, f, PlaneZ, 1),
957 Canvas.Translate(OffsetX, f, PlaneZ);
959 new Vector4(-5 * LabelMargin - Size.Width, LabelMargin - Size.Height / 2, 0, 1),
961 Canvas.ModelTransformation = M;
965 if (!
string.IsNullOrEmpty(this.labelY))
967 Size = Canvas.TextDimensions(this.labelY,
Settings.
FontName, TextSize0 * 1.25f);
969 Canvas.Translate(OffsetX, OffsetY + Height / 2, PlaneZ);
971 Canvas.Text(this.labelY,
972 new Vector4(-Size.Width / 2, 2 * Size.Height, 0, 1),
974 Canvas.ModelTransformation = M;
977 if (!
string.IsNullOrEmpty(this.title))
979 Size = Canvas.TextDimensions(this.title,
Settings.
FontName, TextSize0 * 1.5f);
981 Canvas.Translate(OffsetX + Width / 2, OffsetY + Height, OffsetZ + Depth / 2);
982 Canvas.Text(this.title,
983 new Vector4(-Size.Width / 2, Size.Height / 2, 0, 1),
985 Canvas.ModelTransformation = M;
991 this.DrawPlane(Canvas,
992 new Vector4(OffsetX, OffsetY, PlaneZ, 1),
993 new Vector4(OffsetX + Width, OffsetY, PlaneZ, 1),
994 new Vector4(OffsetX + Width, OffsetY + Height, PlaneZ, 1),
995 new Vector4(OffsetX, OffsetY + Height, PlaneZ, 1),
996 AxisPlaneShader,
true, 3);
998 this.DrawPlane(Canvas,
999 new Vector4(OffsetX, PlaneY, OffsetZ, 1),
1000 new Vector4(OffsetX + Width, PlaneY, OffsetZ, 1),
1001 new Vector4(OffsetX + Width, PlaneY, OffsetZ + Depth, 1),
1002 new Vector4(OffsetX, PlaneY, OffsetZ + Depth, 1),
1003 AxisPlaneShader,
true, 3);
1005 this.DrawPlane(Canvas,
1006 new Vector4(PlaneX, OffsetY, OffsetZ, 1),
1007 new Vector4(PlaneX, OffsetY, OffsetZ + Depth, 1),
1008 new Vector4(PlaneX, OffsetY + Height, OffsetZ + Depth, 1),
1009 new Vector4(PlaneX, OffsetY + Height, OffsetZ, 1),
1010 AxisPlaneShader,
true, 3);
1012 return Canvas.CreatePixels(
Settings, out States);
1015 private float CalcTextSize(
double[] LabelPositions,
float TextSize)
1017 int i, c = LabelPositions.Length;
1020 for (i = 1; i < c; i++)
1022 Diff = (float)(Math.Abs(LabelPositions[i] - LabelPositions[i - 1]));
1023 if (Diff < TextSize)
1030 private void DrawPlaneLine(Canvas3D Canvas, Vector4 P0, Vector4 P1,
1031 SKColor Color,
int Halvings)
1034 Canvas.Line(P0, P1, Color);
1039 Vector4 Pm = (P0 + P1) / 2;
1041 this.DrawPlaneLine(Canvas, P0, Pm, Color, Halvings);
1042 this.DrawPlaneLine(Canvas, Pm, P1, Color, Halvings);
1046 private void DrawPlane(Canvas3D Canvas, Vector4 P0, Vector4 P1, Vector4 P2, Vector4 P3,
1047 I3DShader Shader,
bool TwoSided,
int Halvings)
1050 Canvas.Polygon(
new Vector4[] { P0, P1, P2, P3 }, Shader, TwoSided);
1055 Vector4 Pm = (P0 + P1 + P2 + P3) / 4;
1056 Vector4 P0p = (P3 + P0) / 2;
1057 Vector4 P1p = (P0 + P1) / 2;
1058 Vector4 P2p = (P1 + P2) / 2;
1059 Vector4 P3p = (P2 + P3) / 2;
1061 this.DrawPlane(Canvas, Pm, P2p, P2, P3p, Shader, TwoSided, Halvings);
1062 this.DrawPlane(Canvas, P1p, P1, P2p, Pm, Shader, TwoSided, Halvings);
1063 this.DrawPlane(Canvas, P3, P0p, Pm, P3p, Shader, TwoSided, Halvings);
1064 this.DrawPlane(Canvas, P0p, P0, P1p, Pm, Shader, TwoSided, Halvings);
1079 if (
Min.AssociatedObjectValue is
double DMin &&
1080 Max.AssociatedObjectValue is
double DMax)
1085 else if (
Min.AssociatedObjectValue is DateTime DTMin &&
1086 Max.AssociatedObjectValue is DateTime DTMax)
1094 return new ObjectVector(
GetLabels(PQMin.ToPhysicalQuantity(), PQMax.ToPhysicalQuantity(), ApproxNrLabels));
1096 else if (
Min.AssociatedObjectValue is
string &&
Max.AssociatedObjectValue is
string)
1098 Dictionary<string, bool> Indices =
new Dictionary<string, bool>();
1102 foreach (
IMatrix Matrix
in Series)
1107 if (Indices.ContainsKey(s))
1117 if (Labels.Count > 0)
1120 Max = Labels[Labels.Count - 1];
1127 SortedDictionary<string, bool> Labels =
new SortedDictionary<string, bool>();
1129 foreach (
IMatrix Matrix
in Series)
1135 string[] Labels2 =
new string[Labels.Count];
1136 Labels.Keys.CopyTo(Labels2, 0);
1168 double Width,
double Height,
double Depth, Dictionary<string, double> XLabelPositions,
1169 Dictionary<string, double> YLabelPositions, Dictionary<string, double> ZLabelPositions)
1171 int Columns = MatrixX.
Columns;
1172 int Rows = MatrixX.
Rows;
1174 if (MatrixY.
Columns != Columns || MatrixY.
Rows != Rows ||
1175 MatrixZ.
Columns != Columns || MatrixZ.
Rows != Rows)
1180 double[,]
X =
Scale(MatrixX,
MinX,
MaxX, OffsetX, Width, XLabelPositions);
1181 double[,]
Y =
Scale(MatrixY,
MinY,
MaxY, OffsetY, Height, YLabelPositions);
1182 double[,]
Z =
Scale(MatrixZ,
MinZ,
MaxZ, OffsetZ, Depth, ZLabelPositions);
1184 Vector4[,] Points =
new Vector4[Rows, Columns];
1186 for (i = 0; i < Rows; i++)
1188 for (j = 0; j < Columns; j++)
1189 Points[i, j] =
new Vector4((
float)
X[i, j], (
float)
Y[i, j], (
float)
Z[i, j], 1);
1206 double Size, Dictionary<string, double> LabelPositions)
1210 if (!(
Min.AssociatedObjectValue is
double dMin) ||
1211 !(
Max.AssociatedObjectValue is
double dMax))
1216 return Scale(DM.Values, dMin, dMax, Offset, Size);
1243 for (i = 0; i < c; i++)
1245 for (j = 0; j < r; j++)
1257 if (
Min.AssociatedObjectValue is
double MinD &&
1258 Max.AssociatedObjectValue is
double MaxD)
1260 double[,] Matrix2 =
new double[c, r];
1263 for (i = 0; i < c; i++)
1265 for (j = 0; j < r; j++)
1269 Matrix2[i, j] = D.
Value;
1273 return Scale(Matrix2, MinD, MaxD, Offset, Size);
1277 if (
Min.AssociatedObjectValue is DateTime MinDT &&
1278 Max.AssociatedObjectValue is DateTime MaxDT)
1280 DateTime[,] Matrix2 =
new DateTime[c, r];
1283 for (i = 0; i < c; i++)
1285 for (j = 0; j < r; j++)
1289 Matrix2[i, j] = DT.
Value;
1293 return Scale(Matrix2, MinDT, MaxDT, Offset, Size);
1296 return Scale(OM.Values, Offset, Size, LabelPositions);
1313 public static double[,]
Scale(
double[,] Matrix,
double Min,
double Max,
double Offset,
double Size)
1315 int c = Matrix.GetLength(0);
1316 int r = Matrix.GetLength(1);
1318 double[,] Result =
new double[c, r];
1321 for (i = 0; i < c; i++)
1323 for (j = 0; j < r; j++)
1324 Result[i, j] = (Matrix[i, j] -
Min) *
Scale + Offset;
1339 public static double[,]
Scale(DateTime[,] Matrix, DateTime
Min, DateTime
Max,
double Offset,
double Size)
1341 int c = Matrix.GetLength(0);
1342 int r = Matrix.GetLength(1);
1344 double[,] v =
new double[c, r];
1346 for (i = 0; i < c; i++)
1348 for (j = 0; j < r; j++)
1367 int c = Matrix.GetLength(0);
1368 int r = Matrix.GetLength(1);
1370 double[,] v =
new double[c, r];
1373 for (i = 0; i < c; i++)
1375 for (j = 0; j < r; j++)
1396 public static double[,]
Scale(
object[,] Matrix,
double Offset,
double Size,
1397 Dictionary<string, double> LabelPositions)
1399 Dictionary<object, int> Values =
new Dictionary<object, int>();
1401 int c = Matrix.GetLength(0);
1402 int r = Matrix.GetLength(1);
1404 double[,] v =
new double[c, r];
1407 for (i = 0; i < c; i++)
1409 for (j = 0; j < r; j++)
1411 Value = Matrix[i, j];
1412 if (!Values.TryGetValue(Value, out
int k))
1422 double[,] Result =
Scale(v, 0, c, Offset, Size);
1424 if (!(LabelPositions is
null))
1426 for (i = 0; i < c; i++)
1428 for (j = 0; j < r; j++)
1430 string s = Matrix[i, j]?.ToString() ??
string.Empty;
1432 if (LabelPositions.TryGetValue(s, out
double d))
1455 return "[" + X2.ToString() +
"," + Y2.ToString() +
"]";
1468 if (!(Argument is SKColor Color))
1477 new PhongIntensity(Color.Red, Color.Green, Color.Blue, Color.Alpha),
1479 new Vector3(1000, 1000, 0)));
1488 Output.WriteStartElement(
"Graph3D");
1489 Output.WriteAttributeString(
"title", this.title);
1490 Output.WriteAttributeString(
"labelX", this.labelX);
1491 Output.WriteAttributeString(
"labelY", this.labelY);
1492 Output.WriteAttributeString(
"labelZ", this.labelZ);
1493 Output.WriteAttributeString(
"axisTypeX", this.axisTypeX.FullName);
1494 Output.WriteAttributeString(
"axisTypeY", this.axisTypeY.FullName);
1495 Output.WriteAttributeString(
"axisTypeZ", this.axisTypeZ.FullName);
1502 Output.WriteAttributeString(
"showXAxis", this.showXAxis ?
"true" :
"false");
1503 Output.WriteAttributeString(
"showYAxis", this.showYAxis ?
"true" :
"false");
1504 Output.WriteAttributeString(
"showZAxis", this.showZAxis ?
"true" :
"false");
1505 Output.WriteAttributeString(
"showGrid", this.showGrid ?
"true" :
"false");
1508 Output.WriteAttributeString(
"overSampling", this.overSampling.ToString());
1510 Dictionary<string, string> Series =
new Dictionary<string, string>();
1518 if (Series.TryGetValue(s, out Label))
1519 Output.WriteElementString(
"X", Label);
1522 Label =
"X" + (i++).ToString();
1524 Output.WriteElementString(
"X", Label +
":=" + s);
1533 if (Series.TryGetValue(s, out Label))
1534 Output.WriteElementString(
"Y", Label);
1537 Label =
"Y" + (i++).ToString();
1539 Output.WriteElementString(
"Y", Label +
":=" + s);
1548 if (Series.TryGetValue(s, out Label))
1549 Output.WriteElementString(
"Z", Label);
1552 Label =
"Z" + (i++).ToString();
1554 Output.WriteElementString(
"Z", Label +
":=" + s);
1560 foreach (Vector4[,] M
in this.normals)
1562 StringBuilder sb =
new StringBuilder();
1568 int c = M.GetLength(0);
1569 int d = M.GetLength(1);
1573 for (i = 0; i < c; i++)
1580 for (j = 0; j < d; j++)
1595 if (Series.TryGetValue(s, out Label))
1596 Output.WriteElementString(
"Normals", Label);
1599 Label =
"N" + (i++).ToString();
1601 Output.WriteElementString(
"Normals", Label +
":=" + s);
1607 foreach (
object[] v
in this.parameters)
1610 if (Series.TryGetValue(s, out Label))
1611 Output.WriteElementString(
"Parameters", Label);
1614 Label =
"P" + (i++).ToString();
1616 Output.WriteElementString(
"Parameters", Label +
":=" + s);
1620 foreach (
IPainter3D Painter
in this.painters)
1621 Output.WriteElementString(
"Painter", Painter.GetType().FullName);
1623 Output.WriteEndElement();
1634 foreach (XmlAttribute Attr
in Xml.Attributes)
1639 this.title = Attr.Value;
1643 this.labelX = Attr.Value;
1647 this.labelY = Attr.Value;
1651 this.labelZ = Attr.Value;
1691 this.showXAxis = Attr.Value ==
"true";
1695 this.showYAxis = Attr.Value ==
"true";
1699 this.showZAxis = Attr.Value ==
"true";
1703 this.showGrid = Attr.Value ==
"true";
1713 this.inclination = d;
1716 case "overSampling":
1717 this.overSampling =
int.Parse(Attr.Value);
1722 foreach (XmlNode N
in Xml.ChildNodes)
1724 if (N is XmlElement E)
1726 switch (E.LocalName)
1746 this.normals.Add((Vector4[,])
null);
1751 Vector4[,] M2 =
new Vector4[c, d];
1753 for (i = 0; i < c; i++)
1755 for (j = 0; i < d; j++)
1759 this.normals.Add(M2);
1783 IEnumerator<object[]> eParameters = this.parameters.GetEnumerator();
1784 IEnumerator<IPainter3D> ePainter = this.painters.GetEnumerator();
1788 while (eParameters.MoveNext() && ePainter.MoveNext())
1790 if (!ePainter.Current.UsesDefaultColor(eParameters.Current))
1798 eParameters.Dispose();
1814 IEnumerator<object[]> eParameters = this.parameters.GetEnumerator();
1815 IEnumerator<IPainter3D> ePainter = this.painters.GetEnumerator();
1820 while (eParameters.MoveNext() && ePainter.MoveNext())
1822 if (!ePainter.Current.TrySetDefaultColor(Color, eParameters.Current))
1830 eParameters.Dispose();
A chunked list is a linked list of chunks of objects of type T .
void AddRange(IEnumerable< T > Collection)
Adds a range of elements (last) to the list.
void Add(T Item)
Adds an item to the collection.
Static class that dynamically manages types and interfaces available in the runtime environment.
static Type GetType(string FullName)
Gets a type, given its full name.
static object Instantiate(Type Type, params object[] Arguments)
Returns an instance of the type Type . If one needs to be created, it is. If the constructor requires...
Base class for all types of elements.
Element()
Base class for all types of elements.
Base class for script exceptions.
Class managing a script expression.
static bool TryParse(string s, out double Value)
Tries to parse a double-precision floating-point value.
static string ToString(double Value)
Converts a value to a string, that can be parsed as part of an expression.
static string ToExpressionString(object Value)
Converts an object to a string, that can be parsed as part of an expression.
static double CalcMax(double[] Values, ScriptNode Node)
Returns the largest value.
static double CalcMin(double[] Values, ScriptNode Node)
Returns the smallest value.
Matrix4x4 RotateY(float Degrees)
Rotates the world around the Y-axis.
Matrix4x4 Perspective(float NearPlaneDistance, float FarPlaneDistance)
Applies a perspective projection.
Matrix4x4 ModelTransformation
Current model transformation matrix.
Matrix4x4 RotateX(float Degrees)
Rotates the world around the X-axis.
Contains information about the current drawing area.
double[,] ScaleX(IMatrix Matrix)
Scales a matrix with x-coordinates to fit a given volume.
double[,] ScaleY(IMatrix Matrix)
Scales a matrix with y-coordinates to fit a given volume.
Vector4[,] Scale(IMatrix MatrixX, IMatrix MatrixY, IMatrix MatrixZ)
Scales three matrices of equal size to point vectors in space.
double[,] ScaleZ(IMatrix Matrix)
Scales a matrix with z-coordinates to fit a given volume.
Handles three-dimensional graphs.
double Inclination
Inclination, in degrees (rotation angle, around the X-axis).
override async Task ImportGraphAsync(XmlElement Xml)
Imports graph specifics from XML.
static double[,] Scale(IMatrix Matrix, IElement Min, IElement Max, double Offset, double Size, Dictionary< string, double > LabelPositions)
Scales a matrix to fit a given volume.
static double[,] Scale(object[,] Matrix, double Offset, double Size, Dictionary< string, double > LabelPositions)
Scales a matrix to fit a given volume.
Graph3D(Variables Variables, IMatrix X, IMatrix Y, IMatrix Z, Vector4[,] Normals, IPainter3D Painter, bool ShowZeroX, bool ShowZeroY, bool ShowZeroZ, ScriptNode Node, params object[] Parameters)
Base class for three-dimensional graphs.
static double[,] Scale(DateTime[,] Matrix, DateTime Min, DateTime Max, double Offset, double Size)
Scales a matrix to fit a given volume.
override int GetHashCode()
Calculates a hash code of the element. Hash code.
override PixelInformation CreatePixels(GraphSettings Settings, out object[] States)
Creates a bitmap of the graph.
IElement MaxX
Largest X-value.
Graph3D()
Base class for three-dimensional graphs.
static double[,] Scale(PhysicalQuantity[,] Matrix, double Min, double Max, Unit Unit, double Offset, double Size)
Scales a matrix to fit a given volume.
IElement MinX
Smallest X-value.
IElement MaxZ
Largest Z-value.
override ISemiGroupElement AddLeft(ISemiGroupElement Element)
Tries to add an element to the current element, from the left.
static I3DShader ToShader(object Argument)
Gets a shader object from an argument.
override ISemiGroupElementWise AddLeftElementWise(ISemiGroupElementWise Element)
Tries to add an element to the current element, from the left, element-wise.
override bool UsesDefaultColor
If graph uses default color
override bool Equals(object obj)
Compares the element to another. If elements are equal.
double Angle
Rotation angle, in degrees, around the Y-axis.
static Vector4[,] Scale(IMatrix MatrixX, IMatrix MatrixY, IMatrix MatrixZ, IElement MinX, IElement MaxX, IElement MinY, IElement MaxY, IElement MinZ, IElement MaxZ, double OffsetX, double OffsetY, double OffsetZ, double Width, double Height, double Depth, Dictionary< string, double > XLabelPositions, Dictionary< string, double > YLabelPositions, Dictionary< string, double > ZLabelPositions)
Scales three matrices of equal size to point vectors in space.
ChunkedList< object[]> Parameters
Parameters.
override bool TrySetDefaultColor(SKColor Color)
Tries to set the default color.
override string GetBitmapClickScript(double X, double Y, object[] States)
Gets script corresponding to a point in a generated bitmap representation of the graph.
ChunkedList< IMatrix > X
X-axis series.
ChunkedList< Vector4[,]> Normals
Optional normals.
Graph3D(Variables Variables)
Base class for three-dimensional graphs.
string Title
Title for graph.
int Oversampling
Oversampling (for anti-aliasing-purposes).
ISemiGroupElement AddRight(ISemiGroupElement Element, bool _)
Tries to add an element to the current element, from the right.
IElement MinY
Smallest Y-value.
Graph3D(Variables Variables, int? DefaultWidth, int? DefaultHeight)
Base class for three-dimensional graphs.
bool ShowYAxis
If the Y-axis is to be displayed.
IElement MaxY
Largest Y-value.
override void ExportGraph(XmlWriter Output)
Exports graph specifics to XML.
string LabelX
Label for x-axis.
IElement MinZ
Smallest Z-value.
static IVector GetLabels(ref IElement Min, ref IElement Max, IEnumerable< IMatrix > Series, int ApproxNrLabels, out LabelType LabelType)
Gets label values for a series vector.
Graph3D(GraphSettings Settings)
Base class for three-dimensional graphs.
bool ShowZAxis
If the Z-axis is to be displayed.
ChunkedList< IMatrix > Y
Y-axis series.
string LabelZ
Label for z-axis.
bool ShowGrid
If the grid is to be displayed.
override ISemiGroupElementWise AddRightElementWise(ISemiGroupElementWise Element)
Tries to add an element to the current element, from the right, element-wise.
override ISemiGroupElement AddRight(ISemiGroupElement Element)
Tries to add an element to the current element, from the right.
ChunkedList< IMatrix > Z
Z-axis series.
static double[,] Scale(double[,] Matrix, double Min, double Max, double Offset, double Size)
Scales a matrix to fit a given volume.
string LabelY
Label for y-axis.
bool ShowXAxis
If the X-axis is to be displayed.
Contains information about the intensity of a light component, as used in the Phong reflection model....
Contains information about a light source, as used in the Phong reflection model. https://en....
Contains information about a material, as used in the Phong reflection model. https://en....
The Phong Shader uses the Phong Reflection model to generate colors. https://en.wikipedia....
Contains information about the current drawing area.
IElement DescaleY(double Value)
Descales a scaled value along the Y-axis.
IElement DescaleX(double Value)
Descales a scaled value along the X-axis.
Handles two-dimensional graphs.
static string ReducedXmlString(double Value)
Generates an XML value string of an element, possible with reduced resolution, to avoid unnecessary d...
bool SameScale
If the same scale should be used for all axes.
object[] ToObjectArray(IVector v)
Gets an array of objects corresponding to the elements of a vector.
static readonly DateTime referenceTimestamp
Reference time stamp when converting DateTime to System.Double.
static string[] LabelStrings(IVector Labels, LabelType LabelType)
Converts a vector of labels to a string array.
GraphSettings Settings
Graph settings available during creation.
static SKColor ToColor(object Object)
Converts an object to a color.
static async Task< IElement > ParseAsync(string s, Variables Variables)
Parses an element expression string.
SKColor AxisColor
Axis color.
SKColor BackgroundColor
Background color.
int ApproxNrLabelsY
Approximate number of labels along the Y-axis.
int ApproxNrLabelsX
Approximate number of labels along the X-axis.
double LabelFontSize
Label font size
SKColor GridColor
Grid color.
int Width
Width of graph, in pixels. (Default=640 pixels.)
int Height
Height of graph, in pixels. (Default=480 pixels.)
string FontName
Font name.
Base class for all nodes in a parsed script tree.
override string ToString()
DateTime Value
DateTime value.
double Value
Double value.
PhysicalQuantity ToPhysicalQuantity()
Converts underlying object to a physical quantity.
double Magnitude
Magnitude
static IElement Encapsulate(Array Elements, bool CanEncapsulateAsMatrix, ScriptNode Node)
Encapsulates the elements of a vector.
static bool TryConvert(double From, Unit FromUnit, Unit ToUnit, out double To)
Tries to convert a magnitude in one unit to a magnitude in another.
bool IsEmpty
If the unit is empty. (A unit of only a prefix, but no factors, is not empty.)
override bool Equals(object obj)
Basic interface for all types of elements.
object AssociatedObjectValue
Associated object value.
ICollection< IElement > ChildElements
An enumeration of child elements. If the element is a scalar, this property will return null.
ISet AssociatedSet
Associated Set.
Basic interface for matrices.
int Columns
Number of columns.
IElement GetElement(int Column, int Row)
Gets an element of the matrix.
Basic interface for all types of semigroup elements.
Basic interface for all types of element-wise semigroup elements.
Basic interface for vectors.
Basic interface for all types of abelian groups.
Interface for 3D shaders.
Interface for 3D graph drawing functions.
Interface for objects that can be represented as a physical quantity.
PhysicalQuantity ToPhysicalQuantity()
Converts underlying object to a physical quantity.