CGAL中2D Arrangements学习笔记

本文介绍了CGAL库中的2D Arrangement模块,详细解析了该模块如何将一组平面曲线细分为顶点、边和面,并探讨了高效使用此模块的方法及应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

 

CGAL2D Arrangements学习笔记

转载自:http://hi.baidu.com/lihao102/blog/item/33015f63b69b3b6a0c33fab6.html

 

2D Arrangement类型简介:

给定一组平面曲线,2D Arrangement能够将这组曲线所组成的图形细分成顶点、边和面这些最基本的几何单位。其中给定的曲线能够相互相交,甚至能自相交。其组成的图形在2D Arrangemen中描述成双边连接数据结构(doubly-connected edge list data-structure (D CEL for short))即把一条边变成两条半边来描述,其中,这个数据结构包含了对顶点、边、面的描述。

如上图,通过线段构造的2D Arrangements表现成了顶点(vn)、边(un)、面(fn)的形式。 其中f0是一个没有被包装的面(un_bound),其余都是被包装的面,其中f2为普通的面,f1中包含两个洞f3和f4。至于顶点和边,在这里就不多说了,很简单。需要说明的是对于f0面来说,所有里面的(即f1+f2)组成的为其一个洞。

一个面的边界由一系列的边和点组成,我们称其为a connected component of the boundary(or CCB for short)。这个CCB我们是可以迭代的访问其组成的边和顶点的。

2D Arrangement类型基本使用方法:

1、构造组成
经过研究,2D Arrangement主要由内核、DCEL描述和数据类型组成,其中CGAL提供N种内核来构造一个ARRANGMENT,而我们要用到的基本上就是二维空间中ARRANGMENT的应用,即ARRANGMENT_2,所以下面所说明和讨论的都是基于ARRANGMENT_2的;

在所有的内核之中,据文档介绍Arr_segment_traits_2是一种效率高的内核,所以我也主要以其为研究对象。DCEL一般的就是用默认的DCEL足够了,数据类型则用CGAL::MP_Float。

2、迭代访问
我们可以通过给定的迭代器来访问2D Arrangement。如下代码
template<class Arrangement>
void print_arrangement (const Arrangement& arr)
{
CGAL_precondition (arr.is_valid());
// Print the arrangement vertices.
typename Arrangement::Vertex_const_iterator vit;
std::cout << arr.number_of_vertices() << " vertices:" << std::endl;
for (vit = arr.vertices_begin(); vit != arr.vertices_end(); ++vit)
{
std::cout << "(" << vit->point() << ")";
if (vit->is_isolated())
std::cout << " - Isolated." << std::endl;
else
std::cout << " - degree " << vit->degree() << std::endl;
}

// Print the arrangement edges.
typename Arrangement::Edge_const_iterator    eit;
std::cout << arr.number_of_edges() << " edges:" << std::endl;
for (eit = arr.edges_begin(); eit != arr.edges_end(); ++eit)
std::cout << "[" << eit->curve() << "]" << std::endl;

// Print the arrangement faces.
typename Arrangement::Face_const_iterator    fit;
std::cout << arr.number_of_faces() << " faces:" << std::endl;
for (fit = arr.faces_begin(); fit != arr.faces_end(); ++fit)
print_face<Arrangement> (fit);
return;
}

注:arrangement操作方法比较简单,总有来说就是把一组线段插入到一个arrangement对象中,arrangement会自然的构造DCEL结构来描述线段所能组成的图形(不同的图形复杂度,构造需要的时间也不同),然后就可以迭代的访问其中的几何对象了。

经过研究,arrangement对于相交线段与非相交线段的处理方法,可以是不同的(不同的插入处理),见其例子

经过以上分析,就需要针对我们软件中的例子,进行抽象建模。我们的需求是,给定一组线,找出最小区域和最大外包。仔细一分析,CGAL中的arrangement类完全可以满足我们的需求。对于arrangement也是通过一组线段,就能求出其对应的面(这里可以对应我们的最小区域和最大外包),但在arrangement中只有面的概念,那么怎么样区分最小区域和最大外包呢,上文中提到过,所谓最大外包就是对应的最外面一个面,这个面是un_bound的,其余的面,也是就最小区域是被bound的,所以,针对我们的问题,这个标记应该就能够解决的。

