CGAL-Hello world

包含文件和库
C/C++ 常规:附加包含目录
C:\local\CGAL\auxiliary\gmp\include;C:\local\CGAL\build\include;C:\local\CGAL\include;C:\local\boost_1_77_0



链接器:
附加库目录
C:\local\boost_1_77_0\libs;C:\local\CGAL\auxiliary\gmp\lib;C:\local\CGAL\build\lib


附加依赖项
libgmp-10.lib
libmpfr-4.lib
kernel32.lib
user32.lib

CGAL_Core-vc140-mt-gd-4.11.lib
CGAL_ImageIO-vc140-mt-gd-4.11.lib
CGAL_Qt5-vc140-mt-gd-4.11.lib
CGAL-vc140-mt-gd-4.11.lib

C:\Users\duxuan\source\repos\helloworld1

1、三个点和一条有向线段

在第一个例子中,我们演示如何构建一些点和一条有向线段,并对他们执行一些基本操作,
所有CGAL头文件,都在子目录 include/CGAL 中。所有的 CGAL 类和函数都在 CGAL 命名
空间中。类以大写字母开头,全局函数以小写字母开头,常量全部大写。对象的维度用后缀表示。

像点类型这样的几何基元是在坐标系(内核)中定义的。我们为第一个例子选取的坐标系使用
双精度浮点数表示该点的笛卡尔坐标。

除了像三点方向测试这样的判断函数,还有像距离计算和中点计算之类的结构函数。一次判断具一组
(列举的)离散的可能结果,而一个结构函数生成一个数字或另一个几何实体。

#include <iostream>
#include <CGAL/Simple_cartesian.h>
typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_2 Point_2; //kernel : 在计算机领域称为内核,
//然而,CGAL中的这个kernel看起来像解析几何中坐标系的意思多一点
typedef Kernel::Segment_2 Segment_2;
int main()
{
Point_2 p(1, 1), q(10, 10); //二维点
std::cout << "p = " << p << std::endl;
std::cout << "q = " << q.x() << " " << q.y() << std::endl;
std::cout << "sqdist(p,q) = " //两点距离平方
<< CGAL::squared_distance(p, q) << std::endl;
Segment_2 s(p, q); //点连线
Point_2 m(5, 9);
std::cout << "m = " << m << std::endl;
std::cout << "sqdist(Segment_2(p,q), m) = "
<< CGAL::squared_distance(s, m) << std::endl; //点与线距离的平方
std::cout << "p, q, and m ";
switch (CGAL::orientation(p, q, m)) {
case CGAL::COLLINEAR: //三点的位置关系
std::cout << "are collinear\n";
break;
case CGAL::LEFT_TURN:
std::cout << "make a left turn\n";
break;
case CGAL::RIGHT_TURN:
std::cout << "make a right turn\n";
break;
}
std::cout << " midpoint(p,q) = " << CGAL::midpoint(p, q) << std::endl;
return 0;
}


正如下面的例子所示,使用浮点数来做几何计算可能会使人惊讶。


#include <iostream>
#include <CGAL/Simple_cartesian.h>
typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_2 Point_2;
int main02()
{
{
Point_2 p(0, 0.3), q(1, 0.6), r(2, 0.9);
std::cout << (CGAL::collinear(p, q, r) ? "collinear\n" : "not collinear\n");
}
{
Point_2 p(0, 1.0 / 3.0), q(1, 2.0 / 3.0), r(2, 1);
std::cout << (CGAL::collinear(p, q, r) ? "collinear\n" : "not collinear\n");
}
{
Point_2 p(0, 0), q(1, 1), r(2, 2);
std::cout << (CGAL::collinear(p, q, r) ? "collinear\n" : "not collinear\n");
}
return 0;
}

这是因为这些分数不能表示为全精度数,并且共线测试将在内部计算接近但不等于零的3x3
矩阵的行列式,因此前两个测试不共线。

执行左转的点也会发生类似的情况,但由于行列式计算时的舍入误差,这些点似乎是共线的,
或者执行右转。

如果你要确保你的数字以完整的精度得到解释,你可以使用执行精确判断和精确构造。


