1 // Copyright (c) 2006,2007,2008,2009,2010,2011,2012,2013 Tel-Aviv University (Israel).
2 // All rights reserved.
3 //
4 // This file is part of CGAL (www.cgal.org).
5 //
6 // $URL: https://github.com/CGAL/cgal/blob/v5.3/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_construction_ss_visitor.h $
7 // $Id: Arr_construction_ss_visitor.h becf548 2020-08-12T12:46:49+02:00 Simon Giraudot
8 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
9 //
10 //
11 // Author(s)     : Baruch Zukerman <baruchzu@post.tau.ac.il>
12 //                 Ron Wein <wein@post.tau.ac.il>
13 //                 Efi Fogel <efifogel@gmail.com>
14 
15 #ifndef CGAL_ARR_CONSTRUCTION_SS_VISITOR_H
16 #define CGAL_ARR_CONSTRUCTION_SS_VISITOR_H
17 
18 #include <CGAL/license/Arrangement_on_surface_2.h>
19 
20 #ifndef CGAL_ARR_CONSTRUCTION_SS_VISITOR_VERBOSE
21 #define CGAL_ARR_CONSTRUCTION_SS_VISITOR_VERBOSE 0
22 #endif
23 
24 /*! \file
25  *
26  * Definition of the Arr_construction_ss_visitor class-template.
27  */
28 
29 #include <vector>
30 
31 #include <CGAL/Arr_accessor.h>
32 #include <CGAL/Unique_hash_map.h>
33 #include <CGAL/Surface_sweep_2/Default_visitor_base.h>
34 #include <CGAL/Default.h>
35 
36 namespace CGAL {
37 
38 namespace Ss2 = Surface_sweep_2;
39 
40 /*! \struct Integer_hash_function
41  * An auxiliary hash functor for integers.
42  */
43 struct Integer_hash_function {
44   typedef std::size_t result_type;
45 
operatorInteger_hash_function46   std::size_t operator()(unsigned int i) const { return i; }
47 };
48 
49 /*! \class Arr_construction_ss_visitor
50  * A sweep-line visitor for constructing an arrangement embedded on a surface.
51  */
52 template <typename Helper_, typename Visitor_ = Default>
53 class Arr_construction_ss_visitor :
54   public Ss2::Default_visitor_base<typename Helper_::Geometry_traits_2,
55                                    typename Helper_::Event,
56                                    typename Helper_::Subcurve,
57                                    typename Helper_::Allocator,
58                                    typename Default::Get<
59                                      Visitor_,
60                                      Arr_construction_ss_visitor<
61                                        Helper_, Visitor_> >::type>
62 {
63 public:
64   typedef Helper_                                       Helper;
65 
66   typedef typename Helper::Geometry_traits_2            Geometry_traits_2;
67   typedef typename Helper::Event                        Event;
68   typedef typename Helper::Subcurve                     Subcurve;
69   typedef typename Helper::Allocator                    Allocator;
70 
71 private:
72   typedef Geometry_traits_2                             Gt2;
73   typedef Arr_construction_ss_visitor<Helper, Visitor_> Self;
74   typedef typename Default::Get<Visitor_, Self>::type   Visitor;
75   typedef Ss2::Default_visitor_base<Gt2, Event, Subcurve, Allocator, Visitor>
76                                                         Base;
77 
78 public:
79   typedef typename Gt2::X_monotone_curve_2              X_monotone_curve_2;
80   typedef typename Gt2::Point_2                         Point_2;
81 
82 protected:
83   typedef typename Helper::Arrangement_2                Arrangement_2;
84   typedef typename Arrangement_2::Topology_traits       Topology_traits;
85   typedef typename Arrangement_2::Vertex_handle         Vertex_handle;
86   typedef typename Arrangement_2::Halfedge_handle       Halfedge_handle;
87   typedef typename Arrangement_2::Face_handle           Face_handle;
88 
89   typedef typename Base::Event_subcurve_iterator        Event_subcurve_iterator;
90   typedef typename Base::Event_subcurve_reverse_iterator
91     Event_subcurve_reverse_iterator;
92   typedef typename Subcurve::Status_line_iterator       Status_line_iterator;
93 
94   typedef typename Helper::Indices_list                 Indices_list;
95   typedef typename Helper::Halfedge_indices_map         Halfedge_indices_map;
96   typedef Unique_hash_map<unsigned int, Vertex_handle, Integer_hash_function>
97                                                         Iso_vertices_map;
98 
99 protected:
100   Helper m_helper;                          // The helper class.
101 
102   Arrangement_2* m_arr;                     // The arrangement we construct.
103   Topology_traits* m_top_traits;            // The topology-traits class.
104   Arr_accessor<Arrangement_2> m_arr_access; // An arrangement accessor.
105 
106   unsigned int m_sc_counter;                // Counter for subcurves that may
107                                             // represent a hole (the upper
108                                             // subcurves that emarge from event
109                                             // points with only right curves).
110 
111   std::vector<Halfedge_handle> m_sc_he_table; // A table that maps a subcurve
112                                             // index to its halfedge handle,
113                                             // directed from right to left.
114 
115   Iso_vertices_map m_iso_verts_map;         // Maps an index to the isolated
116                                             // vertex.
117 
118   Halfedge_indices_map m_he_indices_table;  // Maps each halfdge to the
119                                             // indices of subcurves that
120                                             // lies below it.
121 
122   const Vertex_handle m_invalid_vertex;     // An invalid vertex handle.
123 
124 public:
125   /*! Constructor. */
Arr_construction_ss_visitor(Arrangement_2 * arr)126   Arr_construction_ss_visitor(Arrangement_2* arr) :
127     m_helper(arr),
128     m_arr(arr),
129     m_top_traits(arr->topology_traits()),
130     m_arr_access(*arr),
131     m_sc_counter(0),
132     m_sc_he_table(1),
133     m_invalid_vertex()
134   { m_helper.set_halfedge_indices_map(m_he_indices_table); }
135 
136   /*! Destructor. */
~Arr_construction_ss_visitor()137   virtual ~Arr_construction_ss_visitor() {}
138 
139   /// \name Sweep-line notifications.
140   //@{
141 
142   /* A notification issued before the sweep process starts. */
143   inline void before_sweep();
144 
145   /* A notification issued after the sweep process stops. */
146   inline void after_sweep();
147 
148   /*!
149    * A notification invoked before the sweep-line starts handling the given
150    * event.
151    */
152   inline void before_handle_event(Event* event);
153 
154   /*!
155    * A notification invoked after the sweep-line finishes handling the given
156    * event.
157    */
158   bool after_handle_event(Event* event, Status_line_iterator iter, bool flag);
159 
160   /*! A notification invoked when a new subcurve is created. */
161   void add_subcurve(const X_monotone_curve_2& cv, Subcurve* sc);
162   //@}
163 
164   /// \name Insertion functions.
165   //@{
166 
167   /*!
168    * Insert the given subcurve in the interior of a face.
169    * \param cv The geometric subcurve.
170    * \param sc The sweep-line subcurve information.
171    * \return A handle to the inserted halfedge.
172    */
173   virtual Halfedge_handle
174   insert_in_face_interior(const X_monotone_curve_2& cv, Subcurve* sc);
175 
176   /*!
177    * Insert the given subcurve given its left end-vertex.
178    * \param cv The geometric entity.
179    * \param prev The predecessor halfedge around the left vertex.
180    * \param sc The sweep-line subcurve information.
181    * \return A handle to the inserted halfedge.
182    */
183   virtual Halfedge_handle
184   insert_from_left_vertex(const X_monotone_curve_2& cv, Halfedge_handle he,
185                           Subcurve* sc);
186 
187   /*!
188    * Insert the given subcurve given its right end-vertex.
189    * \param cv The geometric entity.
190    * \param prev The predecessor halfedge around the right vertex.
191    * \param sc The sweep-line subcurve information.
192    * \return A handle to the inserted halfedge.
193    */
194   virtual Halfedge_handle
195   insert_from_right_vertex(const X_monotone_curve_2& cv,
196                            Halfedge_handle prev,
197                            Subcurve* sc);
198 
199   /*!
200    * Insert the given subcurve given its two end-vertices.
201    * \param cv The geometric subcurve.
202    * \param prev1 The predecessor halfedge around the left vertex.
203    * \param prev2 The predecessor halfedge around the right vertex.
204    * \param sc The sweep-line subcurve information.
205    * \param new_face_created Output: Whether a new face has been created.
206    * \return A handle to the inserted halfedge.
207    */
208   virtual Halfedge_handle insert_at_vertices(const X_monotone_curve_2& cv,
209                                              Halfedge_handle prev1,
210                                              Halfedge_handle prev2,
211                                              Subcurve* sc,
212                                              bool& new_face_created);
213 
214   /*!
215    * Insert an isolated vertex into the arrangement.
216    * \param pt The point associated with the vertex.
217    * \param iter The location of the corresponding event in the status line.
218    * \return A handle to the inserted vertex.
219    */
220   virtual Vertex_handle insert_isolated_vertex(const Point_2& pt,
221                                                Status_line_iterator iter);
222 
223   /*!
224    * Relocate holes and isolated vertices inside a newly created face f2,
225    * that was split from f1 after the insertion of a new edge.
226    * \param he The halfedge that caused the face split. Its incident face is
227    *           the new face f2, and the incident face of its twin is f1.
228    */
229   void relocate_in_new_face(Halfedge_handle he);
230   //@}
231 
232   /*! Get the last event associated with the given subcurve. */
last_event_on_subcurve(Subcurve * sc)233   Event* last_event_on_subcurve(Subcurve* sc) { return sc->last_event(); }
234 
235 private:
236   /// \name Auxiliary functions.
237   //@{
238 
239   /*!
240    * Cast a Traits::Point_2 object into an Arrangement_2::Point_2 object.
241    * These two types may not be the same when the addition visitor inherits
242    * from this base class.
243    */
_point(const Point_2 & p)244   inline const typename Arrangement_2::Point_2& _point(const Point_2& p) const
245   { return (static_cast<const typename Arrangement_2::Point_2&>(p)); }
246 
247   /*!
248    * Cast a Traits::X_monotone_curve_2 object into an
249    * Arrangement_2::X_monotone_curve_2 object.
250    * These two types may not be the same when the addition visitor inherits
251    * from this base class.
252    */
253   inline const typename Arrangement_2::X_monotone_curve_2&
_curve(const X_monotone_curve_2 & cv)254   _curve(const X_monotone_curve_2& cv) const
255   {
256     return (static_cast<const typename Arrangement_2::X_monotone_curve_2&>(cv));
257   }
258 
259   /*! Map the given subcurve index to the given halfedge handle. */
260   void _map_new_halfedge(unsigned int i, Halfedge_handle he);
261   //@}
262 };
263 
264 //-----------------------------------------------------------------------------
265 // Memeber-function definitions:
266 //-----------------------------------------------------------------------------
267 
268 //-----------------------------------------------------------------------------
269 // A notification issued before the sweep process starts.
270 // Notifies the helper that the sweep process now starts.
271 template <typename Hlpr, typename Vis>
before_sweep()272 void Arr_construction_ss_visitor<Hlpr, Vis>::before_sweep()
273 {
274   m_helper.before_sweep();
275   m_arr->set_sweep_mode(true);
276 }
277 
278 
279 //-----------------------------------------------------------------------------
280 // A notification issued after the sweep process stops.
281 template <typename Hlpr, typename Vis>
after_sweep()282 void Arr_construction_ss_visitor<Hlpr, Vis>::after_sweep()
283 {
284   m_arr->clean_inner_ccbs_after_sweep();
285   m_arr->set_sweep_mode(false);
286 }
287 
288 
289 //-----------------------------------------------------------------------------
290 // A notification invoked before the sweep-line starts handling the given
291 // event.
292 //
293 template <class Hlpr, typename Vis>
before_handle_event(Event * event)294 void Arr_construction_ss_visitor<Hlpr, Vis>::before_handle_event(Event* event)
295 {
296 #if CGAL_ARR_CONSTRUCTION_SS_VISITOR_VERBOSE
297   std::cout << "CGAL_CSLV before_handle_event" << std::endl;
298 #endif
299   // We just have to notify the helper class on the event.
300   m_helper.before_handle_event(event);
301 }
302 
303 //-----------------------------------------------------------------------------
304 // A notification invoked after the sweep-line finishes handling the given
305 // event.
306 //
307 template <typename Hlpr, typename Vis>
308 bool Arr_construction_ss_visitor<Hlpr, Vis>::
after_handle_event(Event * event,Status_line_iterator iter,bool)309 after_handle_event(Event* event, Status_line_iterator iter, bool /* flag */)
310 {
311 #if CGAL_ARR_CONSTRUCTION_SS_VISITOR_VERBOSE
312   std::cout << std::endl << "CGAL_CSLV after_handle_event: " << event
313             << std::endl;
314 #endif
315 
316   // Check if the event represents an isolated vertex.
317   if (!event->has_left_curves() && !event->has_right_curves()) {
318     // There are no incident subcurves, so this event is an isolated vertex.
319     // We map the current index to this vertex, and add this index to the
320     // indices list of the curve the vertex "sees" from below.
321     Vertex_handle v = insert_isolated_vertex(event->point(), iter);
322 
323     ++m_sc_counter;
324     m_iso_verts_map[m_sc_counter] = v;
325     _map_new_halfedge(m_sc_counter, Halfedge_handle());
326 
327     if (iter != this->status_line_end()) {
328       // The isolated vertex "sees" the subcurve of the given position from
329       // below.
330       Subcurve* sc_above = *iter;
331       sc_above->add_halfedge_index(m_sc_counter);
332     }
333     else {
334       // The vertex is not located below any valid curve, so we use the helper
335       // class to mark that this index should belong to the current top face.
336 #if CGAL_ARR_CONSTRUCTION_SS_VISITOR_VERBOSE
337       std::cout << "CGAL_CSLV adding a " << m_sc_counter << std::endl;
338 #endif
339       m_helper.add_subcurve_in_top_face(m_sc_counter);
340     }
341 
342     // The event can now be deallocated.
343     return true;
344   }
345 
346   // TODO EBEB 2012-10-16 compile only when non-oblivious
347   if (event->parameter_space_in_x() == CGAL::ARR_LEFT_BOUNDARY) {
348     if (!this->is_status_line_empty()) {
349       Status_line_iterator prev = iter;
350       for (size_t i = 0; i < event->number_of_right_curves(); ++i) --prev;
351       // move items from top face to last inserted curve
352       Indices_list& list_ref = (*prev)->halfedge_indices_list();
353       list_ref.clear();
354       list_ref.splice(list_ref.end(), m_helper.halfedge_indices_list());
355 
356 #if CGAL_ARR_CONSTRUCTION_SS_VISITOR_VERBOSE
357       typename Indices_list::const_iterator it;
358       for (it = list_ref.begin(); it != list_ref.end(); ++it)
359         std::cout << "moved " << *it << " from top to below" << std::endl;
360 #endif
361     }
362   }
363 
364   // Check if the event has only incident subcurves from its right.
365   if (!event->has_left_curves()) {
366     CGAL_assertion(event->has_right_curves());
367 
368     // In case of a finite event that has no incident left curves, it is
369     // associated with a point that may be the leftmost one in a hole.
370     // We give index to the topmost subcurve from the right, and add this
371     // vertex indices list of the curve the event "sees" from below.
372     ++m_sc_counter;
373     (*(event->right_curves_rbegin()))->set_index(m_sc_counter);
374     if (iter != this->status_line_end()) {
375       // The vertex "sees" the subcurve of the given position from below.
376       Subcurve* sc_above = *iter;
377       sc_above->add_halfedge_index(m_sc_counter);
378     }
379     else {
380       // The vertex is not located below any valid curve, so we use the helper
381       // class to mark that this index should belong to the current top face.
382 #if CGAL_ARR_CONSTRUCTION_SS_VISITOR_VERBOSE
383       std::cout << "CGAL_CSLV adding b " << m_sc_counter << std::endl;
384 #endif
385       m_helper.add_subcurve_in_top_face(m_sc_counter);
386     }
387   }
388 
389   // Set the last event of all left subcurve (thus, this event corresponds
390   // to their right endpoint).
391   Event_subcurve_iterator  left_it;
392   for (left_it = event->left_curves_begin();
393        left_it != event->left_curves_end(); ++left_it)
394     (*left_it)->set_last_event(event);
395 
396   // In case there are no right subcurves, the event can be deallocated.
397   if (event->number_of_right_curves() == 0) {
398     // Inform the helper class that the event will soon be deallocated.
399     m_helper.before_deallocate_event(event);
400     return true;
401   }
402 
403   // Mark that all right subcurves incident to the current event are not
404   // in the arrangement yet.
405   event->init_subcurve_in_arrangement_flags(event->number_of_right_curves());
406 
407   // Set the last event of all right subcurve (thus, this event corresponds
408   // to their left endpoint).
409   Event_subcurve_iterator  right_it;
410   for (right_it = event->right_curves_begin();
411        right_it != event->right_curves_end(); ++right_it)
412     (*right_it)->set_last_event(event);
413 
414   // Mark that the event cannot be deallocated just yet.
415   return false;
416 }
417 
418 //-----------------------------------------------------------------------------
419 // A notification invoked when a new subcurve is created.
420 //
421 template <typename Hlpr, typename Vis>
422 void Arr_construction_ss_visitor<Hlpr, Vis>::
add_subcurve(const X_monotone_curve_2 & cv,Subcurve * sc)423 add_subcurve(const X_monotone_curve_2& cv, Subcurve* sc)
424 {
425 #if CGAL_ARR_CONSTRUCTION_SS_VISITOR_VERBOSE
426   std::cout << std::endl << "CGAL_CSLV add_subcurve: " << cv << std::endl;
427 #endif
428 
429   // Obtain all information to perform the insertion of the subcurve into
430   // the arrangement.
431   Event* last_event = last_event_on_subcurve(sc);
432   Halfedge_handle res;
433   Halfedge_handle he_right = this->current_event()->halfedge_handle();
434   Halfedge_handle he_left = last_event->halfedge_handle();
435   const int jump = last_event->compute_halfedge_jump_count(sc);
436 
437   const Halfedge_handle invalid_he;
438 
439 #if CGAL_ARR_CONSTRUCTION_SS_VISITOR_VERBOSE
440   if (last_event->is_closed())
441     std::cout << "CGAL_CSLG lastevent: " << last_event->point() << std::endl;
442   if (he_left != invalid_he) {
443     std::cout << "he_left    : " << &(*he_left) << std::endl;
444     if (!he_left->is_fictitious())
445       std::cout << "he_leftcv  : " << he_left->curve() << std::endl;
446     else std::cout << "he_left    : fictitious" << std::endl;
447     std::cout << "he_leftdir : " << he_left->direction() << std::endl;
448     std::cout << "he_leftfac : " << &(*he_left->face()) << std::endl;
449   }
450   else std::cout << "he_left    : invalid" << std::endl;
451   if (he_right != invalid_he) {
452     std::cout << "he_right   : " << &(*he_right) << std::endl;
453     if (!he_right->is_fictitious())
454       std::cout << "he_rightcv : " << he_right->curve() << std::endl;
455     else std::cout << "he_right   : fictitious" << std::endl;
456     std::cout << "he_rightdir: " << he_right->direction() << std::endl;
457     std::cout << "he_rightfac: " << &(*he_right->face()) << std::endl;
458   } else std::cout << "he_right   : invalid" << std::endl;
459 #endif
460 
461   // Check whether the previous event on the curve is not in the arrangement
462   // yet.
463   if (he_left == invalid_he) {
464     Vertex_handle v_left = last_event->vertex_handle();
465     // Check whether the vertex to be associated with the left end of
466     // the curve has already been created.
467     if ((v_left != m_invalid_vertex) && (v_left->degree() > 0)) {
468       // The left vertex v is a boundary vertex which already has some
469       // incident halfedges. We look for the predecessor halfedge and
470       // insert the curve between two existing vertices.
471       Arr_parameter_space bx = last_event->parameter_space_in_x();
472       Arr_parameter_space by = last_event->parameter_space_in_y();
473       CGAL_assertion((bx != ARR_INTERIOR) || (by != ARR_INTERIOR));
474       he_left = Halfedge_handle
475         (m_top_traits->locate_around_boundary_vertex(&(*v_left), _curve(cv),
476                                                      ARR_MIN_END, bx, by));
477     }
478   }
479   else {
480     // The previous event on the curve is already in the arrangement.
481     // Therefore, we use it to insert the subcurve.
482     // First, we skip some halfedges around the left vertex to get the true
483     // predecessor halfedge for the insertion.
484     for (int i = 0; i < jump; i++) he_left = (he_left->next())->twin();
485 
486 #if CGAL_ARR_CONSTRUCTION_SS_VISITOR_VERBOSE
487     if (jump != 0) {
488       std::cout << "CGAL_CSLV JUMP: " << jump << std::endl;
489       if (!he_left->is_fictitious())
490         std::cout << "he_leftcv  : " << he_left->curve() << std::endl;
491       else std::cout << "he_left    : fictitious" << std::endl;
492       std::cout << "he_leftdir : " << he_left->direction() << std::endl;
493       std::cout << "he_leftfac : " << &(*he_left->face()) << std::endl;
494     }
495 #endif
496   }
497 
498   // Check whether the current event is already in the arrangement
499   if (he_right == invalid_he) {
500     // We do not have handles for any of the curve end, so we insert it in
501     // the interior of a face.
502     Event* curr_event = this->current_event();
503     Vertex_handle v_right = curr_event->vertex_handle();
504     if ((v_right != m_invalid_vertex) && (v_right->degree() > 0)) {
505       // The left vertex v is a boundary vertex which already has some
506       // incident halfedges. We look for the predecessor halfedge and
507       // insert the curve from this right vertex.
508       Arr_parameter_space bx = curr_event->parameter_space_in_x();
509       Arr_parameter_space by = curr_event->parameter_space_in_y();
510       CGAL_assertion((bx != ARR_INTERIOR) || (by != ARR_INTERIOR));
511       he_right = Halfedge_handle
512         (m_top_traits->locate_around_boundary_vertex(&(*v_right), _curve(cv),
513                                                      ARR_MAX_END, bx, by));
514     }
515   }
516 
517   // Check whether the verteices to be associated with the left end and
518   // the right end of the curve have already been created.
519   bool dummy;
520   res = (he_left != invalid_he) ?
521     ((he_right != invalid_he) ?
522      this->insert_at_vertices(cv, he_right, he_left, sc, dummy) :
523      this->insert_from_left_vertex(cv, he_left, sc)) :
524     ((he_right != invalid_he) ?
525      this->insert_from_right_vertex(cv, he_right, sc) :
526      this->insert_in_face_interior(cv, sc));
527 
528 #if CGAL_ARR_CONSTRUCTION_SS_VISITOR_VERBOSE
529   std::cout << "CGAL_CSLV res: " << &(*res) << " with face " << &(*res->face())
530             << " is " << res->direction() << std::endl;
531   std::cout << "CGAL_CSLV twi: " << &(*res->twin()) << " with face "
532             << &(*res->twin()->face()) << " is " << res->twin()->direction()
533             << std::endl;
534 #endif
535 
536   // Make sure that res is a halfedge that is always directed from left to
537   // right (thus its twin is directed from right to left).
538   if (res->direction() != ARR_LEFT_TO_RIGHT) {
539     res = res->twin();
540 #if CGAL_ARR_CONSTRUCTION_SS_VISITOR_VERBOSE
541     std::cout << "CGAL_CSLV twined!" << std::endl;
542 #endif
543   }
544 
545   // Update the last event with the inserted halfegde (if necessary)
546   // and check if we have to update the auxiliary information on the location
547   // of holes.
548   if ((last_event->number_of_left_curves() == 0) &&
549       last_event->is_curve_largest((Subcurve*)sc))
550   {
551     if (last_event->vertex_handle() == m_invalid_vertex)
552       last_event->set_halfedge_handle(res->twin());
553 
554     // If sc has valid index, insert its index to m_sc_he_table.
555     if (sc->has_valid_index()) {
556       CGAL_assertion(res->twin()->direction() == ARR_RIGHT_TO_LEFT);
557       _map_new_halfedge(sc->index(), res->twin());
558     }
559   }
560 
561   // Update the halfedge handle associated with the current event.
562   if (this->current_event()->vertex_handle() == m_invalid_vertex)
563       this->current_event()->set_halfedge_handle(res);
564 
565   // In case the event has no more right subcurves associated with it, we can
566   // deallocate it. Note that we inform the helper class before deallocating
567   // the event.
568   if (((Event*) sc->right_event())==this->current_event() &&
569       last_event->dec_right_curves_counter() == 0)
570   {
571     m_helper.before_deallocate_event(last_event);
572     this->deallocate_event(last_event);
573   }
574 
575   // Clear the list of indices of the subcurve.
576   sc->clear_halfedge_indices();
577 }
578 
579 //-----------------------------------------------------------------------------
580 // Insert the given subcurve in the interior of an arrangement face.
581 //
582 template <typename Hlpr, typename Vis>
583 typename Arr_construction_ss_visitor<Hlpr, Vis>::Halfedge_handle
584 Arr_construction_ss_visitor<Hlpr, Vis>::
insert_in_face_interior(const X_monotone_curve_2 & cv,Subcurve * sc)585 insert_in_face_interior(const X_monotone_curve_2& cv, Subcurve* sc)
586 {
587 #if CGAL_ARR_CONSTRUCTION_SS_VISITOR_VERBOSE
588   std::cout << "CGAL_CSLV insert_in_face_interior\ncurve: " << cv << std::endl;
589 #endif
590 
591   Event* last_event = last_event_on_subcurve(sc);
592   Vertex_handle  v1 = last_event->vertex_handle();
593   CGAL_assertion((v1 == m_invalid_vertex) || (v1->degree() == 0));
594 
595   if (v1 == m_invalid_vertex)
596     // Create the vertex to be associated with the left end of the curve.
597     v1 = m_arr_access.create_vertex(_point(last_event->point()));
598 
599   Event* curr_event = this->current_event();
600   Vertex_handle v2 = curr_event->vertex_handle();
601   CGAL_assertion((v2 == m_invalid_vertex) || (v2->degree() == 0));
602 
603   if (v2 == m_invalid_vertex)
604     // Create the vertex to be associated with the right end of the curve.
605     v2 = m_arr_access.create_vertex(_point(curr_event->point()));
606 
607   // Perform the insertion between the two (currently isolated) vertices in
608   // the interior of the current top face, as given by the helper class.
609   Halfedge_handle res =
610     m_arr_access.insert_in_face_interior_ex(m_helper.top_face(), _curve(cv),
611                                             ARR_LEFT_TO_RIGHT, v1, v2);
612 
613   // Map the new halfedge to the indices list of all subcurves that lie
614   // below it.
615   if (sc->has_halfedge_indices()) {
616     CGAL_assertion(res->twin()->direction() == ARR_RIGHT_TO_LEFT);
617     Indices_list& list_ref = m_he_indices_table[res->twin()];
618     list_ref.clear();
619     list_ref.splice(list_ref.end(), sc->halfedge_indices_list());
620   }
621 
622   // Notify the helper on the creation of the new halfedge.
623   m_helper.add_subcurve(res, sc);
624 
625   return res;
626 }
627 
628 //-----------------------------------------------------------------------------
629 // Insert the given subcurve using its two end-vertices.
630 //
631 template <typename Hlpr, typename Vis>
632 typename Arr_construction_ss_visitor<Hlpr, Vis>::Halfedge_handle
633 Arr_construction_ss_visitor<Hlpr, Vis>::
insert_at_vertices(const X_monotone_curve_2 & cv,Halfedge_handle prev1,Halfedge_handle prev2,Subcurve * sc,bool & new_face_created)634 insert_at_vertices(const X_monotone_curve_2& cv,
635                    Halfedge_handle prev1,
636                    Halfedge_handle prev2,
637                    Subcurve* sc,
638                    bool& new_face_created)
639 {
640 #if CGAL_ARR_CONSTRUCTION_SS_VISITOR_VERBOSE
641   std::cout << "CGAL_CSLV insert_at_vertices:\ncurve:" << cv << std::endl;
642   if (!prev1->is_fictitious())
643     std::cout << "prev1cv   : " << prev1->curve() << std::endl;
644   else std::cout << "prev1     : fictitious" << std::endl;
645   std::cout << "prev1dir  : " << prev1->direction() << std::endl;
646   std::cout << "prev1fac  : " << &(*prev1->face()) << std::endl;
647   if (!prev2->is_fictitious())
648     std::cout << "prev2cv   : " << prev2->curve() << std::endl;
649   else std::cout << "prev2     : fictitious" << std::endl;
650   std::cout << "prev2dir  : " << prev2->direction() << std::endl;
651   std::cout << "prev2fac  : " << &(*prev2->face()) << std::endl;
652 #endif
653 
654   // Use the helper class to determine whether the order of predecessor
655   // halfedges should be swaped, to that the edge directed from prev1->target()
656   // to prev2->target() is incident to the new face (in case a new face is
657   // created).
658   Halfedge_handle res;
659   const bool swap_preds = m_helper.swap_predecessors(this->current_event());
660 
661   // Comment: In some topologies swap_preds is always false,
662   //          thus we use 'false' to disallow swapping
663   //          such that the compiler can optimize awy the
664   //          computation of signs and local/global minima
665   //          that now takes place inside _insert_at_vertices
666   // TODO EBEB 2012-08-06 check whether signs are not needed
667   // it seems that swap_pred is either
668   //   false
669   // if oblivious or
670   //   event->parameter_space_in_x() == CGAL::ARR_INTERIOR &&
671   //   event->parameter_space_in_y() == CGAL::ARR_TOP_BOUNDARY
672   // if not oblivious! But I have the feeling that signs are needed!
673 
674   bool check_swapped_predecessors = true;
675 #if 1
676   res = (swap_preds) ?
677     // if swapping prev2 will become outer of new split face (it it exists)
678     m_arr_access.insert_at_vertices_ex(prev2, _curve(cv), ARR_LEFT_TO_RIGHT,
679                                        prev1->next(), new_face_created,
680                                        check_swapped_predecessors, false) :
681     // usually prev1 is outer of new split face (it it exists)
682     // order is determined by top-traits helper!
683     // "false" disallows swapping of prev1/preve2! ...
684     m_arr_access.insert_at_vertices_ex(prev1, _curve(cv), ARR_RIGHT_TO_LEFT,
685                                        prev2->next(), new_face_created,
686                                        check_swapped_predecessors, false);
687 
688   // ... thus the value should now have changed
689   CGAL_assertion(!check_swapped_predecessors);
690 #else
691   res = m_arr_access.insert_at_vertices_ex(prev1, _curve(cv), ARR_RIGHT_TO_LEFT,
692                                            prev2->next(), new_face_created,
693                                            check_swapped_predecessors);
694   if (check_swapped_predecessors) res = res->twin();
695 #endif
696 
697   // Map the new halfedge to the indices list of all subcurves that lie
698   // below it.
699   if (sc->has_halfedge_indices()) {
700     Halfedge_handle he = res;
701     if (swap_preds) he = he->twin();
702     CGAL_assertion(he->direction() == ARR_RIGHT_TO_LEFT);
703     Indices_list& list_ref = m_he_indices_table[he];
704     list_ref.clear();
705     list_ref.splice(list_ref.end(), sc->halfedge_indices_list());
706   }
707 
708   // Notify the helper on the creation of the new halfedge.
709   // Note that we do this before trying to relocate holes in the new
710   // face (if one is created).
711   m_helper.add_subcurve(res, sc);
712 
713   if (new_face_created) {
714     // TODO EBEB 2012-10-17 needs a tests for outer-outer insertion
715     // In case a new face has been created (pointed by the new halfedge
716     // we obtained), we have to examine the holes and isolated vertices
717     // in the existing face (pointed by the twin halfedge) and relocate
718     // the relevant features in the new face.
719     CGAL_assertion(res->face() != res->twin()->face());
720     this->relocate_in_new_face(res);
721   }
722 
723   return res;
724 }
725 
726 //-----------------------------------------------------------------------------
727 // Insert the given subcurve from a vertex that corresponds to its right end.
728 //
729 template <typename Hlpr, typename Vis>
730 typename Arr_construction_ss_visitor<Hlpr, Vis>::Halfedge_handle
731 Arr_construction_ss_visitor<Hlpr, Vis>::
insert_from_right_vertex(const X_monotone_curve_2 & cv,Halfedge_handle prev,Subcurve * sc)732 insert_from_right_vertex(const X_monotone_curve_2& cv,
733                          Halfedge_handle prev,
734                          Subcurve* sc)
735 {
736 #if CGAL_ARR_CONSTRUCTION_SS_VISITOR_VERBOSE
737   std::cout << "CGAL_CSLV insert_from_right_vertex:\ncurve:" << cv << std::endl;
738   if (!prev->is_fictitious()) {
739     std::cout << "prevcv    : " << prev->curve() << std::endl;
740   } else {
741     std::cout << "prev      : fictitious" << std::endl;
742   }
743   std::cout << "prevdir   : " << prev->direction() << std::endl;
744   std::cout << "prevfac   : " << &(*prev->face()) << std::endl;
745 #endif
746 
747   Event* last_event = last_event_on_subcurve(sc);
748   Vertex_handle v = last_event->vertex_handle();
749   CGAL_assertion((v == m_invalid_vertex) || (v->degree() == 0));
750 
751   // Create the vertex to be associated with the left end of the curve.
752   if (v == m_invalid_vertex)
753     v = m_arr_access.create_vertex(_point(last_event->point()));
754 
755   // Insert the curve given its left vertex and the predecessor around the
756   // right vertex.
757   Halfedge_handle res =
758     m_arr_access.insert_from_vertex_ex(prev, _curve(cv), ARR_RIGHT_TO_LEFT, v);
759 
760   // Map the new halfedge to the indices list of all subcurves that lie
761   // below it.
762   if (sc->has_halfedge_indices()) {
763     CGAL_assertion(res->direction() == ARR_RIGHT_TO_LEFT);
764     Indices_list& list_ref = m_he_indices_table[res];
765     list_ref.clear();
766     list_ref.splice(list_ref.end(), sc->halfedge_indices_list());
767   }
768 
769   // Notify the helper on the creation of the new halfedge.
770   m_helper.add_subcurve(res, sc);
771   return res;
772 }
773 
774 //-----------------------------------------------------------------------------
775 // Insert the given subcurve from a vertex that corresponds to its left end.
776 //
777 template <typename Hlpr, typename Vis>
778 typename Arr_construction_ss_visitor<Hlpr, Vis>::Halfedge_handle
779 Arr_construction_ss_visitor<Hlpr, Vis>::
insert_from_left_vertex(const X_monotone_curve_2 & cv,Halfedge_handle prev,Subcurve * sc)780 insert_from_left_vertex(const X_monotone_curve_2& cv,
781                         Halfedge_handle prev,
782                         Subcurve* sc)
783 {
784 #if CGAL_ARR_CONSTRUCTION_SS_VISITOR_VERBOSE
785   std::cout << "CGAL_CSLV insert_from_left_vertex:\ncurve:" << cv << std::endl;
786   if (!prev->is_fictitious())
787     std::cout << "prevcv    : " << prev->curve() << std::endl;
788   else std::cout << "prev      : fictitious" << std::endl;
789   std::cout << "prevdir   : " << prev->direction() << std::endl;
790   std::cout << "prevfac   : " << &(*prev->face()) << std::endl;
791 #endif
792 
793   Event* curr_event = this->current_event();
794   Vertex_handle v = curr_event->vertex_handle();
795   CGAL_assertion((v == m_invalid_vertex) || (v->degree() == 0));
796 
797   // Create the vertex to be associated with the right end of the curve.
798   if (v == m_invalid_vertex)
799     v = m_arr_access.create_vertex(_point(curr_event->point()));
800 
801   // Insert the curve given its right vertex and the predecessor around the
802   // left vertex.
803   Halfedge_handle  res =
804     m_arr_access.insert_from_vertex_ex(prev, _curve(cv), ARR_LEFT_TO_RIGHT, v);
805 
806   // Map the new halfedge to the indices list of all subcurves that lie
807   // below it.
808   if (sc->has_halfedge_indices()) {
809     CGAL_assertion(res->twin()->direction() == ARR_RIGHT_TO_LEFT);
810     Indices_list& list_ref = m_he_indices_table[res->twin()];
811     list_ref.clear();
812     list_ref.splice(list_ref.end(), sc->halfedge_indices_list());
813   }
814 
815   // Notify the helper on the creation of the new halfedge.
816   m_helper.add_subcurve(res, sc);
817   return res;
818 }
819 
820 //-----------------------------------------------------------------------------
821 // Insert an isolated vertex into the arrangement.
822 //
823 template <typename Hlpr, typename Vis>
824 typename Arr_construction_ss_visitor<Hlpr, Vis>::Vertex_handle
825 Arr_construction_ss_visitor<Hlpr, Vis>::
insert_isolated_vertex(const Point_2 & pt,Status_line_iterator)826 insert_isolated_vertex(const Point_2& pt, Status_line_iterator /* iter */)
827 {
828 #if CGAL_ARR_CONSTRUCTION_SS_VISITOR_VERBOSE
829   std::cout << "CGAL_CSLV insert_isolated_vertex:\npoint:" << pt << std::endl;
830 #endif
831 
832   // Insert the isolated vertex in the interior of the current top face, as
833   // given by the helper class.
834   return m_arr->insert_in_face_interior(_point(pt), m_helper.top_face());
835 }
836 
837 //-----------------------------------------------------------------------------
838 // Reloacte holes and isolated vertices inside a newly created face.
839 //
840 template <typename Hlpr, typename Vis>
841 void Arr_construction_ss_visitor<Hlpr, Vis>::
relocate_in_new_face(Halfedge_handle he)842 relocate_in_new_face(Halfedge_handle he)
843 {
844 #if CGAL_ARR_CONSTRUCTION_SS_VISITOR_VERBOSE
845   std::cout << "CGAL_CSLV relocate" << std::endl;
846   std::cout << "HeCv: " << he->curve() << std::endl;
847   std::cout << "HeDi: " << he->direction() << std::endl;
848 #endif
849 
850   // We use a constant index-map to prvent the introduction of new entries.
851   // When not using a const index-map, erroneous entries might be added!!!
852   const Halfedge_indices_map& const_he_indices_table = m_he_indices_table;
853 
854   // Go along the boundary of the new face.
855   Face_handle new_face = he->face();
856   Halfedge_handle curr_he = he;
857   const Halfedge_handle invalid_he;
858 
859 #if CGAL_ARR_CONSTRUCTION_SS_VISITOR_VERBOSE
860   std::cout << "m_sc_counter: " << m_sc_counter << std::endl;
861   std::cout << "m_sc_he_table: " << m_sc_he_table.size() << std::endl;
862 #endif
863   do {
864     // We are interested only in halfedges directed from right to left.
865     if (curr_he->direction() == ARR_LEFT_TO_RIGHT) {
866       curr_he = curr_he->next();
867       continue;
868     }
869 
870     // Get the indices list associated with the current halfedges, representing
871     // the halfedges and isolated vertices that "see" it from above.
872     const Indices_list& indices_list = const_he_indices_table[curr_he];
873     typename Indices_list::const_iterator itr;
874     for (itr = indices_list.begin(); itr != indices_list.end(); ++itr) {
875       CGAL_assertion(*itr != 0);
876 #if CGAL_ARR_CONSTRUCTION_SS_VISITOR_VERBOSE
877       std::cout << "itr: " << *itr << std::endl;
878 #endif
879 
880       // In case the current subcurve index does not match a valid entry in
881       // m_sc_he_table, we know that this subcurve matches a halfedge that is
882       // not yet mapped. This can happen only if this halfedge is he itself.
883       // As we know that he lies on the outer CCB of the new face, it is
884       // definitely not a hole in the face, therefore we can ignore it.
885       if ((*itr > m_sc_counter) || (*itr >= m_sc_he_table.size())) continue;
886 
887       Halfedge_handle he_on_face = m_sc_he_table[*itr];
888       if (he_on_face == invalid_he) {
889         // If the halfedge handle is invalid, then we have an index for an
890         // isolated vertex. Move this vertex to the new face, if necessary.
891         Vertex_handle v = m_iso_verts_map[*itr];
892         CGAL_assertion(v != m_invalid_vertex);
893         if (v->face() != new_face) {
894           m_arr_access.move_isolated_vertex(v->face(), new_face, v);
895         }
896       }
897       else {
898         // If necessary, move the hole that the halfedge belongs to into the
899         // new face.
900         if ((he_on_face->twin()->face() != new_face) &&
901             he_on_face->twin()->is_on_inner_ccb())
902         {
903           m_arr_access.move_inner_ccb(he_on_face->twin()->face(),
904                                       new_face,
905                                       he_on_face->twin()->ccb());
906 
907           // Perform the relocation process recursively: Namely all holes
908           // and isolated vertices that "see" he_on_face from above should also
909           // be located inside the new face.
910           relocate_in_new_face(he_on_face->twin());
911         }
912       }
913     }
914     curr_he = curr_he->next();
915   } while(curr_he != he);
916 }
917 
918 //-----------------------------------------------------------------------------
919 // Map the given subcurve index to the given halfedge handle.
920 //
921 template <typename Hlpr, typename Vis>
922 void Arr_construction_ss_visitor<Hlpr, Vis>::
_map_new_halfedge(unsigned int i,Halfedge_handle he)923 _map_new_halfedge(unsigned int i, Halfedge_handle he)
924 {
925 #if CGAL_ARR_CONSTRUCTION_SS_VISITOR_VERBOSE
926   std::cout << "map " << i << " to " << he->curve() << " "
927             << he->direction() << std::endl;
928 #endif
929   CGAL_assertion(i != 0);
930   // Resize the index table if needed.
931   if (i >= m_sc_he_table.size()) m_sc_he_table.resize(i+1);
932 
933   // Map the index to the given halfedge handle.
934   m_sc_he_table[i] = he;
935 }
936 
937 } // namespace CGAL
938 
939 #endif
940