//For each block, takes the sum of the heights of the surrounding blocks (and the block's own height), averages it, and sets it to that block's height
        public static void Average()
        {
            Heightmap NewMap = new Heightmap(Map.sizeX, Map.sizeY);

            for (int i = 0; i < Map.sizeX; i++)
            {
                for (int j = 0; j < Map.sizeY; j++)
                {
                    NewMap[i, j] = AverageAround(new Point(i, j), 1);
                }
            }

            Map = NewMap;
        }
 public static void Normalize(int min, int max)
 {
     Map = Map.normalize(min, max);
 }
        /// <summary>
        /// Generates a heightmap using the diamond-square method explained here: http://www.gameprogrammer.com/fractal.html
        /// For any given input size, it returns a square heightmap of dimension 2^size + 1
        /// </summary>
        /// <param name="ReqSize">The size of the resultant heightmap; it will be 2^size+1</param>
        /// <param name="variability">The initial variability in height</param>
        /// <param name="seed">The seeded values</param>
        /// <param name="roughness">How quickly the variability drops off; should be less than one</param>
        /// <param name="holds">Set of points whose seeded value should be maintained</param>
        /// <returns></returns>
        public static Heightmap DiamondSquare(int ReqSize, int variability, double roughness, Heightmap seed = null, HashSet<Point> holds = null, Random Random = null)
        {
            int size = (1 << ReqSize);

            List<List<int>> map = (seed ?? new Heightmap(size)).Map;

            for (int i = 0; i < size; i++)
            {
                if (map.Count <= i)
                {
                    map.Add(new List<int>(size));
                }

                if (map[i].Count < size)
                {
                    for (int j = 0; j < size; j++)
                    {
                        map[i].Add(0);
                    }
                }
            }
            if (seed == null)
            {
                //A default seeding - mountains in the "middle" (actually corners, but whatever).
                map[0][0] = 1000;
                map[0][size - 1] = 1000;
                map[size - 1][0] = 1000;
                map[size - 1][size - 1] = 1000;
            }

            int step = size / 2;
            Map = new Heightmap(map);
            Holds = holds ?? new HashSet<Point>();
            vstep = roughness;
            rand = Random ?? new Random();
            DiamondSquare_Recursive(step, variability, size / 2, size / 2);

            return Map;
        }
        public static List<List<Heightmap>> ChopHeightmap(int SquareSize, Heightmap input)
        {
            List<List<Heightmap>> ret = new List<List<Heightmap>>();
            List<List<int>> rawmap = input.Map;

            IEnumerable<List<int>> RestColumns;
            IEnumerable<IEnumerable<int>> RestRows;
            RestColumns = rawmap;
            int count = 0;
            do
            {
                IEnumerable<List<int>> CurrentColumns = RestColumns.Take(SquareSize);
                RestColumns = RestColumns.Skip(SquareSize);

                ret.Add(new List<Heightmap>());
                RestRows = CurrentColumns;

                do
                {

                    IEnumerable<IEnumerable<int>> CurrentRows = RestRows.Select((x) => x.Take(SquareSize));
                    RestRows = RestRows.Select((x) => x.Skip(SquareSize));

                    List<List<int>> CurrentMap = CurrentRows.Select((x) => x.ToList()).ToList();
                    ret[count].Add(new Heightmap(CurrentMap));
                } while (RestRows.Max((x)=>x.Count()) > 0);

                count++;

            } while (RestColumns.Count() > 0);

            return ret;
        }
        private Heightmap BicubicReduction(int sizeX, int sizeY)
        {
            Heightmap ret = new Heightmap(sizeX, sizeY);

            double[][] window = new double[4][];
            for (int i = 0; i < 4; i++)
            {
                window[i] = new double[4];
            }

            int diffX = myXSize - sizeX;
            int diffY = myYSize - sizeY;

            double xOffset = 0;
            double yOffset = 0;

            //If we're stepping down an odd number of steps, the new points are in between old points. Otherwise they're exactly on them.
            if (diffX % 2 == 1)
            {
                xOffset = 0.5;
            }

            if (diffY % 2 == 1)
            {
                yOffset = 0.5;
            }

            for (int i = 0; i < ret.myXSize; i++)
            {
                for (int j = 0; j < ret.myYSize; j++)
                {
                    //do something that fills the window
                    for (int k = 0; k < 4; k++)
                    {
                        int x;
                        int y;
                        if(xOffset == 0.5)
                        {
                            x = k - 2;
                        }
                        else
                        {
                            x = k - 1;
                        }

                        for (int l = 0; l < 4; l++)
                        {

                            if(yOffset == 0.5)
                            {
                                y = l - 2;
                            }
                            else
                            {
                                y = l - 1;
                            }

                            window[k][l] = this[x + i, y + j];
                        }
                    }

                    ret[i, j] = (int)Math.Round(Terrain.BicubicInterpolate(window, xOffset, yOffset));
                }
            }

            return ret;
        }
        private Heightmap AverageReduction(int sizeX, int sizeY)
        {
            Heightmap ret = new Heightmap(sizeX, sizeY);
            int WindowLengthX = myXSize - sizeX;
            int WindowLengthY = myYSize - sizeY;

            //Store the old out of bounds behavior
            OutOfBoundsType mine = this.OOBType;
            OutOfBoundsType rets = ret.OOBType;

            //Make sure we don't wrap around for the duration of this thingy
            this.OOBType = OutOfBoundsType.Error;
            ret.OOBType = OutOfBoundsType.Error;

            for (int i = 0; i < ret.myXSize; i++)
            {
                for (int j = 0; j < ret.myYSize; j++)
                {
                    int total = 0;
                    for (int l = i; l < i + WindowLengthX; l++)
                    {
                        for (int k = j; k < j + WindowLengthY; k++)
                        {
                            total += this[l, k];
                        }
                    }

                    ret[i, j] = total / (WindowLengthX * WindowLengthY);
                }
            }
            ret.OOBType = rets;
            this.OOBType = mine;

            return ret;
        }