diff options
author | caryclark@google.com <caryclark@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-04-23 11:56:44 +0000 |
---|---|---|
committer | caryclark@google.com <caryclark@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-04-23 11:56:44 +0000 |
commit | 3b97af5add04489d57c7926ba6dc6f0013daf40f (patch) | |
tree | 40db068c2b906575b3afa46cac6a2bbe9a840e39 | |
parent | c7e08bd6d06a421050ddd7060fbafa5b5e047752 (diff) |
path ops -- use standard max, min, double-is-nan
fix a comment or two as well
Review URL: https://codereview.chromium.org/13934009
git-svn-id: http://skia.googlecode.com/svn/trunk@8822 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r-- | include/core/SkFloatingPoint.h | 2 | ||||
-rw-r--r-- | include/core/SkTypes.h | 8 | ||||
-rw-r--r-- | src/pathops/SkDCubicIntersection.cpp | 36 | ||||
-rw-r--r-- | src/pathops/SkDLineIntersection.cpp | 24 | ||||
-rw-r--r-- | src/pathops/SkDQuadIntersection.cpp | 2 | ||||
-rw-r--r-- | src/pathops/SkPathOpsBounds.h | 4 | ||||
-rw-r--r-- | src/pathops/SkPathOpsPoint.h | 12 | ||||
-rw-r--r-- | src/pathops/SkPathOpsQuad.cpp | 2 | ||||
-rw-r--r-- | src/pathops/SkPathOpsTypes.h | 16 | ||||
-rw-r--r-- | tests/PathOpsDRectTest.cpp | 48 |
10 files changed, 75 insertions, 79 deletions
diff --git a/include/core/SkFloatingPoint.h b/include/core/SkFloatingPoint.h index 02880f3d23..44a3eef98d 100644 --- a/include/core/SkFloatingPoint.h +++ b/include/core/SkFloatingPoint.h @@ -77,6 +77,8 @@ static inline float sk_float_copysign(float x, float y) { #define sk_float_isinf(x) isinf(x) #endif +#define sk_double_isnan(a) sk_float_isnan(a) + #ifdef SK_USE_FLOATBITS #define sk_float_floor2int(x) SkFloatToIntFloor(x) #define sk_float_round2int(x) SkFloatToIntRound(x) diff --git a/include/core/SkTypes.h b/include/core/SkTypes.h index ae27089bf7..4f6788c928 100644 --- a/include/core/SkTypes.h +++ b/include/core/SkTypes.h @@ -314,6 +314,14 @@ static inline int32_t SkMin32(int32_t a, int32_t b) { return a; } +template <typename T> const T& SkTMin(const T& a, const T& b) { + return (a < b) ? a : b; +} + +template <typename T> const T& SkTMax(const T& a, const T& b) { + return (b < a) ? a : b; +} + static inline int32_t SkSign32(int32_t a) { return (a >> 31) | ((unsigned) -a >> 31); } diff --git a/src/pathops/SkDCubicIntersection.cpp b/src/pathops/SkDCubicIntersection.cpp index 2f1804d526..10d4e71d03 100644 --- a/src/pathops/SkDCubicIntersection.cpp +++ b/src/pathops/SkDCubicIntersection.cpp @@ -141,12 +141,12 @@ static void intersect(const SkDCubic& cubic1, double t1s, double t1e, const SkDC #if 1 double c1Bottom = tIdx == 0 ? 0 : (t1Start + (t1 - t1Start) * locals[0][tIdx - 1] + to1) / 2; - double c1Min = SkTMax<double>(c1Bottom, to1 - offset); + double c1Min = SkTMax(c1Bottom, to1 - offset); double c1Top = tIdx == tCount - 1 ? 1 : (t1Start + (t1 - t1Start) * locals[0][tIdx + 1] + to1) / 2; - double c1Max = SkTMin<double>(c1Top, to1 + offset); - double c2Min = SkTMax<double>(0., to2 - offset); - double c2Max = SkTMin<double>(1., to2 + offset); + double c1Max = SkTMin(c1Top, to1 + offset); + double c2Min = SkTMax(0., to2 - offset); + double c2Max = SkTMin(1., to2 + offset); #if ONE_OFF_DEBUG SkDebugf("%.*s %s 1 contains1=%d/%d contains2=%d/%d\n", i.depth()*2, tab, __FUNCTION__, @@ -172,8 +172,8 @@ static void intersect(const SkDCubic& cubic1, double t1s, double t1e, const SkDC i.used(), i.used() > 0 ? i[0][i.used() - 1] : -1); #endif if (tCount > 1) { - c1Min = SkTMax<double>(0., to1 - offset); - c1Max = SkTMin<double>(1., to1 + offset); + c1Min = SkTMax(0., to1 - offset); + c1Max = SkTMin(1., to1 + offset); double c2Bottom = tIdx == 0 ? to2 : (t2Start + (t2 - t2Start) * locals[1][tIdx - 1] + to2) / 2; double c2Top = tIdx == tCount - 1 ? to2 : @@ -187,8 +187,8 @@ static void intersect(const SkDCubic& cubic1, double t1s, double t1e, const SkDC if (c2Top == to2) { c2Top = 1; } - c2Min = SkTMax<double>(c2Bottom, to2 - offset); - c2Max = SkTMin<double>(c2Top, to2 + offset); + c2Min = SkTMax(c2Bottom, to2 - offset); + c2Max = SkTMin(c2Top, to2 + offset); #if ONE_OFF_DEBUG SkDebugf("%.*s %s 2 contains1=%d/%d contains2=%d/%d\n", i.depth()*2, tab, __FUNCTION__, @@ -213,8 +213,8 @@ static void intersect(const SkDCubic& cubic1, double t1s, double t1e, const SkDC SkDebugf("%.*s %s 2 i.used=%d t=%1.9g\n", i.depth()*2, tab, __FUNCTION__, i.used(), i.used() > 0 ? i[0][i.used() - 1] : -1); #endif - c1Min = SkTMax<double>(c1Bottom, to1 - offset); - c1Max = SkTMin<double>(c1Top, to1 + offset); + c1Min = SkTMax(c1Bottom, to1 - offset); + c1Max = SkTMin(c1Top, to1 + offset); #if ONE_OFF_DEBUG SkDebugf("%.*s %s 3 contains1=%d/%d contains2=%d/%d\n", i.depth()*2, tab, __FUNCTION__, @@ -243,10 +243,10 @@ static void intersect(const SkDCubic& cubic1, double t1s, double t1e, const SkDC #else double c1Bottom = tIdx == 0 ? 0 : (t1Start + (t1 - t1Start) * locals.fT[0][tIdx - 1] + to1) / 2; - double c1Min = SkTMax<double>(c1Bottom, to1 - offset); + double c1Min = SkTMax(c1Bottom, to1 - offset); double c1Top = tIdx == tCount - 1 ? 1 : (t1Start + (t1 - t1Start) * locals.fT[0][tIdx + 1] + to1) / 2; - double c1Max = SkTMin<double>(c1Top, to1 + offset); + double c1Max = SkTMin(c1Top, to1 + offset); double c2Bottom = tIdx == 0 ? to2 : (t2Start + (t2 - t2Start) * locals.fT[1][tIdx - 1] + to2) / 2; double c2Top = tIdx == tCount - 1 ? to2 : @@ -260,8 +260,8 @@ static void intersect(const SkDCubic& cubic1, double t1s, double t1e, const SkDC if (c2Top == to2) { c2Top = 1; } - double c2Min = SkTMax<double>(c2Bottom, to2 - offset); - double c2Max = SkTMin<double>(c2Top, to2 + offset); + double c2Min = SkTMax(c2Bottom, to2 - offset); + double c2Max = SkTMin(c2Top, to2 + offset); #if ONE_OFF_DEBUG SkDebugf("%s contains1=%d/%d contains2=%d/%d\n", __FUNCTION__, c1Min <= 0.210357794 && 0.210357794 <= c1Max @@ -351,13 +351,13 @@ static void intersectEnd(const SkDCubic& cubic1, bool start, const SkDCubic& cub while (tLast + 1 < tVals.count() && roughly_equal(tVals[tLast + 1], tVals[tIdx])) { ++tLast; } - double tMin2 = SkTMax<double>(tVals[tIdx] - LINE_FRACTION, 0.0); - double tMax2 = SkTMin<double>(tVals[tLast] + LINE_FRACTION, 1.0); + double tMin2 = SkTMax(tVals[tIdx] - LINE_FRACTION, 0.0); + double tMax2 = SkTMin(tVals[tLast] + LINE_FRACTION, 1.0); int lastUsed = i.used(); intersect(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, i); if (lastUsed == i.used()) { - tMin2 = SkTMax<double>(tVals[tIdx] - (1.0 / SkDCubic::gPrecisionUnit), 0.0); - tMax2 = SkTMin<double>(tVals[tLast] + (1.0 / SkDCubic::gPrecisionUnit), 1.0); + tMin2 = SkTMax(tVals[tIdx] - (1.0 / SkDCubic::gPrecisionUnit), 0.0); + tMax2 = SkTMin(tVals[tLast] + (1.0 / SkDCubic::gPrecisionUnit), 1.0); intersect(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, i); } tIdx = tLast + 1; diff --git a/src/pathops/SkDLineIntersection.cpp b/src/pathops/SkDLineIntersection.cpp index 93f0353048..68e1f9e421 100644 --- a/src/pathops/SkDLineIntersection.cpp +++ b/src/pathops/SkDLineIntersection.cpp @@ -109,16 +109,16 @@ int SkIntersections::intersect(const SkDLine& a, const SkDLine& b) { if ((at0 < 0 && at1 < 0) || (at0 > 1 && at1 > 1)) { return fUsed = 0; } - fT[0][0] = SkTMax<double>(SkTMin<double>(at0, 1.0), 0.0); - fT[0][1] = SkTMax<double>(SkTMin<double>(at1, 1.0), 0.0); + fT[0][0] = SkTMax(SkTMin(at0, 1.0), 0.0); + fT[0][1] = SkTMax(SkTMin(at1, 1.0), 0.0); } double bDenom = b0 - b1; if (approximately_zero(bDenom)) { fT[1][0] = fT[1][1] = 0; } else { int bIn = aDenom * bDenom < 0; - fT[1][bIn] = SkTMax<double>(SkTMin<double>((b0 - a0) / bDenom, 1.0), 0.0); - fT[1][!bIn] = SkTMax<double>(SkTMin<double>((b0 - a1) / bDenom, 1.0), 0.0); + fT[1][bIn] = SkTMax(SkTMin((b0 - a0) / bDenom, 1.0), 0.0); + fT[1][!bIn] = SkTMax(SkTMin((b0 - a1) / bDenom, 1.0), 0.0); } bool second = fabs(fT[0][0] - fT[0][1]) > FLT_EPSILON; SkASSERT((fabs(fT[1][0] - fT[1][1]) <= FLT_EPSILON) ^ second); @@ -189,11 +189,11 @@ int SkIntersections::horizontal(const SkDLine& line, double left, double right, if ((at0 < 0 && at1 < 0) || (at0 > 1 && at1 > 1)) { return fUsed = 0; } - fT[0][0] = SkTMax<double>(SkTMin<double>(at0, 1.0), 0.0); - fT[0][1] = SkTMax<double>(SkTMin<double>(at1, 1.0), 0.0); + fT[0][0] = SkTMax(SkTMin(at0, 1.0), 0.0); + fT[0][1] = SkTMax(SkTMin(at1, 1.0), 0.0); int bIn = (a0 - a1) * (b0 - b1) < 0; - fT[1][bIn] = SkTMax<double>(SkTMin<double>((b0 - a0) / (b0 - b1), 1.0), 0.0); - fT[1][!bIn] = SkTMax<double>(SkTMin<double>((b0 - a1) / (b0 - b1), 1.0), 0.0); + fT[1][bIn] = SkTMax(SkTMin((b0 - a0) / (b0 - b1), 1.0), 0.0); + fT[1][!bIn] = SkTMax(SkTMin((b0 - a1) / (b0 - b1), 1.0), 0.0); bool second = fabs(fT[0][0] - fT[0][1]) > FLT_EPSILON; SkASSERT((fabs(fT[1][0] - fT[1][1]) <= FLT_EPSILON) ^ second); return computePoints(line, 1 + second); @@ -250,11 +250,11 @@ int SkIntersections::vertical(const SkDLine& line, double top, double bottom, if ((at0 < 0 && at1 < 0) || (at0 > 1 && at1 > 1)) { return fUsed = 0; } - fT[0][0] = SkTMax<double>(SkTMin<double>(at0, 1.0), 0.0); - fT[0][1] = SkTMax<double>(SkTMin<double>(at1, 1.0), 0.0); + fT[0][0] = SkTMax(SkTMin(at0, 1.0), 0.0); + fT[0][1] = SkTMax(SkTMin(at1, 1.0), 0.0); int bIn = (a0 - a1) * (b0 - b1) < 0; - fT[1][bIn] = SkTMax<double>(SkTMin<double>((b0 - a0) / (b0 - b1), 1.0), 0.0); - fT[1][!bIn] = SkTMax<double>(SkTMin<double>((b0 - a1) / (b0 - b1), 1.0), 0.0); + fT[1][bIn] = SkTMax(SkTMin((b0 - a0) / (b0 - b1), 1.0), 0.0); + fT[1][!bIn] = SkTMax(SkTMin((b0 - a1) / (b0 - b1), 1.0), 0.0); bool second = fabs(fT[0][0] - fT[0][1]) > FLT_EPSILON; SkASSERT((fabs(fT[1][0] - fT[1][1]) <= FLT_EPSILON) ^ second); return computePoints(line, 1 + second); diff --git a/src/pathops/SkDQuadIntersection.cpp b/src/pathops/SkDQuadIntersection.cpp index 5abbbdcd82..5df08ac069 100644 --- a/src/pathops/SkDQuadIntersection.cpp +++ b/src/pathops/SkDQuadIntersection.cpp @@ -243,7 +243,7 @@ static void relaxed_is_linear(const SkDQuad& q1, const SkDQuad& q2, SkIntersecti double m1 = flat_measure(q1); double m2 = flat_measure(q2); #if DEBUG_FLAT_QUADS - double min = SkTMin<double>(m1, m2); + double min = SkTMin(m1, m2); if (min > 5) { SkDebugf("%s maybe not flat enough.. %1.9g\n", __FUNCTION__, min); } diff --git a/src/pathops/SkPathOpsBounds.h b/src/pathops/SkPathOpsBounds.h index e4dd030ecb..61ef7bb874 100644 --- a/src/pathops/SkPathOpsBounds.h +++ b/src/pathops/SkPathOpsBounds.h @@ -17,7 +17,9 @@ struct SkPathOpsBounds : public SkRect { a.fTop <= b.fBottom && b.fTop <= a.fBottom; } - // FIXME: add() is generically useful and could be added directly to SkRect + // Note that add(), unlike SkRect::join() or SkRect::growToInclude() + // does not treat the bounds of horizontal and vertical lines as + // empty rectangles. void add(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) { if (left < fLeft) fLeft = left; if (top < fTop) fTop = top; diff --git a/src/pathops/SkPathOpsPoint.h b/src/pathops/SkPathOpsPoint.h index 713b457418..aca38d8900 100644 --- a/src/pathops/SkPathOpsPoint.h +++ b/src/pathops/SkPathOpsPoint.h @@ -96,8 +96,8 @@ struct SkDPoint { // return approximately_equal(a.fY, fY) && approximately_equal(a.fX, fX); // because that will not take the magnitude of the values bool approximatelyEqual(const SkDPoint& a) const { - double denom = SkTMax<double>(fabs(fX), SkTMax<double>(fabs(fY), - SkTMax<double>(fabs(a.fX), fabs(a.fY)))); + double denom = SkTMax(fabs(fX), SkTMax(fabs(fY), + SkTMax(fabs(a.fX), fabs(a.fY)))); if (denom == 0) { return true; } @@ -107,8 +107,8 @@ struct SkDPoint { } bool approximatelyEqual(const SkPoint& a) const { - double denom = SkTMax<double>(fabs(fX), SkTMax<double>(fabs(fY), - SkScalarToDouble(SkTMax<SkScalar>(fabsf(a.fX), fabsf(a.fY))))); + double denom = SkTMax(fabs(fX), SkTMax(fabs(fY), + SkScalarToDouble(SkTMax(fabsf(a.fX), fabsf(a.fY))))); if (denom == 0) { return true; } @@ -118,8 +118,8 @@ struct SkDPoint { } bool approximatelyEqualHalf(const SkDPoint& a) const { - double denom = SkTMax<double>(fabs(fX), SkTMax<double>(fabs(fY), - SkTMax<double>(fabs(a.fX), fabs(a.fY)))); + double denom = SkTMax(fabs(fX), SkTMax(fabs(fY), + SkTMax(fabs(a.fX), fabs(a.fY)))); if (denom == 0) { return true; } diff --git a/src/pathops/SkPathOpsQuad.cpp b/src/pathops/SkPathOpsQuad.cpp index cbba2a3fe5..685f49e160 100644 --- a/src/pathops/SkPathOpsQuad.cpp +++ b/src/pathops/SkPathOpsQuad.cpp @@ -26,7 +26,7 @@ double SkDQuad::nearestT(const SkDPoint& pt) const { int roots = SkDCubic::RootsValidT(a, b, c, d, ts); double d0 = pt.distanceSquared(fPts[0]); double d2 = pt.distanceSquared(fPts[2]); - double distMin = SkTMin<double>(d0, d2); + double distMin = SkTMin(d0, d2); int bestIndex = -1; for (int index = 0; index < roots; ++index) { SkDPoint onQuad = xyAtT(ts[index]); diff --git a/src/pathops/SkPathOpsTypes.h b/src/pathops/SkPathOpsTypes.h index c3c0cd5b91..4d81586765 100644 --- a/src/pathops/SkPathOpsTypes.h +++ b/src/pathops/SkPathOpsTypes.h @@ -15,22 +15,6 @@ #include "SkPathOpsDebug.h" #include "SkScalar.h" -// FIXME: move these into SkTypes.h -template <typename T> inline T SkTMax(T a, T b) { - if (a < b) - a = b; - return a; -} - -template <typename T> inline T SkTMin(T a, T b) { - if (a > b) - a = b; - return a; -} - -// FIXME: move this into SkFloatingPoint.h -#define sk_double_isnan(a) sk_float_isnan(a) - enum SkPathOpsMask { kWinding_PathOpsMask = -1, kNo_PathOpsMask = 0, diff --git a/tests/PathOpsDRectTest.cpp b/tests/PathOpsDRectTest.cpp index a053ac7f5c..6eb1955d28 100644 --- a/tests/PathOpsDRectTest.cpp +++ b/tests/PathOpsDRectTest.cpp @@ -43,30 +43,30 @@ static void PathOpsDRectTest(skiatest::Reporter* reporter) { for (index = 0; index < lineTests_count; ++index) { const SkDLine& line = lineTests[index]; rect.setBounds(line); - REPORTER_ASSERT(reporter, rect.fLeft == SkTMin<double>(line[0].fX, line[1].fX)); - REPORTER_ASSERT(reporter, rect.fTop == SkTMin<double>(line[0].fY, line[1].fY)); - REPORTER_ASSERT(reporter, rect.fRight == SkTMax<double>(line[0].fX, line[1].fX)); - REPORTER_ASSERT(reporter, rect.fBottom == SkTMax<double>(line[0].fY, line[1].fY)); + REPORTER_ASSERT(reporter, rect.fLeft == SkTMin(line[0].fX, line[1].fX)); + REPORTER_ASSERT(reporter, rect.fTop == SkTMin(line[0].fY, line[1].fY)); + REPORTER_ASSERT(reporter, rect.fRight == SkTMax(line[0].fX, line[1].fX)); + REPORTER_ASSERT(reporter, rect.fBottom == SkTMax(line[0].fY, line[1].fY)); rect2.set(line[0]); rect2.add(line[1]); - REPORTER_ASSERT(reporter, rect2.fLeft == SkTMin<double>(line[0].fX, line[1].fX)); - REPORTER_ASSERT(reporter, rect2.fTop == SkTMin<double>(line[0].fY, line[1].fY)); - REPORTER_ASSERT(reporter, rect2.fRight == SkTMax<double>(line[0].fX, line[1].fX)); - REPORTER_ASSERT(reporter, rect2.fBottom == SkTMax<double>(line[0].fY, line[1].fY)); + REPORTER_ASSERT(reporter, rect2.fLeft == SkTMin(line[0].fX, line[1].fX)); + REPORTER_ASSERT(reporter, rect2.fTop == SkTMin(line[0].fY, line[1].fY)); + REPORTER_ASSERT(reporter, rect2.fRight == SkTMax(line[0].fX, line[1].fX)); + REPORTER_ASSERT(reporter, rect2.fBottom == SkTMax(line[0].fY, line[1].fY)); REPORTER_ASSERT(reporter, rect.contains(line[0])); REPORTER_ASSERT(reporter, rect.intersects(&rect2)); } for (index = 0; index < quadTests_count; ++index) { const SkDQuad& quad = quadTests[index]; rect.setRawBounds(quad); - REPORTER_ASSERT(reporter, rect.fLeft == SkTMin<double>(quad[0].fX, - SkTMin<double>(quad[1].fX, quad[2].fX))); - REPORTER_ASSERT(reporter, rect.fTop == SkTMin<double>(quad[0].fY, - SkTMin<double>(quad[1].fY, quad[2].fY))); - REPORTER_ASSERT(reporter, rect.fRight == SkTMax<double>(quad[0].fX, - SkTMax<double>(quad[1].fX, quad[2].fX))); - REPORTER_ASSERT(reporter, rect.fBottom == SkTMax<double>(quad[0].fY, - SkTMax<double>(quad[1].fY, quad[2].fY))); + REPORTER_ASSERT(reporter, rect.fLeft == SkTMin(quad[0].fX, + SkTMin(quad[1].fX, quad[2].fX))); + REPORTER_ASSERT(reporter, rect.fTop == SkTMin(quad[0].fY, + SkTMin(quad[1].fY, quad[2].fY))); + REPORTER_ASSERT(reporter, rect.fRight == SkTMax(quad[0].fX, + SkTMax(quad[1].fX, quad[2].fX))); + REPORTER_ASSERT(reporter, rect.fBottom == SkTMax(quad[0].fY, + SkTMax(quad[1].fY, quad[2].fY))); rect2.setBounds(quad); REPORTER_ASSERT(reporter, rect.intersects(&rect2)); // FIXME: add a recursive box subdivision method to verify that tight bounds is correct @@ -78,14 +78,14 @@ static void PathOpsDRectTest(skiatest::Reporter* reporter) { for (index = 0; index < cubicTests_count; ++index) { const SkDCubic& cubic = cubicTests[index]; rect.setRawBounds(cubic); - REPORTER_ASSERT(reporter, rect.fLeft == SkTMin<double>(cubic[0].fX, - SkTMin<double>(cubic[1].fX, SkTMin<double>(cubic[2].fX, cubic[3].fX)))); - REPORTER_ASSERT(reporter, rect.fTop == SkTMin<double>(cubic[0].fY, - SkTMin<double>(cubic[1].fY, SkTMin<double>(cubic[2].fY, cubic[3].fY)))); - REPORTER_ASSERT(reporter, rect.fRight == SkTMax<double>(cubic[0].fX, - SkTMax<double>(cubic[1].fX, SkTMax<double>(cubic[2].fX, cubic[3].fX)))); - REPORTER_ASSERT(reporter, rect.fBottom == SkTMax<double>(cubic[0].fY, - SkTMax<double>(cubic[1].fY, SkTMax<double>(cubic[2].fY, cubic[3].fY)))); + REPORTER_ASSERT(reporter, rect.fLeft == SkTMin(cubic[0].fX, + SkTMin(cubic[1].fX, SkTMin(cubic[2].fX, cubic[3].fX)))); + REPORTER_ASSERT(reporter, rect.fTop == SkTMin(cubic[0].fY, + SkTMin(cubic[1].fY, SkTMin(cubic[2].fY, cubic[3].fY)))); + REPORTER_ASSERT(reporter, rect.fRight == SkTMax(cubic[0].fX, + SkTMax(cubic[1].fX, SkTMax(cubic[2].fX, cubic[3].fX)))); + REPORTER_ASSERT(reporter, rect.fBottom == SkTMax(cubic[0].fY, + SkTMax(cubic[1].fY, SkTMax(cubic[2].fY, cubic[3].fY)))); rect2.setBounds(cubic); REPORTER_ASSERT(reporter, rect.intersects(&rect2)); // FIXME: add a recursive box subdivision method to verify that tight bounds is correct |