File: Gps_agg_op_sweep.h

package info (click to toggle)
cgal 3.6.1-2
  • links: PTS
  • area: non-free
  • in suites: squeeze
  • size: 62,184 kB
  • ctags: 95,782
  • sloc: cpp: 453,758; ansic: 96,821; sh: 226; makefile: 120; xml: 2
file content (295 lines) | stat: -rw-r--r-- 9,456 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
// Copyright (c) 2005  Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you may redistribute it under
// the terms of the Q Public License version 1.0.
// See the file LICENSE.QPL distributed with CGAL.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_agg_op_sweep.h $
// $Id: Gps_agg_op_sweep.h 41153 2007-12-10 23:21:34Z efif $ $Date: 2007-12-11 00:21:34 +0100 (Tue, 11 Dec 2007) $
// 
//
// Author(s)     : Baruch Zukerman <baruchzu@post.tau.ac.il>
//                 Ron Wein        <wein@post.tau.ac.il>

#ifndef CGAL_GSP_AGG_OP_SWEEP_H
#define CGAL_GSP_AGG_OP_SWEEP_H

#include <CGAL/Sweep_line_2.h>
#include <CGAL/Unique_hash_map.h>

CGAL_BEGIN_NAMESPACE

template <class Arrangement_,
          class MetaTraits_,
          class SweepVisitor,
          class CurveWrap,
          class SweepEvent,
          typename Allocator = CGAL_ALLOCATOR(int) >
