示例#1
0
 // Building the actual river tree is identical, whether we start from the ocean or a lake
 // Here, treeWorking contains tiles to investigate for riverness along with the parent node they started from.
 void buildRiverTrees(HashSet <Point> done, Dictionary <Point, Node> treeWorking)
 {
     while (treeWorking.Count > 0)  // Next, keep working on tiles until there are no more left to work on.
     {
         Point pt       = treeWorking.Keys.First();
         Node  myParent = treeWorking[pt];
         // move to done.
         treeWorking.Remove(pt);
         if (done.Contains(pt))
         {
             continue;
         }
         done.Add(pt);
         if (isLake(pt))     // If it's a lake, add the tile as the final node.
         {
             Node lake = new Node(pt);
             myParent.insertChild(lake);
             continue;
         }
         else if (!isRiver(pt))     // If it's not a river, don't work on it.
         {
             continue;
         }
         // Make new node and add to parent node of this one.
         Node me = new Node(pt);
         myParent.insertChild(me);
         // Check neighbors for riverness.
         foreach (Point dP in neighbors)
         {
             Point neighbor = dP + (Size)pt;
             if (isRiver(neighbor) || isLake(neighbor))
             {
                 treeWorking[neighbor] = me;     // Needs to add this node as a reference in the data.
             }
         }
     }
 }
示例#2
0
        void processLakeToRiver(List <Point> lakes, List <Node> rivers, HashSet <Point> done)
        {
            List <Tuple <Point, Point> > possibleRiver = new List <Tuple <Point, Point> >();

            // Add (lake tile, river tile) tuple to possibleRiver.
            foreach (Point lake in lakes)
            {
                foreach (Point dP in neighbors)
                {
                    Point neighbor = dP + (Size)lake;
                    if (isRiver(neighbor))
                    {
                        possibleRiver.Add(new Tuple <Point, Point>(lake, neighbor));
                        break;
                    }
                }
            }

            foreach (Tuple <Point, Point> pts in possibleRiver)
            {
                Dictionary <Point, Node> treeWorking = new Dictionary <Point, Node>();
                Node parent = new Node(pts.Item1);
                parent.insertChild(new Node(pts.Item2));
                Point coords = parent._children_[0].center_coords;
                foreach (Point dP in neighbors)
                {
                    Point neighbor = dP + (Size)coords;
                    if (neighbor != pts.Item1) // Make sure not to double back on the origin lake tile.
                    {
                        treeWorking[neighbor] = parent._children_[0];
                    }
                }
                buildRiverTrees(done, treeWorking);

                rivers.Add(parent);
            }
        }
