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);
                    }
                }
            }
        }
        public void AddChart(ChartStyle2D cs, DataSeriesSurface ds)
        {
            switch (ChartType)
            {
            case ChartTypeEnum.XYColor:
                cs.AddChartStyle2D(this);
                if (cs.IsColorBar && IsColormap)
                {
                    cs.AddColorBar2D(cs, ds, this, ds.ZDataMin(), ds.ZDataMax());
                }
                AddXYColor(cs, ds);
                break;

            case ChartTypeEnum.Contour:
                cs.AddChartStyle2D(this);
                if (cs.IsColorBar && IsColormap)
                {
                    cs.AddColorBar2D(cs, ds, this, ds.ZDataMin(), ds.ZDataMax());
                }
                AddContour(cs, ds);
                break;

            case ChartTypeEnum.FillContour:
                cs.AddChartStyle2D(this);
                if (cs.IsColorBar && IsColormap)
                {
                    cs.AddColorBar2D(cs, ds, this, ds.ZDataMin(), ds.ZDataMax());
                }
                AddXYColor(cs, ds);
                AddContour(cs, ds);
                break;

            case ChartTypeEnum.MeshContour3D:
                cs.AddChartStyle();
                AddContour3D(cs, ds);
                AddMesh(cs, ds);
                break;

            case ChartTypeEnum.SurfaceContour3D:
                cs.AddChartStyle();
                AddContour3D(cs, ds);
                AddSurface(cs, ds);
                break;

            case ChartTypeEnum.SurfaceFillContour3D:
                cs.AddChartStyle();
                AddXYColor3D(cs, ds);
                AddContour3D(cs, ds);
                AddSurface(cs, ds);
                break;
            }
        }
        private void DrawPolygon(ChartStyle2D cs, Bar3DStyle bs, Point[] pts, SolidColorBrush fillBrush, SolidColorBrush lineBrush)
        {
            Polygon plg = new Polygon();

            plg.Stroke          = lineBrush;
            plg.StrokeThickness = bs.LineThickness;
            plg.Fill            = fillBrush;
            for (int i = 0; i < pts.Length; i++)
            {
                plg.Points.Add(pts[i]);
            }
            cs.ChartCanvas.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);
                }
            }
        }
Пример #5
0
        private void AddChart()
        {
            chartCanvas.Children.Clear();
            cs                 = new ChartStyle2D();
            cs.ChartCanvas     = this.chartCanvas;
            cs.GridlinePattern = ChartStyle.GridlinePatternEnum.Solid;
            cs.IsColorBar      = true;
            cs.Title           = "No Title";
            ds                 = new DataSeriesSurface();
            Utility.Peak3D(cs, ds);

            d3c = new Draw3DChart();
            d3c.Colormap.ColormapBrushType = ColormapBrush.ColormapBrushEnum.Jet;
            d3c.ChartType        = Draw3DChart.ChartTypeEnum.MeshContour3D;
            d3c.IsLineColorMatch = true;
            d3c.NumberContours   = 15;
            d3c.AddChart(cs, ds);
        }
        private void DrawLine(ChartStyle2D cs2d, DataSeriesSurface ds, SolidColorBrush brush, Point pt0, Point pt1)
        {
            Line line = new Line();

            if (IsLineColorMatch)
            {
                line.Stroke = brush;
            }
            else
            {
                line.Stroke = ds.LineColor;
            }
            line.StrokeThickness = ds.LineThickness;
            line.X1 = pt0.X;
            line.Y1 = pt0.Y;
            line.X2 = pt1.X;
            line.Y2 = pt1.Y;
            cs2d.Chart2dCanvas.Children.Add(line);
        }
 private void AddChart()
 {
     chartCanvas.Children.Clear();
     cs                 = new ChartStyle2D();
     cs.ChartCanvas     = this.chartCanvas;
     cs.GridlinePattern = ChartStyle.GridlinePatternEnum.Solid;
     cs.Elevation       = 30;
     cs.Azimuth         = -37;
     cs.Title           = "No Title";
     cs.IsColorBar      = true;
     ds                 = new DataSeriesSurface();
     ds.LineColor       = Brushes.Transparent;
     Utility.Peak3D(cs, ds);
     d3c           = new Draw3DChart();
     d3c.ChartType = Draw3DChart.ChartTypeEnum.XYColor;
     cs.AddChartStyle2D(d3c);
     d3c.IsInterp     = true;
     d3c.NumberInterp = 5;
     d3c.AddChart(cs, ds);
 }
