protected void PaintOnGraphicsBitmap(IGraphics g, int width, int height)
        {
            if (backBuffer == null || scatterPlot == null)
            {
                return;
            }
            UnsafeBitmap copyBackBuffer = new UnsafeBitmap(backBuffer);

            copyBackBuffer.LockBitmap();
            // selected data-points
            foreach (int s in scatterPlot.Selection)
            {
                double[] w = scatterPlot.GetDataAt(s);
                if (w.Length > 0)
                {
                    double           x  = w[0];
                    double           y  = w[1];
                    SymbolProperties gx = GetPointProperties != null?GetPointProperties(s) : defaultSymbol;

                    SymbolType symbolType = SymbolType.allSymbols[gx.Type];
                    int        symbolSize = gx.Size;
                    if (symbolSize > 0)
                    {
                        int[] pathX;
                        int[] pathY;
                        symbolType.GetPath(symbolSize, out pathX, out pathY);
                        copyBackBuffer.DrawPath(SelectionColor, ModelToViewX(x, width), ModelToViewY(y, height), pathX, pathY);
                    }
                }
            }
            copyBackBuffer.UnlockBitmap();
            // labels
            ScatterPlotLabelMode labelMode = scatterPlot.GetLabelMode();
            bool cutLabels = scatterPlot.CutLabels;

            if (labelMode == ScatterPlotLabelMode.All && scatterPlot.HasLabels)
            {
                Font font = new Font("Arial", scatterPlot.FontSize, scatterPlot.FontStyle);
                for (;;)
                {
                    double[] x;
                    double[] y;
                    double[] z;
                    string[] labels;
                    int      index;
                    try{
                        scatterPlot.GetData(out x, out y, out z, out labels, out index);
                    } catch (IndexOutOfRangeException) {
                        break;
                    }
                    if (x == null)
                    {
                        break;
                    }
                    SymbolProperties gx = GetPointProperties != null?GetPointProperties(index) : defaultSymbol;

                    for (int i = 0; i < x.Length; i++)
                    {
                        if (labelMode == ScatterPlotLabelMode.All || scatterPlot.IsSelected(i))
                        {
                            int   ix = ModelToViewX(x[i], width);
                            int   iy = ModelToViewY(y[i], height);
                            Color c;
                            if (z != null && colorScale != null)
                            {
                                c = colorScale.GetColor(z[i]);
                            }
                            else
                            {
                                c = gx.Color;
                            }
                            Brush b = new SolidBrush(c);
                            if (ix >= 0 && iy >= 0 && ix < width && iy < height)
                            {
                                if (labels[i] != null)
                                {
                                    string s = labels[i];
                                    if (cutLabels)
                                    {
                                        if (s.Contains(";"))
                                        {
                                            s = s.Substring(0, s.IndexOf(';'));
                                        }
                                    }
                                    copyBackBuffer.DrawString(s, font, b, ix, iy);
                                }
                            }
                        }
                    }
                }
                scatterPlot.Reset();
            }
            if (labelMode == ScatterPlotLabelMode.Selected && scatterPlot.HasLabels)
            {
                Brush br   = new SolidBrush(SelectionColor);
                Font  font = new Font("Arial", scatterPlot.FontSize, scatterPlot.FontStyle);
                foreach (int s in scatterPlot.Selection)
                {
                    double[] w     = scatterPlot.GetDataAt(s);
                    string   label = scatterPlot.GetLabelAt(s);
                    double   x     = w[0];
                    double   y     = w[1];
                    int      ix    = ModelToViewX(x, width);
                    int      iy    = ModelToViewY(y, height);
                    if (ix >= 0 && iy >= 0 && ix < width && iy < height)
                    {
                        if (label != null)
                        {
                            if (cutLabels)
                            {
                                if (label.Contains(";"))
                                {
                                    label = label.Substring(0, label.IndexOf(';'));
                                }
                            }
                            copyBackBuffer.DrawString(label, font, br, ix, iy);
                        }
                    }
                }
            }
            // draw the image
            g.DrawImageUnscaled(copyBackBuffer.Bitmap, 0, 0);
            copyBackBuffer.Dispose();
            g.SmoothingMode = SmoothingMode.AntiAlias;
            DrawPolygons(g, width, height);
            if (drawFunctions != null)
            {
                drawFunctions(g, width, height, ModelToViewX, ModelToViewY, ViewToModelX, ViewToModelY);
            }
            g.SmoothingMode = SmoothingMode.Default;
        }
        protected void PaintOnGraphicsVector(IGraphics g, int width, int height)
        {
            if (scatterPlot == null)
            {
                return;
            }
            if (!area.IsEmpty)
            {
                g.FillRectangle(Brushes.LightGray, 0, 0, width, height);
                g.FillRectangle(Brushes.White, area.X, area.Y, area.Width, area.Height);
            }
            else
            {
                g.FillRectangle(new SolidBrush(BackColor), 0, 0, width, height);
            }
            PaintGridVector(g, width, height);
            SymbolProperties[] gg = ArrayUtils.GetKeys(values);
            int[] counts          = new int[gg.Length];
            for (int i = 0; i < counts.Length; i++)
            {
                counts[i] = values[gg[i]].Count;
            }
            int[] o = ArrayUtils.Order(counts);
            Array.Reverse(o);
            gg = ArrayUtils.SubArray(gg, o);
            foreach (SymbolProperties g1 in gg)
            {
                bool[,] vals    = values[g1].Data;
                double[,] zvals = null;
                if (zValues != null)
                {
                    zvals = zValues[g1];
                }
                for (int i = 0; i < width; i++)
                {
                    for (int j = 0; j < height; j++)
                    {
                        if (vals[i, j])
                        {
                            Color color;
                            if (zvals != null && !double.IsNaN(zvals[i, j]) && colorScale != null)
                            {
                                color = colorScale.GetColor(zvals[i, j]);
                            }
                            else
                            {
                                color = g1.Color;
                            }
                            Pen        p          = new Pen(color);
                            Brush      b          = new SolidBrush(color);
                            SymbolType symbolType = SymbolType.allSymbols[g1.Type];
                            int        symbolSize = g1.Size;
                            if (symbolSize == 0)
                            {
                                continue;
                            }
                            int[] pathX;
                            int[] pathY;
                            symbolType.GetPath(symbolSize, out pathX, out pathY);
                            symbolType.Draw(symbolSize, i, j, g, p, b);
                        }
                    }
                }
            }
            // selected data points
            Brush selectionBrush = new SolidBrush(SelectionColor);
            Pen   selectionPen   = new Pen(SelectionColor);

            foreach (int s in scatterPlot.Selection)
            {
                double[] w = scatterPlot.GetDataAt(s);
                if (w.Length > 0)
                {
                    double           x  = w[0];
                    double           y  = w[1];
                    SymbolProperties gx = GetPointProperties != null?GetPointProperties(s) : defaultSymbol;

                    SymbolType symbolType = SymbolType.allSymbols[gx.Type];
                    int        symbolSize = gx.Size;
                    if (symbolSize > 0)
                    {
                        symbolType.Draw(symbolSize, ModelToViewX(x, width), ModelToViewY(y, height), g, selectionPen, selectionBrush);
                    }
                }
            }
            // labels
            ScatterPlotLabelMode labelMode = scatterPlot.GetLabelMode();
            bool cutLabels = scatterPlot.CutLabels;

            if (labelMode == ScatterPlotLabelMode.All && scatterPlot.HasLabels)
            {
                Font font = new Font("Arial", scatterPlot.FontSize, scatterPlot.FontStyle);
                for (;;)
                {
                    double[] x;
                    double[] y;
                    double[] z;
                    string[] labels;
                    int      index;
                    scatterPlot.GetData(out x, out y, out z, out labels, out index);
                    if (x == null)
                    {
                        break;
                    }
                    SymbolProperties gx = GetPointProperties != null?GetPointProperties(index) : defaultSymbol;

                    for (int i = 0; i < x.Length; i++)
                    {
                        if (labelMode == ScatterPlotLabelMode.All || scatterPlot.IsSelected(i))
                        {
                            int   ix = ModelToViewX(x[i], width);
                            int   iy = ModelToViewY(y[i], height);
                            Color c;
                            if (z != null && colorScale != null)
                            {
                                c = colorScale.GetColor(z[i]);
                            }
                            else
                            {
                                c = gx.Color;
                            }
                            Brush b = new SolidBrush(c);
                            if (ix >= 0 && iy >= 0 && ix < width && iy < height)
                            {
                                if (labels[i] != null)
                                {
                                    string s = labels[i];
                                    if (cutLabels)
                                    {
                                        if (s.Contains(";"))
                                        {
                                            s = s.Substring(0, s.IndexOf(';'));
                                        }
                                    }
                                    g.DrawString(s, font, b, ix, iy);
                                }
                            }
                        }
                    }
                }
                scatterPlot.Reset();
            }
            if (labelMode == ScatterPlotLabelMode.Selected && scatterPlot.HasLabels)
            {
                Font font = new Font("Arial", scatterPlot.FontSize, scatterPlot.FontStyle);
                foreach (int s in scatterPlot.Selection)
                {
                    double[] w     = scatterPlot.GetDataAt(s);
                    string   label = scatterPlot.GetLabelAt(s);
                    double   x     = w[0];
                    double   y     = w[1];
                    int      ix    = ModelToViewX(x, width);
                    int      iy    = ModelToViewY(y, height);
                    if (ix >= 0 && iy >= 0 && ix < width && iy < height)
                    {
                        if (label != null)
                        {
                            if (cutLabels)
                            {
                                if (label.Contains(";"))
                                {
                                    label = label.Substring(0, label.IndexOf(';'));
                                }
                            }
                            g.DrawString(label, font, selectionBrush, ix, iy);
                        }
                    }
                }
            }
            DrawPolygons(g, width, height);
            if (drawFunctions != null)
            {
                drawFunctions(g, width, height, ModelToViewX, ModelToViewY, ViewToModelX, ViewToModelY);
            }
        }