# Structural Analysis Reference

- Contour Processing Functions
  - ApproxChains
  - StartReadChainPoints
  - ReadChainPoint
  - ApproxPoly
  - BoundingRect
  - ContourArea
  - ArcLength
  - MatchShapes
  - CreateContourTree
  - ContourFromContourTree
  - MatchContourTrees
- Geometry Functions
  - MaxRect
  - Box2D
  - BoxPoints
  - FitEllipse
  - FitLine2D
  - ConvexHull2
  - CheckContourConvexity
  - ConvexityDefect
  - ConvexityDefects
  - MinAreaRect2
  - MinEnclosingCircle
  - CalcPGH
  - KMeans
  - MinEnclosingCircle
- Planar Subdivisions
  - Subdiv2D
  - QuadEdge2D
  - Subdiv2DPoint
  - Subdiv2DGetEdge
  - Subdiv2DRotateEdge
  - Subdiv2DEdgeOrg
  - Subdiv2DEdgeDst
  - CreateSubdivDelaunay2D
  - SubdivDelaunay2DInsert
  - Subdiv2DLocate
  - FindNearestPoint2D
  - CalcSubdivVoronoi2D
  - ClearSubdivVoronoi2D

## Contour Processing Functions

### ApproxChains

Approximates Freeman chain(s) with polygonal curve

    CvSeq* cvApproxChains( CvSeq* srcSeq, CvMemStorage* storage,
                           CvChainApproxMethod method=CV_CHAIN_APPROX_SIMPLE,
                           double parameter=0, int minimalPerimeter=0, int recursive=0 );

srcSeq
  Pointer to the chain that can refer to other chains.
storage
  Storage location for the resulting polylines.
method
  Approximation method (see the description of the function cvFindContours).
parameter
  Method parameter (not used now).
minimalPerimeter
  Approximates only those contours whose perimeters are not less than minimalPerimeter. Other chains are removed from the resulting structure.
recursive
  If not 0, the function approximates all chains that access can be obtained to from srcSeq by h_next or v_next links. If 0, the single chain is approximated.

This is a stand-alone approximation routine. The function cvApproxChains works exactly in the same way as cvFindContours with the corresponding approximation flag. The function returns pointer to the first resultant contour. Other approximated contours, if any, can be accessed via v_next or h_next fields of the returned structure.

### StartReadChainPoints

Initializes chain reader

    void cvStartReadChainPoints( CvChain* chain, CvChainPtReader* reader );

chain Pointer to chain. reader Chain reader state.

The function cvStartReadChainPoints initializes a special reader (see Dynamic Data Structures for more information on sets and sequences).

### ReadChainPoint

Gets next chain point

    CvPoint cvReadChainPoint( CvChainPtReader* reader );

reader
  Chain reader state.

The function cvReadChainPoint returns the current chain point and updates the reader position.

### ApproxPoly

Approximates polygonal curve(s) with desired precision

    CvSeq* cvApproxPoly( const void* srcSeq, int headerSize, CvMemStorage* storage,
                         int method, double parameter,
                         int parameter2=0 );

srcSeq
  Sequence of array of points.
headerSize
  Header size of approximated curve[s].
storage
  Container for approximated contours. If it is NULL, the input sequences' storage is used.
method
  Approximation method; only CV_POLY_APPROX_DP is supported, that corresponds to Douglas-Peucker algorithm.
parameter
  Method-specific parameter; in case of CV_POLY_APPROX_DP it is a desired approximation accuracy.
parameter2
  If case if srcSeq is sequence it means whether the single sequence should be approximated or all sequences on the same level or below srcSeq (see cvFindContours for description of hierarchical contour structures). And if srcSeq is array (CvMat*) of points, the parameter specifies whether the curve is closed (parameter2!=0) or not (parameter2=0).

The function cvApproxPoly approximates one or more curves and returns the approximation result[s]. In case of multiple curves approximation the resultant tree will have the same structure as the input one (1:1 correspondence).

### BoundingRect

Calculates up-right bounding rectangle of point set

    CvRect cvBoundingRect( CvArr* contour, int update );

contour
  Sequence or array of points.
