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 void cvSubdiv2DDeleteEdge( CvSubdiv2D * subdiv, CvSubdiv2DEdge edge ) { CvQuadEdge2D *quadedge = (CvQuadEdge2D *) (edge & ~3); CV_FUNCNAME( "cvSubdiv2DDeleteEdge" ); __BEGIN__; if( !subdiv || !quadedge ) CV_ERROR( CV_StsNullPtr, "" ); cvSubdiv2DSplice( edge, cvSubdiv2DGetEdge( edge, CV_PREV_AROUND_ORG )); { CvSubdiv2DEdge sym_edge = cvSubdiv2DSymEdge( edge ); cvSubdiv2DSplice( sym_edge, cvSubdiv2DGetEdge( sym_edge, CV_PREV_AROUND_ORG )); } cvSetRemoveByPtr( (CvSet*)(subdiv->edges), quadedge ); subdiv->quad_edges--; __END__; }
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 void cvSubdiv2DDeleteEdge( CvSubdiv2D * subdiv, CvSubdiv2DEdge edge ) { CvQuadEdge2D *quadedge = (CvQuadEdge2D *) (edge & ~3); if( !subdiv || !quadedge ) CV_Error( CV_StsNullPtr, "" ); cvSubdiv2DSplice( edge, cvSubdiv2DGetEdge( edge, CV_PREV_AROUND_ORG )); CvSubdiv2DEdge sym_edge = cvSubdiv2DSymEdge( edge ); cvSubdiv2DSplice( sym_edge, cvSubdiv2DGetEdge( sym_edge, CV_PREV_AROUND_ORG )); cvSetRemoveByPtr( (CvSet*)(subdiv->edges), quadedge ); subdiv->quad_edges--; }
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; }
static void cvSubdiv2DSwapEdges( CvSubdiv2DEdge edge ) { CvSubdiv2DEdge sym_edge = cvSubdiv2DSymEdge( edge ); CvSubdiv2DEdge a = cvSubdiv2DGetEdge( edge, CV_PREV_AROUND_ORG ); CvSubdiv2DEdge b = cvSubdiv2DGetEdge( sym_edge, CV_PREV_AROUND_ORG ); CvSubdiv2DPoint *dstB, *dstA; cvSubdiv2DSplice( edge, a ); cvSubdiv2DSplice( sym_edge, b ); dstA = cvSubdiv2DEdgeDst( a ); dstB = cvSubdiv2DEdgeDst( b ); cvSubdiv2DSetEdgePoints( edge, dstA, dstB ); cvSubdiv2DSplice( edge, cvSubdiv2DGetEdge( a, CV_NEXT_AROUND_LEFT )); cvSubdiv2DSplice( sym_edge, cvSubdiv2DGetEdge( b, CV_NEXT_AROUND_LEFT )); }
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; }