CGAL使用心得(附加说明)

附加说明:
1.       CGAL整体概述
CGAL是一个用C++描述的,包含三个主要部分的计算几何算法库.
第一部分是核心组件(Kernel),它包括基本的几何对象以及做用在这些对象上的各种操作.这些对象被实现成使用表现类参数化的独立的类,这样使得核心更具有灵活性和适应性.
第二部分是一系列的基础几何数据结构和算法.它们被特征类参数化.而特征类定义了数据结构或者算法和它们使用的原生类型(primitives)的接口.在很多情况下CGAL中的核心类可以作为这些数据结构或算法的特征类使用.
第三部分是由一些支持设施比如为方便调试设计的迭代器,随即数源,I/O支持以及一些可视化工具等等.这个部分主要介绍核心部分.核心由一些基础对象组成,比如点,向量,方向,直线,射线,线段,三角形,ISO型长方形和四面体.每个部分都有一些对这些对象进行操作的函数.一般有访问函数(比如一个点的坐标),测试点和这个对象的位置关系,得到对象的包围盒子的函数,长度,面积等等.核心中还包含一些基本超作,比如仿射变幻,相交的检测与计算,距离计算.

2. CGAL核心说明
我们学习的对象是d维欧几里德仿射空间.这里我们主要考虑2维和3维得情况.空间中的对象是有点集组成.表示点的一般方法是使用笛卡儿坐标.它假定了一个参照框架(一个原点和d个正交轴).这个框架中一个点是由一个d维的向量表示的(c0,c1,...,cd-1),相应的线性空间中的向量也是如此.每个点都有唯一的笛卡儿坐标与之对应.另一种表示点的方法是齐次坐标.在这个框架中一个点是有一个d+1(h0,h1...,hd)维向量表示的.根据公式ci=hi/hd,对应的点的笛卡儿坐)标(c0,c1,...,cd-1)可以计算出来.注意齐次坐标的点的表示是不唯一的.当λ≠0时,向量(h0,h1,…hd)和向量(λh0, λh1 …, λhd)表示同一个点.如果一个点的笛卡儿坐标是(c0,c1,…,cd-1),它可以表示成(c0,c1,…,cd-1,1)这个齐次坐标.齐次坐标系可实际上可以在一个更一般的空间的中表示对象.这个空间叫射影空间.在CGAL中我们不会进行射影几何的计算.我们使用齐次坐标是为了避免除法运算,而增加的这个坐标是作为公共分母.

2.1 通过参数化实现泛型
几乎所有的核心对象(已经对应的函数)都是由模板来实现的.而模板参数是用用户来选择从而决定核心对象的表现形式.

2.2 笛卡儿坐标系核心
通过Cartesian你可以给笛卡儿坐标系选择表现形式.当你选择了坐标系的表现形式以后,你必须同时指定坐标的数据类型.这种数据类型必须具有域的性质.前面提到int不是一种域类型.但是在笛卡儿坐标系中不包括除法运算,所以环类型在这种情况下是可以使用的.当指定了Cartesian以后Cartesian::FT和Cartesian::RT都被映射成域类型.
Cartesian的内部使用了引用计数来节省拷贝的开支.CGAL同时也提供了不使用引用计数的Simple_cartesian.调试的时候使用Simple_cartesian 会比较方便,这是因为坐标被保存在类的内部,因此可以直接访问坐标.在使用的不同算法的时候,这两种实现方式将有不同的效率.

