• No results found

Traits-Class Decorators

Arrangement-Traits Classes

5.5 Traits-Class Decorators

Assume that we are given two sets of polyline curves that represent rivers and roads, respectively.

We can construct their arrangement and compute their intersection points. However, we cannot tell the difference between an intersection of two roads (namely a junction) and an intersection of a road and a river (namely a bridge) without storing the type of each curve (road or river in our case), and probably also its name, in an accessible place, such that this information can be retrieved later on. If an efficient retrieval operation is desired, it seems that we cannot use the Arr_polyline_traits_2class template as is, and have to write a new traits class from scratch—

or at least write a new traits class that inherits from Arr_polyline_traits_2 and extends its curve type with the desired information. The Cgal 2D Arrangements package contains traits-class decorators that do exactly that for your convenience.

Geometric traits-class decorators allow you to attach auxiliary data to the geometric objects (curves and points). The data is automatically manipulated by the decorators and distributed to the constructed geometric entities. Additional information can alternatively be maintained by extending the vertex, halfedge, or face types provided by the Dcel class and used by the arrangement; see Section 6.2 for details. In many cases, however, it is convenient to attach the data to the curve itself, exploiting the automatic proliferation of the additional data fields from each curve to all its induced subcurves. Moreover, as two halfedges are associated with a single curve, storing the data once in the curve record either saves space or avoids an indirect access from one halfedge to its twin.

The 2D Arrangements package includes a traits-class decorator used to attach a data field to curves and to x-monotone curves. It is a class template named Arr_curve_data_traits_

2<BaseTraits, XMonotoneCurveData, Merge, CurveData, Convert>parameterized by a base-traits class, which must be substituted with one of the geometric base-traits models described in the previous sections or with a user-defined traits model, when the decorator is instantiated. The curve-data decorator derives from the base-traits class, and in particular inherits its Point_2 type. The remaining nested types are defined as follows:

• Curve_2 is derived from the basic type BaseTraits::Curve_2, extending it by an extra field of type CurveData.

• X_monotone_curve_2 is derived from the basic type BaseTraits::X_monotone_curve_2, extending it by an extra field of type XMonotoneCurveData, which must model the con-cepts CopyConstructible, Comparable,21 and DefaultConstructible. The latter ensures that every instance of the class template Arr_curve_data_traits_2 obtained by substituting the BaseTraits template parameter with a model of the ArrangementLandmarkTraits_2 concept models theArrangementLandmarkTraits_2 concept as well.

Note that the nested types Curve_2 and X_monotone_curve_2 are not necessarily the same, even if the BaseTraits::Curve_2 and BaseTraits::X_monotone_curve_2 are (as in the case of the line-segment traits class, for example). The extended curve types support the additional methods data()and set_data() for accessing and modifying the data field.

You can create an extended curve (or an extendedx-monotone curve) from a basic curve and a curve-data object. When curves are inserted into an arrangement, they may be split, and the decorator handles their data fields automatically as follows:

• When a curve is subdivided into x-monotone subcurves, its data field of type CurveData is converted to an object of type XMonotoneCurveData using the Convert functor. The object is automatically associated with each of the resultingx-monotone subcurves.

By default the CurveData type is identical to the XMonotoneCurveData type, and the con-version functor Convert is trivially defined. In this case the data field associated with the original curve is just duplicated and stored with thex-monotone subcurves.

21A model of the Comparable concept must support the equality operator.

• When an x-monotone curve is split into two (typically, when it intersects another curve), the decorator class automatically copies its data field to both resulting subcurves.

• When two x-monotone curves, C1 and C2, intersect, the result may include overlapping sections represented as x-monotone curves. In this case the data fields of C1 and C2 are merged into a single XMonotoneCurveData object using the Merge functor, which is supplied as a parameter to the traits class-template. The resulting object is assigned to the data field of the overlapping subcurves.

• Merging two x-monotone curves is allowed only when (i) the two curves are geometrically mergeable—that is, the base-traits class allows them to merge—and (ii) the two curves store the same data field.

s4

s5

s6

s1

s2

s3

Example: Another decorator supported by the 2D Arrangements package is the Arr_consolidated_

