public River(IslandTileCorner c) { this.data = c; this.left = null; this.right = null; this.father = null; }
public static int findDischarge(River r) { if (r == null) { return(0); } if (r.left == null && r.right == null) { r.discharge = 1; } else { r.discharge = findDischarge(r.left) + findDischarge(r.right); } keeprivercorners.Add(r.data);//store all river corners return(r.discharge); }
public List <River> GenerateRivers() { List <River> allrivers = new List <River>(); //all rivers //generate startpoints in shore corners List <IslandTileCorner> lshore = new List <IslandTileCorner>(); foreach (var s in shore) { lshore.Add(s); } HashSet <IslandTileCorner> startpoints = new HashSet <IslandTileCorner>(); while (startpoints.Count < num_of_rivers) { int index = _rndGen.Next(0, lshore.Count - 1); bool valid = false; foreach (var neighbor in lshore[index].adjacent) { if (neighbor.elevation > 0f) { valid = true; } } if (valid) { startpoints.Add(lshore[index]); } } foreach (var rs in startpoints) { River root = new River(rs); //generation_Mainriver(highest); GenerateMainRiver(root); allrivers.Add(root); countm = 0; //main river's numofcorners counts = 0; //each sub river's numofcorners } return(allrivers); }
public void GenerateSubRiver(River sr) { //to make it easy I don't concider the subriver of a subriver IslandTileCorner highest = sr.data; foreach (var c in sr.data.adjacent) { if (c.elevation > highest.elevation) { highest = c; } } if (sr.right == null) { sr.right = new River(highest); sr.right.father = sr; } counts++; if (counts < _subStreamLength) { GenerateSubRiver(sr.right); } }
private SRandom _rndGen; //random generator //class constractor public Island(int width, int height, int relaxTime, int centerNum, int riverNum, float maxElevation, float mainStreamLengthRatio, //typical: 0.02 float subStreamLengthRatio, //typical: 0.5 float riverSplitFreq, //typical: 0.2 int seed = 0) { this.width = width; this.height = height; this.relaxationTime = relaxTime; this.num_of_centers = centerNum; this.num_of_rivers = riverNum; this._maxElevation = maxElevation; if (mainStreamLengthRatio < 0f || mainStreamLengthRatio > 0.2f) { throw new ArgumentOutOfRangeException("ratio must be between 0 and 0.2"); } _mainStreamLength = (int)Math.Floor(Math.Max(width, height) * mainStreamLengthRatio); if (subStreamLengthRatio < 0f || subStreamLengthRatio > 1f) { throw new ArgumentOutOfRangeException("ratio must be between 0 and 1"); } _subStreamLength = (int)Math.Floor(_mainStreamLength * subStreamLengthRatio); if (_riverSplitFreq < 0f || _riverSplitFreq > 1f) { throw new ArgumentOutOfRangeException("frequency must be between 0 and 1"); } _riverSplitFreq = riverSplitFreq; _rndGen = new SRandom(seed); centers = random_centers(width, height, num_of_centers); VoronoiGraph vg = Fortune.ComputeVoronoiGraph(centers); //run voronoi diagram algorithm for (int i = 0; i < centers.Count; i++) //Initialize and store IslandTiles { Tiles[centers[i]] = new IslandTile(centers[i], vg, width, height); } //call improveRandomPoints function "relaxation" times for (int re = 0; re < relaxationTime; re++) { centers = improveRandomPoints(Tiles, centers); VoronoiGraph vGraph = Fortune.ComputeVoronoiGraph(centers); Tiles = new Dictionary <Vector, IslandTile>(); for (int j = 0; j < centers.Count; j++) { Tiles[centers[j]] = new IslandTile(centers[j], vGraph, width, height); } } NN = new NearestNeighbor(centers);//builded kdtree foreach (var item in Tiles.Values) { if (item.center.data[0] < (width / 10) || item.center.data[0] > (width - width / 10) || item.center.data[1] < (width / 10) || item.center.data[1] > (width - width / 10)) { item.iswater = true; item.elevation = 0; foreach (var c in item.corners) { c.elevation = 0; // totalcorners[c.position] = c; //water.Add(c); } ocean.Add(item); } else { land.Add(item); } } //spreading ocean area int waterspreadcount = 0; foreach (var item in Tiles.Values) { if (!item.iswater) { foreach (var i in item.neighbors) { if (Tiles[i].iswater) { item.iswater = true; item.elevation = 0; foreach (var c in item.corners) { c.elevation = 0; //totalcorners[c.position] = c; //water.Add(c); } ocean.Add(item); land.Remove(item); waterspreadcount++; } if (waterspreadcount > (num_of_centers / 3)) { break; } } } if (waterspreadcount > (num_of_centers / 3)) { break; } } //remove one tile island foreach (var item in Tiles.Values) { float sum_of_elevation = 0; foreach (var c in item.corners) { sum_of_elevation += c.elevation; } if (sum_of_elevation == 0) { item.iswater = true; item.elevation = 0; ocean.Add(item); land.Remove(item); } } //-----calculate coastline------------------------ foreach (var item in land) { foreach (var c in item.corners) { if (c.elevation == 0) { shore.Add(c); item.isshore = true; } } } //calculate elevation for corners foreach (var t in Tiles.Values) { if (!t.iswater) { float sum_elevation = 0; foreach (var c in t.corners) { float minDistToShore = float.MaxValue; foreach (var s in shore) { float distToShore = (float)Math.Sqrt((c.position - s.position).data[0] * (c.position - s.position).data[0] + (c.position - s.position).data[1] * (c.position - s.position).data[1]); if (minDistToShore > distToShore) { minDistToShore = distToShore; } } c.elevation = minDistToShore * minDistToShore / _maxElevation; c.elevation = Math.Min(c.elevation, _maxElevation); sum_elevation += c.elevation; // totalcorners[c.position] = c; } t.elevation = sum_elevation / t.corners.Count; } } //store total corners /*foreach(var item in Tiles.Values) * { * foreach (var c in item.corners) * totalcorners.Add(c); * }*/ //landcenters foreach (var item in land) { landcenters.Add(item.center); } rivers = GenerateRivers();//generate rivers foreach (var ri in rivers) { River.findDischarge(ri);//get discharge for every corner } //put discharge information in it's tile foreach (var kc in River.keeprivercorners) { foreach (var t in kc.touches) { t.hasriver = true; foreach (var c in t.corners) { if (c.position == kc.position) { c.discharge = kc.discharge; } break; } } } StoreBiome();//set biome type for each tile //from now on, all data of a tile are generated. }
private void GenerateMainRiver(River rc) { IslandTileCorner maxima = rc.data; bool existMaxima = false; foreach (var c in rc.data.adjacent) { if (c.elevation > maxima.elevation) { maxima = c; existMaxima = true; } } if (!existMaxima) { return; } if (rc.right == null) { rc.right = new River(maxima); rc.right.father = rc; } countm++; if (countm < _mainStreamLength) { GenerateMainRiver(rc.right); } double doSplit = _rndGen.NextDouble(); if (doSplit > _riverSplitFreq) { return; } IslandTileCorner secondMaxima = rc.data; bool existSecondMaxima = false; foreach (var c in rc.data.adjacent) { if ((c.elevation > secondMaxima.elevation) && (c != maxima)) { secondMaxima = c; existSecondMaxima = true; } } if (!existSecondMaxima) { return; } if (rc.left == null) { rc.left = new River(secondMaxima); rc.left.father = rc; } GenerateSubRiver(rc.left); counts = 0; }