update
  The update flag. Here is list of possible combination of the flag values and type of contour:
  - update=0, contour ~ CvContour*: the bounding rectangle is not calculated, but it is taken from rect field of the contour header.
  - update=1, contour ~ CvContour*: the bounding rectangle is calculated and written to rect field of the contour header.
  - update=0, contour ~ CvSeq* or CvMat*: the bounding rectangle is calculated and returned.
  - update=1, contour ~ CvSeq* or CvMat*: runtime error is raised.

The function cvBoundingRect returns the up-right bounding rectangle for 2d point set.

### ContourArea

Calculates area of the whole contour or contour section

    double cvContourArea( const CvArr* contour, CvSlice slice=CV_WHOLE_SEQ );

contour
  Contour (sequence or array of vertices).
slice
  Starting and ending points of the contour section of interest, by default area of the whole contour is calculated.

The function cvContourArea calculates area of the whole contour or contour section. In the latter case the total area bounded by the contour arc and the chord connecting the 2 selected points is calculated as shown on the picture below:

NOTE: Orientation of the contour affects the area sign, thus the function may return negative result. Use fabs() function from C runtime to get the absolute value of area.

### ArcLength

Calculates contour perimeter or curve length

    double cvArcLength( const void* curve, CvSlice slice=CV_WHOLE_SEQ, int isClosed=-1 );

curve
  Sequence or array of the curve points.
slice
  Starting and ending points of the curve, by default the whole curve length is calculated.
isClosed
  Indicates whether the curve is closed or not. There are 3 cases:
  - isClosed=0 - the curve is assumed to be unclosed.
  - isClosed>0 - the curve is assumed to be closed.
  - isClosed<0 - if curve is sequence, the flag CV_SEQ_FLAG_CLOSED of ((CvSeq*)curve)->flags is checked to determine if the curve is closed or not, otherwise (curve is represented by array (CvMat*) of points) it is assumed to be unclosed.

The function cvArcLength calculates length or curve as sum of lengths of segments between subsequent points

### MatchShapes

Compares two shapes

    double cvMatchShapes( const void* A, const void* B,
                          int method, double parameter=0 );

A
  First contour or grayscale image
B
  Second contour or grayscale image
method
  Comparison method, one of CV_CONTOUR_MATCH_I1, CV_CONTOURS_MATCH_I2 or CV_CONTOURS_MATCH_I3.
parameter
  Method-specific parameter (is not used now).

The function cvMatchShapes compares two shapes. The 3 implemented methods all use Hu moments (see cvGetHuMoments):

    method=CV_CONTOUR_MATCH_I1:
    I1(A,B)=sumi=1..7abs(1/mAi - 1/mBi)

    method=CV_CONTOUR_MATCH_I2:
    I2(A,B)=sumi=1..7abs(mAi - mBi)

    method=CV_CONTOUR_MATCH_I3:
    I3(A,B)=sumi=1..7abs(mAi - mBi)/abs(mAi)

    where
    mAi=sign(hAi)•log(hAi),
    mBi=sign(hBi)•log(hBi),
    hAi, hBi - Hu moments of A and B, respectively.

### CreateContourTree

Creates hierarchical representation of contour

    CvContourTree* cvCreateContourTree( cont CvSeq* contour, CvMemStorage* storage, double threshold );

contour
  Input contour.
storage
  Container for output tree.
threshold
  Approximation accuracy.

The function cvCreateContourTree creates binary tree representation for the input contour and returns the pointer to its root. If the parameter threshold is less than or equal to 0, the function creates full binary tree representation. If the threshold is greater than 0, the function creates representation with the precision threshold: if the vertices with the interceptive area of its base line are less than threshold, the tree should not be built any further. The function returns the created tree.

### ContourFromContourTree

Restores contour from tree

    CvSeq* cvContourFromContourTree( const CvContourTree* tree, CvMemStorage* storage,
                                     CvTermCriteria criteria );

tree
  Contour tree.
storage
  Container for the reconstructed contour.
criteria
  Criteria, where to stop reconstruction.

The function cvContourFromContourTree restores the contour from its binary tree representation. The parameter criteria determines the accuracy and/or the number of tree levels used for reconstruction, so it is possible to build approximated contour. The function returns reconstructed contour.

### MatchContourTrees

