コード例 #1
0
        public static int SelectIntValue(this IValueGenerator gen, Func <double> random, INamedDataCollection data)
        {
            Contract.Requires(gen != null);
            Contract.Requires(random != null);
            Contract.Requires(data != null);

            checked
            {
                //Rearrange the min and max to be integers (in a narrower or equal range)
                var min = (long)Math.Ceiling(gen.MinValue);
                var max = (long)Math.Floor(gen.MaxValue);

                //If they're the same we don't have a whole lot of choice!
                if (min == max)
                {
                    return((int)min);
                }

                //If they're inverted the range is too narrow (e.g. Min:0.1 Max:0.9 we can't select any integers in that range)
                if (min > max)
                {
                    //Swap max and min
                    var tmp = max;
                    max = min;
                    min = tmp;
                }

                //Clamp and round the value
                return((int)Math.Round(MathHelper.Clamp(gen.SelectFloatValue(random, data), min, max), MidpointRounding.AwayFromZero));
            }
        }
コード例 #2
0
        public float SelectFloatValue(Func <double> random, INamedDataCollection data)
        {
            if (_singleCache.HasValue && !_vary)
            {
                return(_singleCache.Value);
            }

            _singleCache = _transform(_basis.SelectFloatValue(random, data));
            return(_singleCache.Value);
        }
コード例 #3
0
        public static IValueGenerator Average(IValueGenerator a, IValueGenerator b)
        {
            Contract.Requires(a != null);
            Contract.Requires(b != null);
            Contract.Ensures(Contract.Result <IValueGenerator>() != null);

            return(new FuncValue(
                       (r, m) => a.SelectFloatValue(r, m) * 0.5f + b.SelectFloatValue(r, m) * 0.5f,
                       Math.Min(a.MinValue, b.MinValue),
                       Math.Max(a.MinValue, a.MaxValue)
                       ));
        }
コード例 #4
0
        public static IValueGenerator Add(this IValueGenerator a, IValueGenerator b)
        {
            Contract.Requires(a != null);
            Contract.Requires(b != null);
            Contract.Ensures(Contract.Result <IValueGenerator>() != null);

            return(new FuncValue(
                       (r, m) => a.SelectFloatValue(r, m) + b.SelectFloatValue(r, m),
                       a.MinValue + b.MinValue,
                       a.MinValue + a.MaxValue
                       ));
        }
コード例 #5
0
        private IEnumerable <Parcel> RecursiveSplit(Parcel parcel, Func <double> random, INamedDataCollection metadata)
        {
            Contract.Requires(parcel != null);
            Contract.Requires(random != null);
            Contract.Requires(metadata != null);

            //Accumulate chance of termination, checking for any rule which forbods it (i.e. probability zero)
            float accumulator = 0;
            var   noChance    = false;

            for (var i = 0; i < _terminators.Count && !noChance; i++)
            {
                var c = _terminators[i].TerminationChance(parcel);
                if (c.HasValue)
                {
                    accumulator += c.Value;
                    noChance    |= c.Value <= 0;
                }
            }

            //If random chance beats average of all termination chances then stop here
            if (accumulator / _terminators.Count >= random())
            {
                return new[] { parcel }
            }
            ;

            var oabb = FitOabb(parcel, _nonOptionalObbChance.SelectFloatValue(random, metadata), _nonOptionalObbChance.SelectFloatValue(random, metadata), random);

            var splitLine = oabb.SplitDirection();
            var children  = Split(parcel, oabb, splitLine, random, metadata).ToArray();

            //If any children are discarded try splitting the other way
            // ReSharper disable once AccessToModifiedClosure
            if (_terminators.Any(t => children.Any(c => t.Discard(c, random))))
            {
                splitLine = splitLine.Perpendicular();

                children = Split(parcel, oabb, splitLine, random, metadata).ToArray();
            }

            //Either return this parcel because we can't find any valid children, or continue recursive splitting
            if (_terminators.Any(t => children.Any(c => t.Discard(c, random))))
            {
                return new[] { parcel }
            }
            ;
            else
            {
                return(children.SelectMany(a => RecursiveSplit(a, random, metadata)).ToArray());
            }
        }
コード例 #6
0
        private IEnumerable <Parcel> Split(Parcel parcel, OABR oabb, Vector2 sliceDirection, Func <double> random, INamedDataCollection metadata)
        {
            Contract.Requires(parcel != null);
            Contract.Requires(random != null);
            Contract.Requires(metadata != null);

            var extent = (oabb.Max - oabb.Min) / 2;
            var point  = oabb.Middle + Math.Max(extent.X, extent.Y) * sliceDirection.Perpendicular() * _splitPoint.SelectFloatValue(random, metadata);

            var slices = parcel.Points().SlicePolygon(new Ray2(point, sliceDirection));

            return(slices.Select(a => ToParcel(parcel, a)));
        }