CGAL::2D Arrangements


  • 1 前言

1.1  什么是arrangement 

        给定一组平面曲线C,arrangement  将平面细分成零维,一维,二维单元,称为顶点,边和面, Arrangements 在计算几何中无处不在并有广泛的应用。

        C中的曲线可以彼此相交(一条曲线也可以是自相交的,也可以是由几个不相连的分支组成的),而且不一定是x单调的*1。我们用如下两步构造一个C”集合,它是由内部成对不相交的x-单调子曲线组成的。首先,我们将C中的每条曲线分解为极大的x-单调子曲线(以及可能孤立的点),得到集合C ',注意x-单调曲线不能是自交的。然后,我们将C '中的每条曲线分解为C '中不与任何其他曲线(或点)相交的最大连通子曲线。如果C的曲线包含孤立点,。集合C”也可能包含孤立的点。集合C”产生的arrangement  可以方便地嵌入成一个平面图(planar graph),其顶点与曲线端点或孤立点相关联,其边与子曲线相关联。显而易见:。这个图(graph)可以用双连接边表数据结构(DCEL)来表示。

1.2  什么是半边数据结构(DCEL)

        DCEL数据结的主要思想是使用一对有向半边来表示每条边,由于每个半边是有向的,我们说它有一个源顶点(source)和一个目标顶点(target)。半边缘用于分离面,连接顶点(孤立的顶点除外,它是不连接的)。

        如果顶点v是半边e的目标(target),我们说v和e是相互关联的。关联到顶点v的半边形成一个围绕这个顶点顺时针方向的循环链表。

        每个半边e存储一个指向其关联面(ncident face)(位于其左侧的面)的指针。此外,每一个半边之后都有另一个共享同一关联面的半边,使得该半边的目标顶点与下一个半边的源顶点相同。因此,半边在循环链表链接, 并形成链,使链的所有边都关联同一面并沿其边界缠绕。我们称这样的链为边界的连接组件(简称CCB)。

       沿面的边界以逆时针方向环绕的半边称为面的外CCB。我们暂时只考虑有界曲线的排列(arrangement ),以便在每一排列中都恰好存在一个无界面。无边界面没有外部边界。面的边界上的任何其他连接部件称为(或inner CCB),并且可以表示为沿顺时针方向绕着它的半边环绕。注意,一个孔不一定对应于一个单一的面,因为它可能没有面积,或者它可能由几个连通面的组成。每一个面的内部都可能有几个洞(或者根本没有洞)。此外,每个面在其内部可能包含孤立的顶点。

CGAL::2D Arrangements_第1张图片

        图1. 一种内部不相交线段的排列,用一些表示线段的DCEL记录来表示。无界面f0有一个单独的连接组件,在它里面形成一个孔,这个孔由几个面组成。半边e从源顶点v1指向目标顶点v2,这条边,连同它的孪生边e '对应于一条线段,连接与v1和v2相关的点,并将面f1和f2分离。e的前驱e_{prex}和后继e_{next}是构成面f2外边界的链的一部分。面f1有一个更复杂的结构,因为它包含两个洞在它的内部:一个孔由两个相邻的面f3和f4组成,另一个孔由两条边组成。f1的内部也包含两个孤立的顶点u1和u2。

        arrangement 的x-单调曲线嵌入一个称为参数空间的矩形二维区域。参数空间定义为X×Y,其中X和Y是端点在紧实直线上的开、半开或闭区间。令b_l,b_r,b_b,和b_t定义为X和Y的端点,我们通常将这些值称为参数空间边界的左、右、下和上边界。例如,如果参数空间是整个紧致平面,这是包当前支持的唯一选项,

        本章的其余部分组织如下:在 The Main Arrangement Class 一节中,我们详细回顾了 Arrangement_2 类模板的接口,它是Arrangement包中的中心组件。在“Issuing Queries on an Arrangement ”一节中,我们展示了如何发出Arrangement上的查询。在Arrangement包中的Free Functions in the Arrangement Package 一节中,我们回顾了一些重要的对Arrangement进行操作的自由(全局)函数,其中最重要的是自由插入函数。节  Traits Classes 包含了Arrangement包中包含的各种几何特征类的详细描述。利用这些特征类,可以构造不同曲线族的排列。在 The Notification Mechanism一节中,我们将回顾允许外部类跟踪Arrangement实例所经历的更改的通知机制。Extending the DCEL一节解释了如何扩展DCEL记录,如何用它们存储额外的数据,以及如何有效地更新这些数据。在 Overlaying Arrangements一节中,我们介绍叠加两种Arrangement的基本操作。节 Storing the Curve History 描述了Arrangement_with_history_2类模板,它通过在其曲线中存储额外的历史记录来扩展排列。最后,在“ Input/Output Streams”一节中,我们将回顾输入/输出函数的安排。

  • 2. The Main Arrangement Class

        类 Arrangement_2是Arrangement包中的主类。它用于表示平面Arrangement,并提供了构建它们、遍历它们和维护它们所需的接口。Arrangement由几何特征类和DCEL类定义,几何特征类决定形成Arrangement的平面曲线族,DCEL类表示平面细分的拓扑结构。它提供了最少的几何操作集(谓词和构造),用于构造和维护Arrangement并对其进行操作。

        arrangement包的设计是根据需要将arrangement的表示和对其进行操作的各种几何算法分离开来的,以及将平面细分的拓扑和几何方面分离开来的。这种分离由 Arrangement_2模板的两个模板参数表现出来:

  •         Traits模板参数应该用一个 ArrangementBasicTraits_2概念的模型和其他可选的几何特征概念来实例化。ArrangementBasicTraits_2概念的模型定义了x-单调曲线和二维点的类型,分别是X_monotone_curve_2 和 Point_2,并支持它们的基本几何谓词。在本章的第一节中,我们总是使用Arr_segment_traits_2 作为我们的traits类,来构造线段的Arrangement。然而,Arrangement包包含其他几个特征类,可以处理其他类型的曲线,如折线(连续的分段线性曲线)、二次曲线和有理函数的曲线。我们在Section Traits Classes.中举例说明了这些trait类的用法。
  • Dcel模板参数应该用一个类实例化,这个类是ArrangementDcel概念的一个模型。默认值为Arr_default_dcel。然而,在许多应用程序中,有必要扩展DCEL特性;请参阅扩展DCEL小节以获得更多的解释和示例。