Compares two contours using their tree representations

    double cvMatchContourTrees( const CvContourTree* tree1, const CvContourTree* tree2,
                                CvTreeMatchMethod method, double threshold );

tree1
  First contour tree.
tree2
  Second contour tree.
method
  Similarity measure, only CV_CONTOUR_TREES_MATCH_I1 is supported.
threshold
  Similarity threshold.

The function cvMatchContourTrees calculates the value of the matching measure for two contour trees. The similarity measure is calculated level by level from the binary tree roots. If at the certain level difference between contours becomes less than threshold, the reconstruction process is interrupted and the current difference is returned.

## Geometry Functions

### MaxRect

Finds bounding rectangle for two given rectangles

    CvRect cvMaxRect( const CvRect* rect1, const CvRect* rect2 );

rect1
  First rectangle
rect2
  Second rectangle

The function cvMaxRect finds minimum area rectangle that contains both input rectangles inside:

### CvBox2D

Rotated 2D box

    typedef struct CvBox2D
    {
        CvPoint2D32f center;  /* center of the box */
        CvSize2D32f  size;    /* box width and length */
        float angle;          /* angle between the horizontal axis
                                 and the first side (i.e. length) in radians */
    }
    CvBox2D;

### BoxPoints

Finds box vertices

    void cvBoxPoints( CvBox2D box, CvPoint2D32f pt[4] );

box
  Box
pt
  Array of vertices

The function cvBoxPoints calculates vertices of the input 2d box. Here is the function code:

    void cvBoxPoints( CvBox2D box, CvPoint2D32f pt[4] )
    {
        float a = (float)cos(box.angle)*0.5f;
        float b = (float)sin(box.angle)*0.5f;

        pt[0].x = box.center.x - a*box.size.height - b*box.size.width;
        pt[0].y = box.center.y + b*box.size.height - a*box.size.width;
        pt[1].x = box.center.x + a*box.size.height - b*box.size.width;
        pt[1].y = box.center.y - b*box.size.height - a*box.size.width;
        pt[2].x = 2*box.center.x - pt[0].x;
        pt[2].y = 2*box.center.y - pt[0].y;
        pt[3].x = 2*box.center.x - pt[1].x;
        pt[3].y = 2*box.center.y - pt[1].y;
    }

### FitEllipse

Fits ellipse to set of 2D points

    CvBox2D cvFitEllipse2( const CvArr* points );

points
  Sequence or array of points.

The function cvFitEllipse calculates ellipse that fits best (in least-squares sense) to a set of 2D points. The meaning of the returned structure fields is similar to those in cvEllipse except that size stores the full lengths of the ellipse axises, not half-lengths

### FitLine

Fits line to 2D or 3D point set

    void  cvFitLine( const CvArr* points, CvDisType disType, double C,
                     double reps, double aeps, float* line );

points
  Sequence or array of 2D or 3D points with 32-bit integer or floating-point coordinates.
disType
  The distance used for fitting (see the discussion).
C
  Numerical parameter for some types of distances, if 0 then some optimal value is chosen.
reps, aeps
  Sufficient accuracy for radius (distance between the coordinate origin and the line) and angle, respectively, 0.01 would be a good defaults for both. is used.
line
  The output line parameters. In case of 2d fitting it is array of 4 floats (vx, vy, x0, y0) where (vx, vy) is a normalized vector collinear to the line and (x0, y0) is some point on the line. In case of 3D fitting it is array of 6 floats (vx, vy, vz, x0, y0, z0) where (vx, vy, vz) is a normalized vector collinear to the line and (x0, y0, z0) is some point on the line.

The function cvFitLine fits line to 2D or 3D point set by minimizing sumiρ(ri), where ri is distance between i-th point and the line and ρ(r) is a distance function, one of:

    disType=CV_DIST_L2 (L2):
    ρ(r)=r2/2 (the simplest and the fastest least-squares method)

    disType=CV_DIST_L1 (L1):
    ρ(r)=r

    disType=CV_DIST_L12 (L1-L2):
    ρ(r)=2•[sqrt(1+r2/2) - 1]

    disType=CV_DIST_FAIR (Fair):
    ρ(r)=C2•[r/C - log(1 + r/C)],  C=1.3998

    disType=CV_DIST_WELSCH (Welsch):
    ρ(r)=C2/2•[1 - exp(-(r/C)2)],  C=2.9846

    disType=CV_DIST_HUBER (Huber):
    ρ(r)= r2/2,   if r < C
          C•(r-C/2),   otherwise;   C=1.345

