@ -51,15 +51,15 @@ static int _rotatedRectangleIntersection( const RotatedRect& rect1, const Rotate
{
{
CV_INSTRUMENT_REGION ( ) ;
CV_INSTRUMENT_REGION ( ) ;
// L2 metric
const float samePointEps = std : : max ( 1e-16 f , 1e-6 f * ( float ) std : : max ( rect1 . size . area ( ) , rect2 . size . area ( ) ) ) ;
Point2f vec1 [ 4 ] , vec2 [ 4 ] ;
Point2f vec1 [ 4 ] , vec2 [ 4 ] ;
Point2f pts1 [ 4 ] , pts2 [ 4 ] ;
Point2f pts1 [ 4 ] , pts2 [ 4 ] ;
rect1 . points ( pts1 ) ;
rect1 . points ( pts1 ) ;
rect2 . points ( pts2 ) ;
rect2 . points ( pts2 ) ;
// L2 metric
float samePointEps = 1e-6 f * ( float ) std : : max ( rect1 . size . area ( ) , rect2 . size . area ( ) ) ;
int ret = INTERSECT_FULL ;
int ret = INTERSECT_FULL ;
// Specical case of rect1 == rect2
// Specical case of rect1 == rect2
@ -99,14 +99,22 @@ static int _rotatedRectangleIntersection( const RotatedRect& rect1, const Rotate
vec2 [ i ] . y = pts2 [ ( i + 1 ) % 4 ] . y - pts2 [ i ] . y ;
vec2 [ i ] . y = pts2 [ ( i + 1 ) % 4 ] . y - pts2 [ i ] . y ;
}
}
//we adapt the epsilon to the smallest dimension of the rects
for ( int i = 0 ; i < 4 ; i + + )
{
samePointEps = std : : min ( samePointEps , std : : sqrt ( vec1 [ i ] . x * vec1 [ i ] . x + vec1 [ i ] . y * vec1 [ i ] . y ) ) ;
samePointEps = std : : min ( samePointEps , std : : sqrt ( vec2 [ i ] . x * vec2 [ i ] . x + vec2 [ i ] . y * vec2 [ i ] . y ) ) ;
}
samePointEps = std : : max ( 1e-16 f , samePointEps ) ;
// Line test - test all line combos for intersection
// Line test - test all line combos for intersection
for ( int i = 0 ; i < 4 ; i + + )
for ( int i = 0 ; i < 4 ; i + + )
{
{
for ( int j = 0 ; j < 4 ; j + + )
for ( int j = 0 ; j < 4 ; j + + )
{
{
// Solve for 2x2 Ax=b
// Solve for 2x2 Ax=b
float x21 = pts2 [ j ] . x - pts1 [ i ] . x ;
const float x21 = pts2 [ j ] . x - pts1 [ i ] . x ;
float y21 = pts2 [ j ] . y - pts1 [ i ] . y ;
const float y21 = pts2 [ j ] . y - pts1 [ i ] . y ;
float vx1 = vec1 [ i ] . x ;
float vx1 = vec1 [ i ] . x ;
float vy1 = vec1 [ i ] . y ;
float vy1 = vec1 [ i ] . y ;
@ -114,10 +122,22 @@ static int _rotatedRectangleIntersection( const RotatedRect& rect1, const Rotate
float vx2 = vec2 [ j ] . x ;
float vx2 = vec2 [ j ] . x ;
float vy2 = vec2 [ j ] . y ;
float vy2 = vec2 [ j ] . y ;
float det = vx2 * vy1 - vx1 * vy2 ;
float normalizationScale = std : : min ( vx1 * vx1 + vy1 * vy1 , vx2 * vx2 + vy2 * vy2 ) ; //sum of squares : this is >= 0
//normalizationScale is a square, and we usually limit accuracy around 1e-6, so normalizationScale should be rather limited by ((1e-6)^2)=1e-12
normalizationScale = ( normalizationScale < 1e-12 f ) ? 1.f : 1.f / normalizationScale ;
vx1 * = normalizationScale ;
vy1 * = normalizationScale ;
vx2 * = normalizationScale ;
vy2 * = normalizationScale ;
const float det = vx2 * vy1 - vx1 * vy2 ;
if ( std : : abs ( det ) < 1e-12 ) //like normalizationScale, we consider accuracy around 1e-6, i.e. 1e-12 when squared
continue ;
const float detInvScaled = normalizationScale / det ;
float t1 = ( vx2 * y21 - vy2 * x21 ) / det ;
const float t1 = ( vx2 * y21 - vy2 * x21 ) * detInvScaled ;
float t2 = ( vx1 * y21 - vy1 * x21 ) / det ;
const float t2 = ( vx1 * y21 - vy1 * x21 ) * detInvScaled ;
// This takes care of parallel lines
// This takes care of parallel lines
if ( cvIsInf ( t1 ) | | cvIsInf ( t2 ) | | cvIsNaN ( t1 ) | | cvIsNaN ( t2 ) )
if ( cvIsInf ( t1 ) | | cvIsInf ( t2 ) | | cvIsNaN ( t1 ) | | cvIsNaN ( t2 ) )
@ -127,8 +147,8 @@ static int _rotatedRectangleIntersection( const RotatedRect& rect1, const Rotate
if ( t1 > = 0.0f & & t1 < = 1.0f & & t2 > = 0.0f & & t2 < = 1.0f )
if ( t1 > = 0.0f & & t1 < = 1.0f & & t2 > = 0.0f & & t2 < = 1.0f )
{
{
float xi = pts1 [ i ] . x + vec1 [ i ] . x * t1 ;
const float xi = pts1 [ i ] . x + vec1 [ i ] . x * t1 ;
float yi = pts1 [ i ] . y + vec1 [ i ] . y * t1 ;
const float yi = pts1 [ i ] . y + vec1 [ i ] . y * t1 ;
intersection . push_back ( Point2f ( xi , yi ) ) ;
intersection . push_back ( Point2f ( xi , yi ) ) ;
}
}
@ -149,18 +169,20 @@ static int _rotatedRectangleIntersection( const RotatedRect& rect1, const Rotate
int posSign = 0 ;
int posSign = 0 ;
int negSign = 0 ;
int negSign = 0 ;
float x = pts1 [ i ] . x ;
const float x = pts1 [ i ] . x ;
float y = pts1 [ i ] . y ;
const float y = pts1 [ i ] . y ;
for ( int j = 0 ; j < 4 ; j + + )
for ( int j = 0 ; j < 4 ; j + + )
{
{
float normalizationScale = vec2 [ j ] . x * vec2 [ j ] . x + vec2 [ j ] . y * vec2 [ j ] . y ;
normalizationScale = ( normalizationScale < 1e-12 f ) ? 1.f : 1.f / normalizationScale ;
// line equation: Ax + By + C = 0
// line equation: Ax + By + C = 0
// see which side of the line this point is at
// see which side of the line this point is at
float A = - vec2 [ j ] . y ;
const float A = - vec2 [ j ] . y * normalizationScale ;
float B = vec2 [ j ] . x ;
const float B = vec2 [ j ] . x * normalizationScale ;
float C = - ( A * pts2 [ j ] . x + B * pts2 [ j ] . y ) ;
const float C = - ( A * pts2 [ j ] . x + B * pts2 [ j ] . y ) ;
float s = A * x + B * y + C ;
const float s = A * x + B * y + C ;
if ( s > = 0 )
if ( s > = 0 )
{
{
@ -187,18 +209,22 @@ static int _rotatedRectangleIntersection( const RotatedRect& rect1, const Rotate
int posSign = 0 ;
int posSign = 0 ;
int negSign = 0 ;
int negSign = 0 ;
float x = pts2 [ i ] . x ;
const float x = pts2 [ i ] . x ;
float y = pts2 [ i ] . y ;
const float y = pts2 [ i ] . y ;
for ( int j = 0 ; j < 4 ; j + + )
for ( int j = 0 ; j < 4 ; j + + )
{
{
// line equation: Ax + By + C = 0
// line equation: Ax + By + C = 0
// see which side of the line this point is at
// see which side of the line this point is at
float A = - vec1 [ j ] . y ;
float normalizationScale = vec2 [ j ] . x * vec2 [ j ] . x + vec2 [ j ] . y * vec2 [ j ] . y ;
float B = vec1 [ j ] . x ;
normalizationScale = ( normalizationScale < 1e-12 f ) ? 1.f : 1.f / normalizationScale ;
float C = - ( A * pts1 [ j ] . x + B * pts1 [ j ] . y ) ;
if ( std : : isinf ( normalizationScale ) )
normalizationScale = 1.f ;
const float A = - vec1 [ j ] . y * normalizationScale ;
const float B = vec1 [ j ] . x * normalizationScale ;
const float C = - ( A * pts1 [ j ] . x + B * pts1 [ j ] . y ) ;
float s = A * x + B * y + C ;
const float s = A * x + B * y + C ;
if ( s > = 0 )
if ( s > = 0 )
{
{
@ -223,7 +249,7 @@ static int _rotatedRectangleIntersection( const RotatedRect& rect1, const Rotate
}
}
// Get rid of duplicated points
// Get rid of duplicated points
int Nstride = N ;
const int Nstride = N ;
cv : : AutoBuffer < float , 100 > distPt ( N * N ) ;
cv : : AutoBuffer < float , 100 > distPt ( N * N ) ;
cv : : AutoBuffer < int > ptDistRemap ( N ) ;
cv : : AutoBuffer < int > ptDistRemap ( N ) ;
for ( int i = 0 ; i < N ; + + i )
for ( int i = 0 ; i < N ; + + i )
@ -233,7 +259,7 @@ static int _rotatedRectangleIntersection( const RotatedRect& rect1, const Rotate
for ( int j = i + 1 ; j < N ; )
for ( int j = i + 1 ; j < N ; )
{
{
const Point2f pt1 = intersection [ j ] ;
const Point2f pt1 = intersection [ j ] ;
float d2 = normL2Sqr < float > ( pt1 - pt0 ) ;
const float d2 = normL2Sqr < float > ( pt1 - pt0 ) ;
if ( d2 < = samePointEps )
if ( d2 < = samePointEps )
{
{
if ( j < N - 1 )
if ( j < N - 1 )
@ -252,10 +278,10 @@ static int _rotatedRectangleIntersection( const RotatedRect& rect1, const Rotate
float minD = distPt [ 1 ] ;
float minD = distPt [ 1 ] ;
for ( int i = 0 ; i < N - 1 ; + + i )
for ( int i = 0 ; i < N - 1 ; + + i )
{
{
float * pDist = distPt . data ( ) + Nstride * ptDistRemap [ i ] ;
const float * pDist = distPt . data ( ) + Nstride * ptDistRemap [ i ] ;
for ( int j = i + 1 ; j < N ; + + j )
for ( int j = i + 1 ; j < N ; + + j )
{
{
float d = pDist [ ptDistRemap [ j ] ] ;
const float d = pDist [ ptDistRemap [ j ] ] ;
if ( d < minD )
if ( d < minD )
{
{
minD = d ;
minD = d ;