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