1. cgal在ubuntu下的安装及Hello World的测试

文章目录

  • ubuntu下的安装
  • 教程 Hello World
  • 1 三点一线
  • 2 点序列的凸包
    • 2.1 内置数组中的点的凸包
    • 2.2 向量中点的凸包
  • 3 关于内核和特征类
  • 4 概念和模型
  • 5 进一步阅读

ubuntu下的安装

CGAL安装

参考地址:https://doc.cgal.org/latest/Manual/usage.html

本在在ubuntu下安装:

sudo apt-get install libcgal-dev

安装后的路径:

头文件路径: /usr/include/CGAL

库文件路径: /usr/lib/x86_64-linux-gnu

在qt cretator 中使用示例:

在.pro中添加 LIBS += -lCGAL

教程 Hello World

原文地址:https://doc.cgal.org/latest/Manual/tutorial_hello_world.html

本教程适用于了解 C++ 并具有几何算法基础知识的 CGAL 新手。第一部分展示如何定义点和线段类,以及如何对其应用几何谓词。本节进一步提高了人们的认识,即使用浮点数作为坐标时存在严重问题。在第二部分中,您将遇到一个典型的 CGAL 函数,它计算 2D 凸包。第三部分展示了Traits类的含义,第四部分解释了概念模型的概念。

1 三点一线

在第一个示例中,我们演示了如何构造一些点和一段,并对它们执行一些基本操作。

所有 CGAL 头文件都位于子目录中include/CGAL。所有 CGAL 类和函数都在命名空间中CGAL。类以大写字母开头,全局函数以小写字母开头,常量全部大写。物体的尺寸用后缀表示。

几何基元,如点类型,是在kernel中定义的。我们为第一个示例选择的内核使用double精度浮点数作为该点的笛卡尔坐标。

除了类型之外,我们还看到诸如三点方向测试之类的谓词,以及诸如距离和中点计算之类的*结构。*谓词具有一组离散的可能结果,而构造则产生一个数字或另一个几何实体。

文件 Kernel_23/points_and_segment.cpp

#include <iostream>
#include <CGAL/Simple_cartesian.h>
typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_2 Point_2;
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;
}

正如下一个示例所示,用浮点数处理几何图形可能会令人惊讶。

文件 Kernel_23/surprising.cpp