示例#3
0
        Dictionary<Point, int> render(processedResults pr, string filename, bool edges = false)
        {
            List<Node> rivers = pr.rivers;
            List<Point> oceans = pr.oceans;
            List<Point> lakes = pr.lakes;

            List<Node> rendernodes = new List<Node>();
            foreach (Node r in rivers) // rendernodes are different from river nodes in that they are not necessarily actual river trees.
                // They should sometimes be smaller branches of main rivers.
                rendernodes.Add(r);

            List<List<PointF>> curvepoints = new List<List<PointF>>(); // This is the result of this function, a list of list of points for use in drawCurve()
            //
            while (rendernodes.Count > 0)
            {
                List<PointF> points = new List<PointF>();
                Node current = rendernodes.First();
                rendernodes.Remove(current);

                // Initially add the coords to the list.
                points.Add(current.center_coords); // Always starts with the center coords, because the first tile never gets an edge coord set.

                while (current.numChildren() > 0)
                {
                    int largestIndex = current.maxLengthIndex;
                    // Except for the largest index, add every other child node to the rendernodes list as a separate branch.
                    for (int i = 0; i < current._children_.Count; i++)
                    {
                        if (largestIndex != i)
                        {
                            Node newparent = new Node();
                            newparent.center_coords = current.center_coords;
                            newparent.edge_coords = current.edge_coords;
                            newparent.insertChild(current._children_[i]);

                            // Extending new river tree size by 2 for smoother rivers.
                            if (current.parent != null)
                            {
                                Node newnewparent = new Node();
                                newnewparent.center_coords = current.parent.center_coords;
                                newnewparent.edge_coords = current.edge_coords;
                                newnewparent.insertChild(newparent);
                                rendernodes.Add(newnewparent);
                            }
                            else
                                rendernodes.Add(newparent);
                        }
                    }
                    current = current._children_[largestIndex]; // Finally, change the current to point to the new node.

                    if (edges)
                        points.Add(current.edge_coords);
                    else
                        points.Add(current.center_coords); // Also, extend the pointslist.
                }

                curvepoints.Add(points);
            }

            Bitmap output = new Bitmap(width * scale, height * scale);
            Graphics graphic = Graphics.FromImage(output);
            SolidBrush oceanbrush = new SolidBrush(ocean_c);
            SolidBrush landbrush = new SolidBrush(land_c);
            SolidBrush lakebrush = new SolidBrush(lake_c);

            // Draws the land
            graphic.FillRectangle(landbrush, new Rectangle(0, 0, width * scale, height * scale));

            // Draw rivers
            Pen pen = new Pen(river_c, (float)scale/2.0f);
            Random rng = new Random();

            Dictionary<PointF, PointF> RandPointFromPoint = new Dictionary<PointF, PointF>();

            foreach (var pointlist in curvepoints)
            {
                PointF[] points = pointlist.ToArray();
                for (int i = 0; i < pointlist.Count; i++ ) // Scale coordinates
                {
                    if (RandPointFromPoint.ContainsKey(points[i]))
                        points[i] = RandPointFromPoint[points[i]];
                    else
                    {
                        PointF oldpoint = points[i];

                        points[i].X *= scale;
                        points[i].X += scale / 2;
                        points[i].Y *= scale;
                        points[i].Y += scale / 2;

                        // Experimental: Add noise to coordinates.
                        points[i].X += rng.Next(-scale / 4, scale / 4);
                        points[i].Y += rng.Next(-scale / 4, scale / 4);

                        PointF newpoint = points[i];
                        RandPointFromPoint[oldpoint] = newpoint;
                    }

                }

                if (pointlist.Count == 1)
                    continue;//g.DrawRectangle(pen, new Rectangle(points[0].X, points[0].Y, scale, scale));
                else
                    graphic.DrawCurve(pen, points, 0.4f);
            }

            // Finally, draw the oceans and lakes over the rivers to "hide" the ends of the river.
            foreach (var point in oceans)
            {
                graphic.FillRectangle(oceanbrush, new Rectangle(point.X * scale, point.Y * scale, scale, scale));
            }
            foreach (var point in lakes)
            {
                graphic.FillRectangle(lakebrush, new Rectangle(point.X * scale, point.Y * scale, scale, scale));
            }

            output.Save(filename);
            var result = DictionaryFromBitmap(output);
            output.Dispose();
            return result;
        }
