Update the changelog
[opencv] / cvaux / src / decomppoly.cpp
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 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of Intel Corporation may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41
42 #include "_cvaux.h"
43
44 #if 0
45
46 #include <malloc.h>
47 //#include "decomppoly.h"
48
49 #define ZERO_CLOSE 0.00001f
50 #define ONE_CLOSE  0.99999f
51
52 #define CHECK_COLLINEARITY(vec1_x,vec1_y,vec2_x,vec2_y) \
53     if( vec1_x == 0 ) {                                 \
54         if( vec1_y * vec2_y > 0 ) {                     \
55             return 0;                                   \
56         }                                               \
57     }                                                   \
58     else {                                              \
59         if( vec1_x * vec2_x > 0 ) {                     \
60             return 0;                                   \
61         }                                               \
62     }
63
64 // determines if edge number one lies in counterclockwise
65 //  earlier than edge number two
66 inline int  icvIsFirstEdgeClosier( int x0,
67                                    int y0,
68                                    int x0_end,
69                                    int y0_end,
70                                    int x1_end,
71                                    int y1_end,
72                                    int x2_end,
73                                    int y2_end )
74 {
75     int mult, mult1, mult2;
76     int vec0_x, vec0_y;
77     int vec1_x, vec1_y;
78     int vec2_x, vec2_y;
79
80     vec0_x = x0_end - x0;
81     vec0_y = y0_end - y0;
82     vec1_x = x1_end - x0;
83     vec1_y = y1_end - y0;
84     vec2_x = x2_end - x0;
85     vec2_y = y2_end - y0;
86
87     mult1 = vec1_x * vec0_y - vec0_x * vec1_y;
88     mult2 = vec2_x * vec0_y - vec0_x * vec2_y;
89
90     if( mult1 == 0 ) {
91         CHECK_COLLINEARITY( vec0_x, vec0_y, vec1_x, vec1_y );
92     }
93     if( mult2 == 0 ) {
94         CHECK_COLLINEARITY( vec0_x, vec0_y, vec2_x, vec2_y );
95     }
96     if( mult1 > 0 && mult2 < 0 ) {
97         return 1;
98     }
99     if( mult1 < 0 && mult2 > 0 ) {
100         return -1;
101     }
102
103     mult = vec1_x * vec2_y - vec2_x * vec1_y;
104     if( mult == 0 ) {
105         CHECK_COLLINEARITY( vec1_x, vec1_y, vec2_x, vec2_y );
106     }
107
108     if( mult1 > 0 )
109     {
110         if( mult > 0 ) {
111             return -1;
112         }
113         else {
114             return 1;
115         }
116     } // if( mult1 > 0 )
117     else
118     {
119         if( mult1 != 0 ) {
120             if( mult > 0 ) {
121                 return 1;
122             }
123             else {
124                 return -1;
125             }
126         } // if( mult1 != 0 )
127         else {
128             if( mult2 > 0 ) {
129                 return -1;
130             }
131             else {
132                 return 1;
133             }
134         } // if( mult1 != 0 ) else
135
136     } // if( mult1 > 0 ) else
137
138 } // icvIsFirstEdgeClosier
139
140 bool icvEarCutTriangulation( CvPoint* contour,
141                                int num,
142                                int* outEdges,
143                                int* numEdges )
144 {
145     int i;
146     int notFoundFlag = 0;
147     int begIndex = -1;
148     int isInternal;
149     int currentNum = num;
150     int index1, index2, index3;
151     int ix0, iy0, ix1, iy1, ix2, iy2;
152     int x1, y1, x2, y2, x3, y3;
153     int dx1, dy1, dx2, dy2;
154     int* pointExist = ( int* )0;
155     int det, det1, det2;
156     float t1, t2;
157
158     (*numEdges) = 0;
159
160     if( num <= 2 ) {
161         return false;
162     }
163
164     pointExist = ( int* )malloc( num * sizeof( int ) );
165
166     for( i = 0; i < num; i ++ ) {
167         pointExist[i] = 1;
168     }
169
170     for( i = 0; i < num; i ++ ) {
171         outEdges[ (*numEdges) * 2 ] = i;
172         if( i != num - 1 ) {
173             outEdges[ (*numEdges) * 2 + 1 ] = i + 1;
174         }
175         else {
176             outEdges[ (*numEdges) * 2 + 1 ] = 0;
177         }
178         (*numEdges) ++;
179     } // for( i = 0; i < num; i ++ )
180
181     // initializing data before while cycle
182     index1 = 0;
183     index2 = 1;
184     index3 = 2;
185     x1 = contour[ index1 ].x;
186     y1 = contour[ index1 ].y;
187     x2 = contour[ index2 ].x;
188     y2 = contour[ index2 ].y;
189     x3 = contour[ index3 ].x;
190     y3 = contour[ index3 ].y;
191
192     while( currentNum > 3 )
193     {
194         dx1 = x2 - x1;
195         dy1 = y2 - y1;
196         dx2 = x3 - x2;
197         dy2 = y3 - y2;
198         if( dx1 * dy2 - dx2 * dy1 < 0 ) // convex condition
199         {
200             // checking for noncrossing edge
201             ix1 = x3 - x1;
202             iy1 = y3 - y1;
203             isInternal = 1;
204             for( i = 0; i < num; i ++ )
205             {
206                 if( i != num - 1 ) {
207                     ix2 = contour[ i + 1 ].x - contour[ i ].x;
208                     iy2 = contour[ i + 1 ].y - contour[ i ].y;
209                 }
210                 else {
211                     ix2 = contour[ 0 ].x - contour[ i ].x;
212                     iy2 = contour[ 0 ].y - contour[ i ].y;
213                 }
214                 ix0 = contour[ i ].x - x1;
215                 iy0 = contour[ i ].y - y1;
216
217                 det  = ix2 * iy1 - ix1 * iy2;
218                 det1 = ix2 * iy0 - ix0 * iy2;
219                 if( det != 0.0f )
220                 {
221                     t1 = ( ( float )( det1 ) ) / det;
222                     if( t1 > ZERO_CLOSE && t1 < ONE_CLOSE )
223                     {
224                         det2 = ix1 * iy0 - ix0 * iy1;
225                         t2 = ( ( float )( det2 ) ) / det;
226                         if( t2 > ZERO_CLOSE && t2 < ONE_CLOSE ) {
227                             isInternal = 0;
228                         }
229     
230                     } // if( t1 > ZERO_CLOSE && t1 < ONE_CLOSE )
231
232                 } // if( det != 0.0f )
233
234             } // for( i = 0; i < (*numEdges); i ++ )
235
236             if( isInternal )
237             {
238                 // this edge is internal
239                 notFoundFlag = 0;
240                 outEdges[ (*numEdges) * 2     ] = index1;
241                 outEdges[ (*numEdges) * 2 + 1 ] = index3;
242                 (*numEdges) ++;
243                 pointExist[ index2 ] = 0;
244                 index2 = index3;
245                 x2 = x3;
246                 y2 = y3;
247                 currentNum --;
248                 if( currentNum >= 3 ) {
249                     do {
250                         index3 ++;
251                         if( index3 == num ) {
252                             index3 = 0;
253                         }
254                     } while( !pointExist[ index3 ] );
255                     x3 = contour[ index3 ].x;
256                     y3 = contour[ index3 ].y;
257                 } // if( currentNum >= 3 )
258
259             } // if( isInternal )
260             else {
261                 // this edge intersects some other initial edges
262                 if( !notFoundFlag ) {
263                     notFoundFlag = 1;
264                     begIndex = index1;
265                 }
266                 index1 = index2;
267                 x1 = x2;
268                 y1 = y2;
269                 index2 = index3;
270                 x2 = x3;
271                 y2 = y3;
272                 do {
273                     index3 ++;
274                     if( index3 == num ) {
275                         index3 = 0;
276                     }
277                     if( index3 == begIndex ) {
278                         if( pointExist ) {
279                             free( pointExist );
280                         }
281                         return false;
282                     }
283                 } while( !pointExist[ index3 ] );
284                 x3 = contour[ index3 ].x;
285                 y3 = contour[ index3 ].y;
286             } // if( isInternal ) else
287
288         } // if( dx1 * dy2 - dx2 * dy1 < 0 )
289         else
290         {
291             if( !notFoundFlag ) {
292                 notFoundFlag = 1;
293                 begIndex = index1;
294             }
295             index1 = index2;
296             x1 = x2;
297             y1 = y2;
298             index2 = index3;
299             x2 = x3;
300             y2 = y3;
301             do {
302                 index3 ++;
303                 if( index3 == num ) {
304                     index3 = 0;
305                 }
306                 if( index3 == begIndex ) {
307                     if( pointExist ) {
308                         free( pointExist );
309                     }
310                     return false;
311                 }
312             } while( !pointExist[ index3 ] );
313             x3 = contour[ index3 ].x;
314             y3 = contour[ index3 ].y;
315         } // if( dx1 * dy2 - dx2 * dy1 < 0 ) else
316
317     } // while( currentNum > 3 )
318
319     if( pointExist ) {
320         free( pointExist );
321     }
322
323     return true;
324
325 } // icvEarCutTriangulation
326
327 inline bool icvFindTwoNeighbourEdges( CvPoint* contour,
328                                       int* edges,
329                                       int numEdges,
330                                       int vtxIdx,
331                                       int mainEdgeIdx,
332                                       int* leftEdgeIdx,
333                                       int* rightEdgeIdx )
334 {
335     int i;
336     int compRes;
337     int vec0_x, vec0_y;
338     int x0, y0, x0_end, y0_end;
339     int x1_left = 0, y1_left = 0, x1_right = 0, y1_right = 0, x2, y2;
340
341     (*leftEdgeIdx)  = -1;
342     (*rightEdgeIdx) = -1;
343
344     if( edges[ mainEdgeIdx * 2 ] == vtxIdx ) {
345         x0 = contour[ vtxIdx ].x;
346         y0 = contour[ vtxIdx ].y;
347         x0_end = contour[ edges[ mainEdgeIdx * 2 + 1 ] ].x;
348         y0_end = contour[ edges[ mainEdgeIdx * 2 + 1 ] ].y;
349         vec0_x = x0_end - x0;
350         vec0_y = y0_end - y0;
351     }
352     else {
353         //x0 = contour[ edges[ mainEdgeIdx * 2 ] ].x;
354         //y0 = contour[ edges[ mainEdgeIdx * 2 ] ].y;
355         //x0_end = contour[ vtxIdx ].x;
356         //y0_end = contour[ vtxIdx ].y;
357         x0 = contour[ vtxIdx ].x;
358         y0 = contour[ vtxIdx ].y;
359         x0_end = contour[ edges[ mainEdgeIdx * 2 ] ].x;
360         y0_end = contour[ edges[ mainEdgeIdx * 2 ] ].y;
361         vec0_x = x0_end - x0;
362         vec0_y = y0_end - y0;
363     }
364
365     for( i = 0; i < numEdges; i ++ )
366     {
367         if( ( i != mainEdgeIdx ) &&
368             ( edges[ i * 2 ] == vtxIdx || edges[ i * 2 + 1 ] == vtxIdx ) )
369         {
370             if( (*leftEdgeIdx) == -1 )
371             {
372                 (*leftEdgeIdx) = (*rightEdgeIdx) = i;
373                 if( edges[ i * 2 ] == vtxIdx ) {
374                     x1_left = x1_right = contour[ edges[ i * 2 + 1 ] ].x;
375                     y1_left = y1_right = contour[ edges[ i * 2 + 1 ] ].y;
376                 }
377                 else {
378                     x1_left = x1_right = contour[ edges[ i * 2 ] ].x;
379                     y1_left = y1_right = contour[ edges[ i * 2 ] ].y;
380                 }
381
382             } // if( (*leftEdgeIdx) == -1 )
383             else
384             {
385                 if( edges[ i * 2 ] == vtxIdx ) {
386                     x2 = contour[ edges[ i * 2 + 1 ] ].x;
387                     y2 = contour[ edges[ i * 2 + 1 ] ].y;
388                 }
389                 else {
390                     x2 = contour[ edges[ i * 2 ] ].x;
391                     y2 = contour[ edges[ i * 2 ] ].y;
392                 }
393
394                 compRes = icvIsFirstEdgeClosier( x0,
395                     y0, x0_end, y0_end, x1_left, y1_left, x2, y2 );
396                 if( compRes == 0 ) {
397                     return false;
398                 }
399                 if( compRes == -1 ) {
400                     (*leftEdgeIdx) = i;
401                     x1_left = x2;
402                     y1_left = y2;
403                 } // if( compRes == -1 )
404                 else {
405                     compRes = icvIsFirstEdgeClosier( x0,
406                         y0, x0_end, y0_end, x1_right, y1_right, x2, y2 );
407                     if( compRes == 0 ) {
408                         return false;
409                     }
410                     if( compRes == 1 ) {
411                         (*rightEdgeIdx) = i;
412                         x1_right = x2;
413                         y1_right = y2;
414                     }
415
416                 } // if( compRes == -1 ) else
417
418             } // if( (*leftEdgeIdx) == -1 ) else
419
420         } // if( ( i != mainEdgesIdx ) && ...
421
422     } // for( i = 0; i < numEdges; i ++ )
423
424     return true;
425
426 } // icvFindTwoNeighbourEdges
427
428 bool icvFindReferences( CvPoint* contour,
429                         int num,
430                         int* outEdges,
431                         int* refer,
432                         int* numEdges )
433 {
434     int i;
435     int currPntIdx;
436     int leftEdgeIdx, rightEdgeIdx;
437
438     if( icvEarCutTriangulation( contour, num, outEdges, numEdges ) )
439     {
440         for( i = 0; i < (*numEdges); i ++ )
441         {
442             refer[ i * 4     ] = -1;
443             refer[ i * 4 + 1 ] = -1;
444             refer[ i * 4 + 2 ] = -1;
445             refer[ i * 4 + 3 ] = -1;
446         } // for( i = 0; i < (*numEdges); i ++ )
447
448         for( i = 0; i < (*numEdges); i ++ )
449         {
450             currPntIdx = outEdges[ i * 2 ];
451             if( !icvFindTwoNeighbourEdges( contour,
452                 outEdges, (*numEdges), currPntIdx,
453                 i, &leftEdgeIdx, &rightEdgeIdx ) )
454             {
455                 return false;
456             } // if( !icvFindTwoNeighbourEdges( contour, ...
457             else
458             {
459                 if( outEdges[ leftEdgeIdx * 2 ] == currPntIdx ) {
460                     if( refer[ i * 4     ] == -1 ) {
461                         refer[ i * 4     ] = ( leftEdgeIdx << 2 );
462                     }
463                 }
464                 else {
465                     if( refer[ i * 4     ] == -1 ) {
466                         refer[ i * 4     ] = ( leftEdgeIdx << 2 ) | 2;
467                     }
468                 }
469                 if( outEdges[ rightEdgeIdx * 2 ] == currPntIdx ) {
470                     if( refer[ i * 4 + 1 ] == -1 ) {
471                         refer[ i * 4 + 1 ] = ( rightEdgeIdx << 2 ) | 3;
472                     }
473                 }
474                 else {
475                     if( refer[ i * 4 + 1 ] == -1 ) {
476                         refer[ i * 4 + 1 ] = ( rightEdgeIdx << 2 ) | 1;
477                     }
478                 }
479
480             } // if( !icvFindTwoNeighbourEdges( contour, ... ) else
481
482             currPntIdx = outEdges[ i * 2 + 1 ];
483             if( i == 18 ) {
484                 i = i;
485             }
486             if( !icvFindTwoNeighbourEdges( contour,
487                 outEdges, (*numEdges), currPntIdx,
488                 i, &leftEdgeIdx, &rightEdgeIdx ) )
489             {
490                 return false;
491             } // if( !icvFindTwoNeighbourEdges( contour, ...
492             else
493             {
494                 if( outEdges[ leftEdgeIdx * 2 ] == currPntIdx ) {
495                     if( refer[ i * 4 + 3 ] == -1 ) {
496                         refer[ i * 4 + 3 ] = ( leftEdgeIdx << 2 );
497                     }
498                 }
499                 else {
500                     if( refer[ i * 4 + 3 ] == -1 ) {
501                         refer[ i * 4 + 3 ] = ( leftEdgeIdx << 2 ) | 2;
502                     }
503                 }
504                 if( outEdges[ rightEdgeIdx * 2 ] == currPntIdx ) {
505                     if( refer[ i * 4 + 2 ] == -1 ) {
506                         refer[ i * 4 + 2 ] = ( rightEdgeIdx << 2 ) | 3;
507                     }
508                 }
509                 else {
510                     if( refer[ i * 4 + 2 ] == -1 ) {
511                         refer[ i * 4 + 2 ] = ( rightEdgeIdx << 2 ) | 1;
512                     }
513                 }
514
515             } // if( !icvFindTwoNeighbourEdges( contour, ... ) else
516
517         } // for( i = 0; i < (*numEdges); i ++ )
518
519     } // if( icvEarCutTriangulation( contour, num, outEdges, numEdges ) )
520     else {
521         return false;
522     } // if( icvEarCutTriangulation( contour, num, outEdges, ... ) else
523
524     return true;
525
526 } // icvFindReferences
527
528 void cvDecompPoly( CvContour* cont,
529                       CvSubdiv2D** subdiv,
530                       CvMemStorage* storage )
531 {
532     int*    memory;
533     CvPoint*    contour;
534     int*        outEdges;
535     int*        refer;
536     CvSubdiv2DPoint**   pntsPtrs;
537     CvQuadEdge2D**      edgesPtrs;
538     int numVtx;
539     int numEdges;
540     int i;
541     CvSeqReader reader;
542     CvPoint2D32f pnt;
543     CvQuadEdge2D* quadEdge;
544     
545     numVtx = cont -> total;
546     if( numVtx < 3 ) {
547         return;
548     }
549
550     *subdiv = ( CvSubdiv2D* )0;
551
552     memory = ( int* )malloc( sizeof( int ) * ( numVtx * 2
553         + numVtx * numVtx * 2 * 5 )
554         + sizeof( CvQuadEdge2D* ) * ( numVtx * numVtx )
555         + sizeof( CvSubdiv2DPoint* ) * ( numVtx * 2 ) );
556     contour     = ( CvPoint* )memory;
557     outEdges    = ( int* )( contour + numVtx );
558     refer       = outEdges + numVtx * numVtx * 2;
559     edgesPtrs   = ( CvQuadEdge2D** )( refer + numVtx * numVtx * 4 );
560     pntsPtrs    = ( CvSubdiv2DPoint** )( edgesPtrs + numVtx * numVtx );
561
562     cvStartReadSeq( ( CvSeq* )cont, &reader, 0 );
563     for( i = 0; i < numVtx; i ++ )
564     {
565         CV_READ_SEQ_ELEM( (contour[ i ]), reader );
566     } // for( i = 0; i < numVtx; i ++ )
567
568     if( !icvFindReferences( contour, numVtx, outEdges, refer, &numEdges ) )
569     {
570         free( memory );
571         return;
572     } // if( !icvFindReferences( contour, numVtx, outEdges, refer, ...
573
574     *subdiv = cvCreateSubdiv2D( CV_SEQ_KIND_SUBDIV2D,
575                                 sizeof( CvSubdiv2D ),
576                                 sizeof( CvSubdiv2DPoint ),
577                                 sizeof( CvQuadEdge2D ),
578                                 storage );
579
580     for( i = 0; i < numVtx; i ++ )
581     {
582         pnt.x = ( float )contour[ i ].x;
583         pnt.y = ( float )contour[ i ].y;
584         pntsPtrs[ i ] = cvSubdiv2DAddPoint( *subdiv, pnt, 0 );
585     } // for( i = 0; i < numVtx; i ++ )
586
587     for( i = 0; i < numEdges; i ++ )
588     {
589         edgesPtrs[ i ] = ( CvQuadEdge2D* )
590             ( cvSubdiv2DMakeEdge( *subdiv ) & 0xfffffffc );
591     } // for( i = 0; i < numEdges; i ++ )
592
593     for( i = 0; i < numEdges; i ++ )
594     {
595         quadEdge = edgesPtrs[ i ];
596         quadEdge -> next[ 0 ] =
597             ( ( CvSubdiv2DEdge )edgesPtrs[ refer[ i * 4     ] >> 2 ] )
598             | ( refer[ i * 4     ] & 3 );
599         quadEdge -> next[ 1 ] =
600             ( ( CvSubdiv2DEdge )edgesPtrs[ refer[ i * 4 + 1 ] >> 2 ] )
601             | ( refer[ i * 4 + 1 ] & 3 );
602         quadEdge -> next[ 2 ] =
603             ( ( CvSubdiv2DEdge )edgesPtrs[ refer[ i * 4 + 2 ] >> 2 ] )
604             | ( refer[ i * 4 + 2 ] & 3 );
605         quadEdge -> next[ 3 ] =
606             ( ( CvSubdiv2DEdge )edgesPtrs[ refer[ i * 4 + 3 ] >> 2 ] )
607             | ( refer[ i * 4 + 3 ] & 3 );
608         quadEdge -> pt[ 0 ] = pntsPtrs[ outEdges[ i * 2     ] ];
609         quadEdge -> pt[ 1 ] = ( CvSubdiv2DPoint* )0;
610         quadEdge -> pt[ 2 ] = pntsPtrs[ outEdges[ i * 2 + 1 ] ];
611         quadEdge -> pt[ 3 ] = ( CvSubdiv2DPoint* )0;
612     } // for( i = 0; i < numEdges; i ++ )
613
614     (*subdiv) -> topleft.x = ( float )cont -> rect.x;
615     (*subdiv) -> topleft.y = ( float )cont -> rect.y;
616     (*subdiv) -> bottomright.x =
617         ( float )( cont -> rect.x + cont -> rect.width );
618     (*subdiv) -> bottomright.y =
619         ( float )( cont -> rect.y + cont -> rect.height );
620
621     free( memory );
622     return;
623
624 } // cvDecompPoly
625
626 #endif
627
628 // End of file decomppoly.cpp
629