#include <iostream>
#include <CGAL/Simple_cartesian.h>
typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_2 Point_2;
int main()
{{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 矩阵的行列式,该行列式接近但不等于 0,因此前两个测试的非共线性。

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

如果您必须确保以完全精度解释您的数字,您可以使用执行精确谓词和提取结构的 CGAL 内核。

文件 Kernel_23/exact.cpp

#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 内置数组中的点的凸包

在第一个示例中,我们有一个由五个点组成的数组作为输入。由于这些点的凸包是输入的子集,因此提供一个用于存储具有相同大小的结果的数组是安全的。

文件 Convex_hull_2/array_convex_hull_2.cpp

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

我们在上一节中已经看到 CGAL 附带了多个内核。由于凸包算法仅对输入点的坐标和方向进行比较,因此我们可以选择提供精确谓词但不提供精确几何构造的内核。

凸包函数采用三个参数,即输入的起始指针和结束指针,以及结果数组的起始指针。该函数将指针返回到结果数组中,正好位于最后写入的凸包点后面,因此指针差异告诉我们凸包上有多少个点。

2.2 向量中点的凸包

在第二个示例中,我们将内置数组替换为std::vector标准模板库的数组。

文件 Convex_hull_2/vector_convex_hull_2.cpp

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

我们将一些点放入向量中,调用类push_back()的方法std::vector

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

第三个参数是结果写入的位置。在前面的示例中,我们提供了指向已分配内存的指针。这种指针的泛化是输出迭代器,它允许递增并向取消引用的迭代器赋值。在此示例中,我们从一个空向量开始,该向量根据需要增长。因此,我们不能简单地传递它result.begin(),而是传递一个由辅助函数生成的输出迭代器std::back_inserter(result)。该输出迭代器在递增时不执行任何操作,而是调用result.push_back(..)赋值。

如果您了解 STL(标准模板库),那么上面的内容就很有意义,因为这就是 STL 将算法与容器解耦的方式。如果您不了解STL,您最好先熟悉一下它的基本思想。

3 关于内核和特征类

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

如果您查看该函数convex_hull_2()和其他 2D 凸包算法的手册页,您会发现它们有两个版本。在我们到目前为止看到的示例中,该函数采用两个用于输入点范围的迭代器和一个用于写入结果的输出迭代器。第二个版本有一个附加的模板参数Traits和一个此类型的附加参数。

template<class InputIterator , class OutputIterator , class Traits >
OutputIterator
convex_hull_2(InputIterator first,InputIterator beyond,OutputIterator result,const Traits & ch_traits)

典型的凸包算法使用哪些几何基元?当然,这取决于算法,所以让我们考虑什么可能是最简单有效的算法,即所谓的“Graham/Andrew Scan”。该算法首先从左到右对点进行排序,然后通过从排序列表中逐个添加点来增量构建凸包。为此,它至少必须了解某种点类型,应该知道如何对这些点进行排序,并且必须能够评估三重点的方向。

这就是模板参数的用武之地Traits。因为ch_graham_andrew()它必须提供以下嵌套类型:

  • Traits::Point_2
  • Traits::Less_xy_2
  • Traits::Left_turn_2
  • Traits::Equal_2

你可以猜到,Left_turn_2负责方向测试,而 则Less_xy_2用于对点进行排序。这些类型必须满足的要求已与该概念一起完整记录ConvexHullTraits_2

这些类型被重新分组的原因很简单。另一种选择是使用相当冗长的函数模板,以及更长的函数调用。

template <class InputIterator, class OutputIterator, class Point_2, class Less_xy_2, class Left_turn_2, class Equal_2>
OutputIterator
ch_graham_andrew( InputIterator  first,InputIterator  beyond,OutputIterator result);

有两个明显的问题:什么可以用作此模板参数的参数?为什么我们有模板参数?

为了回答第一个问题,CGAL概念的任何Kernel模型都提供了该概念所需的内容ConvexHullTraits_2

至于第二个问题,考虑一个我们想要计算投影到平面上的 3D 点的凸包的应用程序yz。使用该类Projection_traits_yz_3是对前面示例的一个小修改。

文件 Convex_hull_2/convex_hull_yz.cpp

#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 K::Point_2 Point_2;
int main()
{std::istream_iterator< Point_2 >  input_begin( std::cin );std::istream_iterator< Point_2 >  input_end;std::ostream_iterator< Point_2 >  output( std::cout, "\n" );CGAL::convex_hull_2( input_begin, input_end, output, K() );return 0;
}

另一个示例是关于用户定义的点类型,或来自 CGAL 之外的第三方库的点类型。将点类型与该点类型所需的谓词放在类的范围内,您就可以convex_hull_2()使用这些点来运行。

最后,让我们解释一下为什么将一个traits对象传递给凸包函数?它将允许使用更通用的投影特征对象来存储状态,例如,如果投影平面由方向给出,则该方向在类中是硬连线的Projection_traits_yz_3

4 概念和模型

在上一节中,我们写道:CGAL概念的任何**模型都提供了该概念所需的内容。 Kernel``ConvexHullTraits_2

概念是对类型的一组要求,即它具有某些嵌套类型、某些成员函数或带有某些以该类型为基础的自由函数*。**概念的模型*是满足概念要求的类。

我们来看看下面的函数。

template <typename T>
T
duplicate(T t)
{return t;
}

如果你想用一个类来实例化这个函数C,这个类至少必须提供一个复制构造函数,我们说这个类C必须是一个模型CopyConstructible。单例类不能满足此要求。

另一个例子是函数:

template <typename T>
T& std::min(const T& a, const T& b)
{return (a<b)?a:b;
}

operator<(..)仅当为用作 as 的类型定义时,此函数才会编译T,并且我们说该类型必须是LessThanComparable的模型。

具有所需自由函数的概念的一个示例是HalfedgeListGraphCGAL 包CGAL 和 Boost Graph Library。为了成为HalfedgeListGraph类的模型G,必须有全局函数halfedges(const G&)等。

具有所需特征类的概念的一个示例是InputIterator。对于模型来说,InputIterator类的专门化std::iterator_traits必须存在(或者通用模板必须适用)。

5 进一步阅读

我们还推荐 Addison-Wesley 的 Nicolai M. Josuttis 所著的标准教科书“The C++ Standard Library, A Tutorial and Reference”,或 Matthew H. Austern 所著的“Generic Planning and the STL”,介绍 STL 及其概念和概念楷模

CGAL 的其他资源包括教程的其余部分以及https://www.cgal.org/上的用户支持页面。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/228677.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

gcc介绍

gcc编译有四个步骤&#xff1a;预处理、编译、汇编、链接 前提条件: hello.c 1 预处理 gcc -E hello.c -o hello.i -o 指定输出文件为hello.i 展开宏、头文件&#xff0c;替换条件编译&#xff0c;删除注释、空行、空白 2 gcc -S 编译 gcc -S hello.i -o hello.s 检查语法…

基于Springboot的旅游网站设计与实现(论文+调试+源码)

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

数据手册Datasheet解读-MOS管笔记

数据手册Datasheet解读-MOS管笔记 NMOS应用场景一般特征第一个参数Vdss第二、三个参数Rds&#xff08;on&#xff09;、IdMOS管的散热绝对最大额定值第一个参数-Vd第二个参数-Vdgr第三个参数-Vg(栅源电压)第四个参数-Id第五个参数-Idm第六个参数-Ptot第七个参数-Viso第七和八的…

模块四(一):搭建自己的SSR

前言&#xff1a;同构渲染是将服务器渲染和客户端渲染相结合的一种渲染方式&#xff0c;在服务端生成初始页面&#xff0c;提升首屏加载速度&#xff0c;并且有利于SEO&#xff1b;在客户端接管HTML&#xff0c;并且将静态HTML激活为数据绑定的动态HTML&#xff0c;为用户提供更…

Unity 常用资料

1. Layer layer本质是按序左移的一个Int32数字&#xff0c;int32有4个字节》32位&#xff0c;故可以支持32个层级。系统自身使用了5个层&#xff0c;意味着用户还有27个层可以使用。 0000 0000 0000 0000 0000 0000 0000 0000 可以且只能任意位为1。unity具体的0-31的层级分布…

13个NPM快速开发技巧:提升前端开发效率

在现代前端开发中&#xff0c;NPM&#xff08;Node Package Manager&#xff09;是无法被忽视的利器之一。除了基本的包管理功能外&#xff0c;NPM还提供了许多强大的开发工具。下面&#xff0c;让我们一起探索13个NPM的快速开发技巧&#xff0c;助你事半功倍。 1. 初始化项目 …

Python实战 | 如何抓取腾讯视频

嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 爬虫: 作用: 批量采集数据 / 模拟用户行为 原理: 模拟成 客户端 向 服务器 发送网络请求 环境介绍: python 3.8 解释器 pycharm 编辑器 第三方模块: reques…

委托线程安全

委托线程安全是指将对共享数据的访问委托给线程安全的类&#xff0c;从而避免在调用方代码中进行额外的同步控制。这可以通过将线程安全性限定在一个类内部来实现。以下是一个简单的例子&#xff1a; 假设有一个计数器类 Counter&#xff0c;它不是线程安全的。 public class…

Unity 关于刚体模拟爆炸效果使用的方法

Unity刚体要模拟爆炸效果&#xff0c;可以使用AddExplosionForce方法。 它有3个语法&#xff1a; public void AddExplosionForce(float explosionForce, Vector3 explosionPosition, float explosionRadius); //默认upwardsModifie0.0f,ForceMode.Force模式public void AddE…

Docker可视化管理工具docker.ui的搭建

1、拉取镜像 docker pull joinsunsoft/docker.ui:1.0.1 2、运行容器 docker run -d --name docker.ui --restart always -v /var/run/docker.sock:/var/run/docker.sock -p 8999:8999 joinsunsoft/docker.ui:1.0.13、地址访问 访问地址&#xff1a;http://localhost:8999/lo…

CXL RAS功能简介

一般来说&#xff0c;RAS&#xff08;可靠性、可用性和可服务性&#xff09;是计算机硬件和系统设计中的重要概念。 在CXL&#xff08;Compute Express Link&#xff09;接口中&#xff0c;RAS功能包括以下方面&#xff1a; 错误检测和纠正&#xff1a;CXL可能支持各种错误检测…

使用git命令行来拉取项目

哈哈哈&#xff0c;在校的我可能更偏向用git&#xff0c;可是在实习过程中大家都用的是图形化工具&#xff0c;因为还不是太熟练&#xff0c;所以我目前还是在用的git命令行。 下边说一下大致流程吧&#xff01; //拉项目 git clone 仓库地址 //根据项目来安装依赖 npm或者y…

IP小知识

概述 IP是英文Internet Protocol&#xff08;互联网协议&#xff09;的缩写。它是一种网络通信协议&#xff0c;用于在计算机网络中传输数据。 IP协议定义了数据在网络中的传输方式和交换方式&#xff0c;它为每台连接到互联网的计算机分配一个唯一的标识符&#xff0c;称为IP…

Java8实战-总结51

Java8实战-总结51 CompletableFuture&#xff1a;组合式异步编程响应 CompletableFuture 的 completion 事件付诸实践 小结 新的日期和时间AP CompletableFuture&#xff1a;组合式异步编程 响应 CompletableFuture 的 completion 事件 付诸实践 现在通过randomDelay方法模拟…

AOA_send_camer_data

Host端 Host 端获取到Camera 数据流经过Mediacodec编码后为H264流发送到另一个设备上面进行显示预览; /**1.建立AOA通信 *2.获取Camera预览数据流 *3.对Camera进行编码为H264 *4.发送数据到device端,AOA数据发送最大量为16K(分包处理) *5.接收到数据后Mediacodec进行解码显…

公众号提高上限怎么操作?

一般可以申请多少个公众号&#xff1f;众所周知&#xff0c;在2013年前后&#xff0c;公众号申请是不限制数量的&#xff0c;后来企业开始限制申请50个&#xff0c;直到2018年的11月tx又发布&#xff0c;其中个人主体可申请公众号由2个调整为1个&#xff0c;企业主体由50个调整…

CAPL——发送自定义报文

文章目录 一、前言二、CANoe操作二、CAPL程序三、Trace结果一、前言 CAPL是CANoe自带的一个编程语言,基本语法基于C语言,通过CAPL可以发挥CANoe更高效、更强大的功能。CAPL最大的特点就是可以编程灵活的完成报文的发送,报文包括通信报文及诊断报文 本文讲述模拟一个报文周…

14 Vue3中组件的props属性

概述 Let’s look at a simple HelloWorld single-file component. You can find this at ./src/components/HelloWorld.vue, generated automatically when you create a Vue project with Vite. 让我们来看一个简单的 HelloWorld 单文件组件。您可以在 ./src/components/He…

腾讯技术工程总结-如何写好技术文章?

文章参考&#xff1a;腾讯技术工程《写好一篇高质量的技术文章》 如何写好技术文章&#xff1f; 大家可以先思考一下&#xff0c;为什么要写技术文章&#xff1f; 我们写技术文章的目的是什么呢&#xff1f;面向哪些人呢&#xff1f; 面向人群 写技术文章的目的毫无疑问是为…

腾讯地图绘画多边形和计算面积

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>地图</title></head><script src…