delaunay细分和 Voronoi细分的创建和遍历

#include 
#include 
#include "opencv2/highgui/highgui.hpp"
#include
#include
#include 
using namespace std;
using namespace cv;
static CvSubdiv2D* init_delaunay(CvMemStorage* storage,//初始化三角剖分结构,为其分配单元
    CvRect rect)
{
    CvSubdiv2D* subdiv;//三角剖分的数据单元

    subdiv = cvCreateSubdiv2D(CV_SEQ_KIND_SUBDIV2D, sizeof(*subdiv),
        sizeof(CvSubdiv2DPoint),
        sizeof(CvQuadEdge2D),
        storage);
    cvInitSubdivDelaunay2D(subdiv, rect);

    return subdiv;
}


static void draw_subdiv_point(IplImage* img, CvPoint2D32f fp, CvScalar color)//画出三角剖分的顶点
{
    cvCircle(img, cvPoint(cvRound(fp.x), cvRound(fp.y)), 5, color, CV_FILLED, 8, 0);
}


static void draw_subdiv_edge(IplImage* img, CvSubdiv2DEdge edge, CvScalar color)//画出三角剖分的边
{
    CvSubdiv2DPoint* org_pt;//源顶点
    CvSubdiv2DPoint* dst_pt;//目地顶点
    CvPoint2D32f org;
    CvPoint2D32f dst;
    CvPoint iorg, idst;

    org_pt = cvSubdiv2DEdgeOrg(edge);//通过边获取顶点
    dst_pt = cvSubdiv2DEdgeDst(edge);

    if (org_pt && dst_pt)//如果两个端点不为空
    {
        org = org_pt->pt;
        dst = dst_pt->pt;

        iorg = cvPoint(cvRound(org.x), cvRound(org.y));
        idst = cvPoint(cvRound(dst.x), cvRound(dst.y));

        cvLine(img, iorg, idst, color, 1, CV_AA, 0);
    }
}


static void draw_subdiv(IplImage* img, CvSubdiv2D* subdiv,
    CvScalar delaunay_color, CvScalar voronoi_color)//画出剖分和细分
{
    CvSeqReader  reader;
    int i, total = subdiv->edges->total;//边的数量
    int elem_size = subdiv->edges->elem_size;//边的大小
    cout << typeid(subdiv->edges).name() << endl;

    cvStartReadSeq((CvSeq*)(subdiv->edges), &reader, 0);//使用CvSeqReader遍历Delaunay或者Voronoi边

    for (i = 0; i < total; i++)
    {
        CvQuadEdge2D* edge = (CvQuadEdge2D*)(reader.ptr);

        if (CV_IS_SET_ELEM(edge))
        {
            // draw_subdiv_edge( img, (CvSubdiv2DEdge)edge + 1, voronoi_color );
            draw_subdiv_edge(img, (CvSubdiv2DEdge)edge, delaunay_color);
        }

        CV_NEXT_SEQ_ELEM(elem_size, reader);
    }

}


static void locate_point(CvSubdiv2D* subdiv, CvPoint2D32f fp, IplImage* img,//遍历三角剖分的边
    CvScalar active_color)
{
    CvSubdiv2DEdge e;
    CvSubdiv2DEdge e0 = 0;
    CvSubdiv2DPoint* p = 0;

    cvSubdiv2DLocate(subdiv, fp, &e0, &p);

    if (e0)
    {
        e = e0;
        do
        {
            draw_subdiv_edge(img, e, active_color);
            e = cvSubdiv2DGetEdge(e, CV_NEXT_AROUND_LEFT);
        } while (e != e0);
    }

    draw_subdiv_point(img, fp, active_color);
}

//@author andme-单目视觉
void dashLine(Mat &img, Point2d& pt1, Point2d& pt2, int n)//n为虚线段数
{
    Point sub = pt2 - pt1;
    for (int i = 0; i < 2 * n; i += 2)
    {
        line(img, Point(pt1.x + sub.x * i / (2 * n - 1), pt1.y + sub.y * i / (2 * n - 1)), Point(pt1.x + sub.x * (i + 1) / (2 * n - 1), pt1.y + sub.y * (i + 1) / (2 * n - 1)), Scalar(0, 255, 0), 2);
    }
}



//调用形式draw_subdiv_facet( img, cvSubdiv2DRotateEdge( e, 1 ));
static void draw_subdiv_facet(IplImage* img, CvSubdiv2DEdge edge)//画出voronoi面   
{
    //cout< points;
    for (i = 0; i < 5; i++)
    {
        CvPoint2D32f fp = cvPoint2D32f((float)(rand() % (rect.width - 10)),//使点约束在距离边框10像素之内。
            (float)(rand() % (rect.height - 10)));
        points.push_back(fp);

        locate_point(subdiv, fp, img, active_facet_color);//定位点的位置,并画出点所在delaunay面的边。
        cvShowImage(win, img);//刷新显示

    /*  if (cvWaitKey(100) >= 0)
            break;*/ 
        //cvWaitKey(0);

        cvSubdivDelaunay2DInsert(subdiv, fp);//向三角剖分中插入该点,即对该点进行三角剖分
        cvCalcSubdivVoronoi2D(subdiv);//计算Voronoi细分,有时候我们不需要
        cvSet(img, bkgnd_color, 0);//设置图像的背景颜色为白色
        draw_subdiv(img, subdiv, delaunay_color, voronoi_color);
        cvShowImage(win, img);

        //cvWaitKey();
        /*if (cvWaitKey(100) >= 0)
            break;*/
        //cvWaitKey(0);
    }
    for (int i = 0; i

你可能感兴趣的:(delaunay细分和 Voronoi细分的创建和遍历)