private void ComputeOverlaps(int start0, int end0, MonotoneChain mc, int start1, int end1, MonotoneChainOverlapAction mco) { // terminating condition for the recursion if (end0 - start0 == 1 && end1 - start1 == 1) { mco.Overlap(this, start0, mc, start1); return; } // nothing to do if the envelopes of these sub-chains don't overlap if (!Overlaps(start0, end0, mc, start1, end1)) { return; } // the chains overlap, so split each in half and iterate (binary search) int mid0 = (start0 + end0) / 2; int mid1 = (start1 + end1) / 2; // Assert: mid != start or end (since we checked above for end - start <= 1) // check terminating conditions before recursing if (start0 < mid0) { if (start1 < mid1) { ComputeOverlaps(start0, mid0, mc, start1, mid1, mco); } if (mid1 < end1) { ComputeOverlaps(start0, mid0, mc, mid1, end1, mco); } } if (mid0 < end0) { if (start1 < mid1) { ComputeOverlaps(mid0, end0, mc, start1, mid1, mco); } if (mid1 < end1) { ComputeOverlaps(mid0, end0, mc, mid1, end1, mco); } } }
/// <summary> /// Determine all the line segments in two chains which may overlap, and process them. /// </summary> /// <remarks> /// The monotone chain search algorithm attempts to optimize /// performance by not calling the overlap action on chain segments /// which it can determine do not overlap. /// However, it *may* call the overlap action on segments /// which do not actually interact. /// This saves on the overhead of checking intersection /// each time, since clients may be able to do this more efficiently. /// </remarks> /// <param name="mc">The monotone chain</param> /// <param name="mco">The overlap action to execute on selected segments</param> public void ComputeOverlaps(MonotoneChain mc, MonotoneChainOverlapAction mco) { ComputeOverlaps(_start, _end, mc, mc._start, mc._end, mco); }