예제 #1
0
        public static IEnumerable <IInterval <uint> > Subtract([NotNull] this IInterval <uint> source,
                                                               [NotNull, ItemNotNull] IEnumerable <IInterval <uint> > others)
        {
            // need to order the intervals so using an intervaltree for this
            others = (others as IIntervalTree <uint, IInterval <uint> > ?? others.ToIntervalTree <uint, IInterval <uint> >()).Search(source);

            var returnFinalTarget = true;

            foreach (var other in others)
            {
                var overlap = source.TryGetOverlap(other).GetOrDefault();
                if (overlap == null) // sanity check, but since we search a tree, this should never happen.
                {
                    continue;
                }

                IInterval <uint> firstOne = null, secondOne = null;
                // subtraction only gives a result of 0, 1, or 2 returns, everything else is impossible.
                foreach (var leftover in source.SubtractOverlap(overlap))
                {
                    if (firstOne == null) // means first time in loop
                    {
                        firstOne = leftover;
                    }
                    else
                    {
                        secondOne = leftover;
                    }
                }

                if (firstOne == null) // means there was no leftovers
                {
                    // if this is the last one, then we should not release the final one.
                    returnFinalTarget = false;
                    continue;
                }

                // some leftover stuff, so should release those.
                returnFinalTarget = true;
                if (secondOne == null) // means only one leftover, we just continue subtracting.
                {
                    source = firstOne;
                }
                else // means 2 leftover, which means we yield the first one and then continue subtracting from the second one.
                {
                    yield return(firstOne);

                    source = secondOne;
                }
            }

            if (returnFinalTarget)
            {
                yield return(source); // return last one or only one if no loops
            }
        }