Пример #8
0
        private void AddChart()
        {
            chartCanvas.Children.Clear();
            cs                 = new ChartStyle2D();
            cs.ChartCanvas     = this.chartCanvas;
            cs.GridlinePattern = ChartStyle.GridlinePatternEnum.Solid;
            cs.IsColorBar      = true;
            cs.Title           = "No Title";
            ds                 = new Bar3DStyle();
            ds.LineColor       = Brushes.Black;
            ds.ZOrigin         = 0;
            ds.XLength         = 0.6;
            ds.YLength         = 0.6;
            Utility.Peak3D(cs, ds);

            d3c = new Draw3DChart();
            d3c.Colormap.ColormapBrushType = ColormapBrush.ColormapBrushEnum.Jet;
            d3c.IsBarSingleColor           = true;
            d3c.IsColormap = true;

            cs.AddChartStyle();
            d3c.AddBar3D(cs, ds);
        }
        public void AddColorBar2D(ChartStyle2D cs, DataSeriesSurface ds, Draw3DChart dsc, double zmin, double zmax)
        {
            TextBlock tb;

            tb            = new TextBlock();
            tb.Text       = "A";
            tb.FontFamily = cs.TickFont;
            tb.FontSize   = cs.TickFontSize;
            tb.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
            Size tickSize = tb.DesiredSize;

            double x      = 8 * cs.ChartCanvas.Width / 9;
            double y      = 7;
            double width  = cs.ChartCanvas.Width / 25;
            double height = chart2dCanvas.Height;

            Point3D[] pts = new Point3D[64];
            double    dz  = (zmax - zmin) / 63;

            // Create the color bar:
            Polygon plg;

            for (int i = 0; i < 64; i++)
            {
                pts[i] = new Point3D(x, y, zmin + i * dz);
            }
            for (int i = 0; i < 63; i++)
            {
                SolidColorBrush brush = dsc.GetBrush(pts[i].Z, zmin, zmax);
                double          y1    = y + height - (pts[i].Z - zmin) * height / (zmax - zmin);
                double          y2    = y + height - (pts[i + 1].Z - zmin) * height / (zmax - zmin);
                plg = new Polygon();
                plg.Points.Add(new Point(x, y2));
                plg.Points.Add(new Point(x + width, y2));
                plg.Points.Add(new Point(x + width, y1));
                plg.Points.Add(new Point(x, y1));
                plg.Fill   = brush;
                plg.Stroke = brush;
                cs.ChartCanvas.Children.Add(plg);
            }
            Rectangle rect = new Rectangle();

            rect.Width  = width + 2;
            rect.Height = height + 2;
            rect.Stroke = Brushes.Black;
            Canvas.SetLeft(rect, x - 1);
            Canvas.SetTop(rect, y - 1);
            cs.ChartCanvas.Children.Add(rect);

            // Add ticks and labels to the color bar:
            double tickLength = 0.15 * width;

            for (double z = zmin; z <= zmax; z = z + (zmax - zmin) / 6)
            {
                double yy = y + height - (z - zmin) * height / (zmax - zmin);
                dsc.AddTickLine(cs, new Point(x, yy), new Point(x + tickLength, yy));
                dsc.AddTickLine(cs, new Point(x + width, yy), new Point(x + width - tickLength, yy));
                tb            = new TextBlock();
                tb.Text       = (Math.Round(z, 2)).ToString();
                tb.FontFamily = cs.TickFont;
                tb.FontSize   = cs.TickFontSize;
                cs.ChartCanvas.Children.Add(tb);
                Canvas.SetLeft(tb, x + width + 5);
                Canvas.SetTop(tb, yy - tickSize.Height / 2);
            }
        }
        private void DrawBar(ChartStyle2D cs, Bar3DStyle bs, Matrix3D m, Point3D pt, double xlength, double ylength,
                             double zorign, double zmax, double zmin)
        {
            SolidColorBrush lineBrush = (SolidColorBrush)bs.LineColor;
            SolidColorBrush fillBrush = GetBrush(pt.Z, zmin, zmax);

            Point3D[] pts  = new Point3D[8];
            Point3D[] pts1 = new Point3D[8];
            Point3D[] pt3  = new Point3D[4];
            Point[]   pta  = new Point[4];

            pts[0] = new Point3D(pt.X - xlength, pt.Y - ylength, zorign);
            pts[1] = new Point3D(pt.X - xlength, pt.Y + ylength, zorign);
            pts[2] = new Point3D(pt.X + xlength, pt.Y + ylength, zorign);
            pts[3] = new Point3D(pt.X + xlength, pt.Y - ylength, zorign);
            pts[4] = new Point3D(pt.X + xlength, pt.Y - ylength, pt.Z);
            pts[5] = new Point3D(pt.X + xlength, pt.Y + ylength, pt.Z);
            pts[6] = new Point3D(pt.X - xlength, pt.Y + ylength, pt.Z);
            pts[7] = new Point3D(pt.X - xlength, pt.Y - ylength, pt.Z);

            for (int i = 0; i < pts.Length; i++)
            {
                pts1[i] = new Point3D(pts[i].X, pts[i].Y, pts[i].Z);
                pts[i]  = cs.Normalize3D(m, pts[i]);
            }

            int[] nconfigs = new int[8];
            if (IsBarSingleColor)
            {
                pta[0] = new Point(pts[4].X, pts[4].Y);
                pta[1] = new Point(pts[5].X, pts[5].Y);
                pta[2] = new Point(pts[6].X, pts[6].Y);
                pta[3] = new Point(pts[7].X, pts[7].Y);
                DrawPolygon(cs, bs, pta, fillBrush, lineBrush);

                if (cs.Azimuth >= -180 && cs.Azimuth < -90)
                {
                    nconfigs = new int[8] {
                        1, 2, 5, 6, 1, 0, 7, 6
                    };
                }
                else if (cs.Azimuth >= -90 && cs.Azimuth < 0)
                {
                    nconfigs = new int[8] {
                        1, 0, 7, 6, 0, 3, 4, 7
                    };
                }
                else if (cs.Azimuth >= 0 && cs.Azimuth < 90)
                {
                    nconfigs = new int[8] {
                        0, 3, 4, 7, 2, 3, 4, 5
                    };
                }
                else if (cs.Azimuth >= 90 && cs.Azimuth < 180)
                {
                    nconfigs = new int[8] {
                        2, 3, 4, 5, 1, 2, 5, 6
                    };
                }
                pta[0] = new Point(pts[nconfigs[0]].X, pts[nconfigs[0]].Y);
                pta[1] = new Point(pts[nconfigs[1]].X, pts[nconfigs[1]].Y);
                pta[2] = new Point(pts[nconfigs[2]].X, pts[nconfigs[2]].Y);
                pta[3] = new Point(pts[nconfigs[3]].X, pts[nconfigs[3]].Y);
                DrawPolygon(cs, bs, pta, fillBrush, lineBrush);

                pta[0] = new Point(pts[nconfigs[4]].X, pts[nconfigs[4]].Y);
                pta[1] = new Point(pts[nconfigs[5]].X, pts[nconfigs[5]].Y);
                pta[2] = new Point(pts[nconfigs[6]].X, pts[nconfigs[6]].Y);
                pta[3] = new Point(pts[nconfigs[7]].X, pts[nconfigs[7]].Y);
                DrawPolygon(cs, bs, pta, fillBrush, lineBrush);
            }
            else if (!IsBarSingleColor && IsColormap)
            {
                pta[0] = new Point(pts[4].X, pts[4].Y);
                pta[1] = new Point(pts[5].X, pts[5].Y);
                pta[2] = new Point(pts[6].X, pts[6].Y);
                pta[3] = new Point(pts[7].X, pts[7].Y);
                DrawPolygon(cs, bs, pta, fillBrush, lineBrush);

                pta[0]    = new Point(pts[0].X, pts[0].Y);
                pta[1]    = new Point(pts[1].X, pts[1].Y);
                pta[2]    = new Point(pts[2].X, pts[2].Y);
                pta[3]    = new Point(pts[3].X, pts[3].Y);
                fillBrush = GetBrush(pts1[0].Z, zmin, zmax);
                DrawPolygon(cs, bs, pta, fillBrush, lineBrush);

                double dz = (zmax - zmin) / 63;
                if (pt.Z < zorign)
                {
                    dz = -dz;
                }
                int nz = (int)((pt.Z - zorign) / dz) + 1;
                if (nz < 1)
                {
                    nz = 1;
                }
                double z = zorign;

                if (cs.Azimuth >= -180 && cs.Azimuth < -90)
                {
                    nconfigs = new int[4] {
                        1, 2, 1, 0
                    };
                }
                else if (cs.Azimuth >= -90 && cs.Azimuth < 0)
                {
                    nconfigs = new int[4] {
                        1, 0, 0, 3
                    };
                }
                else if (cs.Azimuth >= 0 && cs.Azimuth < 90)
                {
                    nconfigs = new int[4] {
                        0, 3, 2, 3
                    };
                }
                else if (cs.Azimuth >= 90 && cs.Azimuth <= 180)
                {
                    nconfigs = new int[4] {
                        2, 3, 1, 2
                    };
                }
                for (int i = 0; i < nz; i++)
                {
                    z      = zorign + i * dz;
                    pt3[0] = new Point3D(pts1[nconfigs[0]].X, pts1[nconfigs[0]].Y, z);
                    pt3[1] = new Point3D(pts1[nconfigs[1]].X, pts1[nconfigs[1]].Y, z);
                    pt3[2] = new Point3D(pts1[nconfigs[1]].X, pts1[nconfigs[1]].Y, z + dz);
                    pt3[3] = new Point3D(pts1[nconfigs[0]].X, pts1[nconfigs[0]].Y, z + dz);
                    for (int j = 0; j < pt3.Length; j++)
                    {
                        pt3[j] = cs.Normalize3D(m, pt3[j]);
                    }
                    pta[0]    = new Point(pt3[0].X, pt3[0].Y);
                    pta[1]    = new Point(pt3[1].X, pt3[1].Y);
                    pta[2]    = new Point(pt3[2].X, pt3[2].Y);
                    pta[3]    = new Point(pt3[3].X, pt3[3].Y);
                    fillBrush = GetBrush(z, zmin, zmax);
                    DrawPolygon(cs, bs, pta, fillBrush, fillBrush);
                }
                pt3[0] = new Point3D(pts1[nconfigs[0]].X, pts1[nconfigs[0]].Y, zorign);
                pt3[1] = new Point3D(pts1[nconfigs[1]].X, pts1[nconfigs[1]].Y, zorign);
                pt3[2] = new Point3D(pts1[nconfigs[1]].X, pts1[nconfigs[1]].Y, pt.Z);
                pt3[3] = new Point3D(pts1[nconfigs[0]].X, pts1[nconfigs[0]].Y, pt.Z);
                for (int j = 0; j < pt3.Length; j++)
                {
                    pt3[j] = cs.Normalize3D(m, pt3[j]);
                }
                pta[0]    = new Point(pt3[0].X, pt3[0].Y);
                pta[1]    = new Point(pt3[1].X, pt3[1].Y);
                pta[2]    = new Point(pt3[2].X, pt3[2].Y);
                pta[3]    = new Point(pt3[3].X, pt3[3].Y);
                fillBrush = Brushes.Transparent;
                DrawPolygon(cs, bs, pta, fillBrush, lineBrush);

                for (int i = 0; i < nz; i++)
                {
                    z      = zorign + i * dz;
                    pt3[0] = new Point3D(pts1[nconfigs[2]].X, pts1[nconfigs[2]].Y, z);
                    pt3[1] = new Point3D(pts1[nconfigs[3]].X, pts1[nconfigs[3]].Y, z);
                    pt3[2] = new Point3D(pts1[nconfigs[3]].X, pts1[nconfigs[3]].Y, z + dz);
                    pt3[3] = new Point3D(pts1[nconfigs[2]].X, pts1[nconfigs[2]].Y, z + dz);

                    for (int j = 0; j < pt3.Length; j++)
                    {
                        pt3[j] = cs.Normalize3D(m, pt3[j]);
                    }
                    pta[0]    = new Point(pt3[0].X, pt3[0].Y);
                    pta[1]    = new Point(pt3[1].X, pt3[1].Y);
                    pta[2]    = new Point(pt3[2].X, pt3[2].Y);
                    pta[3]    = new Point(pt3[3].X, pt3[3].Y);
                    fillBrush = GetBrush(z, zmin, zmax);
                    DrawPolygon(cs, bs, pta, fillBrush, fillBrush);
                }
                pt3[0] = new Point3D(pts1[nconfigs[2]].X, pts1[nconfigs[2]].Y, zorign);
                pt3[1] = new Point3D(pts1[nconfigs[3]].X, pts1[nconfigs[3]].Y, zorign);
                pt3[2] = new Point3D(pts1[nconfigs[3]].X, pts1[nconfigs[3]].Y, pt.Z);
                pt3[3] = new Point3D(pts1[nconfigs[2]].X, pts1[nconfigs[2]].Y, pt.Z);
                for (int j = 0; j < pt3.Length; j++)
                {
                    pt3[j] = cs.Normalize3D(m, pt3[j]);
                }
                pta[0]    = new Point(pt3[0].X, pt3[0].Y);
                pta[1]    = new Point(pt3[1].X, pt3[1].Y);
                pta[2]    = new Point(pt3[2].X, pt3[2].Y);
                pta[3]    = new Point(pt3[3].X, pt3[3].Y);
                fillBrush = Brushes.Transparent;
                DrawPolygon(cs, bs, pta, fillBrush, lineBrush);
            }
        }
        public void AddBar3D(ChartStyle2D cs, Bar3DStyle bs)
        {
            Matrix3D m = Utility.AzimuthElevation(cs.Elevation, cs.Azimuth);

            Point[] pta = new Point[4];
            Point3D[,] pts = bs.PointArray;

            // Find the minumum and maximum z values:
            double zmin = bs.ZDataMin();
            double zmax = bs.ZDataMax();

            // Check parameters:
            double xlength = bs.XLength;

            if (xlength <= 0)
            {
                xlength = 0.1 * bs.XSpacing;
            }
            else if (xlength > 0.5)
            {
                xlength = 0.5 * bs.XSpacing;
            }
            else
            {
                xlength = bs.XLength * bs.XSpacing;
            }
            double ylength = bs.YLength;

            if (ylength <= 0)
            {
                ylength = 0.1 * bs.YSpacing;
            }
            else if (ylength > 0.5)
            {
                ylength = 0.5 * bs.YSpacing;
            }
            else
            {
                ylength = bs.YLength * bs.YSpacing;
            }
            double zorigin = bs.ZOrigin;

            // Draw 3D bars:
            for (int i = 0; i < pts.GetLength(0) - 1; i++)
            {
                for (int j = 0; j < pts.GetLength(1) - 1; j++)
                {
                    int ii = i;
                    int jj = j;
                    if (cs.Azimuth >= -180 && cs.Azimuth < -90)
                    {
                        ii = pts.GetLength(0) - 2 - i;
                        jj = j;
                    }
                    else if (cs.Azimuth >= -90 && cs.Azimuth < 0)
                    {
                        ii = pts.GetLength(0) - 2 - i;
                        jj = pts.GetLength(1) - 2 - j;
                    }
                    else if (cs.Azimuth >= 0 && cs.Azimuth < 90)
                    {
                        ii = i;
                        jj = pts.GetLength(1) - 2 - j;
                    }
                    else if (cs.Azimuth >= 90 && cs.Azimuth <= 180)
                    {
                        ii = i;
                        jj = j;
                    }
                    DrawBar(cs, bs, m, pts[ii, jj], xlength, ylength, zorigin, zmax, zmin);
                }
            }
            if (cs.IsColorBar && IsColormap)
            {
                AddColorBar(cs, bs, zmin, zmax);
            }
        }
        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]);
                        }
                    }
                }
            }
        }