[CGAL]带岛多边形三角化

Posted 岁寒然后知松柏之后凋也!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CGAL]带岛多边形三角化相关的知识,希望对你有一定的参考价值。

CGAL带岛多边形三角化,并输出(*.ply)格式的模型

模型输出的关键是节点和索引

#include <CGAL/Triangulation_vertex_base_with_id_2.h>
#include <CGAL/Triangulation_face_base_with_info_2.h>

因此注意这两个泛型,对比不带信息的

#include <CGAL/Triangulation_vertex_base_2.h>
#include <CGAL/Triangulation_face_base_2.h>,这两个增加了部分信息作为拓展。

这样Vertex_handle就可以读取这部分拓展的信息。

心得:CGAL的泛型机制真的很强大,拓展性很好。

// AxModelDelaunay.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "shapefil.h"

#include "CGAL/exceptions.h"
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
#include <CGAL/Triangulation_vertex_base_with_id_2.h>
#include <CGAL/Triangulation_face_base_with_info_2.h>
#include <CGAL/Polygon_2.h>
#include <iostream>
struct FaceInfo2
{
    FaceInfo2(){}
    int nesting_level;
    bool in_domain()
    {
        return nesting_level % 2 == 1;
    }
};

typedef CGAL::Exact_predicates_inexact_constructions_kernel       K;
typedef CGAL::Triangulation_vertex_base_with_id_2<K>        Vb;
typedef CGAL::Triangulation_face_base_with_info_2<FaceInfo2, K>    Fbb;
typedef CGAL::Constrained_triangulation_face_base_2<K, Fbb>        Fb;
typedef CGAL::Triangulation_data_structure_2<Vb, Fb>               TDS;
typedef CGAL::Exact_predicates_tag                                Itag;
typedef CGAL::Constrained_Delaunay_triangulation_2<K, TDS, Itag>  CDT;
typedef CDT::Point                                                Point;
typedef CGAL::Polygon_2<K>                                        Polygon_2;
typedef CDT::Vertex_handle    Vertex_handle;

void mark_domains(CDT& ct, CDT::Face_handle start, int index, std::list<CDT::Edge>& border)
{
    if (start->info().nesting_level != -1){
        return;
    }
    std::list<CDT::Face_handle> queue;
    queue.push_back(start);
    while (!queue.empty()){
        CDT::Face_handle fh = queue.front();
        queue.pop_front();
        if (fh->info().nesting_level == -1){
            fh->info().nesting_level = index;
            for (int i = 0; i < 3; i++){
                CDT::Edge e(fh, i);
                CDT::Face_handle n = fh->neighbor(i);
                if (n->info().nesting_level == -1){
                    if (ct.is_constrained(e)) border.push_back(e);
                    else queue.push_back(n);
                }
            }
        }
    }
}
//explore set of facets connected with non constrained edges,
//and attribute to each such set a nesting level.
//We start from facets incident to the infinite vertex, with a nesting
//level of 0. Then we recursively consider the non-explored facets incident 
//to constrained edges bounding the former set and increase the nesting level by 1.
//Facets in the domain are those with an odd nesting level.
void mark_domains(CDT& cdt)
{
    for (CDT::All_faces_iterator it = cdt.all_faces_begin(); it != cdt.all_faces_end(); ++it){
        it->info().nesting_level = -1;
    }
    std::list<CDT::Edge> border;
    mark_domains(cdt, cdt.infinite_face(), 0, border);
    while (!border.empty()){
        CDT::Edge e = border.front();
        border.pop_front();
        CDT::Face_handle n = e.first->neighbor(e.second);
        if (n->info().nesting_level == -1){
            mark_domains(cdt, n, e.first->info().nesting_level + 1, border);
        }
    }
}


