public static void contour(double step)
        {
            PyDraw.clear();
            //PyDraw.fill(128, 255, 128);
            //PyDraw.stroke(96, 255, 96);
            //PyDraw.thickness(1);
            //PyDraw.alpha(48);

            var gridCells = ValueBuffer.GetGrid();
            var values    = Functional.Seq.range(0, gridCells.Max(x => x.Value), step).ToArray();
            var cityLoops = new List <List <Geometry.Point2D> >();

            foreach (var value in values)
            {
                var binarizedPixels = ValueBuffer.GetBinarizedPixels(gridCells.Cast <GridCell>().ToList(), x => x.Value >= value);
                var pb    = new Geometry.PixelBound(binarizedPixels);
                var loops = pb.Trace();
                foreach (var loop in loops)
                {
                    var loopPoints = loop.Select(x => (ValueBuffer.GetGridCell(gridCells, x.X, x.Y) as GridCell).Position).ToList();
                    loopPoints = Geometry.PixelBound.Align(loopPoints, 5);

                    //PyDraw.cityspline(loopPoints.ToArray(), true);
                    //loopPoints.ForEach(p => PyDraw.cityellipse(p.x, p.y, 1, 1));
                    cityLoops.Add(loopPoints);
                }
            }
            ViewerTool tool = new ViewerTool
            {
                PaintAction = () =>
                {
                    cityLoops.ForEach(loop =>
                    {
                        var pts = loop.Select(p => display.CanvasCoordinateF(p)).ToList();
                        pts.ForEach(p => display.g.FillEllipse(new SolidBrush(Color.Black), p.X, p.Y, 3, 3));
                    });
                }
            };

            viewer.SetTool(tool);
        }
        public static void voronoi(int level = 5)
        {
            PyDraw.clear();
            PyDraw.fill(128, 128, 128);
            PyDraw.thickness(3);
            PyDraw.alpha(128);

            var coverRangeCells = ValueBuffer.GetCoverRangeGrid();
            var values          = coverRangeCells.Select(x => x.Value).Distinct().ToArray();

            foreach (var value in values)
            {
                var binarizedPixels = ValueBuffer.GetBinarizedPixels(coverRangeCells.Cast <GridCell>().ToList(), x => x.Value == value);
                var pb         = new Geometry.PixelBound(binarizedPixels);
                var loop       = pb.Trace()[0];
                var loopPoints = loop.Select(x => (ValueBuffer.GetGridCell(coverRangeCells, x.X, x.Y) as GridCell).Position).ToList();
                loopPoints = Geometry.PixelBound.Align(loopPoints, level);

                PyDraw.cityspline(loopPoints.ToArray(), true);
            }
        }
        public static void pixelboundtest(int i, int j = 6)
        {
            var values = ValueBuffer.Units.Select(x => x.Value).Distinct().ToArray();
            var cells  = ValueBuffer.Units.Where(x => x.Value == values[i]).Select(x =>
            {
                var cell = x as GridCell;
                return(new Point(cell.Col, cell.Row));
            }).ToList();

            Geometry.PixelBound pb  = new Geometry.PixelBound(cells);
            var        loop         = pb.Trace()[0];
            var        loopPoints   = loop.Select(x => (ValueBuffer.GetGridCell(x.X, x.Y) as GridCell).Position).ToList();
            var        spline       = new Geometry.BSpline2D(loopPoints.Select(x => new Geometry.Point2D(x.x, x.y)).ToList());
            var        splinePoints = Enumerable.Range(0, 5 * (loopPoints.Count - 1) + 1).Select(x => spline.SolveAt(x / 5.0)).ToArray();
            ViewerTool tool         = new ViewerTool
            {
                PaintAction = () =>
                {
                    display.g.DrawPolygon(new Pen(Brushes.Black, 1), splinePoints.Select(x => display.CanvasCoordinateF(x)).ToArray());
                }
            };

            viewer.SetTool(tool);
        }