public void Transform(Matrix3 m, Chart3D chart3d, Axes ax, ChartStyle cs, ChartLabels cl) { // Normalize the point: float x1 = (X - ax.XMin) / (ax.XMax - ax.XMin) - 0.5f; float y1 = (Y - ax.YMin) / (ax.YMax - ax.YMin) - 0.5f; float z1 = (Z - ax.ZMin) / (ax.ZMax - ax.ZMin) - 0.5f; // Perform transformation on the point using matrix m: float[] result = m.VectorMultiply(new float[4] { x1, y1, z1, W }); X = result[0]; Y = result[1]; // Coordinate transformation from World to Device system: float xShift = 1.05f; float xScale = 1; float yShift = 1.05f; float yScale = 0.9f; if (cl.Title == "No Title") { yShift = 0.95f; yScale = 1; } if (cs.IsColorBar) { xShift = 0.95f; xScale = 0.9f; } X = (xShift + xScale * X) * chart3d.Width / 2; Y = (yShift - yScale * Y) * chart3d.Height / 2; }
public void Transform(Matrix3 m) { float[] result = m.VectorMultiply(new float[4] { X, Y, Z, W }); X = result[0]; Y = result[1]; Z = result[2]; W = result[3]; }
// Axonometric projection matrix: public static Matrix3 Axonometric(float alpha, float beta) { Matrix3 result = new Matrix3(); float sna = (float)Math.Sin(alpha * Math.PI / 180); float cna = (float)Math.Cos(alpha * Math.PI / 180); float snb = (float)Math.Sin(beta * Math.PI / 180); float cnb = (float)Math.Cos(beta * Math.PI / 180); result.M[0, 0] = cnb; result.M[0, 2] = snb; result.M[1, 0] = sna * snb; result.M[1, 1] = cna; result.M[1, 2] = -sna * cnb; result.M[2, 2] = 0; return result; }
// Multiply two matrices together: public static Matrix3 operator *(Matrix3 m1, Matrix3 m2) { Matrix3 result = new Matrix3(); for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { float element = 0; for (int k = 0; k < 4; k++) { element += m1.M[i, k] * m2.M[k, j]; } result.M[i, j] = element; } } return result; }
// Create a translation matrix public static Matrix3 Translate3(float dx, float dy, float dz) { Matrix3 result = new Matrix3(); result.M[0, 3] = dx; result.M[1, 3] = dy; result.M[2, 3] = dz; return result; }
// Top view projection matrix: public static Matrix3 TopView() { Matrix3 result = new Matrix3(); result.M[1, 1] = 0; result.M[2, 2] = 0; result.M[1, 2] = -1; return result; }
// Side view projection matrix: public static Matrix3 SideView() { Matrix3 result = new Matrix3(); result.M[0, 0] = 0; result.M[2, 2] = 0; result.M[0, 2] = -1; return result; }
// Create a scaling matrix: public static Matrix3 Scale3(float sx, float sy, float sz) { Matrix3 result = new Matrix3(); result.M[0, 0] = sx; result.M[1, 1] = sy; result.M[2, 2] = sz; return result; }
// Create a rotation matrix around the z axis: public static Matrix3 Rotate3Z(float theta) { theta = theta * (float)Math.PI / 180.0f; float sn = (float)Math.Sin(theta); float cn = (float)Math.Cos(theta); Matrix3 result = new Matrix3(); result.M[0, 0] = cn; result.M[0, 1] = -sn; result.M[1, 0] = sn; result.M[1, 1] = cn; return result; }
private void DrawBar(Graphics g, DataSeries ds, ChartStyle cs, Matrix3 m, Point3 pt, float xlength, float ylength, float zorign, float zmax, float zmin, Axes ax, ViewAngle va, ChartLabels cl) { Pen aPen = new Pen(ds.LineStyle.LineColor, ds.LineStyle.Thickness); aPen.DashStyle = ds.LineStyle.Pattern; Color color = AddColor(cs, pt, zmin, zmax, ax, va, cl); SolidBrush aBrush = new SolidBrush(color); Point3[] pts = new Point3[8]; Point3[] pts1 = new Point3[8]; Point3[] pt3 = new Point3[4]; PointF[] pta = new PointF[4]; pts[0] = new Point3(pt.X - xlength, pt.Y - ylength, zorign, 1); pts[1] = new Point3(pt.X - xlength, pt.Y + ylength, zorign, 1); pts[2] = new Point3(pt.X + xlength, pt.Y + ylength, zorign, 1); pts[3] = new Point3(pt.X + xlength, pt.Y - ylength, zorign, 1); pts[4] = new Point3(pt.X + xlength, pt.Y - ylength, pt.Z, 1); pts[5] = new Point3(pt.X + xlength, pt.Y + ylength, pt.Z, 1); pts[6] = new Point3(pt.X - xlength, pt.Y + ylength, pt.Z, 1); pts[7] = new Point3(pt.X - xlength, pt.Y - ylength, pt.Z, 1); for (int i = 0; i < pts.Length; i++) { pts1[i] = new Point3(pts[i].X, pts[i].Y, pts[i].Z, 1); pts[i].Transform(m, chart3d, ax, cs, cl); } int[] nconfigs = new int[8]; if (ds.BarStyle.IsBarSingleColor) { pta[0] = new PointF(pts[4].X, pts[4].Y); pta[1] = new PointF(pts[5].X, pts[5].Y); pta[2] = new PointF(pts[6].X, pts[6].Y); pta[3] = new PointF(pts[7].X, pts[7].Y); g.FillPolygon(aBrush, pta); g.DrawPolygon(aPen, pta); pta[0] = new PointF(pts[0].X, pts[0].Y); pta[1] = new PointF(pts[1].X, pts[1].Y); pta[2] = new PointF(pts[2].X, pts[2].Y); pta[3] = new PointF(pts[3].X, pts[3].Y); g.FillPolygon(aBrush, pta); g.DrawPolygon(aPen, pta); if (va.Azimuth >= -180 && va.Azimuth < -90) { nconfigs = new int[8] { 1, 2, 5, 6, 1, 0, 7, 6 }; } else if (va.Azimuth >= -90 && va.Azimuth < 0) { nconfigs = new int[8] { 1, 0, 7, 6, 0, 3, 4, 7 }; } else if (va.Azimuth >= 0 && va.Azimuth < 90) { nconfigs = new int[8] { 0, 3, 4, 7, 2, 3, 4, 5 }; } else if (va.Azimuth >= 90 && va.Azimuth < 180) { nconfigs = new int[8] { 2, 3, 4, 5, 1, 2, 5, 6 }; } pta[0] = new PointF(pts[nconfigs[0]].X, pts[nconfigs[0]].Y); pta[1] = new PointF(pts[nconfigs[1]].X, pts[nconfigs[1]].Y); pta[2] = new PointF(pts[nconfigs[2]].X, pts[nconfigs[2]].Y); pta[3] = new PointF(pts[nconfigs[3]].X, pts[nconfigs[3]].Y); g.FillPolygon(aBrush, pta); g.DrawPolygon(aPen, pta); pta[0] = new PointF(pts[nconfigs[4]].X, pts[nconfigs[4]].Y); pta[1] = new PointF(pts[nconfigs[5]].X, pts[nconfigs[5]].Y); pta[2] = new PointF(pts[nconfigs[6]].X, pts[nconfigs[6]].Y); pta[3] = new PointF(pts[nconfigs[7]].X, pts[nconfigs[7]].Y); g.FillPolygon(aBrush, pta); g.DrawPolygon(aPen, pta); } else if (!ds.BarStyle.IsBarSingleColor && IsColorMap) { pta[0] = new PointF(pts[4].X, pts[4].Y); pta[1] = new PointF(pts[5].X, pts[5].Y); pta[2] = new PointF(pts[6].X, pts[6].Y); pta[3] = new PointF(pts[7].X, pts[7].Y); g.FillPolygon(aBrush, pta); g.DrawPolygon(aPen, pta); pta[0] = new PointF(pts[0].X, pts[0].Y); pta[1] = new PointF(pts[1].X, pts[1].Y); pta[2] = new PointF(pts[2].X, pts[2].Y); pta[3] = new PointF(pts[3].X, pts[3].Y); color = AddColor(cs, pts[0], zmin, zmax, ax, va, cl); aBrush = new SolidBrush(color); g.FillPolygon(aBrush, pta); g.DrawPolygon(aPen, pta); float dz = (zmax - zmin) / 63; if (pt.Z < zorign) dz = -dz; int nz = (int)((pt.Z - zorign) / dz) + 1; if (nz < 1) nz = 1; float z = zorign; if (va.Azimuth >= -180 && va.Azimuth < -90) { nconfigs = new int[4] { 1, 2, 1, 0 }; } else if (va.Azimuth >= -90 && va.Azimuth < 0) { nconfigs = new int[4] { 1, 0, 0, 3 }; } else if (va.Azimuth >= 0 && va.Azimuth < 90) { nconfigs = new int[4] { 0, 3, 2, 3 }; } else if (va.Azimuth >= 90 && va.Azimuth <= 180) { nconfigs = new int[4] { 2, 3, 1, 2 }; } for (int i = 0; i < nz; i++) { z = zorign + i * dz; pt3[0] = new Point3(pts1[nconfigs[0]].X, pts1[nconfigs[0]].Y, z, 1); pt3[1] = new Point3(pts1[nconfigs[1]].X, pts1[nconfigs[1]].Y, z, 1); pt3[2] = new Point3(pts1[nconfigs[1]].X, pts1[nconfigs[1]].Y, z + dz, 1); pt3[3] = new Point3(pts1[nconfigs[0]].X, pts1[nconfigs[0]].Y, z + dz, 1); for (int j = 0; j < pt3.Length; j++) { pt3[j].Transform(m, chart3d, ax, cs, cl); } pta[0] = new PointF(pt3[0].X, pt3[0].Y); pta[1] = new PointF(pt3[1].X, pt3[1].Y); pta[2] = new PointF(pt3[2].X, pt3[2].Y); pta[3] = new PointF(pt3[3].X, pt3[3].Y); color = AddColor(cs, pt3[0], zmin, zmax, ax, va, cl); aBrush = new SolidBrush(color); g.FillPolygon(aBrush, pta); } pt3[0] = new Point3(pts1[nconfigs[0]].X, pts1[nconfigs[0]].Y, zorign, 1); pt3[1] = new Point3(pts1[nconfigs[1]].X, pts1[nconfigs[1]].Y, zorign, 1); pt3[2] = new Point3(pts1[nconfigs[1]].X, pts1[nconfigs[1]].Y, pt.Z, 1); pt3[3] = new Point3(pts1[nconfigs[0]].X, pts1[nconfigs[0]].Y, pt.Z, 1); for (int j = 0; j < pt3.Length; j++) { pt3[j].Transform(m, chart3d, ax, cs, cl); } pta[0] = new PointF(pt3[0].X, pt3[0].Y); pta[1] = new PointF(pt3[1].X, pt3[1].Y); pta[2] = new PointF(pt3[2].X, pt3[2].Y); pta[3] = new PointF(pt3[3].X, pt3[3].Y); g.DrawPolygon(aPen, pta); for (int i = 0; i < nz; i++) { z = zorign + i * dz; pt3[0] = new Point3(pts1[nconfigs[2]].X, pts1[nconfigs[2]].Y, z, 1); pt3[1] = new Point3(pts1[nconfigs[3]].X, pts1[nconfigs[3]].Y, z, 1); pt3[2] = new Point3(pts1[nconfigs[3]].X, pts1[nconfigs[3]].Y, z + dz, 1); pt3[3] = new Point3(pts1[nconfigs[2]].X, pts1[nconfigs[2]].Y, z + dz, 1); for (int j = 0; j < pt3.Length; j++) { pt3[j].Transform(m, chart3d, ax, cs, cl); } pta[0] = new PointF(pt3[0].X, pt3[0].Y); pta[1] = new PointF(pt3[1].X, pt3[1].Y); pta[2] = new PointF(pt3[2].X, pt3[2].Y); pta[3] = new PointF(pt3[3].X, pt3[3].Y); color = AddColor(cs, pt3[0], zmin, zmax, ax, va, cl); aBrush = new SolidBrush(color); g.FillPolygon(aBrush, pta); } pt3[0] = new Point3(pts1[nconfigs[2]].X, pts1[nconfigs[2]].Y, zorign, 1); pt3[1] = new Point3(pts1[nconfigs[3]].X, pts1[nconfigs[3]].Y, zorign, 1); pt3[2] = new Point3(pts1[nconfigs[3]].X, pts1[nconfigs[3]].Y, pt.Z, 1); pt3[3] = new Point3(pts1[nconfigs[2]].X, pts1[nconfigs[2]].Y, pt.Z, 1); for (int j = 0; j < pt3.Length; j++) { pt3[j].Transform(m, chart3d, ax, cs, cl); } pta[0] = new PointF(pt3[0].X, pt3[0].Y); pta[1] = new PointF(pt3[1].X, pt3[1].Y); pta[2] = new PointF(pt3[2].X, pt3[2].Y); pta[3] = new PointF(pt3[3].X, pt3[3].Y); g.DrawPolygon(aPen, pta); } aPen.Dispose(); aBrush.Dispose(); }
// Oblique projection matrix: public static Matrix3 Oblique(float alpha, float theta) { Matrix3 result = new Matrix3(); float ta = (float)Math.Tan(alpha * Math.PI / 180); float snt = (float)Math.Sin(theta * Math.PI / 180); float cnt = (float)Math.Cos(theta * Math.PI / 180); result.M[0, 2] = -cnt / ta; result.M[1, 2] = -snt / ta; result.M[2, 2] = 0; return result; }
// Front view projection matrix: public static Matrix3 FrontView() { Matrix3 result = new Matrix3(); result.M[2, 2] = 0; return result; }
public static Matrix3 Euler(float alpha, float beta, float gamma) { Matrix3 result = new Matrix3(); alpha = alpha * (float)Math.PI / 180.0f; float sna = (float)Math.Sin(alpha); float cna = (float)Math.Cos(alpha); beta = beta * (float)Math.PI / 180.0f; float snb = (float)Math.Sin(beta); float cnb = (float)Math.Cos(beta); gamma = gamma * (float)Math.PI / 180.0f; float sng = (float)Math.Sin(gamma); float cng = (float)Math.Cos(gamma); result.M[0, 0] = cna * cng - sna * snb * sng; result.M[0, 1] = -snb * sng; result.M[0, 2] = sna * cng - cna * cnb * sng; result.M[1, 0] = -sna * snb; result.M[1, 1] = cnb; result.M[1, 2] = cna * snb; result.M[2, 0] = -cna * sng - sna * cnb * cng; result.M[2, 1] = -snb * cng; result.M[2, 2] = cna * cnb * cng - sna * snb; return result; }
private void AddContour(Graphics g, DataSeries ds, ChartStyle cs, ChartStyle2D cs2d, Axes ax, ViewAngle va, ChartLabels cl) { Pen aPen = new Pen(ds.LineStyle.LineColor, ds.LineStyle.Thickness); aPen.DashStyle = ds.LineStyle.Pattern; SolidBrush aBrush = new SolidBrush(Color.White); PointF[] pta = new PointF[2]; Point3[,] pts = ds.PointArray; Matrix3 m = new Matrix3(); // Find the minumum and maximum z values: float zmin = ds.ZDataMin(); float zmax = ds.ZDataMax(); float[] zlevels = new float[numberContours]; for (int i = 0; i < numberContours; i++) { zlevels[i] = zmin + i * (zmax - zmin) / (numberContours - 1); } int i0, i1, i2, j0, j1, j2; float zratio = 1; // Draw contour on the XY plane: for (int i = 0; i < pts.GetLength(0) - 1; i++) { for (int j = 0; j < pts.GetLength(1) - 1; j++) { if (IsColorMap && ChartType != ChartTypeEnum.FillContour && ChartType != ChartTypeEnum.SurfaceFillContour) { Color color = AddColor(cs, pts[i, j], zmin, zmax, ax, va, cl); aPen = new Pen(color, ds.LineStyle.Thickness); aPen.DashStyle = ds.LineStyle.Pattern; } for (int k = 0; k < numberContours; k++) { // Left triangle: i0 = i; j0 = j; i1 = i; j1 = j + 1; i2 = i + 1; j2 = j + 1; if ((zlevels[k] >= pts[i0, j0].Z && zlevels[k] < pts[i1, j1].Z || zlevels[k] < pts[i0, j0].Z && zlevels[k] >= pts[i1, j1].Z) && (zlevels[k] >= pts[i1, j1].Z && zlevels[k] < pts[i2, j2].Z || zlevels[k] < pts[i1, j1].Z && zlevels[k] >= pts[i2, j2].Z)) { zratio = (zlevels[k] - pts[i0, j0].Z) / (pts[i1, j1].Z - pts[i0, j0].Z); pta[0] = cs2d.Point2D(new PointF(pts[i0, j0].X, (1 - zratio) * pts[i0, j0].Y + zratio * pts[i1, j1].Y), ax); zratio = (zlevels[k] - pts[i1, j1].Z) / (pts[i2, j2].Z - pts[i1, j1].Z); pta[1] = cs2d.Point2D(new PointF((1 - zratio) * pts[i1, j1].X + zratio * pts[i2, j2].X, pts[i1, j1].Y), ax); g.DrawLine(aPen, pta[0], pta[1]); } else if ((zlevels[k] >= pts[i0, j0].Z && zlevels[k] < pts[i2, j2].Z || zlevels[k] < pts[i0, j0].Z && zlevels[k] >= pts[i2, j2].Z) && (zlevels[k] >= pts[i1, j1].Z && zlevels[k] < pts[i2, j2].Z || zlevels[k] < pts[i1, j1].Z && zlevels[k] >= pts[i2, j2].Z)) { zratio = (zlevels[k] - pts[i0, j0].Z) / (pts[i2, j2].Z - pts[i0, j0].Z); pta[0] = cs2d.Point2D(new PointF((1 - zratio) * pts[i0, j0].X + zratio * pts[i2, j2].X, (1 - zratio) * pts[i0, j0].Y + zratio * pts[i2, j2].Y), ax); zratio = (zlevels[k] - pts[i1, j1].Z) / (pts[i2, j2].Z - pts[i1, j1].Z); pta[1] = cs2d.Point2D(new PointF((1 - zratio) * pts[i1, j1].X + zratio * pts[i2, j2].X, pts[i1, j1].Y), ax); g.DrawLine(aPen, pta[0], pta[1]); } else if ((zlevels[k] >= pts[i0, j0].Z && zlevels[k] < pts[i1, j1].Z || zlevels[k] < pts[i0, j0].Z && zlevels[k] >= pts[i1, j1].Z) && (zlevels[k] >= pts[i0, j0].Z && zlevels[k] < pts[i2, j2].Z || zlevels[k] < pts[i0, j0].Z && zlevels[k] >= pts[i2, j2].Z)) { zratio = (zlevels[k] - pts[i0, j0].Z) / (pts[i1, j1].Z - pts[i0, j0].Z); pta[0] = cs2d.Point2D(new PointF(pts[i0, j0].X, (1 - zratio) * pts[i0, j0].Y + zratio * pts[i1, j1].Y), ax); zratio = (zlevels[k] - pts[i0, j0].Z) / (pts[i2, j2].Z - pts[i0, j0].Z); pta[1] = cs2d.Point2D(new PointF(pts[i0, j0].X * (1 - zratio) + pts[i2, j2].X * zratio, pts[i0, j0].Y * (1 - zratio) + pts[i2, j2].Y * zratio), ax); g.DrawLine(aPen, pta[0], pta[1]); } // right triangle: i0 = i; j0 = j; i1 = i + 1; j1 = j; i2 = i + 1; j2 = j + 1; if ((zlevels[k] >= pts[i0, j0].Z && zlevels[k] < pts[i1, j1].Z || zlevels[k] < pts[i0, j0].Z && zlevels[k] >= pts[i1, j1].Z) && (zlevels[k] >= pts[i1, j1].Z && zlevels[k] < pts[i2, j2].Z || zlevels[k] < pts[i1, j1].Z && zlevels[k] >= pts[i2, j2].Z)) { zratio = (zlevels[k] - pts[i0, j0].Z) / (pts[i1, j1].Z - pts[i0, j0].Z); pta[0] = cs2d.Point2D(new PointF(pts[i0, j0].X * (1 - zratio) + pts[i1, j1].X * zratio, pts[i0, j0].Y), ax); zratio = (zlevels[k] - pts[i1, j1].Z) / (pts[i2, j2].Z - pts[i1, j1].Z); pta[1] = cs2d.Point2D(new PointF(pts[i1, j1].X, pts[i1, j1].Y * (1 - zratio) + pts[i2, j2].Y * zratio), ax); g.DrawLine(aPen, pta[0], pta[1]); } else if ((zlevels[k] >= pts[i0, j0].Z && zlevels[k] < pts[i2, j2].Z || zlevels[k] < pts[i0, j0].Z && zlevels[k] >= pts[i2, j2].Z) && (zlevels[k] >= pts[i1, j1].Z && zlevels[k] < pts[i2, j2].Z || zlevels[k] < pts[i1, j1].Z && zlevels[k] >= pts[i2, j2].Z)) { zratio = (zlevels[k] - pts[i0, j0].Z) / (pts[i2, j2].Z - pts[i0, j0].Z); pta[0] = cs2d.Point2D(new PointF(pts[i0, j0].X * (1 - zratio) + pts[i2, j2].X * zratio, pts[i0, j0].Y * (1 - zratio) + pts[i2, j2].Y * zratio), ax); zratio = (zlevels[k] - pts[i1, j1].Z) / (pts[i2, j2].Z - pts[i1, j1].Z); pta[1] = cs2d.Point2D(new PointF(pts[i1, j1].X, pts[i1, j1].Y * (1 - zratio) + pts[i2, j2].Y * zratio), ax); g.DrawLine(aPen, pta[0], pta[1]); } else if ((zlevels[k] >= pts[i0, j0].Z && zlevels[k] < pts[i1, j1].Z || zlevels[k] < pts[i0, j0].Z && zlevels[k] >= pts[i1, j1].Z) && (zlevels[k] >= pts[i0, j0].Z && zlevels[k] < pts[i2, j2].Z || zlevels[k] < pts[i0, j0].Z && zlevels[k] >= pts[i2, j2].Z)) { zratio = (zlevels[k] - pts[i0, j0].Z) / (pts[i1, j1].Z - pts[i0, j0].Z); pta[0] = cs2d.Point2D(new PointF(pts[i0, j0].X * (1 - zratio) + pts[i1, j1].X * zratio, pts[i0, j0].Y), ax); zratio = (zlevels[k] - pts[i0, j0].Z) / (pts[i2, j2].Z - pts[i0, j0].Z); pta[1] = cs2d.Point2D(new PointF(pts[i0, j0].X * (1 - zratio) + pts[i2, j2].X * zratio, pts[i0, j0].Y * (1 - zratio) + pts[i2, j2].Y * zratio), ax); g.DrawLine(aPen, pta[0], pta[1]); } } } } }
private void Interp(Graphics g, ChartStyle cs, ChartStyle2D cs2d, Matrix3 m, Point3[] pta, float zmin, float zmax, int flag, Axes ax, ViewAngle va, ChartLabels cl) { SolidBrush aBrush = new SolidBrush(Color.Black); PointF[] points = new PointF[4]; int npoints = NumberInterp; Point3[,] pts = new Point3[npoints + 1, npoints + 1]; Point3[,] pts1 = new Point3[npoints + 1, npoints + 1]; float x0 = pta[0].X; float y0 = pta[0].Y; float x1 = pta[2].X; float y1 = pta[2].Y; float dx = (x1 - x0) / npoints; float dy = (y1 - y0) / npoints; float C00 = pta[0].Z; float C10 = pta[3].Z; float C11 = pta[2].Z; float C01 = pta[1].Z; float x, y, C; Color color; if (flag == 1) // For Surface chart { for (int i = 0; i <= npoints; i++) { x = x0 + i * dx; for (int j = 0; j <= npoints; j++) { y = y0 + j * dy; C = (y1 - y) * ((x1 - x) * C00 + (x - x0) * C10) / (x1 - x0) / (y1 - y0) + (y - y0) * ((x1 - x) * C01 + (x - x0) * C11) / (x1 - x0) / (y1 - y0); pts[i, j] = new Point3(x, y, C, 1); pts[i, j].Transform(m, chart3d, ax, cs, cl); } } for (int i = 0; i < npoints; i++) { for (int j = 0; j < npoints; j++) { color = AddColor(cs, pts[i, j], zmin, zmax, ax, va, cl); aBrush = new SolidBrush(color); points[0] = new PointF(pts[i, j].X, pts[i, j].Y); points[1] = new PointF(pts[i + 1, j].X, pts[i + 1, j].Y); points[2] = new PointF(pts[i + 1, j + 1].X, pts[i + 1, j + 1].Y); points[3] = new PointF(pts[i, j + 1].X, pts[i, j + 1].Y); g.FillPolygon(aBrush, points); aBrush.Dispose(); } } } else if (flag == 2) // For XYColor chart { for (int i = 0; i <= npoints; i++) { x = x0 + i * dx; for (int j = 0; j <= npoints; j++) { y = y0 + j * dy; C = (y1 - y) * ((x1 - x) * C00 + (x - x0) * C10) / (x1 - x0) / (y1 - y0) + (y - y0) * ((x1 - x) * C01 + (x - x0) * C11) / (x1 - x0) / (y1 - y0); pts[i, j] = new Point3(x, y, C, 1); } } for (int i = 0; i < npoints; i++) { for (int j = 0; j < npoints; j++) { color = AddColor(cs, pts[i, j], zmin, zmax, ax, va, cl); aBrush = new SolidBrush(color); points[0] = cs2d.Point2D(new PointF(pts[i, j].X, pts[i, j].Y), ax); points[1] = cs2d.Point2D(new PointF(pts[i + 1, j].X, pts[i + 1, j].Y), ax); points[2] = cs2d.Point2D(new PointF(pts[i + 1, j + 1].X, pts[i + 1, j + 1].Y), ax); points[3] = cs2d.Point2D(new PointF(pts[i, j + 1].X, pts[i, j + 1].Y), ax); g.FillPolygon(aBrush, points); aBrush.Dispose(); } } } else if (flag == 3) // For XYColor3D chart { for (int i = 0; i <= npoints; i++) { x = x0 + i * dx; for (int j = 0; j <= npoints; j++) { y = y0 + j * dy; C = (y1 - y) * ((x1 - x) * C00 + (x - x0) * C10) / (x1 - x0) / (y1 - y0) + (y - y0) * ((x1 - x) * C01 + (x - x0) * C11) / (x1 - x0) / (y1 - y0); pts1[i, j] = new Point3(x, y, C, 1); pts[i, j] = new Point3(x, y, ax.ZMin, 1); pts[i, j].Transform(m, chart3d, ax, cs, cl); } } for (int i = 0; i < npoints; i++) { for (int j = 0; j < npoints; j++) { color = AddColor(cs, pts1[i, j], zmin, zmax, ax, va, cl); aBrush = new SolidBrush(color); points[0] = new PointF(pts[i, j].X, pts[i, j].Y); points[1] = new PointF(pts[i + 1, j].X, pts[i + 1, j].Y); points[2] = new PointF(pts[i + 1, j + 1].X, pts[i + 1, j + 1].Y); points[3] = new PointF(pts[i, j + 1].X, pts[i, j + 1].Y); g.FillPolygon(aBrush, points); aBrush.Dispose(); } } } }
// Perspective projection matrix: public static Matrix3 Perspective(float d) { Matrix3 result = new Matrix3(); result.M[3, 2] = -1 / d; return result; }
public static Matrix3 AzimuthElevation(float elevation, float azimuth) { Matrix3 result = new Matrix3(); // make sure elevation in the range of [-90, 90]: if (elevation > 90) elevation = 90; else if (elevation < -90) elevation = -90; // Make sure azimuth in the range of [-180, 180]: if (azimuth > 180) azimuth = 180; else if (azimuth < -180) azimuth = -180; elevation = elevation * (float)Math.PI / 180.0f; float sne = (float)Math.Sin(elevation); float cne = (float)Math.Cos(elevation); azimuth = azimuth * (float)Math.PI / 180.0f; float sna = (float)Math.Sin(azimuth); float cna = (float)Math.Cos(azimuth); result.M[0, 0] = cna; result.M[0, 1] = sna; result.M[0, 2] = 0; result.M[1, 0] = -sne * sna; result.M[1, 1] = sne * cna; result.M[1, 2] = cne; result.M[2, 0] = cne * sna; result.M[2, 1] = -cne * cna; result.M[2, 2] = sne; return result; }
private void AddXYColor(Graphics g, DataSeries ds, ChartStyle cs, ChartStyle2D cs2d, Axes ax, ViewAngle va, ChartLabels cl) { Pen aPen = new Pen(ds.LineStyle.LineColor, ds.LineStyle.Thickness); aPen.DashStyle = ds.LineStyle.Pattern; SolidBrush aBrush = new SolidBrush(Color.White); PointF[] pta = new PointF[4]; Point3[,] pts = ds.PointArray; Matrix3 m = new Matrix3(); // Find the minumum and maximum z values: float zmin = ds.ZDataMin(); float zmax = ds.ZDataMax(); // Draw surface on the XY plane: if (!IsInterp) { for (int i = 0; i < pts.GetLength(0) - 1; i++) { for (int j = 0; j < pts.GetLength(1) - 1; j++) { pta[0] = cs2d.Point2D(new PointF(pts[i, j].X, pts[i, j].Y), ax); pta[1] = cs2d.Point2D(new PointF(pts[i, j + 1].X, pts[i, j + 1].Y), ax); pta[2] = cs2d.Point2D(new PointF(pts[i + 1, j + 1].X, pts[i + 1, j + 1].Y), ax); pta[3] = cs2d.Point2D(new PointF(pts[i + 1, j].X, pts[i + 1, j].Y), ax); Color color = AddColor(cs, pts[i, j], zmin, zmax, ax, va, cl); aBrush = new SolidBrush(color); g.FillPolygon(aBrush, pta); if (ds.LineStyle.IsVisible) { g.DrawPolygon(aPen, pta); } } } } // Draw refined surface: else if (IsInterp) { for (int i = 0; i < pts.GetLength(0) - 1; i++) { for (int j = 0; j < pts.GetLength(1) - 1; j++) { Point3[] points = new Point3[4]; points[0] = pts[i, j]; points[1] = pts[i, j + 1]; points[2] = pts[i + 1, j + 1]; points[3] = pts[i + 1, j]; Interp(g, cs, cs2d, m, points, zmin, zmax, 2, ax, va, cl); pta[0] = cs2d.Point2D(new PointF(pts[i, j].X, pts[i, j].Y), ax); pta[1] = cs2d.Point2D(new PointF(pts[i, j + 1].X, pts[i, j + 1].Y), ax); pta[2] = cs2d.Point2D(new PointF(pts[i + 1, j + 1].X, pts[i + 1, j + 1].Y), ax); pta[3] = cs2d.Point2D(new PointF(pts[i + 1, j].X, pts[i + 1, j].Y), ax); if (ds.LineStyle.IsVisible) { g.DrawPolygon(aPen, pta); } } } } }