curve_data_traits_2<BaseTraits, Data> class tem-plate. It derives from the Arr_curve_data_traits_

2 class template, and it extends the basic type BaseTraits::Curve_2 by a single Data field, and the basic type BaseTraits::X_monotone_curve_2 with a set of (distinct) data objects. The Data type must model the concept Comparable to ensure that each set contains only distinct data objects with no duplicates.

When a curve with a data field d is subdivided into x-monotone subcurves, each subcurve is associated with a set S = {d}. In the case of an overlap between two x-monotone curves c1 and c2 with associated data sets S1 and S2, respectively, the overlapping subcurve is as-sociated with the consolidated set S1∪ S2.

The example below uses Arr_segment_traits_2 as the base-traits class, attaching an addi-tional color field to the segments using the consolidated curve-data traits class. A color may be either blue or red. Having constructed the arrangement of colored segments, as depicted in the figure on the previous page, we detect the vertices that have incident edges mapped to both blue and red segments. These vertices, drawn as black discs in the figure, correspond to red-blue intersection points. We also locate the edge that corresponds to the overlap between a red line segment and a blue line segment (its endpoints are also drawn as black discs).

// F i l e : ex_consolidated_curve_data . cpp

#include <CGAL/ b a s i c . h>

#include <CGAL/Arr_consolidated_curve_data_traits_2 . h>

#include "arr_exact_construction_segments . h"

enum Segment_color { RED, BLUE } ;

typedef CGAL: : Arr_consolidated_curve_data_traits_2<Traits , Segment_color>

Data_traits ;

typedef Data_traits : : Curve_2 Colored_segment ;

typedef CGAL: : Arrangement_2<Data_traits> Colored_arr ; int main ( )

{

Colored_arr a r r ;

// Construct an arrangement containing three RED l i n e segments .

i n s e r t ( arr , Colored_segment ( Segment( Point (−1, −1), Point (1 , 3)) , RED) ) ; i n s e r t ( arr , Colored_segment ( Segment( Point ( 2 , 0 ) , Point ( 3 , 3 ) ) , RED) ) ; i n s e r t ( arr , Colored_segment ( Segment( Point ( 0 , 3 ) , Point ( 2 , 5 ) ) , RED) ) ; // I n s e r t three BLUE l i n e segments .

i n s e r t ( arr , Colored_segment ( Segment( Point (−1, 3) , Point (4 , 1)) , BLUE) ) ; i n s e r t ( arr , Colored_segment ( Segment( Point (−1, 0) , Point (4 , 1)) , BLUE) ) ; i n s e r t ( arr , Colored_segment ( Segment( Point (−2, 1) , Point (1 , 4)) , BLUE) ) ; //Go over a l l v e r t i c e s and p r i n t j u s t the ones corresponding to i n t e r s e c t i o n // p o i n t s between RED segments and BLUE segments . Skip endpoints o f

// overlapping s e c t i o n s .

Colored_arr : : Vertex_const_iterator v i t ;

for ( v i t = a r r . ver tices_beg in ( ) ; v i t != a r r . vertices_end ( ) ; ++v i t ) {

// Go over the current−vertex incident−halfedges and examine their colors . bool has_red = false , has_blue = fal se ;

Colored_arr : : Halfedge_around_vertex_const_circulator e i t , f i r s t ; e i t = f i r s t = vit−>incident_halfedges ( ) ;

do {

// Get the c o l o r o f the current h a l f e d g e . i f ( e i t−>curve ( ) . data ( ) . size () == 1) {

Segment_color c o l o r = e i t−>curve ( ) . data ( ) . front ( ) ; i f ( c o l o r == RED) has_red = true ;

else i f ( c o l o r == BLUE) has_blue = true ; }

} while (++e i t != f i r s t ) ;

// Print the v e r t e x only i f i n c i d e n t RED and BLUE edges were found . i f ( has_red && has_blue) {

std : : cout << "Red␣ i n t e r s e c t ␣blue␣at␣( " << vit−>point () << ")"<<std : : endl ; }

}

// Locate the edges t h a t correspond to a red−blue overlap . Colored_arr : : Edge_iterator e i t ;

