让我们考虑使用 CGAL 的二维约束 Delaunay 三角剖分。
在这个小例子中,我考虑了一组由 5 个 5 个点组成的正方形。点的“内部正方形”将在三角剖分中受到约束。
我需要在 CGAL 的脸上存储一些数据。我用这个
Triangulation_face_base_with_info_2
。在下面的代码片段中,数据只是一个double
,如果我们在“内部正方形”内则为 1,否则为 0,在我的实际项目中,这是一个计算成本更高的数据。
在代码片段的第一步中,三角测量和数据被初始化,我们得到以下内容(红色 -> 1,紫色 -> 0):
现在让我们在“内部正方形”内添加一个点,看看存储的数据发生了什么:
编辑:现在让我们删除中心的点:
现在问题来了:有没有一种方法,当adding or removing a point from the triangulation, to obtain modified faces list to update their data (stored in a face's info) and keep the old data in未修改的面孔,而不是再次遍历整个面孔列表(这会很昂贵)?
#include <iostream>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Triangulation_face_base_with_info_2.h>
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
#include <CGAL/Delaunay_mesh_face_base_2.h>
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
struct FaceInfo
{
double superComplexData = 0.0;
};
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::FT FT;
typedef CGAL::Triangulation_face_base_with_info_2<FaceInfo, K> Fb2;
typedef CGAL::Triangulation_vertex_base_with_info_2<std::size_t, K> Vb2;
typedef CGAL::Constrained_triangulation_face_base_2<K, Fb2> CFb2;
typedef CGAL::Triangulation_data_structure_2<Vb2,CFb2> Tds2;
typedef CGAL::Constrained_Delaunay_triangulation_2<K,Tds2> Triangulation_2;
typedef K::Point_2 Point_2;
int main()
{
// Part 0: initialize the triangulation
std::vector<std::pair<Point_2, std::size_t>> pointsList {
//Outer points
{Point_2(0.0, 0.0), 0},
{Point_2(1.0, 0.0), 1},
{Point_2(2.0, 0.0), 2},
{Point_2(3.0, 0.0), 3},
{Point_2(4.0, 0.0), 4},
{Point_2(0.0, 1.0), 5},
{Point_2(0.0, 2.0), 6},
{Point_2(0.0, 3.0), 7},
{Point_2(0.0, 4.0), 8},
{Point_2(1.0, 4.0), 9},
{Point_2(2.0, 4.0), 10},
{Point_2(3.0, 4.0), 11},
{Point_2(4.0, 4.0), 12},
{Point_2(4.0, 3.0), 13},
{Point_2(4.0, 2.0), 14},
{Point_2(4.0, 1.0), 15},
//Inner points (constraint)
{Point_2(1.0, 1.0), 16},
{Point_2(2.0, 1.0), 17},
{Point_2(3.0, 1.0), 18},
{Point_2(1.0, 2.0), 19},
{Point_2(1.0, 3.0), 20},
{Point_2(2.0, 3.0), 21},
{Point_2(3.0, 3.0), 22},
{Point_2(3.0, 2.0), 23},
{Point_2(3.0, 1.0), 24},
//Center point
{Point_2(2.0, 2.0), 25}
};
std::vector<std::pair<Point_2, Point_2>> constraintsList {
{Point_2(1.0, 1.0), Point_2(2.0, 1.0)},
{Point_2(2.0, 1.0), Point_2(3.0, 1.0)},
{Point_2(3.0, 1.0), Point_2(3.0, 2.0)},
{Point_2(3.0, 2.0), Point_2(3.0, 3.0)},
{Point_2(3.0, 3.0), Point_2(2.0, 3.0)},
{Point_2(2.0, 3.0), Point_2(1.0, 3.0)},
{Point_2(1.0, 3.0), Point_2(1.0, 2.0)},
{Point_2(1.0, 2.0), Point_2(1.0, 1.0)},
};
Triangulation_2 cdt;
cdt.insert_constraints(constraintsList.begin(), constraintsList.end());
cdt.insert(pointsList.begin(), pointsList.end());
// Part 1: face data is 1 inside the "inner square"
for(auto fit = cdt.finite_faces_begin(); fit < cdt.finite_faces_end() ; ++fit)
{
Triangulation_2::Face_handle face {fit};
Point_2 centroid = CGAL::centroid(face->vertex(0)->point(), face->vertex(1)->point(), face->vertex(2)->point());
if(centroid.x() > 1.0 && centroid.x() < 3.0 && centroid.y() > 1.0 && centroid.y() < 3.0)
face->info().superComplexData = 1.0; //Normally super complex function
}
std::size_t counter = 0;
for(auto fit = cdt.finite_faces_begin(); fit < cdt.finite_faces_end() ; ++fit)
{
Triangulation_2::Face_handle face {fit};
std::cout << counter<< ": " << face->info().superComplexData << ": "
<< face->vertex(0)->point() << ", " << face->vertex(1)->point() << ", " << face->vertex(2)->point() << ", " << std::endl;
counter++;
}
// Part 2: add point and check face data
Point_2 pointToAdd = Point_2(1.5, 1.5);
Triangulation_2::Vertex_handle vh = cdt.insert(pointToAdd);
vh->info() = pointsList.size();
pointsList.push_back({pointToAdd, vh->info()});
// EDIT: Part 3: remove point at he center
for(auto vit = cdt.finite_vertices_begin() ; vit < cdt.finite_vertices_end() ; ++vit)
{
if(vit->point().x() > 1.9 && vit->point().x() < 2.1 && vit->point().y() > 1.9 && vit->point().y() < 2.1)
cdt.remove(vit);
}
counter = 0;
for(auto fit = cdt.finite_faces_begin(); fit < cdt.finite_faces_end() ; ++fit)
{
Triangulation_2::Face_handle face {fit};
std::cout << counter<< ": " << face->info().superComplexData << ": "
<< face->vertex(0)->point() << ", " << face->vertex(1)->point() << ", " << face->vertex(2)->point() << ", " << std::endl;
counter++;
}
return 0;
}