示例#4
0
        void processOceanToRiver(List<Point> oceans, List<Node> rivers, HashSet<Point> done)
        {
            List<Point> possibleRiver = new List<Point>(); // Ocean tiles that touch at least one land tile
            HashSet<Point> working = new HashSet<Point>(); // River tiles that have yet to be added to a tree.

            // Move all land tiles bounding ocean tiles to the possibleRiver list.
            foreach (Point pt in oceans)
                foreach (Point dP in neighbors)
                {
                    Point neighbor = dP + (Size)pt; // Von Neumann neighbors! Because C# does not provide an Addition operator for Point + Point for no good reason, one Point must be cast to Size to get the sum.
                    // Check bounds first.
                    if (0 > neighbor.X || width <= neighbor.X || 0 > neighbor.Y || height <= neighbor.Y)
                        continue;
                    if (isLand(neighbor))
                    {
                        possibleRiver.Add(neighbor);
                    }
                }

            // For every land tile neighbor of the Ocean tile, check if there is river. If there is river, add the river point to the working list.
            foreach (Point pt in possibleRiver)
            {
                foreach (Point dP in neighbors)
                {
                    Point neighbor = dP + (Size)pt;
                    if (isRiver(neighbor) && !working.Contains(neighbor)) // If it's any kind of river plus it hasn't already been added to the list, because duplicates are bad
                    {
                        working.Add(neighbor);
                    }
                }
            }

            // Finally, let's start building River trees.
            while (working.Count > 0)
            {
                Point basePoint = working.First();
                working.Remove(basePoint);
                if (done.Contains(basePoint)) // Skip if the point was already touched.
                    continue;
                done.Add(basePoint); // Mark this point as Done, so future iterations don't accidentally touch it.

                Node parent = null;

                // First, find the land tile connecting this river start and the ocean.
                foreach (Point dP in neighbors)
                {
                    Point neighbor = dP + (Size)basePoint;
                    // For each land tile surrounding the start of the ocean, find the nearest ocean tile and go there.
                    if (isLand(neighbor))
                        foreach (Point ddP in neighbors)
                        {
                            Point neighbor2 = ddP + (Size)neighbor;
                            if (isOcean(neighbor2))
                            {
                                parent = new Node(neighbor2);
                                parent.insertChild(new Node(neighbor));
                                parent._children_[0].insertChild(new Node(basePoint));
                                goto exit;
                            }
                        }
                }
                if (parent == null)
                    parent = new Node(basePoint);
            exit:
                Dictionary<Point, Node> treeWorking = new Dictionary<Point, Node>(); // This working hashset is for building a river tree. The Node is a reference to the parent of this node.
                // There is no need for a treeDone set because what's done is done.

                // Now, if the parent has children, it means the place we are going to start looking for the river is the third node of the tree.
                if (parent._children_.Count > 0)
                {
                    Node startnode = parent._children_[0]._children_[0];
                    Point startcoords = startnode.center_coords;
                    foreach (Point dP in neighbors)
                    {
                        treeWorking[dP + (Size)startcoords] = startnode;
                    }
                }
                else
                    foreach (Point dP in neighbors)
                    {
                        treeWorking[dP + (Size)basePoint] = parent;
                    }

                buildRiverTrees(done, treeWorking);

                // At this point, the river tree should be fully built. Add the parent node to a list of rivers.
                rivers.Add(parent);
            }
        }
示例#5
0
        void processLakeToRiver(List<Point> lakes, List<Node> rivers, HashSet<Point> done)
        {
            List<Tuple<Point, Point>> possibleRiver = new List<Tuple<Point, Point>>();

            // Add (lake tile, river tile) tuple to possibleRiver.
            foreach (Point lake in lakes)
                foreach (Point dP in neighbors)
                {
                    Point neighbor = dP + (Size)lake;
                    if (isRiver(neighbor))
                    {
                        possibleRiver.Add(new Tuple<Point,Point>(lake, neighbor));
                        break;
                    }
                }

            foreach (Tuple<Point, Point> pts in possibleRiver)
            {
                Dictionary<Point, Node> treeWorking = new Dictionary<Point, Node>();
                Node parent = new Node(pts.Item1);
                parent.insertChild(new Node(pts.Item2));
                Point coords = parent._children_[0].center_coords;
                foreach (Point dP in neighbors)
                {
                    Point neighbor = dP + (Size)coords;
                    if (neighbor != pts.Item1) // Make sure not to double back on the origin lake tile.
                        treeWorking[neighbor] = parent._children_[0];
                }
                buildRiverTrees(done, treeWorking);

                rivers.Add(parent);
            }
        }