### ConvexHull2

Finds convex hull of points set

    CvSeq* cvConvexHull2( const void* points, void* hullStorage=0,
                          int orientation=CV_CLOCKWISE, int returnPoints=0 );

points
  Sequence or array of 2D points with 32-bit integer or floating-point coordinates.
hullStorage
  The destination array (CvMat*) or memory storage (CvMemStorage*) that will store the convex hull. If it is array, it should be 1d and have the same number of elements as the input array/sequence. On output the header is modified so to truncate the array downto the hull size.
orientation
  Desired orientation of convex hull: CV_CLOCKWISE or CV_COUNTER_CLOCKWISE.
returnPoints
  If non-zero, the points themselves will be stored in the hull instead of indices if hullStorage is array, or pointers if hullStorage is memory storage.

The function cvConvexHull2 finds convex hull of 2D point set using Sklansky's algorithm. If hullStorage is memory storage, the function creates a sequence containing the hull points or pointers to them, depending on returnPoints value and returns the sequence on output.

#### Example. Building convex hull for a sequence or array of points

    #include "cv.h"
    #include "highgui.h"
    #include <stdlib.h>

    #define ARRAY  0 /* switch between array/sequence method by replacing 0<=>1 */

    void main( int argc, char** argv )
    {
        IplImage* img = cvCreateImage( cvSize( 500, 500 ), 8, 3 );
        cvNamedWindow( "hull", 1 );

    #if !ARRAY
            CvMemStorage* storage = cvCreateMemStorage();
    #endif

        for(;;)
        {
            int i, count = rand()%100 + 1, hullcount;
            CvPoint pt0;
    #if !ARRAY
            CvSeq* ptseq = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvContour),
                                         sizeof(CvPoint), storage );
            CvSeq* hull;

            for( i = 0; i < count; i++ )
            {
                pt0.x = rand() % (img->width/2) + img->width/4;
                pt0.y = rand() % (img->height/2) + img->height/4;
                cvSeqPush( ptseq, &pt0 );
            }
            hull = cvConvexHull2( ptseq, 0, CV_CLOCKWISE, 0 );
            hullcount = hull->total;
    #else
            CvPoint* points = (CvPoint*)malloc( count * sizeof(points[0]));
            int* hull = (int*)malloc( count * sizeof(hull[0]));
            CvMat pointMat = cvMat( 1, count, CV_32SC2, points );
            CvMat hullMat = cvMat( 1, count, CV_32SC1, hull );

            for( i = 0; i < count; i++ )
            {
                pt0.x = rand() % (img->width/2) + img->width/4;
                pt0.y = rand() % (img->height/2) + img->height/4;
                points[i] = pt0;
            }
            cvConvexHull2( &pointMat, &hullMat, CV_CLOCKWISE, 0 );
            hullcount = hullMat.cols;
    #endif
            cvZero( img );
            for( i = 0; i < count; i++ )
            {
    #if !ARRAY
                pt0 = *CV_GET_SEQ_ELEM( CvPoint, ptseq, i );
    #else
                pt0 = points[i];
    #endif
                cvCircle( img, pt0, 2, CV_RGB( 255, 0, 0 ), CV_FILLED );
            }

    #if !ARRAY
            pt0 = **CV_GET_SEQ_ELEM( CvPoint*, hull, hullcount - 1 );
    #else
            pt0 = points[hull[hullcount-1]];
    #endif

            for( i = 0; i < hullcount; i++ )
            {
    #if !ARRAY
                CvPoint pt = **CV_GET_SEQ_ELEM( CvPoint*, hull, i );
    #else
                CvPoint pt = points[hull[i]];
    #endif
                cvLine( img, pt0, pt, CV_RGB( 0, 255, 0 ));
                pt0 = pt;
            }

            cvShowImage( "hull", img );

            int key = cvWaitKey(0);
            if( key == 27 ) // 'ESC'
                break;

    #if !ARRAY
            cvClearMemStorage( storage );
    #else
            free( points );
            free( hull );
    #endif
        }
    }

### CheckContourConvexity

