public static WaterTableField GenerateWaters(Bitmap bmp, IField2d <float> baseField = null, WaterTableArgs args = null, Random random = null) { args = args ?? new WaterTableArgs() { seed = System.DateTime.UtcNow.Ticks }; random = random ?? new Random((int)args.seed); baseField = baseField ?? new Simplex2D(bmp.Width, bmp.Height, args.baseNoiseScale, args.seed); Field2d <float> field = new FieldFromBitmap(bmp); baseField = new NormalizedComposition2d <float>(baseField, new ScaleTransform(new Simplex2D(baseField.Width, baseField.Height, args.baseNoiseScale, args.seed), args.baseNoiseScalar)); BrownianTree tree = BrownianTree.CreateFromOther(field, (x) => x > 0.5f ? BrownianTree.Availability.Available : BrownianTree.Availability.Unavailable, random); tree.RunDefaultTree(); HydrologicalField hydro = new HydrologicalField(tree, args.hydroSensitivity, args.hydroShoreThreshold); WaterTableField wtf = new WaterTableField(baseField, hydro, args.wtfShore, args.wtfIt, args.wtfLen, args.wtfGrade, () => { return((float)(args.wtfCarveAdd + random.NextDouble() * args.wtfCarveMul)); }); return(wtf); }
public static void RunWateryScenario() { Bitmap jranjana = new Bitmap("C:\\Users\\Justin Murray\\Desktop\\maps\\input\\rivers_lr.png"); Field2d <float> field = new Utils.FieldFromBitmap(jranjana); BrownianTree tree = BrownianTree.CreateFromOther(field, (x) => x > 0.5f ? BrownianTree.Availability.Available : BrownianTree.Availability.Unavailable); tree.RunDefaultTree(); HydrologicalField hydro = new HydrologicalField(tree); var sets = hydro.FindContiguousSets(); List <TreeNode <Point2d> > riverForest = new List <TreeNode <Point2d> >(); foreach (var river in sets[HydrologicalField.LandType.Shore]) { riverForest.Add(river.MakeTreeFromContiguousSet(pt => { // Warning: naive non-boundary-checking test-only implementation. This will probably CRASH THE PROGRAM // if a river happens to border the edge of the map. return (hydro[pt.y + 1, pt.x + 1] == HydrologicalField.LandType.Ocean || hydro[pt.y + 1, pt.x + 0] == HydrologicalField.LandType.Ocean || hydro[pt.y + 1, pt.x - 1] == HydrologicalField.LandType.Ocean || hydro[pt.y + 0, pt.x - 1] == HydrologicalField.LandType.Ocean || hydro[pt.y - 1, pt.x - 1] == HydrologicalField.LandType.Ocean || hydro[pt.y - 1, pt.x + 0] == HydrologicalField.LandType.Ocean || hydro[pt.y - 1, pt.x + 1] == HydrologicalField.LandType.Ocean || hydro[pt.y + 0, pt.x + 1] == HydrologicalField.LandType.Ocean); })); } DrainageField draino = new DrainageField(hydro, riverForest); List <TreeNode <TreeNode <Point2d> > > riverSets = new List <TreeNode <TreeNode <Point2d> > >(); foreach (var river in riverForest) { riverSets.Add(river.GetMajorSubtrees(node => node.Depth() > 15)); } using (var file = System.IO.File.OpenWrite("C:\\Users\\Justin Murray\\Desktop\\maps\\output\\report.txt")) using (var writer = new System.IO.StreamWriter(file)) { riverSets.OrderByDescending(set => set.Size()).Select(riverSet => { writer.WriteLine("River of size " + riverSet.value.Size() + " with " + riverSet.Size() + " separate sub-rivers."); foreach (var river in riverSet.ToArray().OrderByDescending(t => t.Depth())) { writer.WriteLine("\tPart of river with " + river.value.Depth() + " depth and " + (river.Size() - 1) + " tributaries."); } writer.WriteLine(); return(0); }).ToArray(); } Utils.OutputAsTributaryMap(sets, riverSets, draino, jranjana, "C:\\Users\\Justin Murray\\Desktop\\maps\\output\\tree.png"); }
private static WaterTableField InitializeWaterTableField(Args args, Random random) { BrownianTree tree = BrownianTree.CreateFromOther(args.watersDrawing, (x) => x > 0.5f ? BrownianTree.Availability.Available : BrownianTree.Availability.Unavailable, random); tree.RunDefaultTree(); HydrologicalField hydro = new HydrologicalField(tree, args.hydroSensitivity, args.hydroShoreThreshold); IField2d <float> scaledHeights = new ScaleTransform(args.heightsDrawing, args.baseHeightMaxInMeters); WaterTableField wtf = new WaterTableField(scaledHeights, hydro, args.wtfShore, args.wtfIt, args.wtfLen, args.wtfGrade, () => { return((float)(args.wtfCarveAdd + random.NextDouble() * args.wtfCarveMul)); }); return(wtf); }
static void Main() { #if true Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); var form = new Form1(); Application.Run(form); #else int width = 1000, height = 1000; var bitmap = new Bitmap(width, height); var graphics = Graphics.FromImage(bitmap); graphics.FillRectangle(Brushes.Black, 0, 0, width, height); int halfWidth = width / 2, halfHeight = height / 2; // var radiusSquared = halfWidth * halfWidth + halfHeight * halfHeight; var bestRadiusSquared = int.MaxValue; var values = new BrownianTree().Generate(width, height, (x, y) => { var deltaX = halfWidth - x; var deltaY = halfHeight - y; var radiusSquared = deltaX * deltaX + deltaY * deltaY; if (radiusSquared < bestRadiusSquared) { Console.WriteLine(); Console.WriteLine("Radius: " + Math.Sqrt(radiusSquared)); bestRadiusSquared = radiusSquared; } Console.Write("."); }); for (var i = 0; i < width; i++) { for (var j = 0; j < height; j++) { if (values[i, j]) { graphics.FillRectangle(Brushes.White, i, j, 1, 1); } } } bitmap.Save(@"c:\temp\testing1.bmp"); #endif }
public static void RunWaterHeightScenario(string simpleWatersMapName, string simpleAltitudesMapName) { WaterTableArgs args = new WaterTableArgs(); args.seed = System.DateTime.UtcNow.Ticks; Random random = new Random((int)args.seed); Bitmap jranjana = new Bitmap(args.inputPath + simpleWatersMapName); Field2d <float> field = new Utils.FieldFromBitmap(jranjana); IField2d <float> bf = new Utils.FieldFromBitmap(new Bitmap(args.inputPath + simpleAltitudesMapName)); bf = new NormalizedComposition2d <float>(bf, new ScaleTransform(new Simplex2D(bf.Width, bf.Height, args.baseNoiseScale, args.seed), args.baseNoiseScalar)); Utils.OutputField(bf, jranjana, args.outputPath + "basis.png"); BrownianTree tree = BrownianTree.CreateFromOther(field, (x) => x > 0.5f ? BrownianTree.Availability.Available : BrownianTree.Availability.Unavailable, random); tree.RunDefaultTree(); Utils.OutputField(new Transformation2d <BrownianTree.Availability, float>(tree, val => val == BrownianTree.Availability.Available ? 1f : 0f), jranjana, args.outputPath + "rivers.png"); HydrologicalField hydro = new HydrologicalField(tree, args.hydroSensitivity, args.hydroShoreThreshold); WaterTableField wtf = new WaterTableField(bf, hydro, args.wtfShore, args.wtfIt, args.wtfLen, args.wtfGrade, () => { return((float)(args.wtfCarveAdd + random.NextDouble() * args.wtfCarveMul)); }); Utils.OutputAsTributaryMap(wtf.GeographicFeatures, wtf.RiverSystems, wtf.DrainageField, jranjana, args.outputPath + "tributaries.png"); Utils.OutputField(new NormalizedComposition2d <float>(new Transformation2d <float, float, float>(bf, wtf, (b, w) => Math.Abs(b - w))), jranjana, args.outputPath + "errors.png"); Utils.SerializeMap(hydro, wtf, args.seed, args.outputPath + "serialization.bin"); Utils.OutputField(wtf, jranjana, args.outputPath + "heightmap.png"); Utils.OutputAsColoredMap(wtf, wtf.RiverSystems, jranjana, args.outputPath + "colored_map.png"); }