2.1 A Simple Program

CGAL::2D Arrangements_第2张图片

        下面列出的简单程序构造了一个由三条线段组成的三角形的平面map。arrangement 的构造是用Arr_segment_traits_2 traits类实例化的,只处理段(segment)。所得到的arrangement 包括两个面,一个有界三角形面和一个无界三角形面。

#include 
#include 
#include 
#include 
#include 
typedef CGAL::Quotient Number_type;
typedef CGAL::Cartesian Kernel;
typedef CGAL::Arr_segment_traits_2 Traits_2;
typedef Traits_2::Point_2 Point_2;
typedef Traits_2::X_monotone_curve_2 Segment_2;
typedef CGAL::Arrangement_2 Arrangement_2;
int main()
{
  Arrangement_2 arr;
  Segment_2 cv[3];
  Point_2 p1 (0, 0), p2 (0, 4), p3 (4, 0);
  cv[0] = Segment_2 (p1, p2);
  cv[1] = Segment_2 (p2, p3);
  cv[2] = Segment_2 (p3, p1);
  CGAL::insert (arr, &cv[0], &cv[3]);
  return (0);
}

2.2 Traversing the Arrangement

        最简单和最基本的arrangement 操作是各种遍历方法,它允许用户系统地查看手边的arrangement 的相关特性。如上所述,这种arrangement 被表示为一个DCEL,它存储了三个容器:顶点、半边和面。因此,Arrangement_2类为这些容器提供了迭代器。例如,vertices_begin()vertices_end()方法返回的对象是arrange顶点有效范围内的Arrangement_2::Vertex_iterator对象,该迭代器的取值类型是 Arrangement_2::Vertex,此外,顶点迭代器类型等效于Arrangement_2::Vertex_handle,它用作指向顶点的指针。所有与arrangement 特性相关的函数都接受句柄类型作为输入参数,并返回句柄类型作为输出。

        除了用于arrangement 顶点、半边和面的迭代器外,arrangement类还提供了edges_begin()和edges_end(),它们返回用于遍历arrangement 边的Arrangement_2::Edge_iterator对象。注意,该迭代器的值类型为arrangement::Halfedge,表示表示边的两个半边中的一个。

2.3 Arrangement顶点的遍历方法

        一个顶点总是与一个几何实体相关联,即与一个Point_2对象相关联,这个对象可以通过嵌套在Arrangement_2中的vertex类的point()方法获得。方法is_isolated()的作用是:确定一个顶点是否是孤立点。incident_halfedges()方法返回一个类型为Arrangement_2:: Halfedge_around_vertex_circulator 的循环器,它允许沿顺时针方向遍历这个循环列表。这个循环器的值类型是halffedge。下面的函数打印给定arrangement 顶点的所有邻居(假设可以使用<<操作符将Point_2类型插入到标准输出中)。arrangement 类型与上面的简单示例相同。

void print_neighboring_vertices (Arrangement_2::Vertex_const_handle v)
{
  if (v->is_isolated()) {
    std::cout << "The vertex (" << v->point() << ") is isolated" << std::endl;
   return;
  }
  Arrangement_2::Halfedge_around_vertex_const_circulator first, curr;
  first = curr = v->incident_halfedges();
  std::cout << "The neighbors of the vertex (" << v->point() << ") are:";
  do {
    // Note that the current halfedge is directed from u to v:
    Arrangement_2::Vertex_const_handle u = curr->source();
    std::cout << " (" << u->point() << ")";
  } while (++curr != first);
  std::cout << std::endl;
}

未完待续。。。。。

注释:*1 如果每一条垂直线与平面曲线C最多相交一次,那么连续的平面曲线C是x单调的。

你可能感兴趣的:(CGAL)