public HydraulicErosionCell getCopy() { HydraulicErosionCell copy = new HydraulicErosionCell(); copy.Altitude = Altitude; copy.Water = Water; copy.Sediment = Sediment; return(copy); }
private static HydraulicErosionCell[][] createHydraulicErosionCells(float?[][] heightMap) { int side = heightMap.Length; HydraulicErosionCell[][] hydraulicErosionCells = new HydraulicErosionCell[side][]; for (int i = 0; i < side; i++) { hydraulicErosionCells[i] = new HydraulicErosionCell[side]; } for (int x = 0; x < side; x++) { for (int y = 0; y < side; y++) { HydraulicErosionCell cell = new HydraulicErosionCell(); cell.Altitude = (float)heightMap[x][y]; hydraulicErosionCells[x][y] = cell; } } return(hydraulicErosionCells); }
private static HydraulicErosionCell[][] hydraulicErosionIteration(HydraulicErosionCell[][] hydraulicErosionCells) { int side = hydraulicErosionCells.Length; //HydraulicErosionCell[][] resultHydraulicErosionCells = new HydraulicErosionCell[side][side]; // Step1 Rain water added for (int x = 0; x < side; x++) { for (int y = 0; y < side; y++) { hydraulicErosionCells[x][y].Water = hydraulicErosionCells[x][y].Water + Kr; } } // Step2 Create sediment for (int x = 0; x < side; x++) { for (int y = 0; y < side; y++) { hydraulicErosionCells[x][y].Altitude = hydraulicErosionCells[x][y].Altitude - Ks * hydraulicErosionCells[x][y].Water; hydraulicErosionCells[x][y].Sediment = hydraulicErosionCells[x][y].Sediment + Ks * hydraulicErosionCells[x][y].Water; } } // Step3 water and sediment transport HydraulicErosionCell[][] resultHydraulicErosionCells = new HydraulicErosionCell[side][]; for (int i = 0; i < side; i++) { resultHydraulicErosionCells[i] = new HydraulicErosionCell[side]; } for (int x = 0; x < side; x++) { for (int y = 0; y < side; y++) { resultHydraulicErosionCells[x][y] = hydraulicErosionCells[x][y].getCopy(); } } for (int x = 0; x < side; x++) { for (int y = 0; y < side; y++) { HydraulicErosionCell current = hydraulicErosionCells[x][y]; HydraulicErosionCell resultCurrent = resultHydraulicErosionCells[x][y]; List <HydraulicErosionCell> neighbours = new List <HydraulicErosionCell>(); List <HydraulicErosionCell> resultNeighbours = new List <HydraulicErosionCell>(); if (x > 0 && y > 0) { neighbours.Add(hydraulicErosionCells[x - 1][y - 1]); } if (y > 0) { neighbours.Add(hydraulicErosionCells[x][y - 1]); } if (x < side - 1 && y > 0) { neighbours.Add(hydraulicErosionCells[x + 1][y - 1]); } if (x < side - 1) { neighbours.Add(hydraulicErosionCells[x + 1][y]); } if (x < side - 1 && y < side - 1) { neighbours.Add(hydraulicErosionCells[x + 1][y + 1]); } if (y < side - 1) { neighbours.Add(hydraulicErosionCells[x][y + 1]); } if (x > 0 && y < side - 1) { neighbours.Add(hydraulicErosionCells[x - 1][y + 1]); } if (x > 0) { neighbours.Add(hydraulicErosionCells[x - 1][y]); } if (x > 0 && y > 0) { resultNeighbours.Add(resultHydraulicErosionCells[x - 1][y - 1]); } if (y > 0) { resultNeighbours.Add(resultHydraulicErosionCells[x][y - 1]); } if (x < side - 1 && y > 0) { resultNeighbours.Add(resultHydraulicErosionCells[x + 1][y - 1]); } if (x < side - 1) { resultNeighbours.Add(resultHydraulicErosionCells[x + 1][y]); } if (x < side - 1 && y < side - 1) { resultNeighbours.Add(resultHydraulicErosionCells[x + 1][y + 1]); } if (y < side - 1) { resultNeighbours.Add(resultHydraulicErosionCells[x][y + 1]); } if (x > 0 && y < side - 1) { resultNeighbours.Add(resultHydraulicErosionCells[x - 1][y + 1]); } if (x > 0) { resultNeighbours.Add(resultHydraulicErosionCells[x - 1][y]); } transportWater(neighbours, resultNeighbours, current, resultCurrent); } } hydraulicErosionCells = resultHydraulicErosionCells; // Step4 Evaporation and deposition for (int x = 0; x < side; x++) { for (int y = 0; y < side; y++) { hydraulicErosionCells[x][y].Water = hydraulicErosionCells[x][y].Water * (1 - Ke); float mmax = Kc * hydraulicErosionCells[x][y].Water; float dm = Math.Max(0, hydraulicErosionCells[x][y].Sediment - mmax); hydraulicErosionCells[x][y].Sediment = hydraulicErosionCells[x][y].Sediment - dm; hydraulicErosionCells[x][y].Altitude = hydraulicErosionCells[x][y].Altitude + dm; } } return(hydraulicErosionCells); }
private static void transportSediment(List <HydraulicErosionCell> neighbours, List <HydraulicErosionCell> resultNeighbours, HydraulicErosionCell current, HydraulicErosionCell resultCurrent) { float dtotal = 0; float dmax = 0; for (int i = 0; i < neighbours.Count; i++) { float di = current.Altitude - neighbours[i].Altitude; if (di > T) { dtotal += di; if (di > dmax) { dmax = di; } } } if (dtotal > 0) { for (int i = 0; i < neighbours.Count; i++) { float di = current.Altitude - neighbours[i].Altitude; if (di > T) { float dh = C * (dmax - T) * (di / dtotal); resultNeighbours[i].Altitude = resultNeighbours[i].Altitude + dh; resultCurrent.Altitude = resultCurrent.Altitude - dh; } } } }
private static HydraulicErosionCell[][] thermalErosionIteration(HydraulicErosionCell[][] hydraulicErosionCells) { int side = hydraulicErosionCells.Length; HydraulicErosionCell[][] resultHydraulicErosionCells = new HydraulicErosionCell[side][]; for (int i = 0; i < side; i++) { resultHydraulicErosionCells[i] = new HydraulicErosionCell[side]; } for (int x = 0; x < side; x++) { for (int y = 0; y < side; y++) { resultHydraulicErosionCells[x][y] = hydraulicErosionCells[x][y].getCopy(); } } for (int x = 0; x < side; x++) { for (int y = 0; y < side; y++) { HydraulicErosionCell current = hydraulicErosionCells[x][y]; HydraulicErosionCell resultCurrent = resultHydraulicErosionCells[x][y]; List <HydraulicErosionCell> neighbours = new List <HydraulicErosionCell>(); List <HydraulicErosionCell> resultNeighbours = new List <HydraulicErosionCell>(); if (x > 0 && y > 0) { neighbours.Add(hydraulicErosionCells[x - 1][y - 1]); } if (y > 0) { neighbours.Add(hydraulicErosionCells[x][y - 1]); } if (x < side - 1 && y > 0) { neighbours.Add(hydraulicErosionCells[x + 1][y - 1]); } if (x < side - 1) { neighbours.Add(hydraulicErosionCells[x + 1][y]); } if (x < side - 1 && y < side - 1) { neighbours.Add(hydraulicErosionCells[x + 1][y + 1]); } if (y < side - 1) { neighbours.Add(hydraulicErosionCells[x][y + 1]); } if (x > 0 && y < side - 1) { neighbours.Add(hydraulicErosionCells[x - 1][y + 1]); } if (x > 0) { neighbours.Add(hydraulicErosionCells[x - 1][y]); } if (x > 0 && y > 0) { resultNeighbours.Add(resultHydraulicErosionCells[x - 1][y - 1]); } if (y > 0) { resultNeighbours.Add(resultHydraulicErosionCells[x][y - 1]); } if (x < side - 1 && y > 0) { resultNeighbours.Add(resultHydraulicErosionCells[x + 1][y - 1]); } if (x < side - 1) { resultNeighbours.Add(resultHydraulicErosionCells[x + 1][y]); } if (x < side - 1 && y < side - 1) { resultNeighbours.Add(resultHydraulicErosionCells[x + 1][y + 1]); } if (y < side - 1) { resultNeighbours.Add(resultHydraulicErosionCells[x][y + 1]); } if (x > 0 && y < side - 1) { resultNeighbours.Add(resultHydraulicErosionCells[x - 1][y + 1]); } if (x > 0) { resultNeighbours.Add(resultHydraulicErosionCells[x - 1][y]); } transportSediment(neighbours, resultNeighbours, current, resultCurrent); } } return(resultHydraulicErosionCells); }
private static void transportWater(List <HydraulicErosionCell> neighbours, List <HydraulicErosionCell> resultNeighbours, HydraulicErosionCell current, HydraulicErosionCell resultCurrent) { float a = current.Altitude + current.Water; float aa = 0; float dtotal = 0; int validCount = 0; for (int i = 0; i < neighbours.Count; i++) { float ai = neighbours[i].Altitude + neighbours[i].Water; if (ai < a) { aa += ai; dtotal += (a - ai); validCount++; } } aa /= (float)validCount; float da = a - aa; for (int i = 0; i < neighbours.Count; i++) { float ai = neighbours[i].Altitude + neighbours[i].Water; if (ai < a) { float di = a - ai; float dw = Math.Min(current.Water, da) * (di / dtotal); float dm = current.Sediment * (dw / current.Water); resultNeighbours[i].Water = resultNeighbours[i].Water + dw; resultCurrent.Water = resultCurrent.Water - dw; resultNeighbours[i].Sediment = resultNeighbours[i].Sediment + dm; resultCurrent.Sediment = resultCurrent.Sediment - dm; } } }