Tests contour convex

    int cvCheckContourConvexity( const void* contour );

contour
  Tested contour (sequence or array of points).

The function cvCheckContourConvexity tests whether the input contour is convex or not. The contour must be simple, i.e. without self-intersections.

### CvConvexityDefect

Structure describing a single contour convexity detect

    typedef struct CvConvexityDefect
    {
        CvPoint* start; /* point of the contour where the defect begins */
        CvPoint* end; /* point of the contour where the defect ends */
        CvPoint* depth_point; /* the farthest from the convex hull point within the defect */
        float depth; /* distance between the farthest point and the convex hull */
    } CvConvexityDefect;

#### Picture. Convexity defects for hand contour.

### ConvexityDefects

Finds convexity defects of contour

    CvSeq* cvConvexityDefects( const void* contour, const void* convexhull,
                               CvMemStorage* storage=0 );

contour
  Input contour.
convexhull
  Convex hull obtained using cvConvexHull2 that should contain pointers or indices to the contour points, not the hull points themselves, i.e. returnPoints parameter in cvConvexHull2 should be 0.
storage
  Container for output sequence of convexity defects. If it is NULL, contour or hull (in that order) storage is used.

The function cvConvexityDefects finds all convexity defects of the input contour and returns a sequence of the CvConvexityDefect structures.

### MinAreaRect2

Finds circumscribed rectangle of minimal area for given 2D point set

    CvBox2D  cvMinAreaRect2( const void* points, CvMemStorage* storage=0 );

points
  Sequence or array of points.
storage
  Optional temporary memory storage.

The function cvMinAreaRect2 finds a circumscribed rectangle of the minimal area for 2D point set by building convex hull for the set and applying rotating calipers technique to the hull.

#### Picture. Minimal-area bounding rectangle for contour

### MinEnclosingCircle

Finds circumscribed circle of minimal area for given 2D point set

    void cvMinEnclosingCircle( const void* points, CvPoint2D32f* center, float* radius );

points
  Sequence or array of 2D points.
center
  Output parameter. The center of the enclosing circle.
radius
  Output parameter. The radius of the enclosing circle.

The function cvMinEnclosingCircle finds the minimal circumscribed circle for 2D point set using iterative algorithm.

### CalcPGH

Calculates pair-wise geometrical histogram for contour

    void cvCalcPGH( const CvSeq* contour, CvHistogram* hist );

contour
  Input contour. Currently, only integer point coordinates are allowed.
hist
  Calculated histogram; must be two-dimensional.

The function cvCalcPGH calculates 2D pair-wise geometrical histogram (PGH), described in [Iivarinen97], for the contour. The algorithm considers every pair of the contour edges. The angle between the edges and the minimum/maximum distances are determined for every pair. To do this each of the edges in turn is taken as the base, while the function loops through all the other edges. When the base edge and any other edge are considered, the minimum and maximum distances from the points on the non-base edge and line of the base edge are selected. The angle between the edges defines the row of the histogram in which all the bins that correspond to the distance between the calculated minimum and maximum distances are incremented (that is, the histogram is transposed relatively to [Iivarninen97] definition). The histogram can be used for contour matching.

[Iivarinen97] Jukka Iivarinen, Markus Peura, Jaakko Srel, and Ari Visa. Comparison of Combined Shape Descriptors for Irregular Objects, 8th British Machine Vision Conference, BMVC'97. You may find online version at http://www.cis.hut.fi/research/IA/paper/publications/bmvc97/bmvc97.html

### KMeans

Splits set of vectors by given number of clusters

    void cvKMeans2( const CvArr* samples, int numClusters,
                    CvArr* clusterIdx, CvTermCriteria termcrit );

samples
  Floating-point matrix of input samples, one row per sample.
numClusters
  Number of clusters to split the set by.
clusterIdx
  Output integer vector storing cluster indices for every sample.
termcrit
  Specifies maximum number of iterations and/or accuracy (distance the centers move by between the subsequent iterations).

The function cvKMeans2 implements k-means algorithm that finds centers of numClusters clusters and groups the input samples around the clusters. On output clusterIdx(i) contains a cluster index for sample stored in i-th rows of samples.

