Example #1
0
        /// <summary>
        ///     Tries to merge two <see cref="AngleInterval" />.
        /// </summary>
        /// <param name="newInterval"><see cref="AngleInterval" /> to be merged.</param>
        /// <param name="resultInterval">Result <see cref="AngleInterval" /> if merge is success.</param>
        /// <returns>True if merge is success.</returns>
        public bool TryMerge(AngleInterval newInterval, out AngleInterval resultInterval)
        {
            if (newInterval._full)
            {
                resultInterval = newInterval;
                return(true);
            }
            if (_full || Equals(newInterval))
            {
                resultInterval = this;
                return(true);
            }
            var aStart     = _from;
            var aEnd       = aStart > _to ? _to + 360 : _to;
            var bStart     = newInterval._from;
            var bEnd       = bStart > newInterval._to ? newInterval._to + 360 : newInterval._to;
            var diffA      = (aEnd - aStart) / 2;
            var diffB      = (bEnd - bStart) / 2;
            var avgA       = (aStart + aEnd) / 2;
            var avgB       = (bStart + bEnd) / 2;
            var cosDiffA   = Math.Cos(diffA.ToRadians());
            var cosDiffB   = Math.Cos(diffB.ToRadians());
            var resultFlag = MergeFlag.None;

            if (Math.Cos((avgA - bStart).ToRadians()).AboutGreaterThanOrEqual(cosDiffA))
            {
                resultFlag |= MergeFlag.BStartInsideA;
            }
            if (Math.Cos((avgA - bEnd).ToRadians()).AboutGreaterThanOrEqual(cosDiffA))
            {
                resultFlag |= MergeFlag.BEndInsideA;
            }
            if (Math.Cos((avgB - aStart).ToRadians()).AboutGreaterThanOrEqual(cosDiffB))
            {
                resultFlag |= MergeFlag.AStartInsideB;
            }
            if (Math.Cos((avgB - aEnd).ToRadians()).AboutGreaterThanOrEqual(cosDiffB))
            {
                resultFlag |= MergeFlag.AEndInsideB;
            }
            if (NotHasFlags(resultFlag, MergeFlag.BStartInsideA, MergeFlag.BEndInsideA,
                            MergeFlag.AEndInsideB, MergeFlag.AStartInsideB))
            {
                resultInterval = null;
                return(false);
            }
            if (HasFlags(resultFlag, MergeFlag.BStartInsideA, MergeFlag.BEndInsideA,
                         MergeFlag.AEndInsideB, MergeFlag.AStartInsideB))
            {
                resultInterval = new AngleInterval(true);
                return(true);
            }
            if (HasFlags(resultFlag, MergeFlag.BStartInsideA, MergeFlag.BEndInsideA))
            {
                resultInterval = this;
                return(true);
            }
            if (HasFlags(resultFlag, MergeFlag.AEndInsideB, MergeFlag.AStartInsideB))
            {
                resultInterval = newInterval;
                return(true);
            }
            if (HasFlags(resultFlag, MergeFlag.AEndInsideB, MergeFlag.BStartInsideA) &&
                NotHasFlags(resultFlag, MergeFlag.AStartInsideB, MergeFlag.BEndInsideA))
            {
                resultInterval = new AngleInterval(aStart, bEnd);
                return(true);
            }

            // Invert if
            if (!HasFlags(resultFlag, MergeFlag.AStartInsideB, MergeFlag.BEndInsideA) ||
                !NotHasFlags(resultFlag, MergeFlag.AEndInsideB, MergeFlag.BStartInsideA))
            {
                throw new InvalidOperationException("This should never happen.");
            }
            resultInterval = new AngleInterval(bStart, aEnd);
            return(true);
        }
Example #2
0
 public bool Equals(AngleInterval shadow)
 {
     return(_from.AboutEqual(shadow._from) && _to.AboutEqual(shadow._to) && _full == shadow._full);
 }