#include <iostream>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <sstream> //精确判断和精确计算
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef Kernel::Point_2 Point_2;
int main()
{
Point_2 p(0, 0.3), q, r(2, 0.9);
{
q = Point_2(1, 0.6);
std::cout << (CGAL::collinear(p, q, r) ? "collinear\n" : "not collinear\n");
}
{
std::istringstream input("0 0.3 1 0.6 2 0.9");
input >> p >> q >> r;
std::cout << (CGAL::collinear(p, q, r) ? "collinear\n" : "not collinear\n");
}
{
q = CGAL::midpoint(p, r);
std::cout << (CGAL::collinear(p, q, r) ? "collinear\n" : "not collinear\n");
}
return 0;
}

在第一个块中点仍然是非线性的,因为你看到的文本坐标转变成了浮点数。当它们转变成任意精度的
有理数时,它们就完全被浮点数所代替,不再是文本了。

而第二个块则不同,这相当于从文件中读取数字。然后直接从字符串计算任意精度的有理数,以精确
的表示文本。

在第三个块中,你会看到重点的计算是精确地,正如坐标类型所暗示的那样。

在许多情况下,您将得到“精确”的浮点数,因为它们是由某些应用程序计算的或从传感器获得的。它们
不是字符串'0.1"或动态计算为“1.0/10.0”,而是一个全精度浮点数。如果将它们输入到不进行计算的算法,
则可以使用提供精确判断但计算不精确的坐标。一个这样的例子是我们将在下一节中看到的凸包算法。
输出是输入的子集,算法只比较坐标和执行方向测试。

乍一看,坐标执行精确的判断和计算似乎是完美的选择,但性能限制或内存限制使其并非如此。此外,
对于许多算法来说,进行精确的计算是无关紧要的。例如,通过将边缘折叠到边缘的中点来迭代收缩边缘
的表面网格简化算法。

大多数 CGAL 包解释了它们应该使用或支持哪种坐标。


2、点序列的凸包

本节中的所有示例都计算一组点的 2D 凸包。我们展示了算法将其输入作为表示点范围的开始/结束
迭代器对,并将结果(在示例中为凸包上的点)写入输出迭代器。

2.1内置数组中的凸包

第一个例子,我们有一个包含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 );//convex_hull_2函数在CGAL的名称空间
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;
}

//数组中点的凸包
#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);//convex_hull_2函数在CGAL的名称空间
//凸包函数接受3个参数,输入的开始和结束指针,以及结果数组的开始指针。该函数将指针返回
//到最后写入的凸包点的结果数组中,然后指针差告诉我们凸包上有多少个点。
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;
}

//向量容器中点的凸包

#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;

retuen 0;
}

通过调用 std::vector 类的 push_back() 方法,我们在vector中放置一些点。

然后调用凸包函数。前两个参数,points.begin(),point.end(),
是迭代器,这是指针的概括:它们可以被取消引用和递增。凸包函数是通用的,因为它
将任何可以取消引用和递增的参数输入。

第3个参数时结果被写入的地方。在前面的示例中,我们提供了一个指向已分配内存的指针。
这种指针的一般化(泛化)是输出迭代器,它允许自增并赋值给引用的迭代器。

在这个例子中,我们从一个会根据需要增长的empty vector开始。因此,不能简单的给它
传递result.begin()的,而是给它传递一个由帮助函数 std::back_inserter(result)生成的
输出迭代器。这个输出迭代器在自增时什么都不做,并在赋值时调用result.push_back(……)。

3、关于坐标和特性类

在本节中,我们将展示如何表达必须满足的要求,以便于将类似于convex_hull_2()的函数
用于任意类型的点。

如果你查看函数convex_hull_2()和其它2D凸包算法的手册页,你可看到它有两个版本。

在前面的例子中,函数接受两个迭代器来表示输入点的范围,并接受一个输出迭代器来将结果写到。

第二个版本有一个额外的模板参数Traits,以及一个这种类型的额外参数。

posted @ 2022-04-02 14:31  彩色回形针  阅读(185)  评论(0编辑  收藏  举报