#### Example. Clustering random samples of multi-gaussian distribution with k-means

    #include "cv.h"
    #include "highgui.h"

    void main( int argc, char** argv )
    {
        #define MAX_CLUSTERS 5
        static const int color_tab[MAX_CLUSTERS] =
        {
            CV_RGB(255,0,0), CV_RGB(0,255,0), CV_RGB(100,100,255),
            CV_RGB(255,0,255), CV_RGB(255,255,0)
        };
        IplImage* img = cvCreateImage( cvSize( 500, 500 ), 8, 3 );
        CvRandState rng;
        cvRandInit( &rng, 0, 1, -1, CV_RAND_NORMAL );

        cvNamedWindow( "clusters", 1 );

        for(;;)
        {
            int k, cluster_count = cvRandNext(&rng)%MAX_CLUSTERS + 1;
            int i, sample_count = cvRandNext(&rng)%1000 + 1;
            CvMat* points = cvCreateMat( sample_count, 1, CV_32FC2 );
            CvMat* clusters = cvCreateMat( sample_count, 1, CV_32SC1 );

            /* generate random sample from multigaussian distribution */
            for( k = 0; k < cluster_count; k++ )
            {
                CvPoint center;
                CvMat point_chunk;
                center.x = cvRandNext(&rng)%img->width;
                center.y = cvRandNext(&rng)%img->height;
                cvRandSetRange( &rng, center.x, img->width/6, 0 );
                cvRandSetRange( &rng, center.y, img->height/6, 1 );
                cvGetRows( points, &point_chunk, k*sample_count/cluster_count,
                           k == cluster_count - 1 ? sample_count : (k+1)*sample_count/cluster_count );

                cvRand( &rng, &point_chunk );
            }

            /* shuffle samples */
            for( i = 0; i < sample_count/2; i++ )
            {
                CvPoint2D32f* pt1 = (CvPoint2D32f*)points->data.fl + cvRandNext(&rng)%sample_count;
                CvPoint2D32f* pt2 = (CvPoint2D32f*)points->data.fl + cvRandNext(&rng)%sample_count;
                CvPoint2D32f temp;
                CV_SWAP( *pt1, *pt2, temp );
            }

            cvKMeans2( points, cluster_count, clusters,
                       cvTermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0 ));

            cvZero( img );

            for( i = 0; i < sample_count; i++ )
            {
                CvPoint2D32f pt = ((CvPoint2D32f*)points->data.fl)[i];
                int cluster_idx = clusters->data.i[i];
                cvCircle( img, cvPointFrom32f(pt), 2, color_tab[cluster_idx], CV_FILLED );
            }

            cvReleaseMat( &points );
            cvReleaseMat( &clusters );

            cvShowImage( "clusters", img );

            int key = cvWaitKey(0);
            if( key == 27 ) // 'ESC'
                break;
        }
    }

### MinEnclosingCircle

Finds circumscribed circle of minimal area for given 2D point set

    void cvMinEnclosingCircle( const void* points, CvPoint2D32f* center, float* radius );

points
  Sequence or array of 2D points.
center
  Output parameter. The center of the enclosing circle.
radius
  Output parameter. The radius of the enclosing circle.

The function cvMinEnclosingCircle finds the minimal circumscribed circle for 2D point set using iterative algorithm.

## Planar Subdivisions

### CvSubdiv2D

Planar subdivision

    #define CV_SUBDIV2D_FIELDS()    \
        CV_GRAPH_FIELDS()           \
        int  quad_edges;            \
        int  is_geometry_valid;     \
        CvSubdiv2DEdge recent_edge; \
        CvPoint2D32f  topleft;      \
        CvPoint2D32f  bottomright;

    typedef struct CvSubdiv2D
    {
        CV_SUBDIV2D_FIELDS()
    }
    CvSubdiv2D;

Planar subdivision is a subdivision of a plane into a set of non-overlapped regions (facets) that cover the whole plane. The above structure describes a subdivision built on 2d point set, where the points are linked together and form a planar graph, which, together with a few edges connecting exterior subdivision points (namely, convex hull points) with infinity, subdivides a plane into facets by its edges.

For every subdivision there exists dual subdivision there facets and points (subdivision vertices) swap their roles, that is, a facet is treated as a vertex (called virtual point below) of dual subdivision and the original subdivision vertices become facets. On the picture below original subdivision is marked with solid lines and dual subdivision with dot lines