示例#6
0
        Dictionary <Point, int> render(processedResults pr, string filename, bool edges = false)
        {
            List <Node>  rivers = pr.rivers;
            List <Point> oceans = pr.oceans;
            List <Point> lakes  = pr.lakes;

            List <Node> rendernodes = new List <Node>();

            foreach (Node r in rivers) // rendernodes are different from river nodes in that they are not necessarily actual river trees.
            // They should sometimes be smaller branches of main rivers.
            {
                rendernodes.Add(r);
            }

            List <List <PointF> > curvepoints = new List <List <PointF> >(); // This is the result of this function, a list of list of points for use in drawCurve()

            //
            while (rendernodes.Count > 0)
            {
                List <PointF> points  = new List <PointF>();
                Node          current = rendernodes.First();
                rendernodes.Remove(current);

                // Initially add the coords to the list.
                points.Add(current.center_coords); // Always starts with the center coords, because the first tile never gets an edge coord set.

                while (current.numChildren() > 0)
                {
                    int largestIndex = current.maxLengthIndex;
                    // Except for the largest index, add every other child node to the rendernodes list as a separate branch.
                    for (int i = 0; i < current._children_.Count; i++)
                    {
                        if (largestIndex != i)
                        {
                            Node newparent = new Node();
                            newparent.center_coords = current.center_coords;
                            newparent.edge_coords   = current.edge_coords;
                            newparent.insertChild(current._children_[i]);

                            // Extending new river tree size by 2 for smoother rivers.
                            if (current.parent != null)
                            {
                                Node newnewparent = new Node();
                                newnewparent.center_coords = current.parent.center_coords;
                                newnewparent.edge_coords   = current.edge_coords;
                                newnewparent.insertChild(newparent);
                                rendernodes.Add(newnewparent);
                            }
                            else
                            {
                                rendernodes.Add(newparent);
                            }
                        }
                    }
                    current = current._children_[largestIndex]; // Finally, change the current to point to the new node.

                    if (edges)
                    {
                        points.Add(current.edge_coords);
                    }
                    else
                    {
                        points.Add(current.center_coords); // Also, extend the pointslist.
                    }
                }

                curvepoints.Add(points);
            }

            Bitmap     output     = new Bitmap(width * scale, height * scale);
            Graphics   graphic    = Graphics.FromImage(output);
            SolidBrush oceanbrush = new SolidBrush(ocean_c);
            SolidBrush landbrush  = new SolidBrush(land_c);
            SolidBrush lakebrush  = new SolidBrush(lake_c);

            // Draws the land
            graphic.FillRectangle(landbrush, new Rectangle(0, 0, width * scale, height * scale));

            // Draw rivers
            Pen    pen = new Pen(river_c, (float)scale / 2.0f);
            Random rng = new Random();

            Dictionary <PointF, PointF> RandPointFromPoint = new Dictionary <PointF, PointF>();

            foreach (var pointlist in curvepoints)
            {
                PointF[] points = pointlist.ToArray();
                for (int i = 0; i < pointlist.Count; i++)  // Scale coordinates
                {
                    if (RandPointFromPoint.ContainsKey(points[i]))
                    {
                        points[i] = RandPointFromPoint[points[i]];
                    }
                    else
                    {
                        PointF oldpoint = points[i];

                        points[i].X *= scale;
                        points[i].X += scale / 2;
                        points[i].Y *= scale;
                        points[i].Y += scale / 2;

                        // Experimental: Add noise to coordinates.
                        points[i].X += rng.Next(-scale / 4, scale / 4);
                        points[i].Y += rng.Next(-scale / 4, scale / 4);

                        PointF newpoint = points[i];
                        RandPointFromPoint[oldpoint] = newpoint;
                    }
                }

                if (pointlist.Count == 1)
                {
                    continue;//g.DrawRectangle(pen, new Rectangle(points[0].X, points[0].Y, scale, scale));
                }
                else
                {
                    graphic.DrawCurve(pen, points, 0.4f);
                }
            }

            // Finally, draw the oceans and lakes over the rivers to "hide" the ends of the river.
            foreach (var point in oceans)
            {
                graphic.FillRectangle(oceanbrush, new Rectangle(point.X * scale, point.Y * scale, scale, scale));
            }
            foreach (var point in lakes)
            {
                graphic.FillRectangle(lakebrush, new Rectangle(point.X * scale, point.Y * scale, scale, scale));
            }


            output.Save(filename);
            var result = DictionaryFromBitmap(output);

            output.Dispose();
            return(result);
        }
