private void AddXYColor(ChartStyle2D cs2d, DataSeriesSurface ds)
        {
            Point3D[,] pts = ds.PointArray;
            double zmin = ds.ZDataMin();
            double 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++)
                    {
                        plg                 = new Polygon();
                        plg.Stroke          = ds.LineColor;
                        plg.StrokeThickness = ds.LineThickness;
                        plg.Fill            = GetBrush(pts[i, j].Z, zmin, zmax);
                        if (IsLineColorMatch)
                        {
                            plg.Stroke = GetBrush(pts[i, j].Z, zmin, zmax);
                        }
                        plg.Points.Add(cs2d.NormalizePoint(new Point(pts[i, j].X, pts[i, j].Y)));
                        plg.Points.Add(cs2d.NormalizePoint(new Point(pts[i, j + 1].X, pts[i, j + 1].Y)));
                        plg.Points.Add(cs2d.NormalizePoint(new Point(pts[i + 1, j + 1].X, pts[i + 1, j + 1].Y)));
                        plg.Points.Add(cs2d.NormalizePoint(new Point(pts[i + 1, j].X, pts[i + 1, j].Y)));
                        cs2d.Chart2dCanvas.Children.Add(plg);
                    }
                }
            }
            else if (IsInterp)
            {
                for (int i = 0; i < pts.GetLength(0) - 1; i++)
                {
                    for (int j = 0; j < pts.GetLength(1) - 1; j++)
                    {
                        Point3D[] points = new Point3D[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];

                        Interp2D(cs2d, points, zmin, zmax);
                        plg        = new Polygon();
                        plg.Stroke = ds.LineColor;
                        if (IsLineColorMatch)
                        {
                            plg.Stroke = GetBrush(pts[i, j].Z, zmin, zmax);
                        }
                        plg.StrokeThickness = ds.LineThickness;
                        plg.Fill            = Brushes.Transparent;
                        plg.Points.Add(cs2d.NormalizePoint(new Point(pts[i, j].X, pts[i, j].Y)));
                        plg.Points.Add(cs2d.NormalizePoint(new Point(pts[i, j + 1].X, pts[i, j + 1].Y)));
                        plg.Points.Add(cs2d.NormalizePoint(new Point(pts[i + 1, j + 1].X, pts[i + 1, j + 1].Y)));
                        plg.Points.Add(cs2d.NormalizePoint(new Point(pts[i + 1, j].X, pts[i + 1, j].Y)));
                        cs2d.Chart2dCanvas.Children.Add(plg);
                    }
                }
            }
        }
        private void Interp2D(ChartStyle2D cs2d, Point3D[] pta, double zmin, double zmax)
        {
            Polygon plg = new Polygon();

            Point[] points  = new Point[4];
            int     npoints = NumberInterp;

            Point3D[,] pts = new Point3D[npoints + 1, npoints + 1];
            double x0 = pta[0].X;
            double y0 = pta[0].Y;
            double x1 = pta[2].X;
            double y1 = pta[2].Y;
            double dx = (x1 - x0) / npoints;
            double dy = (y1 - y0) / npoints;
            double c00 = pta[0].Z;
            double c10 = pta[3].Z;
            double c11 = pta[2].Z;
            double c01 = pta[1].Z;
            double x, y, c;

            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 Point3D(x, y, c);
                }
            }

            for (int i = 0; i < npoints; i++)
            {
                for (int j = 0; j < npoints; j++)
                {
                    plg = new Polygon();
                    Brush brush = GetBrush(pts[i, j].Z, zmin, zmax);
                    plg.Fill   = brush;
                    plg.Stroke = brush;
                    plg.Points.Add(cs2d.NormalizePoint(new Point(pts[i, j].X, pts[i, j].Y)));
                    plg.Points.Add(cs2d.NormalizePoint(new Point(pts[i, j + 1].X, pts[i, j + 1].Y)));
                    plg.Points.Add(cs2d.NormalizePoint(new Point(pts[i + 1, j + 1].X, pts[i + 1, j + 1].Y)));
                    plg.Points.Add(cs2d.NormalizePoint(new Point(pts[i + 1, j].X, pts[i + 1, j].Y)));
                    cs2d.Chart2dCanvas.Children.Add(plg);
                }
            }
        }
        private void AddContour(ChartStyle2D cs2d, DataSeriesSurface ds)
        {
            Point[]         pta   = new Point[2];
            SolidColorBrush brush = Brushes.Black;
            Line            line  = new Line();

            Point3D[,] pts = ds.PointArray;
            double zmin = ds.ZDataMin();
            double zmax = ds.ZDataMax();

            double[] zlevels = new double[NumberContours];

            for (int i = 0; i < NumberContours; i++)
            {
                zlevels[i] = zmin + i * (zmax - zmin) / (NumberContours - 1);
            }

            int    i0, i1, i2, j0, j1, j2;
            double 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)
                    {
                        brush = GetBrush(pts[i, j].Z, zmin, zmax);
                    }
                    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.NormalizePoint(new Point(pts[i0, j0].X, (1 - zratio) * pts[i0, j0].Y + zratio * pts[i1, j1].Y));
                            zratio = (zlevels[k] - pts[i1, j1].Z) / (pts[i2, j2].Z - pts[i1, j1].Z);
                            pta[1] = cs2d.NormalizePoint(new Point((1 - zratio) * pts[i1, j1].X + zratio * pts[i2, j2].X, pts[i1, j1].Y));
                            DrawLine(cs2d, ds, brush, 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.NormalizePoint(new Point((1 - zratio) * pts[i0, j0].X + zratio * pts[i2, j2].X,
                                                                   (1 - zratio) * pts[i0, j0].Y + zratio * pts[i2, j2].Y));
                            zratio = (zlevels[k] - pts[i1, j1].Z) / (pts[i2, j2].Z - pts[i1, j1].Z);
                            pta[1] = cs2d.NormalizePoint(new Point((1 - zratio) * pts[i1, j1].X + zratio * pts[i2, j2].X, pts[i1, j1].Y));
                            DrawLine(cs2d, ds, brush, 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.NormalizePoint(new Point(pts[i0, j0].X, (1 - zratio) * pts[i0, j0].Y + zratio * pts[i1, j1].Y));
                            zratio = (zlevels[k] - pts[i0, j0].Z) / (pts[i2, j2].Z - pts[i0, j0].Z);
                            pta[1] = cs2d.NormalizePoint(new Point(pts[i0, j0].X * (1 - zratio) + pts[i2, j2].X * zratio,
                                                                   pts[i0, j0].Y * (1 - zratio) + pts[i2, j2].Y * zratio));
                            DrawLine(cs2d, ds, brush, 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.NormalizePoint(new Point(pts[i0, j0].X * (1 - zratio) + pts[i1, j1].X * zratio, pts[i0, j0].Y));
                            zratio = (zlevels[k] - pts[i1, j1].Z) / (pts[i2, j2].Z - pts[i1, j1].Z);
                            pta[1] = cs2d.NormalizePoint(new Point(pts[i1, j1].X, pts[i1, j1].Y * (1 - zratio) + pts[i2, j2].Y * zratio));
                            DrawLine(cs2d, ds, brush, 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.NormalizePoint(new Point(pts[i0, j0].X * (1 - zratio) +
                                                                   pts[i2, j2].X * zratio, pts[i0, j0].Y * (1 - zratio) + pts[i2, j2].Y * zratio));
                            zratio = (zlevels[k] - pts[i1, j1].Z) / (pts[i2, j2].Z - pts[i1, j1].Z);
                            pta[1] = cs2d.NormalizePoint(new Point(pts[i1, j1].X, pts[i1, j1].Y * (1 - zratio) + pts[i2, j2].Y * zratio));
                            DrawLine(cs2d, ds, brush, 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.NormalizePoint(new Point(pts[i0, j0].X * (1 - zratio) + pts[i1, j1].X * zratio, pts[i0, j0].Y));
                            zratio = (zlevels[k] - pts[i0, j0].Z) / (pts[i2, j2].Z - pts[i0, j0].Z);
                            pta[1] = cs2d.NormalizePoint(new Point(pts[i0, j0].X * (1 - zratio) + pts[i2, j2].X * zratio,
                                                                   pts[i0, j0].Y * (1 - zratio) + pts[i2, j2].Y * zratio));
                            DrawLine(cs2d, ds, brush, pta[0], pta[1]);
                        }
                    }
                }
            }
        }