OpenCV subdivides plane into triangles using Delaunay's algorithm. Subdivision is built iteratively starting from a dummy triangle that includes all the subdivision points for sure. In this case the dual subdivision is Voronoi diagram of input 2d point set. The subdivisions can be used for 3d piece-wise transformation of a plane, morphing, fast location of points on the plane, building special graphs (such as NNG,RNG) etc.

### CvQuadEdge2D

Quad-edge of planar subdivision

    /* one of edges within quad-edge, lower 2 bits is index (0..3)
       and upper bits are quad-edge pointer */
    typedef long CvSubdiv2DEdge;

    /* quad-edge structure fields */
    #define CV_QUADEDGE2D_FIELDS()     \
        int flags;                     \
        struct CvSubdiv2DPoint* pt[4]; \
        CvSubdiv2DEdge  next[4];

    typedef struct CvQuadEdge2D
    {
        CV_QUADEDGE2D_FIELDS()
    }
    CvQuadEdge2D;

Quad-edge is a basic element of subdivision, it contains four edges (e, eRot and reversed e & eRot):

### CvSubdiv2DPoint

Point of original or dual subdivision

    #define CV_SUBDIV2D_POINT_FIELDS()\
        int            flags;      \
        CvSubdiv2DEdge first;      \
        CvPoint2D32f   pt;

    #define CV_SUBDIV2D_VIRTUAL_POINT_FLAG (1 << 30)

    typedef struct CvSubdiv2DPoint
    {
        CV_SUBDIV2D_POINT_FIELDS()
    }
    CvSubdiv2DPoint;

### Subdiv2DGetEdge

Returns one of edges related to given

    CvSubdiv2DEdge  cvSubdiv2DGetEdge( CvSubdiv2DEdge edge, CvNextEdgeType type );
    #define cvSubdiv2DNextEdge( edge ) cvSubdiv2DGetEdge( edge, CV_NEXT_AROUND_ORG )

edge
  Subdivision edge (not a quad-edge)
type
  Specifies, which of related edges to return, one of:
  - CV_NEXT_AROUND_ORG - next around the edge origin (eOnext on the picture above if e is the input edge)
  - CV_NEXT_AROUND_DST - next around the edge vertex (eDnext)
  - CV_PREV_AROUND_ORG - previous around the edge origin (reversed eRnext)
  - CV_PREV_AROUND_DST - previous around the edge destination (reversed eLnext)
  - CV_NEXT_AROUND_LEFT - next around the left facet (eLnext)
  - CV_NEXT_AROUND_RIGHT - next around the right facet (eRnext)
  - CV_PREV_AROUND_LEFT - previous around the left facet (reversed eOnext)
  - CV_PREV_AROUND_RIGHT - previous around the right facet (reversed eDnext)

The function cvSubdiv2DGetEdge returns one the edges related to the input edge.

### Subdiv2DRotateEdge

Returns another edge of the same quad-edge

    CvSubdiv2DEdge  cvSubdiv2DRotateEdge( CvSubdiv2DEdge edge, int rotate );

edge
  Subdivision edge (not a quad-edge)
type
  Specifies, which of edges of the same quad-edge as the input one to return, one of:
  - 0 - the input edge (e on the picture above if e is the input edge)
  - 1 - the rotated edge (eRot)
  - 2 - the reversed edge (reversed e (in green))
  - 3 - the reversed rotated edge (reversed eRot (in green))

The function cvSubdiv2DRotateEdge returns one the edges of the same quad-edge as the input edge.

### Subdiv2DEdgeOrg

Returns edge origin

    CvSubdiv2DPoint* cvSubdiv2DEdgeOrg( CvSubdiv2DEdge edge );

edge
  Subdivision edge (not a quad-edge)

The function cvSubdiv2DEdgeOrg returns the edge origin. The returned pointer may be NULL if the edge is from dual subdivision and the virtual point coordinates are not calculated yet. The virtual points can be calculated using function cvCalcSubdivVoronoi2D.

### Subdiv2DEdgeDst

Returns edge destination

    CvSubdiv2DPoint* cvSubdiv2DEdgeDst( CvSubdiv2DEdge edge );

