Path: blob/master/modules/imgproc/src/intersection.cpp
16354 views
/*M///////////////////////////////////////////////////////////////////////////////////////1//2// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.3//4// By downloading, copying, installing or using the software you agree to this license.5// If you do not agree to this license, do not download, install,6// copy or use the software.7//8//9// License Agreement10// For Open Source Computer Vision Library11//12// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.13// Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved.14// Third party copyrights are property of their respective owners.15//16// @Authors17// Nghia Ho, [email protected]18//19// Redistribution and use in source and binary forms, with or without modification,20// are permitted provided that the following conditions are met:21//22// * Redistribution's of source code must retain the above copyright notice,23// this list of conditions and the following disclaimer.24//25// * Redistribution's in binary form must reproduce the above copyright notice,26// this list of conditions and the following disclaimer in the documentation27// and/or other materials provided with the distribution.28//29// * The name of OpenCV Foundation may not be used to endorse or promote products30// derived from this software without specific prior written permission.31//32// This software is provided by the copyright holders and contributors "as is" and33// any express or implied warranties, including, but not limited to, the implied34// warranties of merchantability and fitness for a particular purpose are disclaimed.35// In no event shall the OpenCV Foundation or contributors be liable for any direct,36// indirect, incidental, special, exemplary, or consequential damages37// (including, but not limited to, procurement of substitute goods or services;38// loss of use, data, or profits; or business interruption) however caused39// and on any theory of liability, whether in contract, strict liability,40// or tort (including negligence or otherwise) arising in any way out of41// the use of this software, even if advised of the possibility of such damage.42//43//M*/44#include "precomp.hpp"4546namespace cv47{4849int rotatedRectangleIntersection( const RotatedRect& rect1, const RotatedRect& rect2, OutputArray intersectingRegion )50{51CV_INSTRUMENT_REGION();5253// L2 metric54const float samePointEps = std::max(1e-16f, 1e-6f * (float)std::max(rect1.size.area(), rect2.size.area()));5556Point2f vec1[4], vec2[4];57Point2f pts1[4], pts2[4];5859std::vector <Point2f> intersection; intersection.reserve(24);6061rect1.points(pts1);62rect2.points(pts2);6364int ret = INTERSECT_FULL;6566// Specical case of rect1 == rect267{68bool same = true;6970for( int i = 0; i < 4; i++ )71{72if( fabs(pts1[i].x - pts2[i].x) > samePointEps || (fabs(pts1[i].y - pts2[i].y) > samePointEps) )73{74same = false;75break;76}77}7879if(same)80{81intersection.resize(4);8283for( int i = 0; i < 4; i++ )84{85intersection[i] = pts1[i];86}8788Mat(intersection).copyTo(intersectingRegion);8990return INTERSECT_FULL;91}92}9394// Line vector95// A line from p1 to p2 is: p1 + (p2-p1)*t, t=[0,1]96for( int i = 0; i < 4; i++ )97{98vec1[i].x = pts1[(i+1)%4].x - pts1[i].x;99vec1[i].y = pts1[(i+1)%4].y - pts1[i].y;100101vec2[i].x = pts2[(i+1)%4].x - pts2[i].x;102vec2[i].y = pts2[(i+1)%4].y - pts2[i].y;103}104105// Line test - test all line combos for intersection106for( int i = 0; i < 4; i++ )107{108for( int j = 0; j < 4; j++ )109{110// Solve for 2x2 Ax=b111float x21 = pts2[j].x - pts1[i].x;112float y21 = pts2[j].y - pts1[i].y;113114float vx1 = vec1[i].x;115float vy1 = vec1[i].y;116117float vx2 = vec2[j].x;118float vy2 = vec2[j].y;119120float det = vx2*vy1 - vx1*vy2;121122float t1 = (vx2*y21 - vy2*x21) / det;123float t2 = (vx1*y21 - vy1*x21) / det;124125// This takes care of parallel lines126if( cvIsInf(t1) || cvIsInf(t2) || cvIsNaN(t1) || cvIsNaN(t2) )127{128continue;129}130131if( t1 >= 0.0f && t1 <= 1.0f && t2 >= 0.0f && t2 <= 1.0f )132{133float xi = pts1[i].x + vec1[i].x*t1;134float yi = pts1[i].y + vec1[i].y*t1;135136intersection.push_back(Point2f(xi,yi));137}138}139}140141if( !intersection.empty() )142{143ret = INTERSECT_PARTIAL;144}145146// Check for vertices from rect1 inside recct2147for( int i = 0; i < 4; i++ )148{149// We do a sign test to see which side the point lies.150// If the point all lie on the same sign for all 4 sides of the rect,151// then there's an intersection152int posSign = 0;153int negSign = 0;154155float x = pts1[i].x;156float y = pts1[i].y;157158for( int j = 0; j < 4; j++ )159{160// line equation: Ax + By + C = 0161// see which side of the line this point is at162float A = -vec2[j].y;163float B = vec2[j].x;164float C = -(A*pts2[j].x + B*pts2[j].y);165166float s = A*x+ B*y+ C;167168if( s >= 0 )169{170posSign++;171}172else173{174negSign++;175}176}177178if( posSign == 4 || negSign == 4 )179{180intersection.push_back(pts1[i]);181}182}183184// Reverse the check - check for vertices from rect2 inside recct1185for( int i = 0; i < 4; i++ )186{187// We do a sign test to see which side the point lies.188// If the point all lie on the same sign for all 4 sides of the rect,189// then there's an intersection190int posSign = 0;191int negSign = 0;192193float x = pts2[i].x;194float y = pts2[i].y;195196for( int j = 0; j < 4; j++ )197{198// line equation: Ax + By + C = 0199// see which side of the line this point is at200float A = -vec1[j].y;201float B = vec1[j].x;202float C = -(A*pts1[j].x + B*pts1[j].y);203204float s = A*x + B*y + C;205206if( s >= 0 )207{208posSign++;209}210else211{212negSign++;213}214}215216if( posSign == 4 || negSign == 4 )217{218intersection.push_back(pts2[i]);219}220}221222int N = (int)intersection.size();223if (N == 0)224{225return INTERSECT_NONE;226}227228// Get rid of duplicated points229int Nstride = N;230cv::AutoBuffer<float, 100> distPt(N * N);231cv::AutoBuffer<int> ptDistRemap(N);232for (int i = 0; i < N; ++i)233{234const Point2f pt0 = intersection[i];235ptDistRemap[i] = i;236for (int j = i + 1; j < N; )237{238const Point2f pt1 = intersection[j];239float d2 = normL2Sqr<float>(pt1 - pt0);240if(d2 <= samePointEps)241{242if (j < N - 1)243intersection[j] = intersection[N - 1];244N--;245continue;246}247distPt[i*Nstride + j] = d2;248++j;249}250}251while (N > 8) // we still have duplicate points after samePointEps threshold (eliminate closest points)252{253int minI = 0;254int minJ = 1;255float minD = distPt[1];256for (int i = 0; i < N - 1; ++i)257{258float* pDist = distPt.data() + Nstride * ptDistRemap[i];259for (int j = i + 1; j < N; ++j)260{261float d = pDist[ptDistRemap[j]];262if (d < minD)263{264minD = d;265minI = i;266minJ = j;267}268}269}270CV_Assert(fabs(normL2Sqr<float>(intersection[minI] - intersection[minJ]) - minD) < 1e-6); // ptDistRemap is not corrupted271// drop minJ point272if (minJ < N - 1)273{274intersection[minJ] = intersection[N - 1];275ptDistRemap[minJ] = ptDistRemap[N - 1];276}277N--;278}279280// order points281for (int i = 0; i < N - 1; ++i)282{283Point2f diffI = intersection[i + 1] - intersection[i];284for (int j = i + 2; j < N; ++j)285{286Point2f diffJ = intersection[j] - intersection[i];287if (diffI.cross(diffJ) < 0)288{289std::swap(intersection[i + 1], intersection[j]);290diffI = diffJ;291}292}293}294295intersection.resize(N);296Mat(intersection).copyTo(intersectingRegion);297298return ret;299}300301} // end namespace302303304