int _tmain(int argc, _TCHAR* argv[])
{
    //读取shp
    const char * pszShapeFile = "data\\\\walltest.shp";
    SHPHandle hShp = SHPOpen(pszShapeFile, "r");
    int nShapeType, nVertices;
    int nEntities = 0;
    double* minB = new double[4];
    double* maxB = new double[4];
    SHPGetInfo(hShp, &nEntities, &nShapeType, minB, maxB);
    printf("ShapeType:%d\\n", nShapeType);
    printf("Entities:%d\\n", nEntities);
    CDT cdt;
    for (int i = 0; i < nEntities; i++)
    {
        int iShape = i;
        SHPObject *obj = SHPReadObject(hShp, iShape);
        printf("--------------Feature:%d------------\\n", iShape);
        int parts = obj->nParts;
        int* partStart = obj->panPartStart;
        int verts = obj->nVertices;
        printf("nParts:%d\\n", parts);
        printf("nVertices:%d\\n", verts);
        for (int k = 0; k < parts; k++)
        {
            Polygon_2 polygon1;
            int fromIdx = partStart[k];
            int toIdx = fromIdx;
            if (k<parts-1)
            {
                toIdx = partStart[k + 1];
            }
            else
            {
                toIdx = verts;
            }
            
            for (size_t j = fromIdx; j < toIdx; j++)
            {
                double x = obj->padfX[j];
                double y = obj->padfY[j];
                //Point_2 pt(x, y);
                printf("%f,%f;", x, y);
                polygon1.push_back(Point(x, y));

            }
            cdt.insert_constraint(polygon1.vertices_begin(), polygon1.vertices_end(), true);
        }
        printf("\\n");
    }

    //construct two non-intersecting nested polygons  
    //Polygon_2 polygon1;
    //polygon1.push_back(Point(0, 0));
    //polygon1.push_back(Point(2, 0));
    //polygon1.push_back(Point(2, 2));
    //polygon1.push_back(Point(0, 2));
    //Polygon_2 polygon2;
    //polygon2.push_back(Point(0.5, 0.5));
    //polygon2.push_back(Point(1.5, 0.5));
    //polygon2.push_back(Point(1.5, 1.5));
    //polygon2.push_back(Point(0.5, 1.5));

    ////Insert the polygons into a constrained triangulation
    //CDT cdt;
    //cdt.insert_constraint(polygon1.vertices_begin(), polygon1.vertices_end(), true);
    //cdt.insert_constraint(polygon2.vertices_begin(), polygon2.vertices_end(), true);

    //Mark facets that are inside the domain bounded by the polygon
    mark_domains(cdt);
    FILE *ply = fopen("data\\\\floorpeint.ply", "w");
    
    int idx = 0;
    for (CDT::Vertex_iterator v = cdt.vertices_begin(); v != cdt.vertices_end(); ++v)
    {
        Vertex_handle vv = v->handle();
        vv->id() = idx;
        idx++;
    }

    int count = 0;
    for (CDT::Finite_faces_iterator fit = cdt.finite_faces_begin();
        fit != cdt.finite_faces_end(); ++fit)
    {
        if (fit->info().in_domain())
        {
            ++count;
            for (int i = 0; i < 3; i++)
            {
                Vertex_handle vert = fit->vertex(i);
                int x=vert->id();
                std::cout << "The Id is " << x << std::endl;
                CDT::Edge ed(fit, i);
                ed.second;
            }
        }
            
    }
    if (ply)
    {
        fprintf(ply, "ply\\nformat %s 1.0\\n", "ascii");
        fprintf(ply, "element vertex %d\\n",idx );
        fprintf(ply, "property float x\\n");
        fprintf(ply, "property float y\\n");
        fprintf(ply, "property float z\\n");
        fprintf(ply, "element face %d\\n", count);
        fprintf(ply, "property list uint8 int32 vertex_indices\\n");
        fprintf(ply, "end_header\\n");

        for (CDT::Vertex_iterator v = cdt.vertices_begin(); v != cdt.vertices_end(); ++v)
        {
            Vertex_handle vv = v->handle();
            double x = vv->point().x();
            double y = vv->point().y();
            fprintf(ply, "%f %f %f\\n", x, y, 0.0);
        }
        for (CDT::Finite_faces_iterator fit = cdt.finite_faces_begin();    fit != cdt.finite_faces_end(); ++fit)
        {
            if (fit->info().in_domain())
            {

                Vertex_handle vertId0 = fit->vertex(0);
                Vertex_handle vertId1 = fit->vertex(1);
                Vertex_handle vertId2 = fit->vertex(2);
                int id0 = vertId0->id();
                int id1 = vertId1->id();
                int id2 = vertId2->id();
                fprintf(ply, "%d %d %d %d\\n", 3, id0, id1, id2);
            }

        }
    }

    std::cout << "There are " << count << " facets in the domain." << std::endl;
    system("pause");
    return 0;
}
View Code

效果图

 

以上是关于[CGAL]带岛多边形三角化的主要内容,如果未能解决你的问题,请参考以下文章

使用耳切法将多边形三角化转

基于CGAL的Delaunay三角网应用

为啥保守光栅化无法为某些三角形调用片段着色器?

PCL源码分析:Ear Clipping三角化算法(阅读经典)

如何在 CGAL 中将三角测量对象(Constrained_Delaunay_triangulation_2)保存到文件(vtk、vtu、msh 等)

网格到网格交叉点