Пример #1
0
 public River(IslandTileCorner c)
 {
     this.data   = c;
     this.left   = null;
     this.right  = null;
     this.father = null;
 }
Пример #2
0
 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);
 }
Пример #3
0
        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);
        }
Пример #4
0
        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);
            }
        }
Пример #5
0
        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.
        }
Пример #6
0
        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;
        }