void csRectRegion::Exclude (const csRect &nrect) { // Ignore an empty rect if (nrect.IsEmpty ()) return; // If there are no rects in the region, just leave. if (region.IsEmpty()) return; size_t i; csRect rect (nrect); /// Clear the fragment buffer for (i = 0; i < FRAGMENT_BUFFER_SIZE; ++i) fragment[i].MakeEmpty (); // Otherwise, we have to see if this rect overlaps or touches any other. for (i = 0; i < region.GetSize(); i++) { csRect r1 (region[i]); csRect r2 (rect); // Check to see if these even touch if (r2.Intersects (r1) == false) continue; // Check to see if the inclusion rect is totally dominated by the // exclusion rect. r1.Exclude (r2); if (r1.IsEmpty ()) { region.DeleteIndex (i); i--; continue; } // Check to see if the exclusion rect is totally dominated by the // exclusion rect r1.Set (region[i]); r2.Exclude (r1); if (r2.IsEmpty ()) { r2.Set (rect); region.DeleteIndex (i); fragmentContainedRect (r1, r2); i = 0; continue; } r2.Set (rect); // This part is similiar to Include, except that we are trying to remove // a portion. Instead of calling chopEdgeIntersection, we actually have // to fragment rect1 and chop off an edge of the excluding rect. This // code should be handled inside fragment rect. // Kill rect from list region.DeleteIndex (i); i--; // Fragment it fragmentRect (r1, r2, MODE_EXCLUDE); } }
void csRectRegion::Include (const csRect &nrect) { // Ignore an empty rect if (nrect.IsEmpty ()) return; // If there are no rects in the region, add this and leave. if (region.IsEmpty()) { region.Push (nrect); return; } size_t i; bool no_fragments; csRect rect (nrect); /// Clear the fragment buffer for (i = 0; i < FRAGMENT_BUFFER_SIZE; ++i) fragment[i].MakeEmpty (); do { bool untouched = true; no_fragments = true; // Otherwise, we have to see if this rect creates a union with any other // rectangles. size_t last_to_consider = region.GetSize(); for (i = 0; i < last_to_consider; i++) { csRect &r1 = region[i]; csRect r2 (rect); // Check to see if these even touch, if not, next. if (r2.Intersects (r1) == false) continue; // If r1 totally contains rect, then we leave. r2.Exclude (r1); if (r2.IsEmpty ()) { // Mark it so we don't add it in untouched = false; break; } // If rect totally contains r1, then we kill r1 from the list. r2.Set (r1); r2.Exclude (rect); if (r2.IsEmpty ()) { // Kill from list region.DeleteIndex (i); i--; last_to_consider--; // Iterate continue; } /* // Otherwise we have to do the most irritating part: A full split // operation that may create other rects that need to be tested against // the database recursively. For this algorithm, we fragment the // one that is already in the database, that way we don't cause more // tests: we already know that that rect is good. r2.Set (rect); // Kill rect from list region.DeleteIndex (i); // Fragment it fragmentRect (r1, r2, MODE_INCLUDE); */ r2.Set (rect); nkSplit (r1, r2); region.DeleteIndex (i); i--; last_to_consider--; // Mark it // untouched = true; } // end for // In the end, we need to put the rect on the stack if (!rect.IsEmpty () && untouched) region.Push (rect); // Check and see if we have fragments to consider for (i = 0; i < FRAGMENT_BUFFER_SIZE; ++i) { if (!(fragment[i].IsEmpty ())) { rect.Set (fragment[i]); fragment[i].MakeEmpty (); no_fragments = false; break; } } } while (!no_fragments); }