CV_IMPL void cvInitSubdivDelaunay2D( CvSubdiv2D * subdiv, CvRect rect ) { float big_coord = 3.f * MAX( rect.width, rect.height ); CvPoint2D32f ppA, ppB, ppC; CvSubdiv2DPoint *pA, *pB, *pC; CvSubdiv2DEdge edge_AB, edge_BC, edge_CA; float rx = (float) rect.x; float ry = (float) rect.y; CV_FUNCNAME( "cvSubdivDelaunay2DInit" ); __BEGIN__; if( !subdiv ) CV_ERROR( CV_StsNullPtr, "" ); cvClearSet( (CvSet *) (subdiv->edges) ); cvClearSet( (CvSet *) subdiv ); subdiv->quad_edges = 0; subdiv->recent_edge = 0; subdiv->is_geometry_valid = 0; subdiv->topleft = cvPoint2D32f( rx, ry ); subdiv->bottomright = cvPoint2D32f( rx + rect.width, ry + rect.height ); ppA = cvPoint2D32f( rx + big_coord, ry ); ppB = cvPoint2D32f( rx, ry + big_coord ); ppC = cvPoint2D32f( rx - big_coord, ry - big_coord ); pA = cvSubdiv2DAddPoint( subdiv, ppA, 0 ); pB = cvSubdiv2DAddPoint( subdiv, ppB, 0 ); pC = cvSubdiv2DAddPoint( subdiv, ppC, 0 ); edge_AB = cvSubdiv2DMakeEdge( subdiv ); edge_BC = cvSubdiv2DMakeEdge( subdiv ); edge_CA = cvSubdiv2DMakeEdge( subdiv ); cvSubdiv2DSetEdgePoints( edge_AB, pA, pB ); cvSubdiv2DSetEdgePoints( edge_BC, pB, pC ); cvSubdiv2DSetEdgePoints( edge_CA, pC, pA ); cvSubdiv2DSplice( edge_AB, cvSubdiv2DSymEdge( edge_CA )); cvSubdiv2DSplice( edge_BC, cvSubdiv2DSymEdge( edge_AB )); cvSubdiv2DSplice( edge_CA, cvSubdiv2DSymEdge( edge_BC )); subdiv->recent_edge = edge_AB; __END__; }
static CvSubdiv2DEdge cvSubdiv2DConnectEdges( CvSubdiv2D * subdiv, CvSubdiv2DEdge edgeA, CvSubdiv2DEdge edgeB ) { CvSubdiv2DEdge new_edge = 0; CV_FUNCNAME( "cvSubdiv2DConnectPoints" ); __BEGIN__; CvSubdiv2DPoint *orgB, *dstA; if( !subdiv ) CV_ERROR( CV_StsNullPtr, "" ); new_edge = cvSubdiv2DMakeEdge( subdiv ); cvSubdiv2DSplice( new_edge, cvSubdiv2DGetEdge( edgeA, CV_NEXT_AROUND_LEFT )); cvSubdiv2DSplice( cvSubdiv2DSymEdge( new_edge ), edgeB ); dstA = cvSubdiv2DEdgeDst( edgeA ); orgB = cvSubdiv2DEdgeOrg( edgeB ); cvSubdiv2DSetEdgePoints( new_edge, dstA, orgB ); __END__; return new_edge; }
static CvSubdiv2DEdge cvSubdiv2DConnectEdges( CvSubdiv2D * subdiv, CvSubdiv2DEdge edgeA, CvSubdiv2DEdge edgeB ) { if( !subdiv ) CV_Error( CV_StsNullPtr, "" ); CvSubdiv2DEdge new_edge = cvSubdiv2DMakeEdge( subdiv ); cvSubdiv2DSplice( new_edge, cvSubdiv2DGetEdge( edgeA, CV_NEXT_AROUND_LEFT )); cvSubdiv2DSplice( cvSubdiv2DSymEdge( new_edge ), edgeB ); CvSubdiv2DPoint* dstA = cvSubdiv2DEdgeDst( edgeA ); CvSubdiv2DPoint* orgB = cvSubdiv2DEdgeOrg( edgeB ); cvSubdiv2DSetEdgePoints( new_edge, dstA, orgB ); return new_edge; }
CV_IMPL CvSubdiv2DPoint * cvSubdivDelaunay2DInsert( CvSubdiv2D * subdiv, CvPoint2D32f pt ) { CvSubdiv2DPoint *point = 0; CvSubdiv2DPointLocation location = CV_PTLOC_ERROR; CvSubdiv2DPoint *curr_point = 0, *first_point = 0; CvSubdiv2DEdge curr_edge = 0, deleted_edge = 0, base_edge = 0; int i, max_edges; if( !subdiv ) CV_Error( CV_StsNullPtr, "" ); if( !CV_IS_SUBDIV2D(subdiv) ) CV_Error( CV_StsBadFlag, "" ); location = cvSubdiv2DLocate( subdiv, pt, &curr_edge, &curr_point ); switch (location) { case CV_PTLOC_ERROR: CV_Error( CV_StsBadSize, "" ); case CV_PTLOC_OUTSIDE_RECT: CV_Error( CV_StsOutOfRange, "" ); case CV_PTLOC_VERTEX: point = curr_point; break; case CV_PTLOC_ON_EDGE: deleted_edge = curr_edge; subdiv->recent_edge = curr_edge = cvSubdiv2DGetEdge( curr_edge, CV_PREV_AROUND_ORG ); cvSubdiv2DDeleteEdge( subdiv, deleted_edge ); /* no break */ case CV_PTLOC_INSIDE: assert( curr_edge != 0 ); subdiv->is_geometry_valid = 0; curr_point = cvSubdiv2DAddPoint( subdiv, pt, 0 ); base_edge = cvSubdiv2DMakeEdge( subdiv ); first_point = cvSubdiv2DEdgeOrg( curr_edge ); cvSubdiv2DSetEdgePoints( base_edge, first_point, curr_point ); cvSubdiv2DSplice( base_edge, curr_edge ); do { base_edge = cvSubdiv2DConnectEdges( subdiv, curr_edge, cvSubdiv2DSymEdge( base_edge )); curr_edge = cvSubdiv2DGetEdge( base_edge, CV_PREV_AROUND_ORG ); } while( cvSubdiv2DEdgeDst( curr_edge ) != first_point ); curr_edge = cvSubdiv2DGetEdge( base_edge, CV_PREV_AROUND_ORG ); max_edges = subdiv->quad_edges * 4; for( i = 0; i < max_edges; i++ ) { CvSubdiv2DPoint *temp_dst = 0, *curr_org = 0, *curr_dst = 0; CvSubdiv2DEdge temp_edge = cvSubdiv2DGetEdge( curr_edge, CV_PREV_AROUND_ORG ); temp_dst = cvSubdiv2DEdgeDst( temp_edge ); curr_org = cvSubdiv2DEdgeOrg( curr_edge ); curr_dst = cvSubdiv2DEdgeDst( curr_edge ); if( icvIsRightOf( temp_dst->pt, curr_edge ) > 0 && icvIsPtInCircle3( curr_org->pt, temp_dst->pt, curr_dst->pt, curr_point->pt ) < 0 ) { cvSubdiv2DSwapEdges( curr_edge ); curr_edge = cvSubdiv2DGetEdge( curr_edge, CV_PREV_AROUND_ORG ); } else if( curr_org == first_point ) { break; } else { curr_edge = cvSubdiv2DGetEdge( cvSubdiv2DNextEdge( curr_edge ), CV_PREV_AROUND_LEFT ); } } break; default: CV_Error_(CV_StsError, ("cvSubdiv2DLocate returned invalid location = %d", location) ); } return curr_point; }
CV_IMPL CvSubdiv2DPoint * cvSubdivDelaunay2DInsert( CvSubdiv2D * subdiv, CvPoint2D32f pt ) { CvSubdiv2DPoint *point = 0; CvSubdiv2DPointLocation location = CV_PTLOC_ERROR; CvSubdiv2DPoint *curr_point = 0, *first_point = 0; CvSubdiv2DEdge curr_edge = 0, deleted_edge = 0, base_edge = 0; int i, max_edges; CV_FUNCNAME( "cvSubdivDelaunay2DInsert" ); __BEGIN__; if( !subdiv ) CV_ERROR( CV_StsNullPtr, "" ); if( !CV_IS_SUBDIV2D(subdiv) ) CV_ERROR_FROM_STATUS( CV_BADFLAG_ERR ); location = cvSubdiv2DLocate( subdiv, pt, &curr_edge, &curr_point ); switch (location) { case CV_PTLOC_ERROR: CV_ERROR_FROM_STATUS( CV_BADSIZE_ERR ); case CV_PTLOC_OUTSIDE_RECT: CV_ERROR_FROM_STATUS( CV_BADRANGE_ERR ); case CV_PTLOC_VERTEX: point = curr_point; break; case CV_PTLOC_ON_EDGE: deleted_edge = curr_edge; subdiv->recent_edge = curr_edge = cvSubdiv2DGetEdge( curr_edge, CV_PREV_AROUND_ORG ); cvSubdiv2DDeleteEdge( subdiv, deleted_edge ); /* no break */ case CV_PTLOC_INSIDE: assert( curr_edge != 0 ); subdiv->is_geometry_valid = 0; curr_point = cvSubdiv2DAddPoint( subdiv, pt, 0 ); CV_CHECK(); base_edge = cvSubdiv2DMakeEdge( subdiv ); first_point = cvSubdiv2DEdgeOrg( curr_edge ); cvSubdiv2DSetEdgePoints( base_edge, first_point, curr_point ); cvSubdiv2DSplice( base_edge, curr_edge ); do { base_edge = cvSubdiv2DConnectEdges( subdiv, curr_edge, cvSubdiv2DSymEdge( base_edge )); curr_edge = cvSubdiv2DGetEdge( base_edge, CV_PREV_AROUND_ORG ); } while( cvSubdiv2DEdgeDst( curr_edge ) != first_point ); curr_edge = cvSubdiv2DGetEdge( base_edge, CV_PREV_AROUND_ORG ); max_edges = subdiv->quad_edges * 4; for( i = 0; i < max_edges; i++ ) { CvSubdiv2DPoint *temp_dst = 0, *curr_org = 0, *curr_dst = 0; CvSubdiv2DEdge temp_edge = cvSubdiv2DGetEdge( curr_edge, CV_PREV_AROUND_ORG ); temp_dst = cvSubdiv2DEdgeDst( temp_edge ); curr_org = cvSubdiv2DEdgeOrg( curr_edge ); curr_dst = cvSubdiv2DEdgeDst( curr_edge ); if( icvIsRightOf( temp_dst->pt, curr_edge ) > 0 && icvIsPtInCircle3( curr_org->pt, temp_dst->pt, curr_dst->pt, curr_point->pt ) < 0 ) { cvSubdiv2DSwapEdges( curr_edge ); curr_edge = cvSubdiv2DGetEdge( curr_edge, CV_PREV_AROUND_ORG ); } else if( curr_org == first_point ) { break; } else { curr_edge = cvSubdiv2DGetEdge( cvSubdiv2DNextEdge( curr_edge ), CV_PREV_AROUND_LEFT ); } } break; default: assert( 0 ); CV_ERROR_FROM_STATUS( CV_NOTDEFINED_ERR ); } point = curr_point; __END__; //icvSubdiv2DCheck( subdiv ); return point; }
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