for ( e i t = a r r . edges_begin ( ) ; e i t != a r r . edges_end ( ) ; ++e i t ) {

//Go over t he i n c i d e n t edges o f t he current v e r t e x and examine t h e i r c o l o r s . bool has_red = false , has_blue = fal se ;

Data_traits : : Data_container : : co nst_iter a to r i t ;

for ( i t=e i t−>curve ( ) . data ( ) . begin ( ) ; i t != eit−>curve ( ) . data ( ) . end();++ i t ) {

i f (∗ i t == RED) has_red = true ; else i f (∗ i t == BLUE) has_blue = true ; }

// Print the edge only i f i t corresponds to a red−blue overlap . i f ( has_red && has_blue)

std : : cout << "Red␣ overlap ␣ blue␣ at␣ [ " << e i t−>curve () << " ] "<<std : : endl ; }

return 0 ; }

A D C B Example: The example below uses Arr_polyline_

traits_2 as the base-traits class, attaching an addi-tional name field to each polyline using the generic curve-data traits class. It constructs an arrangement of four polylines, namedA, B, C, and D, as illustrated in the figure to the right. In the case of overlaps, it sim-ply concatenates the names of the overlapping polylines.

At the end of the program the curve associated with the edges that correspond to overlapping polylines are replaced with geometrically equivalent curves, but with different data fields.

// F i l e : ex_generic_curve_data . cpp

#include <s t r i n g>

#include <CGAL/ b a s i c . h>

#include <CGAL/Arr_curve_data_traits_2 . h>

#include " a r r _po lylines . h"

typedef std : : s t r i n g Name; // The name−f i e l d type . struct Merge_names {

Name operator ( ) ( const Name& s1 , const Name& s2 ) const { return( s1 + "␣" + s2 ) ; }

} ;

typedef CGAL: : Arr_curve_data_traits_2<Traits , Name, Merge_names>

Ex_traits ;

typedef Ex_traits : : Curve_2 Ex_polyline ;

typedef Ex_traits : : X_monotone_curve_2 Ex_x_monotone_polyline;

typedef CGAL: : Arrangement_2<Ex_traits> Ex_arrangement;

int main ( ) {

// Construct an arrangement o f fou r p o l y l i n e s named A−−D.

Ex_arrangement a r r ;

Point pts1 [ 5 ] = {Point ( 0 , 0 ) , Point ( 2 , 4 ) , Point ( 3 , 3 ) , Point ( 4 , 4 ) , Point ( 6 , 0 ) } ;

i n s e r t ( arr , Ex_polyline ( P o l y l i n e ( pts1 , pts1 + 5 ) , "A" ) ) ; Point pts2 [ 3 ] = {Point ( 1 , 5 ) , Point ( 3 , 3 ) , Point ( 5 , 5 ) } ; i n s e r t ( arr , Ex_polyline ( P o l y l i n e ( pts2 , pts2 + 3 ) , "B" ) ) ;

Point pts3 [ 4 ] = {Point ( 1 , 0 ) , Point ( 2 , 2 ) , Point ( 4 , 2 ) , Point ( 5 , 0 ) } ; i n s e r t ( arr , Ex_polyline ( P o l y l i n e ( pts3 , pts3 + 4 ) , "C" ) ) ;

Point pts4 [ 2 ] = {Point ( 0 , 2 ) , Point ( 6 , 2 ) } ;

i n s e r t ( arr , Ex_polyline ( P o l y l i n e ( pts4 , pts4 + 2 ) , "D" ) ) ; // Print a l l edges t h a t correspond to an overlapping p o l y l i n e .

Ex_arrangement : : Edge_iterator e i t ;

std : : cout << "The␣ overlapping ␣ subcurves : " << std : : endl ;

for ( e i t = a r r . edges_begin ( ) ; e i t != a r r . edges_end ( ) ; ++e i t ) { i f ( e i t−>curve ( ) . data ( ) . length () > 1) {

std : : cout << "␣␣ [ " << e i t−>curve () << " ] ␣␣"

<< "named: ␣" << e i t−>curve ( ) . data () << std : : endl ; // Modify t he curve a s s o c i a t e d with t he edge .

a r r . modify_edge( e i t , Ex_x_monotone_polyline( e i t−>curve () , "overlap" ) ) ; }

}

return 0 ; }