opencv/modules/legacy/src/decomppoly.cpp
2012-10-17 15:32:23 +04:00

630 lines
20 KiB
C++

/*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 "precomp.hpp"
#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