diff options
Diffstat (limited to 'cvaux/src/decomppoly.cpp')
-rw-r--r-- | cvaux/src/decomppoly.cpp | 629 |
1 files changed, 629 insertions, 0 deletions
diff --git a/cvaux/src/decomppoly.cpp b/cvaux/src/decomppoly.cpp new file mode 100644 index 0000000..713a378 --- /dev/null +++ b/cvaux/src/decomppoly.cpp @@ -0,0 +1,629 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of Intel Corporation may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#include "_cvaux.h" + +#if 0 + +#include <malloc.h> +//#include "decomppoly.h" + +#define ZERO_CLOSE 0.00001f +#define ONE_CLOSE 0.99999f + +#define CHECK_COLLINEARITY(vec1_x,vec1_y,vec2_x,vec2_y) \ + if( vec1_x == 0 ) { \ + if( vec1_y * vec2_y > 0 ) { \ + return 0; \ + } \ + } \ + else { \ + if( vec1_x * vec2_x > 0 ) { \ + return 0; \ + } \ + } + +// determines if edge number one lies in counterclockwise +// earlier than edge number two +inline int icvIsFirstEdgeClosier( int x0, + int y0, + int x0_end, + int y0_end, + int x1_end, + int y1_end, + int x2_end, + int y2_end ) +{ + int mult, mult1, mult2; + int vec0_x, vec0_y; + int vec1_x, vec1_y; + int vec2_x, vec2_y; + + vec0_x = x0_end - x0; + vec0_y = y0_end - y0; + vec1_x = x1_end - x0; + vec1_y = y1_end - y0; + vec2_x = x2_end - x0; + vec2_y = y2_end - y0; + + mult1 = vec1_x * vec0_y - vec0_x * vec1_y; + mult2 = vec2_x * vec0_y - vec0_x * vec2_y; + + if( mult1 == 0 ) { + CHECK_COLLINEARITY( vec0_x, vec0_y, vec1_x, vec1_y ); + } + if( mult2 == 0 ) { + CHECK_COLLINEARITY( vec0_x, vec0_y, vec2_x, vec2_y ); + } + if( mult1 > 0 && mult2 < 0 ) { + return 1; + } + if( mult1 < 0 && mult2 > 0 ) { + return -1; + } + + mult = vec1_x * vec2_y - vec2_x * vec1_y; + if( mult == 0 ) { + CHECK_COLLINEARITY( vec1_x, vec1_y, vec2_x, vec2_y ); + } + + if( mult1 > 0 ) + { + if( mult > 0 ) { + return -1; + } + else { + return 1; + } + } // if( mult1 > 0 ) + else + { + if( mult1 != 0 ) { + if( mult > 0 ) { + return 1; + } + else { + return -1; + } + } // if( mult1 != 0 ) + else { + if( mult2 > 0 ) { + return -1; + } + else { + return 1; + } + } // if( mult1 != 0 ) else + + } // if( mult1 > 0 ) else + +} // icvIsFirstEdgeClosier + +bool icvEarCutTriangulation( CvPoint* contour, + int num, + int* outEdges, + int* numEdges ) +{ + int i; + int notFoundFlag = 0; + int begIndex = -1; + int isInternal; + int currentNum = num; + int index1, index2, index3; + int ix0, iy0, ix1, iy1, ix2, iy2; + int x1, y1, x2, y2, x3, y3; + int dx1, dy1, dx2, dy2; + int* pointExist = ( int* )0; + int det, det1, det2; + float t1, t2; + + (*numEdges) = 0; + + if( num <= 2 ) { + return false; + } + + pointExist = ( int* )malloc( num * sizeof( int ) ); + + for( i = 0; i < num; i ++ ) { + pointExist[i] = 1; + } + + for( i = 0; i < num; i ++ ) { + outEdges[ (*numEdges) * 2 ] = i; + if( i != num - 1 ) { + outEdges[ (*numEdges) * 2 + 1 ] = i + 1; + } + else { + outEdges[ (*numEdges) * 2 + 1 ] = 0; + } + (*numEdges) ++; + } // for( i = 0; i < num; i ++ ) + + // initializing data before while cycle + index1 = 0; + index2 = 1; + index3 = 2; + x1 = contour[ index1 ].x; + y1 = contour[ index1 ].y; + x2 = contour[ index2 ].x; + y2 = contour[ index2 ].y; + x3 = contour[ index3 ].x; + y3 = contour[ index3 ].y; + + while( currentNum > 3 ) + { + dx1 = x2 - x1; + dy1 = y2 - y1; + dx2 = x3 - x2; + dy2 = y3 - y2; + if( dx1 * dy2 - dx2 * dy1 < 0 ) // convex condition + { + // checking for noncrossing edge + ix1 = x3 - x1; + iy1 = y3 - y1; + isInternal = 1; + for( i = 0; i < num; i ++ ) + { + if( i != num - 1 ) { + ix2 = contour[ i + 1 ].x - contour[ i ].x; + iy2 = contour[ i + 1 ].y - contour[ i ].y; + } + else { + ix2 = contour[ 0 ].x - contour[ i ].x; + iy2 = contour[ 0 ].y - contour[ i ].y; + } + ix0 = contour[ i ].x - x1; + iy0 = contour[ i ].y - y1; + + det = ix2 * iy1 - ix1 * iy2; + det1 = ix2 * iy0 - ix0 * iy2; + if( det != 0.0f ) + { + t1 = ( ( float )( det1 ) ) / det; + if( t1 > ZERO_CLOSE && t1 < ONE_CLOSE ) + { + det2 = ix1 * iy0 - ix0 * iy1; + t2 = ( ( float )( det2 ) ) / det; + if( t2 > ZERO_CLOSE && t2 < ONE_CLOSE ) { + isInternal = 0; + } + + } // if( t1 > ZERO_CLOSE && t1 < ONE_CLOSE ) + + } // if( det != 0.0f ) + + } // for( i = 0; i < (*numEdges); i ++ ) + + if( isInternal ) + { + // this edge is internal + notFoundFlag = 0; + outEdges[ (*numEdges) * 2 ] = index1; + outEdges[ (*numEdges) * 2 + 1 ] = index3; + (*numEdges) ++; + pointExist[ index2 ] = 0; + index2 = index3; + x2 = x3; + y2 = y3; + currentNum --; + if( currentNum >= 3 ) { + do { + index3 ++; + if( index3 == num ) { + index3 = 0; + } + } while( !pointExist[ index3 ] ); + x3 = contour[ index3 ].x; + y3 = contour[ index3 ].y; + } // if( currentNum >= 3 ) + + } // if( isInternal ) + else { + // this edge intersects some other initial edges + if( !notFoundFlag ) { + notFoundFlag = 1; + begIndex = index1; + } + index1 = index2; + x1 = x2; + y1 = y2; + index2 = index3; + x2 = x3; + y2 = y3; + do { + index3 ++; + if( index3 == num ) { + index3 = 0; + } + if( index3 == begIndex ) { + if( pointExist ) { + free( pointExist ); + } + return false; + } + } while( !pointExist[ index3 ] ); + x3 = contour[ index3 ].x; + y3 = contour[ index3 ].y; + } // if( isInternal ) else + + } // if( dx1 * dy2 - dx2 * dy1 < 0 ) + else + { + if( !notFoundFlag ) { + notFoundFlag = 1; + begIndex = index1; + } + index1 = index2; + x1 = x2; + y1 = y2; + index2 = index3; + x2 = x3; + y2 = y3; + do { + index3 ++; + if( index3 == num ) { + index3 = 0; + } + if( index3 == begIndex ) { + if( pointExist ) { + free( pointExist ); + } + return false; + } + } while( !pointExist[ index3 ] ); + x3 = contour[ index3 ].x; + y3 = contour[ index3 ].y; + } // if( dx1 * dy2 - dx2 * dy1 < 0 ) else + + } // while( currentNum > 3 ) + + if( pointExist ) { + free( pointExist ); + } + + return true; + +} // icvEarCutTriangulation + +inline bool icvFindTwoNeighbourEdges( CvPoint* contour, + int* edges, + int numEdges, + int vtxIdx, + int mainEdgeIdx, + int* leftEdgeIdx, + int* rightEdgeIdx ) +{ + int i; + int compRes; + int vec0_x, vec0_y; + int x0, y0, x0_end, y0_end; + int x1_left = 0, y1_left = 0, x1_right = 0, y1_right = 0, x2, y2; + + (*leftEdgeIdx) = -1; + (*rightEdgeIdx) = -1; + + if( edges[ mainEdgeIdx * 2 ] == vtxIdx ) { + x0 = contour[ vtxIdx ].x; + y0 = contour[ vtxIdx ].y; + x0_end = contour[ edges[ mainEdgeIdx * 2 + 1 ] ].x; + y0_end = contour[ edges[ mainEdgeIdx * 2 + 1 ] ].y; + vec0_x = x0_end - x0; + vec0_y = y0_end - y0; + } + else { + //x0 = contour[ edges[ mainEdgeIdx * 2 ] ].x; + //y0 = contour[ edges[ mainEdgeIdx * 2 ] ].y; + //x0_end = contour[ vtxIdx ].x; + //y0_end = contour[ vtxIdx ].y; + x0 = contour[ vtxIdx ].x; + y0 = contour[ vtxIdx ].y; + x0_end = contour[ edges[ mainEdgeIdx * 2 ] ].x; + y0_end = contour[ edges[ mainEdgeIdx * 2 ] ].y; + vec0_x = x0_end - x0; + vec0_y = y0_end - y0; + } + + for( i = 0; i < numEdges; i ++ ) + { + if( ( i != mainEdgeIdx ) && + ( edges[ i * 2 ] == vtxIdx || edges[ i * 2 + 1 ] == vtxIdx ) ) + { + if( (*leftEdgeIdx) == -1 ) + { + (*leftEdgeIdx) = (*rightEdgeIdx) = i; + if( edges[ i * 2 ] == vtxIdx ) { + x1_left = x1_right = contour[ edges[ i * 2 + 1 ] ].x; + y1_left = y1_right = contour[ edges[ i * 2 + 1 ] ].y; + } + else { + x1_left = x1_right = contour[ edges[ i * 2 ] ].x; + y1_left = y1_right = contour[ edges[ i * 2 ] ].y; + } + + } // if( (*leftEdgeIdx) == -1 ) + else + { + if( edges[ i * 2 ] == vtxIdx ) { + x2 = contour[ edges[ i * 2 + 1 ] ].x; + y2 = contour[ edges[ i * 2 + 1 ] ].y; + } + else { + x2 = contour[ edges[ i * 2 ] ].x; + y2 = contour[ edges[ i * 2 ] ].y; + } + + compRes = icvIsFirstEdgeClosier( x0, + y0, x0_end, y0_end, x1_left, y1_left, x2, y2 ); + if( compRes == 0 ) { + return false; + } + if( compRes == -1 ) { + (*leftEdgeIdx) = i; + x1_left = x2; + y1_left = y2; + } // if( compRes == -1 ) + else { + compRes = icvIsFirstEdgeClosier( x0, + y0, x0_end, y0_end, x1_right, y1_right, x2, y2 ); + if( compRes == 0 ) { + return false; + } + if( compRes == 1 ) { + (*rightEdgeIdx) = i; + x1_right = x2; + y1_right = y2; + } + + } // if( compRes == -1 ) else + + } // if( (*leftEdgeIdx) == -1 ) else + + } // if( ( i != mainEdgesIdx ) && ... + + } // for( i = 0; i < numEdges; i ++ ) + + return true; + +} // icvFindTwoNeighbourEdges + +bool icvFindReferences( CvPoint* contour, + int num, + int* outEdges, + int* refer, + int* numEdges ) +{ + int i; + int currPntIdx; + int leftEdgeIdx, rightEdgeIdx; + + if( icvEarCutTriangulation( contour, num, outEdges, numEdges ) ) + { + for( i = 0; i < (*numEdges); i ++ ) + { + refer[ i * 4 ] = -1; + refer[ i * 4 + 1 ] = -1; + refer[ i * 4 + 2 ] = -1; + refer[ i * 4 + 3 ] = -1; + } // for( i = 0; i < (*numEdges); i ++ ) + + for( i = 0; i < (*numEdges); i ++ ) + { + currPntIdx = outEdges[ i * 2 ]; + if( !icvFindTwoNeighbourEdges( contour, + outEdges, (*numEdges), currPntIdx, + i, &leftEdgeIdx, &rightEdgeIdx ) ) + { + return false; + } // if( !icvFindTwoNeighbourEdges( contour, ... + else + { + if( outEdges[ leftEdgeIdx * 2 ] == currPntIdx ) { + if( refer[ i * 4 ] == -1 ) { + refer[ i * 4 ] = ( leftEdgeIdx << 2 ); + } + } + else { + if( refer[ i * 4 ] == -1 ) { + refer[ i * 4 ] = ( leftEdgeIdx << 2 ) | 2; + } + } + if( outEdges[ rightEdgeIdx * 2 ] == currPntIdx ) { + if( refer[ i * 4 + 1 ] == -1 ) { + refer[ i * 4 + 1 ] = ( rightEdgeIdx << 2 ) | 3; + } + } + else { + if( refer[ i * 4 + 1 ] == -1 ) { + refer[ i * 4 + 1 ] = ( rightEdgeIdx << 2 ) | 1; + } + } + + } // if( !icvFindTwoNeighbourEdges( contour, ... ) else + + currPntIdx = outEdges[ i * 2 + 1 ]; + if( i == 18 ) { + i = i; + } + if( !icvFindTwoNeighbourEdges( contour, + outEdges, (*numEdges), currPntIdx, + i, &leftEdgeIdx, &rightEdgeIdx ) ) + { + return false; + } // if( !icvFindTwoNeighbourEdges( contour, ... + else + { + if( outEdges[ leftEdgeIdx * 2 ] == currPntIdx ) { + if( refer[ i * 4 + 3 ] == -1 ) { + refer[ i * 4 + 3 ] = ( leftEdgeIdx << 2 ); + } + } + else { + if( refer[ i * 4 + 3 ] == -1 ) { + refer[ i * 4 + 3 ] = ( leftEdgeIdx << 2 ) | 2; + } + } + if( outEdges[ rightEdgeIdx * 2 ] == currPntIdx ) { + if( refer[ i * 4 + 2 ] == -1 ) { + refer[ i * 4 + 2 ] = ( rightEdgeIdx << 2 ) | 3; + } + } + else { + if( refer[ i * 4 + 2 ] == -1 ) { + refer[ i * 4 + 2 ] = ( rightEdgeIdx << 2 ) | 1; + } + } + + } // if( !icvFindTwoNeighbourEdges( contour, ... ) else + + } // for( i = 0; i < (*numEdges); i ++ ) + + } // if( icvEarCutTriangulation( contour, num, outEdges, numEdges ) ) + else { + return false; + } // if( icvEarCutTriangulation( contour, num, outEdges, ... ) else + + return true; + +} // icvFindReferences + +void cvDecompPoly( CvContour* cont, + CvSubdiv2D** subdiv, + CvMemStorage* storage ) +{ + int* memory; + CvPoint* contour; + int* outEdges; + int* refer; + CvSubdiv2DPoint** pntsPtrs; + CvQuadEdge2D** edgesPtrs; + int numVtx; + int numEdges; + int i; + CvSeqReader reader; + CvPoint2D32f pnt; + CvQuadEdge2D* quadEdge; + + numVtx = cont -> total; + if( numVtx < 3 ) { + return; + } + + *subdiv = ( CvSubdiv2D* )0; + + memory = ( int* )malloc( sizeof( int ) * ( numVtx * 2 + + numVtx * numVtx * 2 * 5 ) + + sizeof( CvQuadEdge2D* ) * ( numVtx * numVtx ) + + sizeof( CvSubdiv2DPoint* ) * ( numVtx * 2 ) ); + contour = ( CvPoint* )memory; + outEdges = ( int* )( contour + numVtx ); + refer = outEdges + numVtx * numVtx * 2; + edgesPtrs = ( CvQuadEdge2D** )( refer + numVtx * numVtx * 4 ); + pntsPtrs = ( CvSubdiv2DPoint** )( edgesPtrs + numVtx * numVtx ); + + cvStartReadSeq( ( CvSeq* )cont, &reader, 0 ); + for( i = 0; i < numVtx; i ++ ) + { + CV_READ_SEQ_ELEM( (contour[ i ]), reader ); + } // for( i = 0; i < numVtx; i ++ ) + + if( !icvFindReferences( contour, numVtx, outEdges, refer, &numEdges ) ) + { + free( memory ); + return; + } // if( !icvFindReferences( contour, numVtx, outEdges, refer, ... + + *subdiv = cvCreateSubdiv2D( CV_SEQ_KIND_SUBDIV2D, + sizeof( CvSubdiv2D ), + sizeof( CvSubdiv2DPoint ), + sizeof( CvQuadEdge2D ), + storage ); + + for( i = 0; i < numVtx; i ++ ) + { + pnt.x = ( float )contour[ i ].x; + pnt.y = ( float )contour[ i ].y; + pntsPtrs[ i ] = cvSubdiv2DAddPoint( *subdiv, pnt, 0 ); + } // for( i = 0; i < numVtx; i ++ ) + + for( i = 0; i < numEdges; i ++ ) + { + edgesPtrs[ i ] = ( CvQuadEdge2D* ) + ( cvSubdiv2DMakeEdge( *subdiv ) & 0xfffffffc ); + } // for( i = 0; i < numEdges; i ++ ) + + for( i = 0; i < numEdges; i ++ ) + { + quadEdge = edgesPtrs[ i ]; + quadEdge -> next[ 0 ] = + ( ( CvSubdiv2DEdge )edgesPtrs[ refer[ i * 4 ] >> 2 ] ) + | ( refer[ i * 4 ] & 3 ); + quadEdge -> next[ 1 ] = + ( ( CvSubdiv2DEdge )edgesPtrs[ refer[ i * 4 + 1 ] >> 2 ] ) + | ( refer[ i * 4 + 1 ] & 3 ); + quadEdge -> next[ 2 ] = + ( ( CvSubdiv2DEdge )edgesPtrs[ refer[ i * 4 + 2 ] >> 2 ] ) + | ( refer[ i * 4 + 2 ] & 3 ); + quadEdge -> next[ 3 ] = + ( ( CvSubdiv2DEdge )edgesPtrs[ refer[ i * 4 + 3 ] >> 2 ] ) + | ( refer[ i * 4 + 3 ] & 3 ); + quadEdge -> pt[ 0 ] = pntsPtrs[ outEdges[ i * 2 ] ]; + quadEdge -> pt[ 1 ] = ( CvSubdiv2DPoint* )0; + quadEdge -> pt[ 2 ] = pntsPtrs[ outEdges[ i * 2 + 1 ] ]; + quadEdge -> pt[ 3 ] = ( CvSubdiv2DPoint* )0; + } // for( i = 0; i < numEdges; i ++ ) + + (*subdiv) -> topleft.x = ( float )cont -> rect.x; + (*subdiv) -> topleft.y = ( float )cont -> rect.y; + (*subdiv) -> bottomright.x = + ( float )( cont -> rect.x + cont -> rect.width ); + (*subdiv) -> bottomright.y = + ( float )( cont -> rect.y + cont -> rect.height ); + + free( memory ); + return; + +} // cvDecompPoly + +#endif + +// End of file decomppoly.cpp + |