现在的问题就是,我们采用哪一种方法来处理一组线段,是我们在外面自己离散?还是输入最基本的数据,让arrangement自己去离散?这就在于,是自己的离散算法效率高,还是arrangement的效率高。不管怎么样,我们首先还是用一组数据和结果来说明(以下数据采自己CGAL的两个例子。

其中,图A是没有离散的数据,图B是离散了的数据。运行结果如下:

A

B

其中构造图Aarrangement花了11秒多,而构造图Barrangement只花了半秒多。当然,这两份数据不是描述一个图,所以也只仅做参考和学习之用,但这说明了,arrangement对线段离散的时间和线段的复杂性是成正比的。

下面,我将自己构造的数据来说明两者的差据。(数据为横、竖各一百条线组成的简单轴网):

首先是离散了的数据的运行结果:

然后是没有离散的数据运行结果

从这份数据来看,对于简单的线段复杂度,离散与非离散数据表现出来的差异并不是很大。

但我相信,也不能完全根据这份数据盲目的判断,我将加入一些曲线,来判断运行的时间,关于结果,下次再贴。

 

<think>好的,我现在需要回答用户关于CGAL2D Arrangement如何处理圆弧的问题。首先,我得回忆一下CGAL的相关文档和功能。CGAL的Arrangement包主要用于平面上的曲线排列,但默认支持的曲线类型是线段和直线,圆弧可能不是直接支持的。不过,用户提到的是圆弧,所以可能需要用某种方式来近似或表示圆弧。 首先,我应该确认CGAL是否原生支持圆弧作为Arrangement的输入曲线。根据之前的了解,CGAL的Arrangement主要处理线性几何对象,但可以通过一些扩展或间接的方法来处理圆弧。例如,使用圆锥弧(conic arcs)或者贝塞尔曲线,但可能这些属于其他模块,比如Arr_conic_traits_2或Arr_Bezier_curve_traits_2。不过用户的问题明确提到圆弧,可能需要更具体的处理方式。 接下来,考虑到圆弧是圆的一部分,可能需要将圆弧分解为多个线段来近似,这样就能用现有的线段处理功能来构建Arrangement。这种方法虽然可行,但精度和效率可能存在问题,尤其是在需要高精度的情况下,线段数量会增加,影响性能。 另外,CGAL中可能有处理圆弧的几何特征类(traits class)。Traits类在Arrangement中非常重要,它定义了如何处理几何对象。比如,Arr_circle_segment_traits_2这个traits类可能支持圆弧和圆段的处理。需要确认这个类的存在和用法。例如,这个traits类可以处理圆弧、圆段,以及其他二次曲线,可能通过将圆弧表示为有理二次贝塞尔曲线或者其他数学表示。 然后,应该详细说明如何使用这些traits类来处理圆弧。例如,用户需要包含相应的头文件,使用Arrangement_2模板类,并指定对应的traits类。同时,构造圆弧时需要提供圆心、半径、起始角度和终止角度,或者起点、终点和圆上的某个点等方式。 还需要考虑精度问题,因为圆弧的处理涉及到浮点运算或精确计算。CGAL通常支持精确的几何计算,所以使用合适的数值类型(如Exact_predicates_exact_constructions_kernel)可能很重要,以避免由于精度问题导致的错误。 此外,可能存在的限制或注意事项也需要提及。比如,某些操作可能不支持圆弧的直接操作,或者性能上的考虑,分解为线段后的处理效率等。同时,应该给出一个简单的代码示例,说明如何创建圆弧并将其插入Arrangement中,这样用户能有更直观的理解。 最后,要确保回答结构清晰,分步骤说明,并验证所提供的信息是否正确。需要检查CGAL文档中的相关部分,确认Arr_circle_segment_traits_2是否确实支持圆弧,以及构造圆弧的方法是否正确。可能还需要参考具体的示例代码或用户手册,确保建议的方法在实际中可行。</think>CGAL2D Arrangement模块主要用于管理平面曲线的组合结构,但默认情况下不直接支持圆弧。处理圆弧需通过特定几何特征类(traits class)实现,具体步骤如下: --- ### 1. **使用支持圆弧的几何特征类** CGAL提供`Arr_circle_segment_traits_2`特征类,可处理圆弧、圆段和其他二次曲线(如椭圆弧)。 - **原理**:将圆弧表示为有理二次贝塞尔曲线,通过精确计算交点与拓扑关系。 - **头文件**:需包含`#include <CGAL/Arr_circle_segment_traits_2.h>` --- ### 2. **定义类型与对象** ```cpp #include <CGAL/Exact_predicates_exact_constructions_kernel.h> #include <CGAL/Arr_circle_segment_traits_2.h> #include <CGAL/Arrangement_2.h> typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel; typedef CGAL::Arr_circle_segment_traits_2<Kernel> Traits; typedef CGAL::Arrangement_2<Traits> Arrangement; typedef Traits::Curve_2 Curve; typedef Kernel::Circle_2 Circle; typedef Kernel::Point_2 Point; ``` --- ### 3. **构造圆弧** 圆弧可通过以下方式定义: - **圆心+半径+角度范围**: ```cpp Circle circle(Point(0, 0), 5); // 圆心(0,0),半径5 Curve arc(circle, CGAL::CLOCKWISE, Point(5, 0), Point(0, 5)); // 从(5,0)顺时针到(0,5) ``` - **三点构造法**(起点、终点、圆上一点): ```cpp Point p1(5, 0), p2(0, 5), p3(-5, 0); Curve arc = Curve(p1, p3, p2); // 过p1,p2,p3构造圆弧 ``` --- ### 4. **插入Arrangement** ```cpp Arrangement arr; CGAL::insert(arr, arc); ``` - **内部处理**:特征类将圆弧分解为x单调曲线段,确保精确计算交点与拓扑。 --- ### 5. **注意事项** - **精确计算**:推荐使用`Exact_predicates_exact_constructions_kernel`避免数值误差。 - **性能**:复杂圆弧可能增加计算开销,需权衡精度与效率。 - **限制**:非x单调或垂直接近的圆弧需分段处理。 --- ### 示例:构建圆弧Arrangement ```cpp int main() { Traits traits; Arrangement arr(&traits); // 构造圆弧:圆心(0,0), 半径5,从(5,0)顺时针到(0,5) Circle circle(Point(0, 0), 25); // 半径平方=25 Curve arc(circle, CGAL::CLOCKWISE, Point(5, 0), Point(0, 5)); // 插入Arrangement CGAL::insert(arr, arc); return 0; } ``` --- ### 6. **扩展功能** - **查询操作**:利用Arrangement的DCEL结构进行面、边遍历。 - **布尔运算**:结合`CGAL::Arrangement_with_history_2`支持曲线历史的并/交/差操作。 通过上述方法,CGAL能够有效处理圆弧,适用于几何建模、运动规划等场景。建议参考[CGAL官方文档](https://doc.cgal.org/latest/Arrangement_on_surface_2/)获取最新实现细节。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值