blob: f07cf65800788653dc51b513a2a0c2a0bebd2760 [file] [log] [blame] [edit]
/*****************************************************************************/
// 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;
}
/*****************************************************************************/