Ejemplo n.º 1
0
        public static IField2d <float> GetWaterinessMap(WaterTableField wtf, IField2d <float> rainfall, float waterPortability = 5f, float waterinessAttenuation = 20f)
        {
            // Generate "water flow" map using the rainfall map and the water table map, characterizing
            // how much water is in an area based on upstream.  Note that, in the simplistic case of
            // identical universal rainfall, this is just a scalar on depth; this whole shindig is
            // intended to support variable rainfall, as characterized by the rainfall map.
            Field2d <float> waterFlow = new Field2d <float>(rainfall);
            float           maxValue  = float.MinValue;

            foreach (TreeNode <Point2d> waterway in wtf.Waterways)
            {
                List <TreeNode <Point2d> > flattenedReversedRiverTree = new List <TreeNode <Point2d> >(waterway);
                flattenedReversedRiverTree.Reverse();

                foreach (var node in flattenedReversedRiverTree)
                {
                    if (node.parent != null)
                    {
                        Point2d cur = node.value;
                        Point2d par = node.parent.value;

                        waterFlow[par.y, par.x] += waterFlow[cur.y, cur.x];
                    }

                    maxValue = Math.Max(maxValue, waterFlow[node.value.y, node.value.x]);
                }
            }
            IField2d <float> waterinessUnblurred = new FunctionField <float>(waterFlow.Width, waterFlow.Height,
                                                                             (x, y) => 1f / (1f + (float)Math.Pow(Math.E, -waterinessAttenuation * waterFlow[y, x] / maxValue)));

            return(new BlurredField(waterinessUnblurred, waterPortability));
        }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
0
        public static List <Point2d> GetSettlementLocations(WaterTableField wtf, IField2d <float> wateriness,
                                                            float noiseScale = 0.1f, float noiseBlur = 3f, float noiseContribution = 0.15f)
        {
            IField2d <float> noise = new BlurredField(new MountainNoise(wtf.Width, wtf.Height, noiseScale), noiseBlur);
            Transformation2d <float, float, float> combination = new Transformation2d <float, float, float>(wateriness, noise, (w, n) => w + noiseContribution * n);

            List <Point2d> locations = new List <Point2d>();

            for (int y = 1; y < combination.Height - 1; y++)
            {
                for (int x = 1; x < combination.Width - 1; x++)
                {
                    if (wtf[y, x] > 0f &&
                        combination[y - 1, x - 1] < combination[y, x] &&
                        combination[y - 1, x + 0] < combination[y, x] &&
                        combination[y - 1, x + 1] < combination[y, x] &&
                        combination[y + 0, x + 1] < combination[y, x] &&
                        combination[y + 1, x + 1] < combination[y, x] &&
                        combination[y + 1, x + 0] < combination[y, x] &&
                        combination[y + 1, x - 1] < combination[y, x] &&
                        combination[y + 0, x - 1] < combination[y, x])
                    {
                        locations.Add(new Point2d(x, y));
                    }
                }
            }

            return(locations);
        }
Ejemplo n.º 4
0
        public MeterScaleMap(Args args)
        {
            this.args = args;

            Random random = new Random((int)this.args.seed);

            this.wtf             = InitializeWaterTableField(this.args, random);
            this.distanceToWater = InitializeDistanceFromWater(this.wtf, this.args);
            this.splines         = InitializeSplines(this.wtf, random);
            this.mountainNoise   = InitializeMountainNoise(this.wtf, this.args.seed, this.args.metersPerPixel);
        }
Ejemplo n.º 5
0
        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);
        }
Ejemplo n.º 6
0
        private static ContinuousField InitializeDistanceFromWater(WaterTableField wtf, Args args)
        {
            var dists = new Transformation2d <Point2d, float>(wtf.DrainageField, (x, y, p) =>
            {
                if (wtf.HydroField[y, x] != HydrologicalField.LandType.Land)
                {
                    return(0f);
                }

                // We subtract 1 to compute the distance as water-adjacent as well as on-the-water.
                // This is a slight bit of a hack, but helps account for problems at varying resolutions.
                return(args.metersPerPixel * (Point2d.Distance(new Point2d(x, y), p) - 1f));
            });

            return(new ContinuousField(dists));
        }
Ejemplo n.º 7
0
        private static SparseField2d <List <SplineTree> > InitializeSplines(WaterTableField wtf, Random random)
        {
            var splines = new SparseField2d <List <SplineTree> >(wtf.Width, wtf.Height, null);

            foreach (var system in wtf.RiverSystems)
            {
                SplineTree tree = null;

                foreach (var p in system.value)
                {
                    if (splines[p.value.y, p.value.x] == null)
                    {
                        splines[p.value.y, p.value.x] = new List <SplineTree>();
                    }

                    splines[p.value.y, p.value.x].Add(tree ?? (tree = new SplineTree(system.value, wtf, random)));
                }
            }

            return(splines);
        }
Ejemplo n.º 8
0
        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");
        }
Ejemplo n.º 9
0
 private static ContinuousMountainNoise InitializeMountainNoise(WaterTableField wtf, long seed, float metersPerPixel)
 {
     return(new ContinuousMountainNoise(wtf.Width, wtf.Height, GetMountainNoiseStartingScale(metersPerPixel), seed));
 }