2D 凸包-2D Convex Hulls

18 篇文章 1 订阅
14 篇文章 7 订阅

2D 凸包-2D Convex Hulls

本章描述了CGAL中用于生成二维凸包的函数,以及用于检查点集是否为强凸的函数。还有许多用于计算特殊极值点和包点子序列的函数,如一组点的下包和上包。

CGAL提供了几种经典算法的实现,用于计算二维点集的逆时针极值点序列(即凸包上的逆时针极值点序列)。这两种算法的渐近运行时间不同,所需的几何基元集也略有不同。因此,可以选择最适合设置的算法。
在这里插入图片描述

点序列(数组)的凸包

有一个包含5个点的数组作为输入。由于这些点的凸包是输入的子集,因此可以提供一个大小相同的数组来存储结果。

#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[5] = { Point_2(0,0), Point_2(10,0), Point_2(10,10), Point_2(6,5), Point_2(4,1) };
  Point_2 result[5];
  Point_2 *ptr = CGAL::convex_hull_2( points, points+5, result );
  std::cout <<  ptr - result << " points on the convex hull:" << std::endl;
  for(int i = 0; i < ptr - result; i++){
    std::cout << result[i] << std::endl;
  }
  return 0;
}

在这里插入图片描述

点向量(vector)的凸包

将内置数组替换为标准模板库中的 std::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, result;
  points.push_back(Point_2(0,0));
  points.push_back(Point_2(10,0));
  points.push_back(Point_2(10,10));
  points.push_back(Point_2(6,5));
  points.push_back(Point_2(4,1));
  CGAL::convex_hull_2( points.begin(), points.end(), std::back_inserter(result) );
  std::cout << result.size() << " points on the convex hull" << std::endl;
  return 0;
}

在这里插入图片描述

拓展到三维数据点

计算投影到 yz 平面上的三维点的凸包。使用 Projection_traits_yz_3 类是对前一个示例的一个小修改。

#include <iostream>
#include <iterator>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Projection_traits_yz_3.h>
#include <CGAL/convex_hull_2.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K3;
typedef CGAL::Projection_traits_yz_3<K3> K;
typedef K3::Point_3 Point_3;
int main()
{
	Point_3 points[5] = { Point_3(0,0,0), Point_3(0,10,0), Point_3(0,10,10), Point_3(0,6,5),Point_3(0,4,1) };
	std::ostream_iterator< Point_3 >  output(std::cout, "\n");
	CGAL::convex_hull_2(points, points+5, output, K());
	return 0;
}

在这里插入图片描述

使用Graham-Andrew算法的示例

在下面的示例中,使用 Graham_Andrew 算法构建凸包。得到的凸多边形显示在标准输出控制台。将函数 ch_graham_andrew() 替换为其他函数,如 ch_bykat() ,也可以得到相同的结果。

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/ch_graham_andrew.h>

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

int main()
{
	std::vector<Point_2> input = { Point_2(0, 0), Point_2(1,1), Point_2(2,0), Point_2(2,2), Point_2(1,2), Point_2(0,2) };
	std::ostream_iterator< Point_2 >  out(std::cout, "\n");
	CGAL::ch_graham_andrew(input.begin(), input.end(), out);
	return 0;
}

其中,Point_2(1,1)在内部,Point_2(1,2)共线。
在这里插入图片描述
在这里插入图片描述

使用属性映射的示例

在下面的例子中,我们有一个点向量作为输入,我们检索凸包上点的索引。凸包函数的第四个参数是一个必须为 ConvexHullTraits_2 概念模型的traits类。它提供了诸如定向测试之类的谓词。类 Convex_hull_traits_adapter_2 结合a Pointer_property_map ,就是这样的模型。索引 i 就是“点”,适配器执行 points[i] 上的谓词。

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/convex_hull_2.h>
#include <CGAL/Convex_hull_traits_adapter_2.h>
#include <CGAL/property_map.h>
#include <vector>
#include <numeric>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::Point_2 Point_2;
typedef CGAL::Convex_hull_traits_adapter_2<K,
    CGAL::Pointer_property_map<Point_2>::type > Convex_hull_traits_2;
int main()
{
    std::vector<Point_2> points = { Point_2(10,0),
                                    Point_2(10,0),
                                    Point_2(0,10),
                                    Point_2(1,1),
                                    Point_2(3,4),
                                    Point_2(0,0),
                                    Point_2(10,10),
                                    Point_2(2,6) };
    std::vector<std::size_t> indices(points.size()), out;
    std::iota(indices.begin(), indices.end(), 0);
    CGAL::convex_hull_2(indices.begin(), indices.end(), std::back_inserter(out),
        Convex_hull_traits_2(CGAL::make_property_map(points)));
    for (std::size_t i : out) {
        std::cout << "points[" << i << "] = " << points[i] << std::endl;
    }
    return 0;
}

输出凸包点的索引。
在这里插入图片描述

凸性检查

is_ccw_strongly_convex_2() is_cw_strongly_convex_2() 函数用于检测给定的二维点序列是否构成逆时针或顺时针强凸多边形。它们用于二维凸包函数的后置条件测试。

如果你想保持共线点,可以使用2D Delaunay三角剖分,如下面的例子所示。这个序列不是强凸的。

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Delaunay_triangulation_2.h>
#include <list>
#include <iostream>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::Point_2 Point_2;
typedef CGAL::Delaunay_triangulation_2<K> Delaunay_triangulation_2;
int main()
{
  std::vector<Point_2> input = { Point_2(0, 0), Point_2(1,1), Point_2(2,0), Point_2(2,2), Point_2(1,2), Point_2(0,2) };
  Delaunay_triangulation_2 dt(input.begin(), input.end());
  std::list<Point_2> result;
  Delaunay_triangulation_2::Vertex_circulator vc = dt.incident_vertices(dt.infinite_vertex());
  Delaunay_triangulation_2::Vertex_circulator done(vc);
  do{
    std ::cout << vc->point() << std::endl;
    // push_front in order to obtain the counterclockwise sequence
    result.push_front(vc->point());
    ++vc;
  }while(vc != done);
  return 0;
}

使用2D Delaunay三角剖分,输出凸包点,逆时针打印凸包点。
在这里插入图片描述

参考及相关链接

  1. https://doc.cgal.org/latest/Convex_hull_2/index.html#Chapter_2D_Convex_Hulls_and_Extreme_Points
  2. https://blog.csdn.net/mrbaolong/article/details/141713098?spm=1001.2014.3001.5501
  3. https://juejin.cn/post/7409866963981451299
  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值