一、HELLO WORLD
1. 官方文档:CGAL-TUTORIALS
2. 所有`CGAL`头文件都在子目录中。所有`CGAL`类和函数都在命名空间中。类以大写字母开头,全局函数以小写字母开头,常量全部大写。
3. 几何图元,如点、线等都定义在内核`Kernel`中
#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;
/*
- `Point_2()`:一个2d的点
- `Segment_2`:一个2d的扇形,若只有两点,则为直线
- `CGAL::squared_distance(p, q)`:两点距离or点到直线的距离
- `CGAL::orientation(p, q, m)`:三点是否共线,若不共线,则m在p,q哪一侧
- `CGAL::midpoint(p, q)`:中点坐标
*/
int main()
{
Point_2 p(1, 1), q(10, 10);
std::cout << "p = " << p << std::endl;// p = 1 1
std::cout << "q = " << q.x() << " " << q.y() << std::endl;// q = 10 10
std::cout << "sqdist(p,q) = "
<< CGAL::squared_distance(p, q) << std::endl;// sqdist(p,q) = 162
Segment_2 s(p, q);
Point_2 m(5, 9);
std::cout << "m = " << m << std::endl;// m = 5 9
std::cout << "sqdist(Segment_2(p,q), m) = "
<< CGAL::squared_distance(s, m) << std::endl;// sqdist(Segment_2(p,q), m) = 8
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;
} // p, q, and m make a left turn
std::cout << " midpoint(p,q) = " << CGAL::midpoint(p, q) << std::endl;// midpoint(p,q) = 5.5 5.5
return 0;
}
4. 对于浮点数而言,会出现结果不精确的问题,这时采用如下内核:
#include <iostream>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef Kernel::Point_2 Point_2;
5. 凸包:在高维空间中有一群散布各处的点,凸包是包覆这群点的所有外壳当中,表面积or容积最小的一个外壳,而最小的外壳一定是凸的。
#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(5, 6));
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;
for (int i = 0; i < result.size(); i++) {
std::cout << result[i] << std::endl;
}
return 0;
}
/*
4 points on the convex hull
0 0
10 0
10 10
5 6
*/
二、在GIS上的应用(未完)
1. 数据结构
- TIN:三角化不规则网络,一种 2D 三角结构,可根据 3D 点在水平面上的投影连接 3D 点。
- DSM:数字表面模型,整个扫描表面的模型,包括建筑物和植被。我们使用 TIN 来存储 DSM。
- DTM:数字地形模型,裸露地面的模型,没有建筑物或植被等物体。我们都使用 TIN 和栅格来存储 DTM。
- DEM:数字高程模型,一个更通用的术语,包括 DSM 和 DTM。
2. delaunay三角剖分
一个小demo:(源码位置->CGALlearn(github))
#include<vector>
#include<algorithm>
#include<CGAL/point_generators_2.h>
#include<CGAL/algorithm.h>
#include<CGAL/random_selection.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include<CGAL/Delaunay_triangulation_2.h>
#include <CGAL/draw_triangulation_2.h>
using namespace CGAL;
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef Kernel::Point_2 Point;
typedef Creator_uniform_2<double, Point> Creator;
typedef std::vector<Point> Vector;
typedef CGAL::Delaunay_triangulation_2<Kernel> Delaunay;
typedef Delaunay::Vertex_handle Vertex_handle;
int main() {
Vector points;
points.reserve(10);
Random_points_in_disc_2<Point, Creator> g(150.0);
CGAL::cpp11::copy_n(g, 10, std::back_inserter(points));
Delaunay dt;
dt.insert(points.begin(), points.end());
CGAL::draw(dt);
system("pause");
return EXIT_SUCCESS;
}
在QT5中编译出来的效果为:
三、配置VS 2022+vcpkg+cmake 3.24.0+Qt 5.15.2
1. 前言
这一部分是记录本人在配置环境时遇到一些坑以及查询到的诸多资料,在此作为一个记录,以便日后查阅。
2. 关于vcpkg
vcpkg是微软推出的一款C++的包管理器,便与相关工作者安装与卸载库。
具体安装方法见下文:vcpkg安装指南
常用的命令有:
集成到全局:vcpkg integrate install
移除全局:vcpkg integrate remove
集成到工程:vcpkg integrate project
查看库目录:vcpkg search xxxx
查看支持的架构:vcpkg help triplet
指定编译某种架构的程序库:vcpkg install xxxx:x64-windows(x86-windows)
卸载已安装库:vcpkg remove xxxx
指定卸载平台:vcpkg remove xxxx:x64-windows
移除所有旧版本库:vcpkg remove --outdated
查看已经安装的库:vcpkg list
更新已经安装的库:vcpkg update xxx
导出已经安装的库:vcpkg export xxxx --7zip(–7zip –raw –nuget –ifw –zip)
需要注意的一点是,如果下库出现时间过长,或者下载报错,一般通过科学上网可以解决。
3. 关于Qt 5.15.2
如果只使用CGAL+VS 2022,代码能跑,但是如果涉及到图形时,会报如下错误:
Impossible to draw, CGAL_USE_BASIC_VIEWER is not defined.
在官方文档里也指出:
在下Qt的时候需要注意一点,Qt5.15版本只能通过在线下载的方式下载,而在2022/8/1日的版本中,一般的latest和preview是没有5.15的,只有6.2及以上版本,这时通过点击Archieve即可获取旧版本的下载,勾选MSVC 2019 64-bit即可(32-bit以防有x86的程序)
4. 关于CMake 3.24.0
一言简之,CMake的使用方法:
建立CMakeLists.txt -> CMake(GUI)configure+generate -> VS 2022 生成 ALL BUILD
我的CMakeLists.txt如下:
cmake_minimum_required(VERSION 3.24.0) #最低版本cmake
#设置vcpkg路径
set(VCPKG_ROOT "L:/cpplib/vcpkg/scripts/buildsystems/vcpkg.cmake" CACHE PATH "")
set(CMAKE_TOOLCHAIN_FILE ${VCPKG_ROOT})
# 项目名
project(main)
# 找包
find_package(CGAL REQUIRED COMPONENTS Core OPTIONAL_COMPONENTS Qt5)
# 如果没找到就加路径
if(CGAL_Qt5_FOUND)
add_definitions(-DCGAL_USE_BASIC_VIEWER -DQT_NO_KEYWORDS)
endif()
# 编译cpp
create_single_source_cgal_program("random_point_2d_delaunay.cpp")
# Qt5配置
if(CGAL_Qt5_FOUND)
# 连接仓库,第一个参数(random_point_2d_delaunay)是我们的目标cpp文件,这里放你的cpp即可
target_link_libraries (random_point_2d_delaunay PUBLIC CGAL::CGAL_Qt5)
target_link_libraries (random_point_2d_delaunay PUBLIC CGAL::CGAL_Basic_viewer)
else()
message(
STATUS
"NOTICE: The example main requires Qt and drawing will be disabled."
)
endif()
需要修改的地方:cmake的最低版本、vcpkg的路径、cpp的名称(三处)
然后再打开cmake(GUI),先点击configure,若无报错,再点击generate即可。
找到sln文件,双击打开,右键ALL BUILD生成即可:
5. 可能遇到的报错
5.1 CGAL NOT FOUND
因为使用vcpkg下库,所以诸如cgal的路径未直接添加至环境变量当中,因此只需CMakeLists.txt中find_package前添加如下代码即可:
set(VCPKG_ROOT "L:/cpplib/vcpkg/scripts/buildsystems/vcpkg.cmake" CACHE PATH "")
set(CMAKE_TOOLCHAIN_FILE ${VCPKG_ROOT})
前提是要确定自己vcpkg.cmake的路径。
5.2 “QT”:不明确的符号
右键对应的cpp -> 属性 -> 配置属性 -> 常规 -> c++语言标准
改为C++20即可。