| /*****************************************************************************/ |
| // Copyright 2006-2019 Adobe Systems Incorporated |
| // All Rights Reserved. |
| // |
| // NOTICE: Adobe permits you to use, modify, and distribute this file in |
| // accordance with the terms of the Adobe license agreement accompanying it. |
| /*****************************************************************************/ |
| |
| #include "dng_rect.h" |
| |
| #include "dng_utils.h" |
| |
| /*****************************************************************************/ |
| |
| bool dng_rect::operator== (const dng_rect &rect) const |
| { |
| |
| return (rect.t == t) && |
| (rect.l == l) && |
| (rect.b == b) && |
| (rect.r == r); |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| bool dng_rect::IsZero () const |
| { |
| |
| return (t == 0) && (l == 0) && (b == 0) && (r == 0); |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| bool dng_rect_real64::operator== (const dng_rect_real64 &rect) const |
| { |
| |
| return (rect.t == t) && |
| (rect.l == l) && |
| (rect.b == b) && |
| (rect.r == r); |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| bool dng_rect_real64::IsZero () const |
| { |
| |
| return (t == 0.0) && (l == 0.0) && (b == 0.0) && (r == 0.0); |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| dng_rect operator& (const dng_rect &a, |
| const dng_rect &b) |
| { |
| |
| dng_rect c; |
| |
| c.t = Max_int32 (a.t, b.t); |
| c.l = Max_int32 (a.l, b.l); |
| |
| c.b = Min_int32 (a.b, b.b); |
| c.r = Min_int32 (a.r, b.r); |
| |
| if (c.IsEmpty ()) |
| { |
| |
| c = dng_rect (); |
| |
| } |
| |
| return c; |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| dng_rect operator| (const dng_rect &a, |
| const dng_rect &b) |
| { |
| |
| if (a.IsEmpty ()) |
| { |
| return b; |
| } |
| |
| if (b.IsEmpty ()) |
| { |
| return a; |
| } |
| |
| dng_rect c; |
| |
| c.t = Min_int32 (a.t, b.t); |
| c.l = Min_int32 (a.l, b.l); |
| |
| c.b = Max_int32 (a.b, b.b); |
| c.r = Max_int32 (a.r, b.r); |
| |
| return c; |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| dng_rect_real64 operator& (const dng_rect_real64 &a, |
| const dng_rect_real64 &b) |
| { |
| |
| dng_rect_real64 c; |
| |
| c.t = Max_real64 (a.t, b.t); |
| c.l = Max_real64 (a.l, b.l); |
| |
| c.b = Min_real64 (a.b, b.b); |
| c.r = Min_real64 (a.r, b.r); |
| |
| if (c.IsEmpty ()) |
| { |
| |
| c = dng_rect_real64 (); |
| |
| } |
| |
| return c; |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| dng_rect_real64 operator| (const dng_rect_real64 &a, |
| const dng_rect_real64 &b) |
| { |
| |
| if (a.IsEmpty ()) |
| { |
| return b; |
| } |
| |
| if (b.IsEmpty ()) |
| { |
| return a; |
| } |
| |
| dng_rect_real64 c; |
| |
| c.t = Min_real64 (a.t, b.t); |
| c.l = Min_real64 (a.l, b.l); |
| |
| c.b = Max_real64 (a.b, b.b); |
| c.r = Max_real64 (a.r, b.r); |
| |
| return c; |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| dng_rect_real64 Bounds (const dng_point_real64 &a, |
| const dng_point_real64 &b, |
| const dng_point_real64 &c, |
| const dng_point_real64 &d) |
| { |
| |
| real64 xMin = Min_real64 (a.h, Min_real64 (b.h, Min_real64 (c.h, d.h))); |
| real64 xMax = Max_real64 (a.h, Max_real64 (b.h, Max_real64 (c.h, d.h))); |
| |
| real64 yMin = Min_real64 (a.v, Min_real64 (b.v, Min_real64 (c.v, d.v))); |
| real64 yMax = Max_real64 (a.v, Max_real64 (b.v, Max_real64 (c.v, d.v))); |
| |
| return dng_rect_real64 (yMin, |
| xMin, |
| yMax, |
| xMax); |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| bool Intersect (const dng_oriented_bounding_box &aBox, |
| const dng_oriented_bounding_box &bBox) |
| { |
| |
| // Use separating axis theorem. Only need to check 4 axes in 2D. |
| |
| const dng_point_real64 &a = aBox.fCenter; |
| const dng_point_real64 &b = bBox.fCenter; |
| |
| const dng_point_real64 &a1 = aBox.fVec1; |
| const dng_point_real64 &a2 = aBox.fVec2; |
| |
| const dng_point_real64 &b1 = bBox.fVec1; |
| const dng_point_real64 &b2 = bBox.fVec2; |
| |
| // Case 1: Project to a1. |
| |
| { |
| |
| // Instead of normalizing a1_radius_b and a1_dist by dividing by |
| // a1.Length (), just multiply a1_radius_a by a1.Length (), which is |
| // equivalent to squaring itself. This is perfectly valid for the |
| // intended comparison below. |
| |
| // Reference: Normalization step. |
| |
| // real64 a1_radius_a = a1.Length (); |
| |
| // a1_radius_b /= a1_radius_a; |
| // a1_dist /= a1_radius_a; |
| |
| // Optimized: Just square a1_radius_a, which is equivalent computing |
| // a1_radius_a as Dot (a1, a1) instead of a1.Length (). |
| |
| real64 a1_radius_a = Dot (a1, a1); |
| |
| real64 a1_radius_b = (Abs_real64 (Dot (b1, a1)) + |
| Abs_real64 (Dot (b2, a1))); |
| |
| real64 a1_dist = Abs_real64 (Dot (b - a, a1)); |
| |
| if (a1_dist > a1_radius_a + a1_radius_b) |
| { |
| return false; |
| } |
| |
| } |
| |
| // Case 2: Project to a2. |
| |
| { |
| |
| // See comment in Case 1, above. |
| |
| real64 a2_radius_a = Dot (a2, a2); |
| |
| real64 a2_radius_b = (Abs_real64 (Dot (b1, a2)) + |
| Abs_real64 (Dot (b2, a2))); |
| |
| real64 a2_dist = Abs_real64 (Dot (b - a, a2)); |
| |
| if (a2_dist > a2_radius_a + a2_radius_b) |
| { |
| return false; |
| } |
| |
| } |
| |
| // Case 3: Project to b1. |
| |
| { |
| |
| // See comment in Case 1, above. |
| |
| real64 b1_radius_b = Dot (b1, b1); |
| |
| real64 b1_radius_a = (Abs_real64 (Dot (a1, b1)) + |
| Abs_real64 (Dot (a2, b1))); |
| |
| real64 b1_dist = Abs_real64 (Dot (b - a, b1)); |
| |
| if (b1_dist > b1_radius_a + b1_radius_b) |
| { |
| return false; |
| } |
| |
| } |
| |
| // Case 4: Project to b2. |
| |
| { |
| |
| // See comment in Case 1, above. |
| |
| real64 b2_radius_b = Dot (b2, b2); |
| |
| real64 b2_radius_a = (Abs_real64 (Dot (a1, b2)) + |
| Abs_real64 (Dot (a2, b2))); |
| |
| real64 b2_dist = Abs_real64 (Dot (b - a, b2)); |
| |
| if (b2_dist > b2_radius_a + b2_radius_b) |
| { |
| return false; |
| } |
| |
| } |
| |
| // Projections to all four axes overlap: the two OBBs intersect. |
| |
| return true; |
| |
| } |
| |
| /*****************************************************************************/ |