CGAL 2D Polygons
简单概述 CGAL 2D Polygons使用。
简述
2D Polygon多边形是由一条封闭的边链表组成。对于多边形的操作有若干种常见的算法,有些算法要求多边形是简单多边形。如果边不相交,则多边形为简单多边形,除非连续的边相交于它们的公共顶点。

常见的多边形算法:
- 找出最左边、最右边、最上面和最下面的顶点。
 - 计算(有符号)面积。
 - 检查多边形是否为简单多边形。
 - 检查多边形是否为凸多边形。
 - 寻找到方向(顺时针或逆时针)。
 - 检查一个点是否位于多边形内。
 
所有这些操作都需要两个前向迭代器作为参数来描述多边形。这些形参的值类型与点类型相同。
 类 Polygon_2 可用于表示多边形。多边形是动态的。顶点可以被修改、插入和删除。它们以成员函数的形式提供上述算法。此外,它们还提供了遍历顶点和边的方法。
 Polygon_2 类是一个点容器的包装器,但仅此而已。特别是,计算值不会被缓存。也就是说,当 Polygon_2::is_simple() 成员函数被调用两次或两次以上时,每次都会重新计算结果。
示例
Polygon类
下面的例子创建了一个多边形,并说明了一些成员函数的用法。
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Polygon_2.h>
#include <iostream>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::Point_2 Point;
typedef CGAL::Polygon_2<K> Polygon_2;
using std::cout; using std::endl;
int main()
{
  Point points[] = { Point(0,0), Point(5.1,0), Point(1,1), Point(0.5,6)};
  Polygon_2 pgn(points, points+4);
  // check if the polygon is simple.
  cout << "The polygon is " <<
    (pgn.is_simple() ? "" : "not ") << "simple." << endl;
  // check if the polygon is convex
  cout << "The polygon is " <<
    (pgn.is_convex() ? "" : "not ") << "convex." << endl;
  return 0;
}
 

操作点序列的算法
下面的例子创建了一个多边形,并演示了一些操作点序列的全局函数的用法。
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Polygon_2_algorithms.h>
#include <iostream>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::Point_2 Point;
using std::cout; using std::endl;
void check_inside(Point pt, Point* pgn_begin, Point* pgn_end, K traits)
{
    cout << "The point " << pt;
    switch (CGAL::bounded_side_2(pgn_begin, pgn_end, pt, traits)) {
    case CGAL::ON_BOUNDED_SIDE:
        cout << " is inside the polygon.\n";
        break;
    case CGAL::ON_BOUNDARY:
        cout << " is on the polygon boundary.\n";
        break;
    case CGAL::ON_UNBOUNDED_SIDE:
        cout << " is outside the polygon.\n";
        break;
    }
}
int main()
{
    Point points[] = { Point(0,0), Point(5.1,0), Point(1,1), Point(0.5,6) };
    // check if the polygon is simple.
    cout << "The polygon is "
        << (CGAL::is_simple_2(points, points + 4, K()) ? "" : "not ")
        << "simple." << endl;
    check_inside(Point(0.5, 0.5), points, points + 4, K());
    check_inside(Point(1.5, 2.5), points, points + 4, K());
    check_inside(Point(2.5, 0), points, points + 4, K());
    return 0;
}
 

3D空间中的多边形
有时,在3D数据上运行2D算法很有用。多边形可以是3D对象的轮廓,其中轮廓被组织为通过从扫描仪分割图像数据产生的平行切片。
 为了避免在 xy 平面上的显式投影,可以使用trait类 Projection_traits_xy_3 ,它是2D和3D线性几何内核的一部分。
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Projection_traits_yz_3.h>
#include <CGAL/Polygon_2_algorithms.h>
#include <iostream>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::Point_3 Point_3;
int main()
{
  Point_3 points[4] = { Point_3(0,1,1), Point_3(0,2,1), Point_3(0,2,2), Point_3(0,1,2) };
  bool b =  CGAL::is_simple_2(points,
                              points+4,
                              CGAL::Projection_traits_yz_3<K>());
  if (!b){
    std::cerr << "Error polygon is not simple" << std::endl;
    return 1;
  }
  return 0;
}
 
将三维多边形投影到yz平面上,判断投影的多边形是否为简单多边形。
迭代遍历顶点和边
polygon类提供了 Polygon_2::vertices_begin() 和 Polygon_2::vertices_end() 这样的成员函数来迭代顶点。它还提供了一个成员函数 Polygon_2::vertices() ,它返回一个range,主要用于现代的 for 循环。这同样适用于 Polygon_with_holes_2 类的边和孔。
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Polygon_2.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Polygon_2<K>                                  Polygon_2;
typedef K::Point_2                                          Point_2;
typedef K::Segment_2                                        Segment_2;
int main()
{
  // create a polygon and put some points in it
  Polygon_2 p;
  p.push_back(Point_2(0,0));
  p.push_back(Point_2(4,0));
  p.push_back(Point_2(4,4));
  for(const Point_2& p : p.vertices()){
    std::cout << p << std::endl;
  }
  // As the range is not light weight, we have to use a reference
  const Polygon_2::Vertices& range = p.vertices();
  for(auto it = range.begin(); it!= range.end(); ++it){
    std::cout << *it << std::endl;
  }
  for(const Segment_2& e  : p.edges()){
    std::cout << e << std::endl;
  }
  return EXIT_SUCCESS;
}
 

绘制多边形
调用CGAL::draw()函数可以可视化多边形,如下面的例子所示。这个函数会打开一个显示给定多边形的新窗口。对这个函数的调用是阻塞的,也就是说,只要用户不关闭窗口,程序就会继续运行。Polygon_with_holes_2有一个版本,CGAL::draw<PH>()。
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Polygon_2.h>
#include <CGAL/draw_polygon_2.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Polygon_2<K>                                  Polygon_2;
typedef CGAL::Point_2<K>                                    Point;
int main()
{
	// create a polygon and put some points in it
	Polygon_2 p;
	p.push_back(Point(0, 0));
	p.push_back(Point(4, 0));
	p.push_back(Point(4, 4));
	p.push_back(Point(2, 2));
	p.push_back(Point(0, 4));
	CGAL::draw(p);
	return EXIT_SUCCESS;
}
 

 该函数需要 CGAL_Qt5 ,并且仅在定义宏 CGAL_USE_BASIC_VIEWER 时可用。与cmake目标 CGAL::CGAL_Basic_viewer 连接将与 CGAL_Qt5 连接并添加定义 CGAL_USE_BASIC_VIEWER 。
CMakeLists.txt示例:
cmake_minimum_required(VERSION 3.1...3.23)
project(test)
find_package(CGAL REQUIRED OPTIONAL_COMPONENTS Qt5)
create_single_source_cgal_program("test.cpp")
if(CGAL_Qt5_FOUND)
  #link it with the required CGAL libraries
  target_link_libraries(test PUBLIC CGAL::CGAL_Basic_viewer)
endif()
 
示例demo
ploygon.wkt文件。
POLYGON((0 0,4 0,4 4,2 2,0 4))
 

参考
- https://doc.cgal.org/latest/Polygon/index.html
 

![[001-07-001].Redis中的BigKey使用分析](https://i-blog.csdnimg.cn/direct/bd90f1729d0046c5a466984cfb45e1db.png)

