class Gps_agg_op_sweep_line_2 :
  public Sweep_line_2<MetaTraits_,
                      SweepVisitor,
                      CurveWrap,
                      SweepEvent,
                      Allocator>
{
public:

  typedef Arrangement_                            Arrangement_2;
  typedef MetaTraits_                             Traits_2;
  typedef typename Traits_2::Point_2              Point_2;
  typedef typename Traits_2::X_monotone_curve_2   X_monotone_curve_2;

  typedef typename Arrangement_2::Vertex_handle       Vertex_handle;
  typedef typename Arrangement_2::Halfedge_handle     Halfedge_handle;

  typedef std::pair<Arrangement_2 *,
                    std::vector<Vertex_handle> *>     Arr_entry;

  typedef Sweep_line_2<Traits_2,
                       SweepVisitor,
                       CurveWrap,
                       SweepEvent,
                       Allocator>                 Base;

  typedef SweepEvent                              Event;


  typedef typename Base::Event_queue_iterator     EventQueueIter;
  typedef typename Event::Subcurve_iterator       EventCurveIter;

  typedef typename Base::Base_event               Base_event;
  typedef typename Base_event::Attribute          Attribute;

  typedef typename Base::Base_subcurve            Base_subcurve;
  
  typedef CurveWrap                               Subcurve;

  typedef std::list<Subcurve*>                    SubCurveList;
  typedef typename SubCurveList::iterator         SubCurveListIter; 


  typedef typename Base::Status_line_iterator     StatusLineIter;

public:

  /*!
   * Constructor.
   * \param visitor A pointer to a sweep-line visitor object.
   */
  Gps_agg_op_sweep_line_2 (SweepVisitor* visitor) : 
    Base (visitor)
  {}

  /*!
   * Constructor.
   * \param traits A pointer to a sweep-line traits object.
   * \param visitor A pointer to a sweep-line visitor object.
   */
  Gps_agg_op_sweep_line_2 (Traits_2 *traits, SweepVisitor* visitor) :
    Base(traits, visitor)
  {}

  /*! Perform the sweep. */
  template<class CurveInputIterator>
  void sweep (CurveInputIterator curves_begin,
              CurveInputIterator curves_end,
              unsigned int lower,
              unsigned int upper,
              unsigned int jump,
              std::vector<Arr_entry>& arr_vec)
  {
    CGAL_assertion (this->m_queue->empty() && 
                    this->m_statusLine.size() == 0);

    typedef Unique_hash_map<Vertex_handle, Event *>    Vertices_map;
    typedef typename Traits_2::Compare_xy_2            Compare_xy_2;

    this->m_visitor->before_sweep();
    // Allocate all of the Subcurve objects as one block.
    this->m_num_of_subCurves = std::distance (curves_begin, curves_end);
    this->m_subCurves = 
      this->m_subCurveAlloc.allocate (this->m_num_of_subCurves);

    this->m_curves_pair_set.resize (2 * this->m_num_of_subCurves);

    // Initialize the event queue using the vertices vectors. Note that these
    // vertices are already sorted, we simply have to merge them
    Vertices_map       vert_map;
    Vertex_handle      vh;
    Vertex_handle      invalid_v;
    unsigned int       i = lower;
    unsigned int       n = (arr_vec[i].second)->size();
    unsigned int       j;
    EventQueueIter     q_iter;
    bool               first = true;
    Attribute          event_type;
    Event             *event;

    for (j = 0;
         j < n && (vh = (*(arr_vec[i].second))[j]) != invalid_v;
         j++)
    {
      // Insert the vertices of the first vector one after the other.
      event_type = _type_of_vertex (vh);
      if (event_type == Base_event::DEFAULT)
        continue;

      event = this->_allocate_event (vh->point(), event_type,
                                     ARR_INTERIOR, ARR_INTERIOR);
      // \todo When the boolean set operations are exteneded to support
      //       unbounded curves, we will need here a special treatment.

      #ifndef CGAL_ARRANGEMENT_ON_SURFACE_2_H
        event->set_finite();
      #endif
      
      if (! first)
      {
        q_iter = this->m_queue->insert_after (q_iter, event);
      }
      else
      {
        q_iter = this->m_queue->insert (event);
        first = false;
      }

      vert_map[vh] = event;
    }

    Comparison_result  res = LARGER;
    Compare_xy_2       comp_xy = this->m_traits->compare_xy_2_object();
    EventQueueIter     q_end = this->m_queue->end();

    for (i += jump; i <= upper; i += jump)
    {
      // Merge the vertices of the other vectors into the existing queue.
      q_iter = this->m_queue->begin();
      n = (arr_vec[i].second)->size();

      for (j = 0;
           j < n && (vh = (*(arr_vec[i].second))[j]) != invalid_v;
           j++)
      {
        event_type = _type_of_vertex (vh);
        if (event_type == Base_event::DEFAULT)
          continue;

        while (q_iter != q_end &&
               (res = comp_xy (vh->point(), (*q_iter)->point())) == LARGER)
        {
          ++q_iter;
        }

        if (res == SMALLER || q_iter == q_end)
        {
          event = this->_allocate_event (vh->point(), event_type,
                                         ARR_INTERIOR, ARR_INTERIOR);
          // \todo When the boolean set operations are exteneded to support
          //       unbounded curves, we will need here a special treatment.
          
          #ifndef CGAL_ARRANGEMENT_ON_SURFACE_2_H
             event->set_finite();
          #endif

          this->m_queue->insert_before (q_iter, event);
          vert_map[vh] = event;
        }
        else if (res == EQUAL)
        {
          // In this case q_iter points to an event already associated with
          // the vertex, so we just update the map:
          vert_map[vh] = *q_iter;
        }
      }
    }

    // Go over all curves (which are associated with halfedges) and associate
    // them with the events we have just created.
    unsigned int           index = 0;
    CurveInputIterator     iter;
    Halfedge_handle        he;
    Event                 *e_left;
    Event                 *e_right;

    for (iter = curves_begin; iter != curves_end; ++iter, index++)
    {
      // Get the events associated with the end-vertices of the current
      // halfedge.
      he = iter->data().halfedge();

      CGAL_assertion (vert_map.is_defined (he->source()));
      CGAL_assertion (vert_map.is_defined (he->target()));

      if ((Arr_halfedge_direction)he->direction() == ARR_LEFT_TO_RIGHT)
      {
        e_left = vert_map[he->source()];
        e_right = vert_map[he->target()];
      }
      else
      {
        e_left = vert_map[he->target()];
        e_right = vert_map[he->source()];
      }

      // Create the subcurve object.
      this->m_subCurveAlloc.construct (this->m_subCurves + index,
                                       this->m_masterSubcurve);

      (this->m_subCurves + index)->init (*iter);
      (this->m_subCurves + index)->set_left_event(e_left);
      (this->m_subCurves + index)->set_right_event(e_right);
    
      e_right->add_curve_to_left (this->m_subCurves + index);  
      this->_add_curve_to_right (e_left, this->m_subCurves + index);
    }

    // Perform the sweep:
    this->_sweep();
    this->_complete_sweep();
    this->m_visitor->after_sweep();

    return;
  }
    
private:
   
  /*!
   * Check if the given vertex is an endpoint of an edge we are going
   * to use in the sweep.
   */
  Attribute _type_of_vertex (Vertex_handle v)
  {
    typename Arrangement_2::Halfedge_around_vertex_circulator  first, circ;

    circ = first = v->incident_halfedges();
    do
    {
      // Check if the current edge separates two faces with unequal
      // containment flags (otherwise we will simply not keep it).
      if (circ->face()->contained() != circ->twin()->face()->contained())
      {
        if ((Arr_halfedge_direction)circ->direction() == ARR_LEFT_TO_RIGHT)
          return (Base_event::RIGHT_END);
        else
          return (Base_event::LEFT_END);
      }
      ++circ;

    } while (circ != first);

    // If we reached here, we should not keep this vertex.
    return (Base_event::DEFAULT);
  }
};


CGAL_END_NAMESPACE

#endif