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))