1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                           License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14 // Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved.
15 // Third party copyrights are property of their respective owners.
16 //
17 // @Authors
18 //      Nghia Ho, nghiaho12@yahoo.com
19 //
20 // Redistribution and use in source and binary forms, with or without modification,
21 // are permitted provided that the following conditions are met:
22 //
23 //   * Redistribution's of source code must retain the above copyright notice,
24 //     this list of conditions and the following disclaimer.
25 //
26 //   * Redistribution's in binary form must reproduce the above copyright notice,
27 //     this list of conditions and the following disclaimer in the documentation
28 //     and/or other materials provided with the distribution.
29 //
30 //   * The name of OpenCV Foundation may not be used to endorse or promote products
31 //     derived from this software without specific prior written permission.
32 //
33 // This software is provided by the copyright holders and contributors "as is" and
34 // any express or implied warranties, including, but not limited to, the implied
35 // warranties of merchantability and fitness for a particular purpose are disclaimed.
36 // In no event shall the OpenCV Foundation or contributors be liable for any direct,
37 // indirect, incidental, special, exemplary, or consequential damages
38 // (including, but not limited to, procurement of substitute goods or services;
39 // loss of use, data, or profits; or business interruption) however caused
40 // and on any theory of liability, whether in contract, strict liability,
41 // or tort (including negligence or otherwise) arising in any way out of
42 // the use of this software, even if advised of the possibility of such damage.
43 //
44 //M*/
45 #include "precomp.hpp"
46 
47 namespace cv
48 {
49 
rotatedRectangleIntersection(const RotatedRect & rect1,const RotatedRect & rect2,OutputArray intersectingRegion)50 int rotatedRectangleIntersection( const RotatedRect& rect1, const RotatedRect& rect2, OutputArray intersectingRegion )
51 {
52     const float samePointEps = 0.00001f; // used to test if two points are the same
53 
54     Point2f vec1[4], vec2[4];
55     Point2f pts1[4], pts2[4];
56 
57     std::vector <Point2f> intersection;
58 
59     rect1.points(pts1);
60     rect2.points(pts2);
61 
62     int ret = INTERSECT_FULL;
63 
64     // Specical case of rect1 == rect2
65     {
66         bool same = true;
67 
68         for( int i = 0; i < 4; i++ )
69         {
70             if( fabs(pts1[i].x - pts2[i].x) > samePointEps || (fabs(pts1[i].y - pts2[i].y) > samePointEps) )
71             {
72                 same = false;
73                 break;
74             }
75         }
76 
77         if(same)
78         {
79             intersection.resize(4);
80 
81             for( int i = 0; i < 4; i++ )
82             {
83                 intersection[i] = pts1[i];
84             }
85 
86             Mat(intersection).copyTo(intersectingRegion);
87 
88             return INTERSECT_FULL;
89         }
90     }
91 
92     // Line vector
93     // A line from p1 to p2 is: p1 + (p2-p1)*t, t=[0,1]
94     for( int i = 0; i < 4; i++ )
95     {
96         vec1[i].x = pts1[(i+1)%4].x - pts1[i].x;
97         vec1[i].y = pts1[(i+1)%4].y - pts1[i].y;
98 
99         vec2[i].x = pts2[(i+1)%4].x - pts2[i].x;
100         vec2[i].y = pts2[(i+1)%4].y - pts2[i].y;
101     }
102 
103     // Line test - test all line combos for intersection
104     for( int i = 0; i < 4; i++ )
105     {
106         for( int j = 0; j < 4; j++ )
107         {
108             // Solve for 2x2 Ax=b
109             float x21 = pts2[j].x - pts1[i].x;
110             float y21 = pts2[j].y - pts1[i].y;
111 
112             float vx1 = vec1[i].x;
113             float vy1 = vec1[i].y;
114 
115             float vx2 = vec2[j].x;
116             float vy2 = vec2[j].y;
117 
118             float det = vx2*vy1 - vx1*vy2;
119 
120             float t1 = (vx2*y21 - vy2*x21) / det;
121             float t2 = (vx1*y21 - vy1*x21) / det;
122 
123             // This takes care of parallel lines
124             if( cvIsInf(t1) || cvIsInf(t2) || cvIsNaN(t1) || cvIsNaN(t2) )
125             {
126                 continue;
127             }
128 
129             if( t1 >= 0.0f && t1 <= 1.0f && t2 >= 0.0f && t2 <= 1.0f )
130             {
131                 float xi = pts1[i].x + vec1[i].x*t1;
132                 float yi = pts1[i].y + vec1[i].y*t1;
133 
134                 intersection.push_back(Point2f(xi,yi));
135             }
136         }
137     }
138 
139     if( !intersection.empty() )
140     {
141         ret = INTERSECT_PARTIAL;
142     }
143 
144     // Check for vertices from rect1 inside recct2
145     for( int i = 0; i < 4; i++ )
146     {
147         // We do a sign test to see which side the point lies.
148         // If the point all lie on the same sign for all 4 sides of the rect,
149         // then there's an intersection
150         int posSign = 0;
151         int negSign = 0;
152 
153         float x = pts1[i].x;
154         float y = pts1[i].y;
155 
156         for( int j = 0; j < 4; j++ )
157         {
158             // line equation: Ax + By + C = 0
159             // see which side of the line this point is at
160             float A = -vec2[j].y;
161             float B = vec2[j].x;
162             float C = -(A*pts2[j].x + B*pts2[j].y);
163 
164             float s = A*x+ B*y+ C;
165 
166             if( s >= 0 )
167             {
168                 posSign++;
169             }
170             else
171             {
172                 negSign++;
173             }
174         }
175 
176         if( posSign == 4 || negSign == 4 )
177         {
178             intersection.push_back(pts1[i]);
179         }
180     }
181 
182     // Reverse the check - check for vertices from rect2 inside recct1
183     for( int i = 0; i < 4; i++ )
184     {
185         // We do a sign test to see which side the point lies.
186         // If the point all lie on the same sign for all 4 sides of the rect,
187         // then there's an intersection
188         int posSign = 0;
189         int negSign = 0;
190 
191         float x = pts2[i].x;
192         float y = pts2[i].y;
193 
194         for( int j = 0; j < 4; j++ )
195         {
196             // line equation: Ax + By + C = 0
197             // see which side of the line this point is at
198             float A = -vec1[j].y;
199             float B = vec1[j].x;
200             float C = -(A*pts1[j].x + B*pts1[j].y);
201 
202             float s = A*x + B*y + C;
203 
204             if( s >= 0 )
205             {
206                 posSign++;
207             }
208             else
209             {
210                 negSign++;
211             }
212         }
213 
214         if( posSign == 4 || negSign == 4 )
215         {
216             intersection.push_back(pts2[i]);
217         }
218     }
219 
220     // Get rid of dupes
221     for( int i = 0; i < (int)intersection.size()-1; i++ )
222     {
223         for( size_t j = i+1; j < intersection.size(); j++ )
224         {
225             float dx = intersection[i].x - intersection[j].x;
226             float dy = intersection[i].y - intersection[j].y;
227             double d2 = dx*dx + dy*dy; // can be a really small number, need double here
228 
229             if( d2 < samePointEps*samePointEps )
230             {
231                 // Found a dupe, remove it
232                 std::swap(intersection[j], intersection.back());
233                 intersection.pop_back();
234                 j--; // restart check
235             }
236         }
237     }
238 
239     if( intersection.empty() )
240     {
241         return INTERSECT_NONE ;
242     }
243 
244     // If this check fails then it means we're getting dupes, increase samePointEps
245     CV_Assert( intersection.size() <= 8 );
246 
247     Mat(intersection).copyTo(intersectingRegion);
248 
249     return ret;
250 }
251 
252 } // end namespace
253