CGAL学习之路(二):平面点凸包(Convex Hull)提取

1 凸包问题

简单来说,给定一组平面上的点,求一个包含所有点的最小凸多边形,就是凸包问题。

凸包_百度百科 (baidu.com)对凸包的解释如下:

凸包(Convex Hull)是一个计算几何(图形学)中的概念。

在一个实数向量空间V中,对于给定集合X,所有包含X的凸集交集S被称为X的凸包。X的凸包可以用X内所有点(X1,…Xn)的凸组合来构造.

在二维欧几里得空间中,凸包可想象为一条刚好包著所有点的橡皮圈。

用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边形,它能包含点集中所有的点。

关于凸包的一些博客:

凸包详解_唐宋元明清的博客-CSDN博客_凸包

凸包 —— 五种解法_lxt_Lucia的博客-CSDN博客_凸包

扫描二维码关注公众号,回复: 13741356 查看本文章

2 代码实现

计算一组点的二维凸包,并输出凸包点坐标。

如下图:绿色点为凸包点,红色点为凸包内的点,紫色线为凸包轮廓。
在这里插入图片描述

2.1 在数组Array中提取凸包点

代码:

#include <iostream>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/convex_hull_2.h>

typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::Point_2 Point_2;

int main()
{
    
    
	//定义二维点数组,并赋初值
	Point_2 points[10] = {
    
     Point_2(1,1),Point_2(2,5), Point_2(3,2),Point_2(4,1), Point_2(5,5),Point_2(5,7),Point_2(6,3),Point_2(7,5), Point_2(8,2), Point_2(10,4) };

	//定义凸包点数组,用于接收提取的凸包点
	Point_2 result[10];

	//执行凸包提取
	Point_2 *ptr = CGAL::convex_hull_2(points, points + 10, result);

	//输出凸包点
	std::cout << ptr - result << " 个凸包点:" << std::endl;
	for (int i = 0; i < ptr - result; i++) {
    
    
		std::cout << result[i] << std::endl;
	}

	return 0;
}

输出结果:

6 个凸包点:
1 1
4 1
8 2
10 4
5 7
2 5

凸包函数convex_hull_2说明:

convex_hull_2(ForwardIterator first, ForwardIterator last,
              OutputIterator  result )
{
    
    
    return convex_hull_points_2(first, last, result);
}

凸包函数convex_hull_2接受三个参数。前两个为输入参数,分别为输入数组points的起始指针和结束指针;第三个参数为输出参数,是结果数组result的起始指针。函数将指针返回到结果数组中,就在最后一个写入的凸包点后面(下图用虚线框表示),由ptr接收,因此指针差ptr-result告诉我们凸包上有多少个点。

在这里插入图片描述

2.2 在向量Vector中提取凸包点

下面使用STL标准模板库中的vector代替数组,进行凸包提取

代码:

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/convex_hull_2.h>
#include <vector>

typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::Point_2 Point_2;
typedef std::vector<Point_2> Points;

int main()
{
    
    
	Points points;	//输入向量
	points.push_back(Point_2(1, 1));
	points.push_back(Point_2(2, 5));
	points.push_back(Point_2(3, 2));
	points.push_back(Point_2(4, 1));
	points.push_back(Point_2(5, 5));
	points.push_back(Point_2(5, 7));
	points.push_back(Point_2(6, 3));
	points.push_back(Point_2(7, 5));
	points.push_back(Point_2(8, 2));
	points.push_back(Point_2(10, 4));

	Points result;	//凸包向量
	CGAL::convex_hull_2(points.begin(), points.end(), std::back_inserter(result));
	std::cout << result.size() << "个凸包点" << std::endl;
	for (auto val : result)
	{
    
    
		std::cout << val << std::endl;
	}
	return 0;
}

输出结果:

6个凸包点
1 1
4 1
8 2
10 4
5 7
2 5

使用Array和使用Vector,两种方式结果一致,但后者更加简洁。

猜你喜欢

转载自blog.csdn.net/weixin_46098577/article/details/122620862