edge
  Subdivision edge (not a quad-edge)

The function cvSubdiv2DEdgeDst returns the edge destination. The returned pointer may be NULL if the edge is from dual subdivision and the virtual point coordinates are not calculated yet. The virtual points can be calculated using function cvCalcSubdivVoronoi2D.

### CreateSubdivDelaunay2D

Creates empty Delaunay triangulation

    CvSubdiv2D* cvCreateSubdivDelaunay2D( CvRect rect, CvMemStorage* storage );

rect
  Rectangle that includes all the 2d points that are to be added to subdivision.
storage
  Container for subdivision.

The function cvCreateSubdivDelaunay2D creates an empty Delaunay subdivision, where 2d points can be added further using function cvSubdivDelaunay2DInsert. All the points to be added must be within the specified rectangle, otherwise a runtime error will be raised.

### SubdivDelaunay2DInsert

Inserts a single point to Delaunay triangulation

    CvSubdiv2DPoint*  cvSubdivDelaunay2DInsert( CvSubdiv2D* subdiv, CvPoint2D32f pt);

subdiv
  Delaunay subdivision created by function cvCreateSubdivDelaunay2D.
pt
  Inserted point.

The function cvSubdivDelaunay2DInsert inserts a single point to subdivision and modifies the subdivision topology appropriately. If a points with same coordinates exists already, no new points is added. The function returns pointer to the allocated point. No virtual points coordinates is calculated at this stage.

### Subdiv2DLocate

Inserts a single point to Delaunay triangulation

    CvSubdiv2DPointLocation  cvSubdiv2DLocate( CvSubdiv2D* subdiv, CvPoint2D32f pt,
                                               CvSubdiv2DEdge *edge,
                                               CvSubdiv2DPoint** vertex=0 );

subdiv
  Delaunay or another subdivision.
pt
  The point to locate.
edge
  The output edge the point falls onto or right to.
vertex
  Optional output vertex double pointer the input point coinsides with.

The function cvSubdiv2DLocate locates input point within subdivision. There are 5 cases:

- point falls into some facet. The function returns CV_PTLOC_INSIDE and *edge will contain one of edges of the facet.
- point falls onto the edge. The function returns CV_PTLOC_ON_EDGE and *edge will contain this edge.
- point coinsides with one of subdivision vertices. The function returns CV_PTLOC_VERTEX and *vertex will contain pointer to the vertex.
- point is outside the subdivsion reference rectangle. The function returns CV_PTLOC_OUTSIDE_RECT and no pointers is filled.
- one of input arguments is invalid. Runtime error is raised or, if silent or "parent" error processing mode is selected, CV_PTLOC_ERROR is returnd.

### FindNearestPoint2D

Finds the closest subdivision vertex to given point

    CvSubdiv2DPoint* cvFindNearestPoint2D( CvSubdiv2D* subdiv, CvPoint2D32f pt );

subdiv
  Delaunay or another subdivision.
pt
  Input point.

The function cvFindNearestPoint2D is another function that locates input point within subdivision. It finds subdivision vertex that is the closest to the input point. It is not necessarily one of vertices of the facet containing the input point, though the facet (located using cvSubdiv2DLocate) is used as a starting point. The function returns pointer to the found subdivision vertex

### CalcSubdivVoronoi2D

Calculates coordinates of Voronoi diagram cells

    void cvCalcSubdivVoronoi2D( CvSubdiv2D* subdiv );

subdiv
  Delaunay subdivision, where all the points are added already.

The function cvCalcSubdivVoronoi2D calculates coordinates of virtual points. All virtual points corresponding to some vertex of original subdivision form (when connected together) a boundary of Voronoi cell of that point.

### ClearSubdivVoronoi2D

Removes all virtual points

    void cvClearSubdivVoronoi2D( CvSubdiv2D* subdiv );

subdiv
  Delaunay subdivision.

The function cvClearSubdivVoronoi2D removes all virtual points. It is called internally in cvCalcSubdivVoronoi2D if the subdivision was modified after previous call to the function.

There are a few other lower-level functions that work with planar subdivisions, see cv.h and the sources. Demo script delaunay.c that builds Delaunay triangulation and Voronoi diagram of random 2d point set can be found at opencv/samples/c.