Home | History | Annotate | Download | only in src
      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 #include "_cv.h"
     42 
     43 #define CV_MATCH_CHECK( status, cvFun )                                    \
     44   {                                                                        \
     45     status = cvFun;                                                        \
     46     if( status != CV_OK )                                                  \
     47      goto M_END;                                                           \
     48   }
     49 
     50 static CvStatus
     51 icvCalcTriAttr( const CvSeq * contour, CvPoint t2, CvPoint t1, int n1,
     52                 CvPoint t3, int n3, double *s, double *s_c,
     53                 double *h, double *a, double *b );
     54 
     55 /*F///////////////////////////////////////////////////////////////////////////////////////
     56 //    Name: icvCreateContourTree
     57 //    Purpose:
     58 //    Create binary tree representation for the contour
     59 //    Context:
     60 //    Parameters:
     61 //      contour - pointer to input contour object.
     62 //      storage - pointer to the current storage block
     63 //      tree   -  output pointer to the binary tree representation
     64 //      threshold - threshold for the binary tree building
     65 //
     66 //F*/
     67 static CvStatus
     68 icvCreateContourTree( const CvSeq * contour, CvMemStorage * storage,
     69                       CvContourTree ** tree, double threshold )
     70 {
     71     CvPoint *pt_p;              /*  pointer to previos points   */
     72     CvPoint *pt_n;              /*  pointer to next points      */
     73     CvPoint *pt1, *pt2;         /*  pointer to current points   */
     74 
     75     CvPoint t, tp1, tp2, tp3, tn1, tn2, tn3;
     76     int lpt, flag, i, j, i_tree, j_1, j_3, i_buf;
     77     double s, sp1, sp2, sn1, sn2, s_c, sp1_c, sp2_c, sn1_c, sn2_c, h, hp1, hp2, hn1, hn2,
     78         a, ap1, ap2, an1, an2, b, bp1, bp2, bn1, bn2;
     79     double a_s_c, a_sp1_c;
     80 
     81     _CvTrianAttr **ptr_p, **ptr_n, **ptr1, **ptr2;      /*  pointers to pointers of triangles  */
     82     _CvTrianAttr *cur_adr;
     83 
     84     int *num_p, *num_n, *num1, *num2;   /*   numbers of input contour points   */
     85     int nm, nmp1, nmp2, nmp3, nmn1, nmn2, nmn3;
     86     int seq_flags = 1, i_end, prev_null, prev2_null;
     87     double koef = 1.5;
     88     double eps = 1.e-7;
     89     double e;
     90     CvStatus status;
     91     int hearder_size;
     92     _CvTrianAttr tree_one, tree_two, *tree_end, *tree_root;
     93 
     94     CvSeqWriter writer;
     95 
     96     assert( contour != NULL && contour->total >= 4 );
     97     status = CV_OK;
     98 
     99     if( contour == NULL )
    100         return CV_NULLPTR_ERR;
    101     if( contour->total < 4 )
    102         return CV_BADSIZE_ERR;
    103 
    104     if( !CV_IS_SEQ_POLYGON( contour ))
    105         return CV_BADFLAG_ERR;
    106 
    107 
    108 /*   Convert Sequence to array    */
    109     lpt = contour->total;
    110     pt_p = pt_n = NULL;
    111     num_p = num_n = NULL;
    112     ptr_p = ptr_n = ptr1 = ptr2 = NULL;
    113     tree_end = NULL;
    114 
    115     pt_p = (CvPoint *) cvAlloc( lpt * sizeof( CvPoint ));
    116     pt_n = (CvPoint *) cvAlloc( lpt * sizeof( CvPoint ));
    117 
    118     num_p = (int *) cvAlloc( lpt * sizeof( int ));
    119     num_n = (int *) cvAlloc( lpt * sizeof( int ));
    120 
    121     hearder_size = sizeof( CvContourTree );
    122     seq_flags = CV_SEQ_POLYGON_TREE;
    123     cvStartWriteSeq( seq_flags, hearder_size, sizeof( _CvTrianAttr ), storage, &writer );
    124 
    125     ptr_p = (_CvTrianAttr **) cvAlloc( lpt * sizeof( _CvTrianAttr * ));
    126     ptr_n = (_CvTrianAttr **) cvAlloc( lpt * sizeof( _CvTrianAttr * ));
    127 
    128     memset( ptr_p, 0, lpt * sizeof( _CvTrianAttr * ));
    129     memset( ptr_n, 0, lpt * sizeof( _CvTrianAttr * ));
    130 
    131     if( pt_p == NULL || pt_n == NULL )
    132         return CV_OUTOFMEM_ERR;
    133     if( ptr_p == NULL || ptr_n == NULL )
    134         return CV_OUTOFMEM_ERR;
    135 
    136 /*     write fild for the binary tree root   */
    137 /*  start_writer = writer;   */
    138 
    139     tree_one.pt.x = tree_one.pt.y = 0;
    140     tree_one.sign = 0;
    141     tree_one.area = 0;
    142     tree_one.r1 = tree_one.r2 = 0;
    143     tree_one.next_v1 = tree_one.next_v2 = tree_one.prev_v = NULL;
    144 
    145     CV_WRITE_SEQ_ELEM( tree_one, writer );
    146     tree_root = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
    147 
    148     if( cvCvtSeqToArray( contour, (char *) pt_p ) == (char *) contour )
    149         return CV_BADPOINT_ERR;
    150 
    151     for( i = 0; i < lpt; i++ )
    152         num_p[i] = i;
    153 
    154     i = lpt;
    155     flag = 0;
    156     i_tree = 0;
    157     e = 20.;                    /*  initial threshold value   */
    158     ptr1 = ptr_p;
    159     ptr2 = ptr_n;
    160     pt1 = pt_p;
    161     pt2 = pt_n;
    162     num1 = num_p;
    163     num2 = num_n;
    164 /*  binary tree constraction    */
    165     while( i > 4 )
    166     {
    167         if( flag == 0 )
    168         {
    169             ptr1 = ptr_p;
    170             ptr2 = ptr_n;
    171             pt1 = pt_p;
    172             pt2 = pt_n;
    173             num1 = num_p;
    174             num2 = num_n;
    175             flag = 1;
    176         }
    177         else
    178         {
    179             ptr1 = ptr_n;
    180             ptr2 = ptr_p;
    181             pt1 = pt_n;
    182             pt2 = pt_p;
    183             num1 = num_n;
    184             num2 = num_p;
    185             flag = 0;
    186         }
    187         t = pt1[0];
    188         nm = num1[0];
    189         tp1 = pt1[i - 1];
    190         nmp1 = num1[i - 1];
    191         tp2 = pt1[i - 2];
    192         nmp2 = num1[i - 2];
    193         tp3 = pt1[i - 3];
    194         nmp3 = num1[i - 3];
    195         tn1 = pt1[1];
    196         nmn1 = num1[1];
    197         tn2 = pt1[2];
    198         nmn2 = num1[2];
    199 
    200         i_buf = 0;
    201         i_end = -1;
    202         CV_MATCH_CHECK( status,
    203                         icvCalcTriAttr( contour, t, tp1, nmp1, tn1, nmn1, &s, &s_c, &h, &a,
    204                                         &b ));
    205         CV_MATCH_CHECK( status,
    206                         icvCalcTriAttr( contour, tp1, tp2, nmp2, t, nm, &sp1, &sp1_c, &hp1,
    207                                         &ap1, &bp1 ));
    208         CV_MATCH_CHECK( status,
    209                         icvCalcTriAttr( contour, tp2, tp3, nmp3, tp1, nmp1, &sp2, &sp2_c, &hp2,
    210                                         &ap2, &bp2 ));
    211         CV_MATCH_CHECK( status,
    212                         icvCalcTriAttr( contour, tn1, t, nm, tn2, nmn2, &sn1, &sn1_c, &hn1,
    213                                         &an1, &bn1 ));
    214 
    215 
    216         j_3 = 3;
    217         prev_null = prev2_null = 0;
    218         for( j = 0; j < i; j++ )
    219         {
    220             tn3 = pt1[j_3];
    221             nmn3 = num1[j_3];
    222             if( j == 0 )
    223                 j_1 = i - 1;
    224             else
    225                 j_1 = j - 1;
    226 
    227             CV_MATCH_CHECK( status, icvCalcTriAttr( contour, tn2, tn1, nmn1, tn3, nmn3,
    228                                                     &sn2, &sn2_c, &hn2, &an2, &bn2 ));
    229 
    230             if( (s_c < sp1_c && s_c < sp2_c && s_c <= sn1_c && s_c <= sn2_c && s_c < e) ||
    231                 (((s_c == sp1_c && s_c <= sp2_c) || (s_c == sp2_c && s_c <= sp1_c)) &&
    232                 s_c <= sn1_c && s_c <= sn2_c && s_c < e && j > 1 && prev2_null == 0) ||
    233                 (s_c < eps && j > 0 && prev_null == 0) )
    234             {
    235                 prev_null = prev2_null = 1;
    236                 if( s_c < threshold )
    237                 {
    238                     if( ptr1[j_1] == NULL && ptr1[j] == NULL )
    239                     {
    240                         if( i_buf > 0 )
    241                             ptr2[i_buf - 1] = NULL;
    242                         else
    243                             i_end = 0;
    244                     }
    245                     else
    246                     {
    247 /*   form next vertex  */
    248                         tree_one.pt = t;
    249                         tree_one.sign = (char) (CV_SIGN( s ));
    250                         tree_one.r1 = h / a;
    251                         tree_one.r2 = b / a;
    252                         tree_one.area = fabs( s );
    253                         tree_one.next_v1 = ptr1[j_1];
    254                         tree_one.next_v2 = ptr1[j];
    255 
    256                         CV_WRITE_SEQ_ELEM( tree_one, writer );
    257                         cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
    258 
    259                         if( ptr1[j_1] != NULL )
    260                             ptr1[j_1]->prev_v = cur_adr;
    261                         if( ptr1[j] != NULL )
    262                             ptr1[j]->prev_v = cur_adr;
    263 
    264                         if( i_buf > 0 )
    265                             ptr2[i_buf - 1] = cur_adr;
    266                         else
    267                         {
    268                             tree_end = (_CvTrianAttr *) writer.ptr;
    269                             i_end = 1;
    270                         }
    271                         i_tree++;
    272                     }
    273                 }
    274                 else
    275 /*   form next vertex    */
    276                 {
    277                     tree_one.pt = t;
    278                     tree_one.sign = (char) (CV_SIGN( s ));
    279                     tree_one.area = fabs( s );
    280                     tree_one.r1 = h / a;
    281                     tree_one.r2 = b / a;
    282                     tree_one.next_v1 = ptr1[j_1];
    283                     tree_one.next_v2 = ptr1[j];
    284 
    285                     CV_WRITE_SEQ_ELEM( tree_one, writer );
    286                     cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
    287 
    288                     if( ptr1[j_1] != NULL )
    289                         ptr1[j_1]->prev_v = cur_adr;
    290                     if( ptr1[j] != NULL )
    291                         ptr1[j]->prev_v = cur_adr;
    292 
    293                     if( i_buf > 0 )
    294                         ptr2[i_buf - 1] = cur_adr;
    295                     else
    296                     {
    297                         tree_end = cur_adr;
    298                         i_end = 1;
    299                     }
    300                     i_tree++;
    301                 }
    302             }
    303             else
    304 /*   the current triangle is'not LMIAT    */
    305             {
    306                 prev_null = 0;
    307                 switch (prev2_null)
    308                 {
    309                 case 0:
    310                     break;
    311                 case 1:
    312                     {
    313                         prev2_null = 2;
    314                         break;
    315                     }
    316                 case 2:
    317                     {
    318                         prev2_null = 0;
    319                         break;
    320                     }
    321                 }
    322                 if( j != i - 1 || i_end == -1 )
    323                     ptr2[i_buf] = ptr1[j];
    324                 else if( i_end == 0 )
    325                     ptr2[i_buf] = NULL;
    326                 else
    327                     ptr2[i_buf] = tree_end;
    328                 pt2[i_buf] = t;
    329                 num2[i_buf] = num1[j];
    330                 i_buf++;
    331             }
    332 /*    go to next vertex    */
    333             tp3 = tp2;
    334             tp2 = tp1;
    335             tp1 = t;
    336             t = tn1;
    337             tn1 = tn2;
    338             tn2 = tn3;
    339             nmp3 = nmp2;
    340             nmp2 = nmp1;
    341             nmp1 = nm;
    342             nm = nmn1;
    343             nmn1 = nmn2;
    344             nmn2 = nmn3;
    345 
    346             sp2 = sp1;
    347             sp1 = s;
    348             s = sn1;
    349             sn1 = sn2;
    350             sp2_c = sp1_c;
    351             sp1_c = s_c;
    352             s_c = sn1_c;
    353             sn1_c = sn2_c;
    354 
    355             ap2 = ap1;
    356             ap1 = a;
    357             a = an1;
    358             an1 = an2;
    359             bp2 = bp1;
    360             bp1 = b;
    361             b = bn1;
    362             bn1 = bn2;
    363             hp2 = hp1;
    364             hp1 = h;
    365             h = hn1;
    366             hn1 = hn2;
    367             j_3++;
    368             if( j_3 >= i )
    369                 j_3 = 0;
    370         }
    371 
    372         i = i_buf;
    373         e = e * koef;
    374     }
    375 
    376 /*  constract tree root  */
    377     if( i != 4 )
    378         return CV_BADFACTOR_ERR;
    379 
    380     t = pt2[0];
    381     tn1 = pt2[1];
    382     tn2 = pt2[2];
    383     tp1 = pt2[3];
    384     nm = num2[0];
    385     nmn1 = num2[1];
    386     nmn2 = num2[2];
    387     nmp1 = num2[3];
    388 /*   first pair of the triangles   */
    389     CV_MATCH_CHECK( status,
    390                     icvCalcTriAttr( contour, t, tp1, nmp1, tn1, nmn1, &s, &s_c, &h, &a, &b ));
    391     CV_MATCH_CHECK( status,
    392                     icvCalcTriAttr( contour, tn2, tn1, nmn1, tp1, nmp1, &sn2, &sn2_c, &hn2,
    393                                     &an2, &bn2 ));
    394 /*   second pair of the triangles   */
    395     CV_MATCH_CHECK( status,
    396                     icvCalcTriAttr( contour, tn1, t, nm, tn2, nmn2, &sn1, &sn1_c, &hn1, &an1,
    397                                     &bn1 ));
    398     CV_MATCH_CHECK( status,
    399                     icvCalcTriAttr( contour, tp1, tn2, nmn2, t, nm, &sp1, &sp1_c, &hp1, &ap1,
    400                                     &bp1 ));
    401 
    402     a_s_c = fabs( s_c - sn2_c );
    403     a_sp1_c = fabs( sp1_c - sn1_c );
    404 
    405     if( a_s_c > a_sp1_c )
    406 /*   form child vertexs for the root     */
    407     {
    408         tree_one.pt = t;
    409         tree_one.sign = (char) (CV_SIGN( s ));
    410         tree_one.area = fabs( s );
    411         tree_one.r1 = h / a;
    412         tree_one.r2 = b / a;
    413         tree_one.next_v1 = ptr2[3];
    414         tree_one.next_v2 = ptr2[0];
    415 
    416         tree_two.pt = tn2;
    417         tree_two.sign = (char) (CV_SIGN( sn2 ));
    418         tree_two.area = fabs( sn2 );
    419         tree_two.r1 = hn2 / an2;
    420         tree_two.r2 = bn2 / an2;
    421         tree_two.next_v1 = ptr2[1];
    422         tree_two.next_v2 = ptr2[2];
    423 
    424         CV_WRITE_SEQ_ELEM( tree_one, writer );
    425         cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
    426 
    427         if( s_c > sn2_c )
    428         {
    429             if( ptr2[3] != NULL )
    430                 ptr2[3]->prev_v = cur_adr;
    431             if( ptr2[0] != NULL )
    432                 ptr2[0]->prev_v = cur_adr;
    433             ptr1[0] = cur_adr;
    434 
    435             i_tree++;
    436 
    437             CV_WRITE_SEQ_ELEM( tree_two, writer );
    438             cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
    439 
    440             if( ptr2[1] != NULL )
    441                 ptr2[1]->prev_v = cur_adr;
    442             if( ptr2[2] != NULL )
    443                 ptr2[2]->prev_v = cur_adr;
    444             ptr1[1] = cur_adr;
    445 
    446             i_tree++;
    447 
    448             pt1[0] = tp1;
    449             pt1[1] = tn1;
    450         }
    451         else
    452         {
    453             CV_WRITE_SEQ_ELEM( tree_two, writer );
    454             cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
    455 
    456             if( ptr2[1] != NULL )
    457                 ptr2[1]->prev_v = cur_adr;
    458             if( ptr2[2] != NULL )
    459                 ptr2[2]->prev_v = cur_adr;
    460             ptr1[0] = cur_adr;
    461 
    462             i_tree++;
    463 
    464             CV_WRITE_SEQ_ELEM( tree_one, writer );
    465             cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
    466 
    467             if( ptr2[3] != NULL )
    468                 ptr2[3]->prev_v = cur_adr;
    469             if( ptr2[0] != NULL )
    470                 ptr2[0]->prev_v = cur_adr;
    471             ptr1[1] = cur_adr;
    472 
    473             i_tree++;
    474 
    475             pt1[0] = tn1;
    476             pt1[1] = tp1;
    477         }
    478     }
    479     else
    480     {
    481         tree_one.pt = tp1;
    482         tree_one.sign = (char) (CV_SIGN( sp1 ));
    483         tree_one.area = fabs( sp1 );
    484         tree_one.r1 = hp1 / ap1;
    485         tree_one.r2 = bp1 / ap1;
    486         tree_one.next_v1 = ptr2[2];
    487         tree_one.next_v2 = ptr2[3];
    488 
    489         tree_two.pt = tn1;
    490         tree_two.sign = (char) (CV_SIGN( sn1 ));
    491         tree_two.area = fabs( sn1 );
    492         tree_two.r1 = hn1 / an1;
    493         tree_two.r2 = bn1 / an1;
    494         tree_two.next_v1 = ptr2[0];
    495         tree_two.next_v2 = ptr2[1];
    496 
    497         CV_WRITE_SEQ_ELEM( tree_one, writer );
    498         cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
    499 
    500         if( sp1_c > sn1_c )
    501         {
    502             if( ptr2[2] != NULL )
    503                 ptr2[2]->prev_v = cur_adr;
    504             if( ptr2[3] != NULL )
    505                 ptr2[3]->prev_v = cur_adr;
    506             ptr1[0] = cur_adr;
    507 
    508             i_tree++;
    509 
    510             CV_WRITE_SEQ_ELEM( tree_two, writer );
    511             cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
    512 
    513             if( ptr2[0] != NULL )
    514                 ptr2[0]->prev_v = cur_adr;
    515             if( ptr2[1] != NULL )
    516                 ptr2[1]->prev_v = cur_adr;
    517             ptr1[1] = cur_adr;
    518 
    519             i_tree++;
    520 
    521             pt1[0] = tn2;
    522             pt1[1] = t;
    523         }
    524         else
    525         {
    526             CV_WRITE_SEQ_ELEM( tree_two, writer );
    527             cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
    528 
    529             if( ptr2[0] != NULL )
    530                 ptr2[0]->prev_v = cur_adr;
    531             if( ptr2[1] != NULL )
    532                 ptr2[1]->prev_v = cur_adr;
    533             ptr1[0] = cur_adr;
    534 
    535             i_tree++;
    536 
    537             CV_WRITE_SEQ_ELEM( tree_one, writer );
    538             cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
    539 
    540             if( ptr2[2] != NULL )
    541                 ptr2[2]->prev_v = cur_adr;
    542             if( ptr2[3] != NULL )
    543                 ptr2[3]->prev_v = cur_adr;
    544             ptr1[1] = cur_adr;
    545 
    546             i_tree++;
    547 
    548             pt1[0] = t;
    549             pt1[1] = tn2;
    550 
    551         }
    552     }
    553 
    554 /*    form root   */
    555     s = cvContourArea( contour );
    556 
    557     tree_root->pt = pt1[1];
    558     tree_root->sign = 0;
    559     tree_root->area = fabs( s );
    560     tree_root->r1 = 0;
    561     tree_root->r2 = 0;
    562     tree_root->next_v1 = ptr1[0];
    563     tree_root->next_v2 = ptr1[1];
    564     tree_root->prev_v = NULL;
    565 
    566     ptr1[0]->prev_v = (_CvTrianAttr *) tree_root;
    567     ptr1[1]->prev_v = (_CvTrianAttr *) tree_root;
    568 
    569 /*     write binary tree root   */
    570 /*    CV_WRITE_SEQ_ELEM (tree_one, start_writer);   */
    571     i_tree++;
    572 /*  create Sequence hearder     */
    573     *((CvSeq **) tree) = cvEndWriteSeq( &writer );
    574 /*   write points for the main segment into sequence header   */
    575     (*tree)->p1 = pt1[0];
    576 
    577   M_END:
    578 
    579     cvFree( &ptr_n );
    580     cvFree( &ptr_p );
    581     cvFree( &num_n );
    582     cvFree( &num_p );
    583     cvFree( &pt_n );
    584     cvFree( &pt_p );
    585 
    586     return status;
    587 }
    588 
    589 /****************************************************************************************\
    590 
    591  triangle attributes calculations
    592 
    593 \****************************************************************************************/
    594 static CvStatus
    595 icvCalcTriAttr( const CvSeq * contour, CvPoint t2, CvPoint t1, int n1,
    596                 CvPoint t3, int n3, double *s, double *s_c,
    597                 double *h, double *a, double *b )
    598 {
    599     double x13, y13, x12, y12, l_base, nx, ny, qq;
    600     double eps = 1.e-5;
    601 
    602     x13 = t3.x - t1.x;
    603     y13 = t3.y - t1.y;
    604     x12 = t2.x - t1.x;
    605     y12 = t2.y - t1.y;
    606     qq = x13 * x13 + y13 * y13;
    607     l_base = cvSqrt( (float) (qq) );
    608     if( l_base > eps )
    609     {
    610         nx = y13 / l_base;
    611         ny = -x13 / l_base;
    612 
    613         *h = nx * x12 + ny * y12;
    614 
    615         *s = (*h) * l_base / 2.;
    616 
    617         *b = nx * y12 - ny * x12;
    618 
    619         *a = l_base;
    620 /*   calculate interceptive area   */
    621         *s_c = cvContourArea( contour, cvSlice(n1, n3+1));
    622     }
    623     else
    624     {
    625         *h = 0;
    626         *s = 0;
    627         *s_c = 0;
    628         *b = 0;
    629         *a = 0;
    630     }
    631 
    632     return CV_OK;
    633 }
    634 
    635 /*F///////////////////////////////////////////////////////////////////////////////////////
    636 //    Name: cvCreateContourTree
    637 //    Purpose:
    638 //    Create binary tree representation for the contour
    639 //    Context:
    640 //    Parameters:
    641 //      contour - pointer to input contour object.
    642 //      storage - pointer to the current storage block
    643 //      tree   -  output pointer to the binary tree representation
    644 //      threshold - threshold for the binary tree building
    645 //
    646 //F*/
    647 CV_IMPL CvContourTree*
    648 cvCreateContourTree( const CvSeq* contour, CvMemStorage* storage, double threshold )
    649 {
    650     CvContourTree* tree = 0;
    651 
    652     CV_FUNCNAME( "cvCreateContourTree" );
    653     __BEGIN__;
    654 
    655     IPPI_CALL( icvCreateContourTree( contour, storage, &tree, threshold ));
    656 
    657     __CLEANUP__;
    658     __END__;
    659 
    660     return tree;
    661 }
    662 
    663 
    664 /*F///////////////////////////////////////////////////////////////////////////////////////
    665 //    Name: icvContourFromContourTree
    666 //    Purpose:
    667 //    reconstracts contour from binary tree representation
    668 //    Context:
    669 //    Parameters:
    670 //      tree   -  pointer to the input binary tree representation
    671 //      storage - pointer to the current storage block
    672 //      contour - pointer to output contour object.
    673 //      criteria - criteria for the definition threshold value
    674 //                 for the contour reconstracting (level or precision)
    675 //F*/
    676 CV_IMPL CvSeq*
    677 cvContourFromContourTree( const CvContourTree*  tree,
    678                           CvMemStorage*  storage,
    679                           CvTermCriteria  criteria )
    680 {
    681     CvSeq* contour = 0;
    682     _CvTrianAttr **ptr_buf = 0;     /*  pointer to the pointer's buffer  */
    683     int *level_buf = 0;
    684     int i_buf;
    685 
    686     int lpt;
    687     double area_all;
    688     double threshold;
    689     int cur_level;
    690     int level;
    691     int seq_flags;
    692     char log_iter, log_eps;
    693     int out_hearder_size;
    694     _CvTrianAttr *tree_one = 0, tree_root;  /*  current vertex  */
    695 
    696     CvSeqReader reader;
    697     CvSeqWriter writer;
    698 
    699     CV_FUNCNAME("cvContourFromContourTree");
    700 
    701     __BEGIN__;
    702 
    703     if( !tree )
    704         CV_ERROR( CV_StsNullPtr, "" );
    705 
    706     if( !CV_IS_SEQ_POLYGON_TREE( tree ))
    707         CV_ERROR_FROM_STATUS( CV_BADFLAG_ERR );
    708 
    709     criteria = cvCheckTermCriteria( criteria, 0., 100 );
    710 
    711     lpt = tree->total;
    712     ptr_buf = NULL;
    713     level_buf = NULL;
    714     i_buf = 0;
    715     cur_level = 0;
    716     log_iter = (char) (criteria.type == CV_TERMCRIT_ITER ||
    717                        (criteria.type == CV_TERMCRIT_ITER + CV_TERMCRIT_EPS));
    718     log_eps = (char) (criteria.type == CV_TERMCRIT_EPS ||
    719                       (criteria.type == CV_TERMCRIT_ITER + CV_TERMCRIT_EPS));
    720 
    721     cvStartReadSeq( (CvSeq *) tree, &reader, 0 );
    722 
    723     out_hearder_size = sizeof( CvContour );
    724 
    725     seq_flags = CV_SEQ_POLYGON;
    726     cvStartWriteSeq( seq_flags, out_hearder_size, sizeof( CvPoint ), storage, &writer );
    727 
    728     ptr_buf = (_CvTrianAttr **) cvAlloc( lpt * sizeof( _CvTrianAttr * ));
    729     if( ptr_buf == NULL )
    730         CV_ERROR_FROM_STATUS( CV_OUTOFMEM_ERR );
    731     if( log_iter )
    732     {
    733         level_buf = (int *) cvAlloc( lpt * (sizeof( int )));
    734 
    735         if( level_buf == NULL )
    736             CV_ERROR_FROM_STATUS( CV_OUTOFMEM_ERR );
    737     }
    738 
    739     memset( ptr_buf, 0, lpt * sizeof( _CvTrianAttr * ));
    740 
    741 /*     write the first tree root's point as a start point of the result contour  */
    742     CV_WRITE_SEQ_ELEM( tree->p1, writer );
    743 /*     write the second tree root"s point into buffer    */
    744 
    745 /*     read the root of the tree   */
    746     CV_READ_SEQ_ELEM( tree_root, reader );
    747 
    748     tree_one = &tree_root;
    749     area_all = tree_one->area;
    750 
    751     if( log_eps )
    752         threshold = criteria.epsilon * area_all;
    753     else
    754         threshold = 10 * area_all;
    755 
    756     if( log_iter )
    757         level = criteria.max_iter;
    758     else
    759         level = -1;
    760 
    761 /*  contour from binary tree constraction    */
    762     while( i_buf >= 0 )
    763     {
    764         if( tree_one != NULL && (cur_level <= level || tree_one->area >= threshold) )
    765 /*   go to left sub tree for the vertex and save pointer to the right vertex   */
    766 /*   into the buffer     */
    767         {
    768             ptr_buf[i_buf] = tree_one;
    769             if( log_iter )
    770             {
    771                 level_buf[i_buf] = cur_level;
    772                 cur_level++;
    773             }
    774             i_buf++;
    775             tree_one = tree_one->next_v1;
    776         }
    777         else
    778         {
    779             i_buf--;
    780             if( i_buf >= 0 )
    781             {
    782                 CvPoint pt = ptr_buf[i_buf]->pt;
    783                 CV_WRITE_SEQ_ELEM( pt, writer );
    784                 tree_one = ptr_buf[i_buf]->next_v2;
    785                 if( log_iter )
    786                 {
    787                     cur_level = level_buf[i_buf] + 1;
    788                 }
    789             }
    790         }
    791     }
    792 
    793     contour = cvEndWriteSeq( &writer );
    794     cvBoundingRect( contour, 1 );
    795 
    796     __CLEANUP__;
    797     __END__;
    798 
    799     cvFree( &level_buf );
    800     cvFree( &ptr_buf );
    801 
    802     return contour;
    803 }
    804 
    805