Пример #1
0
        /// <summary>
        /// Implements logic for splitting the interval defined by the <paramref name="valueRange" /> into smaller intervals (ranges) using logarithmic distribution.
        /// The base of the logarithm is the <see cref="LogarithmBase"/> property.
        /// </summary>
        /// <remarks>
        /// <para>
        /// The <paramref name="valueRange"/> is mapped to a made-up interval that is separated into <paramref name="count"/> sub-ranges as follows:
        /// b^0, b^1, ... , b^<paramref name="count"/>.
        /// The actual boundary (upper) value of a range with index i is defined from the following equality:
        /// </para>
        /// <para>
        /// actualBoundaryValue = (max - min) * ratio + min
        /// </para>
        /// <para>
        /// where
        /// </para>
        /// <para>
        /// ratio = (base^i - 1)/(base^count - 1)
        /// </para>
        /// <para>
        /// and min and max are <see cref="T:ValueRange.Minimum"/> and <see cref="T:ValueRange.Maximum"/> of the <paramref name="valueRange" />.
        /// </para>
        /// <para>
        /// This ratio is sensitive to the power values. The <see cref="CalculateMaxPowerForRangeLengthPrecision"/> method returns a value that defines the maximum power x, defined by the following inequality:
        /// </para>
        /// <para>
        /// b^x &lt;= 10^10
        /// </para>
        /// <para>
        /// This power defines the smallest possible width of a range.
        /// </para>
        /// </remarks>
        /// <param name="valueRange">The full range that will be divided.</param>
        /// <param name="count">The count of the generated ranges.</param>
        protected internal override IEnumerable <ColorRange> BuildRanges(ValueRange <double> valueRange, int count)
        {
            this.ranges.Clear();

            double delta = valueRange.maximum - valueRange.minimum;

            if (delta <= 0)
            {
                yield break;
            }

            double startValue = valueRange.minimum;
            double max        = 0d;

            if (this.logBaseCache == 1)
            {
                var step = delta / count;

                foreach (var colorRange in LinearRangeDistribution.BuildLinearRanges(valueRange, count, step))
                {
                    yield return(colorRange);
                }
            }
            else
            {
                var context = new RatioCalculationContext()
                {
                    MaxPower   = this.CalculateMaxPowerForRangeLengthPrecision(),
                    RangeCount = count
                };

                for (int i = 1; i <= count; i++)
                {
                    if (i == count)
                    {
                        max = valueRange.maximum;
                    }
                    else
                    {
                        var ratio = this.logBaseCache > 1 ? this.CalculateRatio(i, context) : this.CalculateRatioForLogBaseBetweenZeroAndOne(i, context);
                        max = valueRange.minimum + delta * ratio;
                    }

                    var range = new ColorRange()
                    {
                        Min   = startValue,
                        Max   = max,
                        Index = i - 1
                    };

                    this.ranges.Add(range);

                    startValue = max;

                    yield return(range);
                }
            }
        }
Пример #2
0
        // calculates (1 - b^i)/(1 - b^n)
        // 0 < b < 1
        // *in this case i = n-i -> reversed order of the intervals
        internal double CalculateRatioForLogBaseBetweenZeroAndOne(int index, RatioCalculationContext context)
        {
            var count    = context.RangeCount;
            var maxPower = context.MaxPower;
            var logBase  = this.logBaseCache;

            if (count > maxPower)
            {
                if (index > maxPower)
                {
                    //// 1/1
                    return(1);
                }
                else
                {
                    if (context.BaseToPowerOfCurrentIndex == 0)
                    {
                        //// 1-b^i
                        context.BaseToPowerOfCurrentIndex = Math.Pow(logBase, index);
                    }
                    else
                    {
                        ////b^i
                        context.BaseToPowerOfCurrentIndex *= logBase;
                    }

                    return(1 - context.BaseToPowerOfCurrentIndex);
                }
            }
            else
            {
                context.BaseToPowerOfCurrentIndex *= logBase;

                if (context.BaseToPowerOfCount == 0)
                {
                    context.BaseToPowerOfCount = Math.Pow(logBase, count);
                }

                return((1 - context.BaseToPowerOfCurrentIndex) / (1 - context.BaseToPowerOfCount));
            }
        }
Пример #3
0
        // calculates (b^i - 1)/(b^n - 1)
        // 1 < b
        internal double CalculateRatio(int index, RatioCalculationContext context)
        {
            var count    = context.RangeCount;
            var maxPower = context.MaxPower;
            var logBase  = this.logBaseCache;

            if (count > maxPower)
            {
                if (count - index > maxPower)
                {
                    //// 1/inf
                    return(0);
                }
                else
                {
                    if (context.BaseToPowerOfCount == 0)
                    {
                        //// b^(i-n)
                        context.BaseToPowerOfCount = Math.Pow(logBase, index - count);
                    }
                    else
                    {
                        //// b^(i-n)
                        context.BaseToPowerOfCount *= logBase;
                    }

                    return(context.BaseToPowerOfCount);
                }
            }
            else
            {
                context.BaseToPowerOfCurrentIndex *= logBase;

                if (context.BaseToPowerOfCount == 0)
                {
                    context.BaseToPowerOfCount = Math.Pow(logBase, count);
                }

                return((context.BaseToPowerOfCurrentIndex - 1) / (context.BaseToPowerOfCount - 1));
            }
        }