Arrangement-Traits Classes
5.4 Traits Classes for Algebraic Curves
5.4.1 A Traits Class for Circular Arcs and Line Segments
Arrangements induced by circular arcs and line segments are very useful and frequently arise in applications, where curves of interleaved line segments and circular arcs are used to model the boundaries of complex shapes. Such curves can fit the original boundary more tightly and more compactly than, for example, a simple polyline; see Section 5.7 for more details and references.
We present two applications of arrangements induced by line segments and circular arcs in the following chapters, namely, (i) computing the union of general polygons the boundaries of which comprise line segments and circular arcs (see Section 8.3), and (ii) coordinating two disc robots amidst polygonal obstacles; see Section 9.3.2.
Besides the importance of arrangements of circular arcs and line segments it turns out that it is possible to implement efficient traits models that handle curves restricted to circular arcs and line segments. Rational numbers cannot represent the coordinates of intersection points that may arise in such arrangements in an exact manner. Thus, algebraic numbers must be used. However, the performance impact that (general) algebraic numbers incur can be reduced by the use of an efficient type of exact algebraic numbers called square root extension that uses rational arithmetic in an almost straightforward fashion.
Square root numbers have the formα + β√γ, where α, β, and γ are rational numbers.12 The rational number γ is referred to as the extension. Each subset that has a particular extension is closed under arithmetic operations and order relations; hence, it is a valid algebraic structure.13
The class template CGAL::Sqrt_extension<NT,Root> implements the square root extension type. Instances of this template represent square root numbers. It is equipped with the imple-mentation of a set of arithmetic operations and order relations that exploit identical extensions of operands. It also provides the ability to compare two numbers with different extensions γ1 = γ2
efficiently. Each operation is implemented using only few rational arithmetic operations. Here, NT is the type of α and β, and Root is the type of γ.
The running times of the arithmetic operations and order relations provided by the square root extension when the identical-extension condition is met are comparable to the running times of the corresponding arithmetic operations of rational-number types. The running times of order relations when the condition is not met are only slightly larger. In practice, using number types that represent (arbitrary) algebraic numbers increases the running time of the application significantly.
We call circles whose center coordinates and squared radii are rational numbers rational circles.
The equation of such a circle, that is, (x − x0)2+ (y − y0)2= r2, where(x0, y0) and r denote the circle center and its radius, respectively, has rational coefficients. The coordinates of the points of intersection between two such circles are therefore solutions of quadratic equations with rational coefficients, in other words, algebraic numbers of degree 2 or simply square root numbers. The same applies to intersection points between such a rational circle and a line, or a line segment, with rational coefficients (a line whose equation isax + by + c = 0, where a, b, and c are rational).
The 2D Arrangements package offers a traits class-template called Arr_circle_segment_
traits_2<Kernel> that exclusively handles line segments, circular arcs, and whole circles and models the conceptArrangementTraits_2 (but it does not model the ArrangementLandmarkTraits_
2 concept).14 It exploits efficient computations with square root numbers, which makes it attractive for arrangements induced by line segments, circular arcs, and whole circles. When the traits class-template is instantiated, the Kernel class-template parameter must be substituted with a geometric kernel that models the Kernel concept; see Section 1.4.4 for more details about this concept.
12Square root numbers are also called one-root numbers.
13The term algebraic structure refers to the set closed under one or more operations satisfying some axioms;
see, e.g.,http://en.wikipedia.org/wiki/Algebraic_structure. For example, all numbers that can be expressed asα + β√
K, where α and β are rational and K is a rational constant, compose an algebraic structure.
14It also models the refined concept ArrangementDirectionalXMonotoneTraits_ 2 defined in Chapter 8; see, in addition, Section5.6.
C1
C2
C3
vmax
Observe that the nested type Point_2 defined by the traits class, whose coordinates are typically algebraic numbers of de-gree2, is not the same as the Kernel::Point_2 type, which is only capable of representing a point with rational coordinates.
The coordinates of a point are represented using the number type CoordNT, nested in the traits class-template.
Example: In the example below an arrangement of three full circles is constructed, as shown in the figure to the right. Each circle is split into two x-monotone circular arcs, the endpoints of which are drawn as full discs; rings mark vertices that cor-respond to intersection points. Once the arrangement is con-structed, we locate the vertex of maximal degree in the ar-rangement. The geometric mapping of this vertex, denoted by
vmax, is the point (4, 3), as all three circles intersect at this point and the associated vertex has six incident edges.
// F i l e : ex _circles . cpp
#include " a r r _ c i r c ul a r . h"
int main ( ) {
Arrangement a r r ;
// Create a c i r c l e centered at the o r i g i n with radiu s 5 (C1) . i n s e r t ( arr , Curve( C i r c l e ( Rational_point( 0 , 0 ) , Number_type ( 2 5 ) ) ) ) ; // Create a c i r c l e centered at (7 ,7) with radiu s 5 (C2) .
i n s e r t ( arr , Curve( C i r c l e ( Rational_point( 7 , 7 ) , Number_type ( 2 5 ) ) ) ) ; // Create a c i r c l e centered at (4 ,−0.5) with radius 3.5 (= 7/2) (C3).
Rational_point c3 = Rational_point( 4 , Number_type(−1) / Number_type (2 ));
i n s e r t ( arr , Curve( C i r c l e ( c3 , Number_type (4 9 ) / Number_type ( 4 ) ) ) ) ; // Locate the v e r t e x with maximal degree .
Arrangement : : Vertex_const_iterator v i t = a r r . ver tices_beg in ( ) ; Arrangement : : Vertex_const_handle v_max = v i t ;
for (++v i t ; v i t != a r r . vertices_end ( ) ; ++v i t ) i f ( vit−>degree () > v_max−>degree ()) v_max = vit ;
std : : cout << "The␣ vertex ␣with␣maximal␣ degree␣ in ␣ the␣arrangement␣ i s : ␣"
<< "v_max␣=␣ ( " << v_max−>point () << ")␣"
<< "with␣ degree␣" << v_max−>degree () << " . " << std : : endl ; return 0 ;
}
The types common to the example programs that use the Arr_circle_segment_traits_2 class template are listed below and defined in the header file arr_circular.h. Even though algebraic numbers are required to represent coordinates of points where the inducing curves are circles or circular arcs, such as the curves handled by the Arr_circle_segment_traits_2 class template, an (exact) rational kernel suffices, and a filtered one improves the performance further.
#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 Kernel : :FT Number_type ;
typedef CGAL: : Arr_circle_segment_traits_2<Kernel> Tr a its ;
typedef Tr a its : : CoordNT CoordNT;
typedef Tr a its : : Point_2 Point ;
typedef Tr a its : : Curve_2 Curve ;
typedef Tr a its : : Rational_point_2 Rational_point ;
typedef Tr a its : : Rational_segment_2 Segment ;
typedef Tr a its : : Rational_circle_2 C i r c l e ; typedef CGAL: : Arrangement_2<Traits> Arrangement ;
The Arr_circle_segment_traits_2<Kernel> class template uses the CGAL::Sqrt_
extension class template to represent numbers of the square root extension type.15 The im-pact of substituting Kernel with a filtered kernel as opposed to a non-filtered kernel when the traits class-template is instantiated can be substantial despite the limited use of kernel functors.
Try: Measure the impact of a filtered kernel. Develop a simple program that constructs an ar-rangement ofm line segments and n circular arcs uniformly distributed in the unit square at ran-dom. Use the program to compare the performance of two instances of the Arr_circle_segment_
traits_2<Kernel> class template—one is obtained by substituting the Kernel parameter with the Exact_predicates_exact_construction_kernel type and the other is by substituting it with the non-filtered kernel type Cartesian<Gmpq>.
The Curve_2 type nested in Arr_circle_segment_traits_2 can be used to represent circles, circular arcs, or line segments. We now describe and demonstrate a variety of ways in which the curves of this type can be constructed. A curve object is constructible from a Kernel::Circle_2 object or from a Kernel::Segment_2 object. A circular arc is typically defined by the supporting circle and two endpoints, where the endpoints are objects of type Point_2, with rational or irrational coordinates. The orientation of the arc is determined by the orientation of the supporting circle. Similarly, we also support the construction of line segments given their supporting line (of type Kernel::Line_2) and two endpoints, which may have irrational coordinates (unlike the Kernel::Segment_2type).
Note that the Kernel::Circle_2 type is used to represent a circle whose squared radius is rational, where the radius itself may be irrational. However, if the radius is known to be rational, its use is recommended for efficiency. It is therefore also possible to construct a circle, or a circular arc specifying the circle center (a Kernel::Point_2 object), its rational radius (of type Kernel::FT), and its orientation. Finally, we also support the construction of a circular arc that is defined by two endpoints and an arbitrary interior point that lies on the arc in between its endpoints. In this case, all three points are required to have rational coordinates; namely, they are all given as Kernel::Point_2 objects.
15At the time this book was written the Arr_circle_segment_traits_2 class template still utilized its own im-plementation of the square root extension number type, as it had been developed before the CGAL::Sqrt_extension class template became available. The latter was expected to replace the former soon after.
C1
C2
C3
C4
C5 C6
C7 Example: The example below demonstrates the
usage of the various construction methods for circu-lar arcs and line segments. The resulting arrange-ment is depicted in the figure to the right. Note the usage of the constructor of CoordNT(alpha, beta, gamma), which creates a degree-2 algebraic number whose value isα + β√γ.
// F i l e : ex_circular_arc . cpp
#include " a r r _ c i r c ul a r . h"
#include " arr_print . h"
int main ( ) {
std : : l i s t <Curve> curves ;
// Create a c i r c l e (C1) centered at the o r i g i n with squared radiu s 2 . curves . push_back ( Curve( C i r c l e ( Rational_point( 0 , 0 ) , Number_type ( 2 ) ) ) ) ; // Create a c i r c l e (C2) centered at (2 , 3) with radiu s 3/2. Note t h a t // as the radiu s i s r a t i o n a l we use a d i f f e r e n t curve constru ctor . Number_type three_halves = Number_type (3 ) / Number_type ( 2 ) ;
curves . push_back ( Curve( Rational_point( 2 , 3 ) , three_halves ) ) ;
// Create a segment (C3) o f the l i n e ( y = x ) with r a t i o n a l endpoints . Segment s3 = Segment( Rational_point(−2, −2), Rational_point(2 , 2));
curves . push_back ( Curve( s3 ) ) ;
// Create a l i n e segment (C4) with the same su pporting l i n e ( y = x ) , but // having one endpoint with i r r a t i o n a l c o e f f i c i e n t s .
CoordNT sqrt_15 = CoordNT( 0 , 1 , 1 5 ) ; // = s q r t (15) curves . push_back ( Curve( s3 . supporting_line ( ) ,
Point ( 3 , 3 ) , Point ( sqrt_15 , sqrt_15 ) ) ) ;
//Create a c i r c u l a r arc (C5) t h a t i s t he upper h a l f o f the c i r c l e centered at // ( 1 , 1) with squared radiu s 3 . Create t he c i r c l e with c l o c k w i s e orient at ion ,
// so t he arc i s d i r e c t e d from (1 − sqrt (3) , 1) to (1 + sqrt (3) , 1).
Rational_point c5 = Rational_point( 1 , 1 ) ;
C i r c l e c i r c 5 = C i r c l e ( c5 , 3 , CGAL: :CLOCKWISE) ; CoordNT one_minus_sqrt_3 = CoordNT( 1 , −1, 3);
CoordNT one_plus_sqrt_3 = CoordNT( 1 , 1 , 3 ) ; Point s5 = Point (one_minus_sqrt_3 , CoordNT( 1 ) ) ; Point t5 = Point ( one_plus_sqrt_3 , CoordNT( 1 ) ) ; curves . push_back ( Curve( c i r c 5 , s5 , t5 ) ) ;
// Create an arc (C6) o f the u nit c i r c l e , d i r e c t e d c l o c k w i s e from // (−1/2, sqrt (3)/2) to (1/2, sqrt (3)/2).
// The su pporting c i r c l e i s oriented accordingly . Rational_point c6 = Rational_point( 0 , 0 ) ;
Number_type h a l f = Number_type (1 ) / Number_type ( 2 ) ;
CoordNT sqrt_3_div_2 = CoordNT(Number_type ( 0 ) , ha lf , 3 ) ; Point s6 = Point(−half , sqrt_3_div_2) ;
Point t6 = Point ( ha lf , sqrt_3_div_2 ) ;
curves . push_back ( Curve( c6 , 1 , CGAL: :CLOCKWISE, s6 , t6 ) ) ;
// Create a c i r c u l a r arc (C7) defined by two endpoints and a midpoint , // a l l having r a t i o n a l coordinates . This arc i s the upper r i g h t
// qu arter o f a c i r c l e centered at the o r i g i n with radiu s 5 . Rational_point s7 = Rational_point( 0 , 5 ) ;
Rational_point mid7 = Rational_point( 3 , 4 ) ; Rational_point t7 = Rational_point( 5 , 0 ) ; curves . push_back ( Curve( s7 , mid7 , t7 ) ) ;
// Construct the arrangement o f the curves and p r i n t i t s s i z e . Arrangement a r r ;
i n s e r t ( arr , curves . begin ( ) , curves . end ( ) ) ; print_arrangement_size ( a r r ) ;
return 0 ; }
It is also possible to constructx-monotone curves, which represent x-monotone circular arcs or line segments, using similar constructors (full circles are notx-monotone).