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); }