2.3 齐次坐标系核心(由于ARRANGMENT的例子都是基于笛卡儿坐标系核心的,所以没有做过多的研究)
齐次坐标系中可以避免除法运算,因为引入的补充坐标可以坐标为公共分母.避免了除法运算对几何计算的精确性相当有利.通过Homogeneous可以指定齐次坐标的表现形式.而在笛卡儿坐标系中我们还必须指定坐标的数值类型.因为齐次坐标系不使用除法,作为齐次坐标表现的数值类型必须被建立成为相对较弱的环数据类型.然而齐次核心提供的一些操作中使用到了除法,例如计算笛卡儿坐标系下的平方距离.为了不改变齐次坐标的弱类型参数,我们使用Quotient来解决需要除法计算的情况.这种类型可以认为是一种把环类型转换成为域类型的配接器.它保存数为分子和分母的形式.使用Homegeneous 后,Homogeneous::FT和Quotient等价,同时Homogeneous::RT和RingNumberType等价.
Homogeneous使用引用计数.CGAL同样也提供了没有引用计数技术的Simple_homogeneous.

2.4 命名约定
使用核心类不仅可以避免出问题,而且使得CGAL类具有一致性.
1.    以大写字母开头的名字表示几何对象,像Point,Segment,Triangle.
2.    下划线加上对象的维度,_2,_3或者_d
3.    核心类型加上参数类型比如Cartesian,Homogeneous.

2.5 作为特征类的核心组件
CGAL基本库中的算法与数据结构是由一些特征类来参数化的.这些特征类包含了一类对象和上面算法或数据结构的操作和函数的行为一致.基础库中的大部分的算法与数据结构都可以由核心组件作为特征类.一些算法可以根据传入的几何对象的类型进行自动的推导,从而不需要直接指定.有些类还需要更多的参数.有些则不能使用核心组件.

2.6 选择一种核心组件和预定义核心组件

如果你使用整形的笛卡儿坐标,大部分的几何计算将只使用整形数值.特别是在只使用断言计算的时候.例如点集三角化和凸包计算.这些情况下笛卡儿坐标系是第一选择,即使是使用RingNumberType.你可以使用精度受限的int和long,使用double来表示整形,或者任意精度的整形例如GMP整形的包装类GMPZ,lead_integer,或者MP_Float.要注意,除非使用任意精度的环类型,溢出将会产生错误.

如果出现新建点的情况,比如求两条直线的交点,笛卡儿坐标中的计算经常出现除法.因此使用笛卡儿坐标的时候需要FieldNumberType.相对的,转换到齐次坐标的时候也一样.double是一个不精确的FieldNumberType.你可以把任何RingNumberType传给Quotient配接器来得到一个FieldNumberType从而可以在笛卡儿坐标系中进行运算.一般来说使用RingNumberType进行齐次坐标运算是比较合适的.其他一些FieldNumberType有leda_rational和leda_real..

如果可靠性对你来说非常重要,使用经过认定的精确计算的数据类型是比较好的选择.Filtered_kernel提供了一种过滤机制使得核心具有既精确又有效率的断言.仍然还有许多人喜欢使用double,因为他们需要速度,而且可以接受近似的结果,甚至可以忍受时不时由于舍入误差而崩溃的算法.

预定义核心组件
为了使用方便,CGAL预定义3个类型
它们都是笛卡儿坐标系核心
它们都支持从double型来建立笛卡儿坐标系里的点
它们用不同的方式处理建立几何对象的问题

---Exact_predicates_exact_constructions:精确的生成几何对象,提供精确的几何断言
---Exact_predicates_exact_construtions_kernel_with_sqrt:和上面一样,但数值类型提供了精确的开方运算
---Exact_predictates_inexact_constructions_kernel:提供精确断言,但是生成几何对象可能存在舍入误差.这对于大部分的CGAL算法来说已经足够了.而且比前面两种情况要快很多.
这三种预定义核心组件都是基于笛卡儿坐标系核心的,只是其构造的域参数类型不同。
我个人建议,内核用基本的笛卡儿坐标系核心,域参数类型用MF_FLOAT或者DOUBLE类型,因为,这样的效率会比其它,对精度对准确度有要求的域参数类型和内核封装类型(其实也是从笛卡儿坐标系核心派生出来的)快。效率最高的Exact_predictates_inexact_constructions_kernel就是Filtered_kernel>

你可能感兴趣的:(CGAL)