示例#7
0
        void processOceanToRiver(List <Point> oceans, List <Node> rivers, HashSet <Point> done)
        {
            List <Point>    possibleRiver = new List <Point>();    // Ocean tiles that touch at least one land tile
            HashSet <Point> working       = new HashSet <Point>(); // River tiles that have yet to be added to a tree.

            // Move all land tiles bounding ocean tiles to the possibleRiver list.
            foreach (Point pt in oceans)
            {
                foreach (Point dP in neighbors)
                {
                    Point neighbor = dP + (Size)pt; // Von Neumann neighbors! Because C# does not provide an Addition operator for Point + Point for no good reason, one Point must be cast to Size to get the sum.
                    // Check bounds first.
                    if (0 > neighbor.X || width <= neighbor.X || 0 > neighbor.Y || height <= neighbor.Y)
                    {
                        continue;
                    }
                    if (isLand(neighbor))
                    {
                        possibleRiver.Add(neighbor);
                    }
                }
            }

            // For every land tile neighbor of the Ocean tile, check if there is river. If there is river, add the river point to the working list.
            foreach (Point pt in possibleRiver)
            {
                foreach (Point dP in neighbors)
                {
                    Point neighbor = dP + (Size)pt;
                    if (isRiver(neighbor) && !working.Contains(neighbor)) // If it's any kind of river plus it hasn't already been added to the list, because duplicates are bad
                    {
                        working.Add(neighbor);
                    }
                }
            }


            // Finally, let's start building River trees.
            while (working.Count > 0)
            {
                Point basePoint = working.First();
                working.Remove(basePoint);
                if (done.Contains(basePoint)) // Skip if the point was already touched.
                {
                    continue;
                }
                done.Add(basePoint); // Mark this point as Done, so future iterations don't accidentally touch it.

                Node parent = null;

                // First, find the land tile connecting this river start and the ocean.
                foreach (Point dP in neighbors)
                {
                    Point neighbor = dP + (Size)basePoint;
                    // For each land tile surrounding the start of the ocean, find the nearest ocean tile and go there.
                    if (isLand(neighbor))
                    {
                        foreach (Point ddP in neighbors)
                        {
                            Point neighbor2 = ddP + (Size)neighbor;
                            if (isOcean(neighbor2))
                            {
                                parent = new Node(neighbor2);
                                parent.insertChild(new Node(neighbor));
                                parent._children_[0].insertChild(new Node(basePoint));
                                goto exit;
                            }
                        }
                    }
                }
                if (parent == null)
                {
                    parent = new Node(basePoint);
                }
exit:
                Dictionary <Point, Node> treeWorking = new Dictionary <Point, Node>(); // This working hashset is for building a river tree. The Node is a reference to the parent of this node.
                // There is no need for a treeDone set because what's done is done.


                // Now, if the parent has children, it means the place we are going to start looking for the river is the third node of the tree.
                if (parent._children_.Count > 0)
                {
                    Node  startnode   = parent._children_[0]._children_[0];
                    Point startcoords = startnode.center_coords;
                    foreach (Point dP in neighbors)
                    {
                        treeWorking[dP + (Size)startcoords] = startnode;
                    }
                }
                else
                {
                    foreach (Point dP in neighbors)
                    {
                        treeWorking[dP + (Size)basePoint] = parent;
                    }
                }

                buildRiverTrees(done, treeWorking);

                // At this point, the river tree should be fully built. Add the parent node to a list of rivers.
                rivers.Add(parent);
            }
        }