1 // Copyright (c) 2012  INRIA Sophia-Antipolis (France).
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/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h $
7 // $Id: Constrained_triangulation_plus_2.h bdc2f3e 2020-10-20T13:28:12+02:00 Sebastien Loriot
8 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
9 //
10 //
11 // Author(s)     : Andreas Fabri, Mariette Yvinec
12 
13 #ifndef CGAL_CONSTRAINED_TRIANGULATION_PLUS_2_H
14 #define CGAL_CONSTRAINED_TRIANGULATION_PLUS_2_H
15 
16 #include <CGAL/license/Triangulation_2.h>
17 
18 #include <CGAL/disable_warnings.h>
19 
20 #include <CGAL/Unique_hash_map.h>
21 #include <CGAL/triangulation_assertions.h>
22 #include <CGAL/Polygon_2.h>
23 #include <CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h>
24 #include <CGAL/Triangulation_2/internal/CTP2_subconstraint_graph.h>
25 #include <boost/tuple/tuple.hpp>
26 #include <boost/type_traits/is_same.hpp>
27 
28 #include <CGAL/Default.h>
29 #include <CGAL/Constrained_Delaunay_triangulation_2.h>
30 #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
31 #include <CGAL/Triangulation_2/insert_constraints.h>
32 
33 #if defined(BOOST_MSVC) && (BOOST_VERSION == 105500)
34 #include <set>
35 #else
36 #include <boost/container/flat_set.hpp>
37 #endif
38 
39 
40 namespace CGAL {
41 
42 // Comparison functor that compares two Vertex_handle.
43 // Used as 'Compare' functor for the constraint hierarchy.
44 template < class Tr >
45 class Pct2_vertex_handle_less_xy {
46   const Tr* tr_p;
47 
48 public:
Pct2_vertex_handle_less_xy(const Tr * tr_p)49   Pct2_vertex_handle_less_xy(const Tr* tr_p) : tr_p(tr_p) {}
50 
51   typedef typename Tr::Vertex_handle Vertex_handle;
52 
operator()53   bool operator()(const Vertex_handle& va,
54                   const Vertex_handle& vb) const
55   {
56     return tr_p->compare_xy(va->point(), vb->point()) == SMALLER;
57   }
58 }; // end class template Pct2_vertex_handle_less_xy
59 
60 // Tr the base triangulation class
61 // Tr has to be Constrained or Constrained_Delaunay with Constrained_triangulation_plus_vertex_base
62 
63 template < class Tr_ = Default >
64 class Constrained_triangulation_plus_2
65   : public
66 Default::Get< Tr_, Constrained_Delaunay_triangulation_2<
67                       Exact_predicates_inexact_constructions_kernel
68                       , Triangulation_data_structure_2<
69                             Triangulation_vertex_base_2<Exact_predicates_inexact_constructions_kernel>
70                           , Constrained_triangulation_face_base_2<Exact_predicates_inexact_constructions_kernel>
71                           >
72                       , CGAL::Exact_predicates_tag
73                       > >::type
74 {
75   typedef typename
76   Default::Get< Tr_, Constrained_Delaunay_triangulation_2<
77                   Exact_predicates_inexact_constructions_kernel
78                   , Triangulation_data_structure_2<
79                         Triangulation_vertex_base_2<Exact_predicates_inexact_constructions_kernel>
80                       , Constrained_triangulation_face_base_2<Exact_predicates_inexact_constructions_kernel>
81                       >
82                   , CGAL::Exact_predicates_tag
83                   > >::type Tr;
84 
85 
86   template<class CDT>
87   class Face_container
88   {
89     typedef typename CDT::Vertex_handle Vertex_handle;
90     typedef typename CDT::Face_handle Face_handle;
91   private:
92     typedef boost::tuple<Vertex_handle, Vertex_handle, Vertex_handle> TFace;
93     std::vector<TFace> faces;
94     CDT& cdt;
95 
96   public:
97     typedef Face_handle value_type;
98     typedef Face_handle& reference;
99     typedef const Face_handle& const_reference;
100 
Face_container(CDT & cdt_)101     Face_container(CDT& cdt_ ) : cdt(cdt_) {}
102 
push_back(Face_handle fh)103     void push_back(Face_handle fh)
104     {
105       faces.push_back(boost::make_tuple(fh->vertex(0),
106                                         fh->vertex(1),
107                                         fh->vertex(2)));
108     }
109 
110     template <class OutputIterator>
111     void
write_faces(OutputIterator out)112     write_faces(OutputIterator out)
113     {
114       for(typename std::vector<TFace>::reverse_iterator
115             it = faces.rbegin(); it != faces.rend(); ++it) {
116         Face_handle fh;
117         if(cdt.is_face(boost::get<0>(*it), boost::get<1>(*it), boost::get<2>(*it), fh)){
118           *out++ = fh;
119         }
120       }
121     }
122   };
123 
124 public:
125   typedef Tr                                   Triangulation;
126   typedef typename Tr::Intersection_tag        Intersection_tag;
127   typedef Constrained_triangulation_plus_2<Tr_> Self;
128   typedef Tr                                   Base;
129 
130 
131 #ifndef CGAL_CFG_USING_BASE_MEMBER_BUG_2
132   using Triangulation::vertices_begin;
133   using Triangulation::vertices_end;
134   using Triangulation::is_infinite;
135   using Triangulation::number_of_vertices;
136 #endif
137 
138   typedef typename Triangulation::Edge             Edge;
139   typedef typename Triangulation::Vertex           Vertex;
140   typedef typename Triangulation::Vertex_handle    Vertex_handle;
141   typedef typename Triangulation::Face_handle      Face_handle;
142   typedef typename Triangulation::Face_circulator  Face_circulator ;
143   typedef typename Triangulation::Vertex_iterator  Vertex_iterator;
144   typedef typename Triangulation::Vertex_circulator  Vertex_circulator;
145   typedef typename Triangulation::Locate_type      Locate_type;
146   typedef typename Triangulation::Line_face_circulator Line_face_circulator;
147   typedef typename Triangulation::Geom_traits      Geom_traits;
148   typedef typename Geom_traits::Point_2            Point;
149   typedef typename Geom_traits::Segment_2          Segment;
150   typedef typename Triangulation::Constraint       Constraint;
151   typedef typename Triangulation::size_type        size_type;
152 
153   typedef typename Triangulation::List_edges       List_edges;
154   typedef typename Triangulation::List_faces       List_faces;
155   typedef typename Triangulation::List_vertices    List_vertices;
156   typedef typename Triangulation::List_constraints List_constraints;
157   typedef typename Triangulation::Constrained_edges_iterator Constrained_edges_iterator;
158 
159   typedef Pct2_vertex_handle_less_xy<Self>         Vh_less_xy;
160   typedef Polyline_constraint_hierarchy_2<Vertex_handle, Vh_less_xy, Point>
161                                                    Constraint_hierarchy;
162 public:
163   // Tag to mark the presence of a hierarchy of constraints
164   typedef Tag_true                                 Constraint_hierarchy_tag;
165 
166   //Tag to distinguish Delaunay from regular triangulations
167   typedef Tag_false                                Weighted_tag;
168 
169   // Tag to distinguish periodic triangulations from others
170   typedef Tag_false                                Periodic_tag;
171 
172   // for user interface with the constraint hierarchy
173   typedef typename Constraint_hierarchy::Vertex_it
174                                             Vertices_in_constraint_iterator;
175 
176   typedef Iterator_range<Vertices_in_constraint_iterator> Vertices_in_constraint;
177 
178   typedef typename Constraint_hierarchy::Point_it
179                                             Points_in_constraint_iterator;
180   typedef Iterator_range<Points_in_constraint_iterator> Points_in_constraint;
181 
182   typedef typename Constraint_hierarchy::Context          Context;
183   typedef typename Constraint_hierarchy::Context_iterator Context_iterator;
184   typedef Iterator_range<Context_iterator>                Contexts;
185 
186   typedef typename Constraint_hierarchy::C_iterator   Constraint_iterator;
187   typedef Iterator_range<Constraint_iterator> Constraints;
188 
189   typedef typename Constraint_hierarchy::Subconstraint_iterator  Subconstraint_iterator;
190   typedef Iterator_range<Subconstraint_iterator> Subconstraints;
191 
192   typedef typename Constraint_hierarchy::Constraint_id Constraint_id;
193 
194   typedef std::pair<Vertex_handle, Vertex_handle> Subconstraint;
195 
196   using Triangulation::geom_traits;
197   using Triangulation::cw;
198   using Triangulation::ccw;
199   using Triangulation::incident_faces;
200 
201 protected:
202   Constraint_hierarchy hierarchy;
203 
204 public:
hierarchy_ref()205   Constraint_hierarchy& hierarchy_ref()
206   {
207     return hierarchy;
208   }
209 
210   Constrained_triangulation_plus_2(const Geom_traits& gt=Geom_traits())
Triangulation(gt)211     : Triangulation(gt)
212     , hierarchy(Vh_less_xy(this))
213   { }
214 
Constrained_triangulation_plus_2(const Constrained_triangulation_plus_2 & ctp)215   Constrained_triangulation_plus_2(const Constrained_triangulation_plus_2& ctp)
216     : Triangulation()
217     , hierarchy(Vh_less_xy(this))
218   { copy_triangulation(ctp);}
219 
220   Constrained_triangulation_plus_2(Constrained_triangulation_plus_2&&) = default;
221 
~Constrained_triangulation_plus_2()222   virtual ~Constrained_triangulation_plus_2() {}
223 
224   Constrained_triangulation_plus_2 & operator=(const Constrained_triangulation_plus_2& ctp)
225   {
226     copy_triangulation(ctp);
227     return *this;
228   }
229 
230   Constrained_triangulation_plus_2& operator=(Constrained_triangulation_plus_2&&) = default;
231 
232   template<class InputIterator>
233   Constrained_triangulation_plus_2(InputIterator first,
234                                    InputIterator last,
235                                    const Geom_traits& gt=Geom_traits() )
Triangulation(gt)236      : Triangulation(gt)
237      , hierarchy(Vh_less_xy(this))
238   {
239     insert_constraints(first, last);
240     CGAL_triangulation_postcondition( this->is_valid() );
241   }
242 
243 
244   Constrained_triangulation_plus_2(const std::list<std::pair<Point,Point> > &constraints,
245                                    const Geom_traits& gt=Geom_traits() )
Triangulation(gt)246     : Triangulation(gt)
247      , hierarchy(Vh_less_xy(this))
248   {
249     insert_constraints(constraints.begin(), constraints.end());
250     CGAL_triangulation_postcondition( this->is_valid() );
251   }
252   //Helping
clear()253   void clear() { Base::clear(); hierarchy.clear(); }
254   void copy_triangulation(const Constrained_triangulation_plus_2 &ctp);
255   void swap(Constrained_triangulation_plus_2 &ctp);
256 
257   // INSERTION
258   Vertex_handle insert(const Point& a,
259                        Face_handle start = Face_handle() );
260   Vertex_handle insert(const Point& p,
261                        Locate_type lt,
262                        Face_handle loc, int li );
263 
insert_constraint(const Point & a,const Point & b)264   Constraint_id insert_constraint(const Point& a, const Point& b)
265   {
266     Vertex_handle va= insert(a);
267     // If the segment is "short" it is a good idea to start the next insertion
268     // close to point a
269     // Otherwise, to start here is as good as elsewhere
270     Vertex_handle vb = insert(b, va->face());
271     return insert_constraint(va, vb);
272   }
273 
insert_constraint(const Constraint & c)274   Constraint_id insert_constraint(const Constraint& c)
275   {
276     return insert_constraint(c.first, c.second);
277   }
278 
insert_constraint(Vertex_handle va,Vertex_handle vb)279   Constraint_id insert_constraint(Vertex_handle va, Vertex_handle vb)
280   {
281 #ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS
282   std::cerr << CGAL::internal::cdt_2_indent_level
283             << "CT_plus_2::insert_constraint( #" << va->time_stamp() << "= " << va->point()
284             << " , #" << vb->time_stamp() << "= " << vb->point()
285             << " )\n";
286 #endif // CGAL_CDT_2_DEBUG_INTERSECTIONS
287     // protects against inserting a zero length constraint
288     if(va == vb){
289       return Constraint_id(nullptr);
290     }
291     // protects against inserting twice the same constraint
292     Constraint_id cid = hierarchy.insert_constraint_old_API(va, vb);
293     if (va != vb && (cid != Constraint_id(nullptr)) )  insert_subconstraint(va,vb);
294 
295     return cid;
296   }
297 
298   template < class InputIterator>
299   Constraint_id insert_constraint(InputIterator first, InputIterator last, bool close=false)
300   {
301     return insert_constraint_seq_impl(first, last, close);
302   }
303 
304   template<typename Range>
insert_constraint(const Range & r)305   Constraint_id insert_constraint(const Range& r)
306   {
307     return insert_constraint_seq_impl(r.begin(), r.end(), false);
308   }
309 
310   template < class PolygonTraits_2, class Container>
insert_constraint(const Polygon_2<PolygonTraits_2,Container> & polygon)311   Constraint_id insert_constraint(const Polygon_2<PolygonTraits_2,Container>& polygon)
312   {
313     return insert_constraint_seq_impl(polygon.vertices_begin(), polygon.vertices_end(), true);
314   }
315   /*
316   template<typename InputIterator>
317   size_type insert_constraints(InputIterator first, InputIterator last)
318   {
319     size_type n = 0;
320 
321     for(; first != last; ++first)
322     {
323       if(insert_constraint(*first))
324         ++n;
325     }
326     return n;
327   }
328   */
329 
330   void split_subconstraint_graph_into_constraints(const std::function<bool(Vertex_handle)>& is_terminal
331                                                   = std::function<bool(Vertex_handle)>())
332   {
333     internal::CTP2_graph_visitor<Self> visitor(*this);
334     if (is_terminal)
335       CGAL::split_graph_into_polylines (internal::CTP2_subconstraint_graph<Self>(*this), visitor,
336                                         [&is_terminal](Vertex_handle vh,
337                                                        const internal::CTP2_subconstraint_graph<Self>&) -> bool
338                                         {
339                                           return is_terminal(vh);
340                                         });
341     else
342       CGAL::split_graph_into_polylines (internal::CTP2_subconstraint_graph<Self>(*this), visitor);
343   }
344 
push_back(const Point & p)345   Vertex_handle push_back(const Point& p)
346   {
347     return insert(p);
348   }
349 
push_back(const Constraint & c)350   Constraint_id push_back(const Constraint& c)
351   {
352     return insert_constraint(c.first, c.second);
353   }
354 
355   // for backward compatibility
356   // not const Point&, because otherwise VC6/7 messes it up with
357   // the insert that takes an iterator range
insert(Point a,Point b)358   Constraint_id insert(Point a, Point b) { return insert_constraint(a, b); }
insert(Vertex_handle va,Vertex_handle vb)359   Constraint_id insert(Vertex_handle va, Vertex_handle  vb) { return insert_constraint(va,vb); }
360 
361 
362 
363   template <class PointIterator, class IndicesIterator>
insert_constraints(PointIterator points_first,PointIterator points_beyond,IndicesIterator indices_first,IndicesIterator indices_beyond)364   std::size_t insert_constraints(PointIterator points_first,
365                                  PointIterator points_beyond,
366                                  IndicesIterator indices_first,
367                                  IndicesIterator indices_beyond)
368   {
369     std::vector<Point> points(points_first, points_beyond);
370     return internal::insert_constraints(*this,points, indices_first, indices_beyond);
371   }
372 
373 
374  template <class ConstraintIterator>
insert_constraints(ConstraintIterator first,ConstraintIterator beyond)375   std::size_t insert_constraints(ConstraintIterator first,
376                                  ConstraintIterator beyond)
377   {
378     return internal::insert_constraints(*this,first,beyond);
379   }
380 
381 
382   Vertices_in_constraint_iterator
insert_vertex_in_constraint(Constraint_id cid,Vertices_in_constraint_iterator pos,Vertex_handle vh)383   insert_vertex_in_constraint(Constraint_id cid, Vertices_in_constraint_iterator pos,
384                               Vertex_handle vh)
385   {
386     return insert_vertex_in_constraint(cid, pos, vh, Emptyset_iterator());
387   }
388 
389   Vertices_in_constraint_iterator
remove_vertex_from_constraint(Constraint_id cid,Vertices_in_constraint_iterator pos)390   remove_vertex_from_constraint(Constraint_id cid, Vertices_in_constraint_iterator pos)
391   {
392     return remove_vertex_from_constraint(cid, pos, Emptyset_iterator());
393   }
394 
395 
396   template <class OutputIterator>
397   Vertices_in_constraint_iterator
remove_vertex_from_constraint(Constraint_id cid,Vertices_in_constraint_iterator pos,OutputIterator out)398   remove_vertex_from_constraint(Constraint_id cid, Vertices_in_constraint_iterator pos,
399                                 OutputIterator out)
400   {
401     if(pos == vertices_in_constraint_begin(cid)){
402       ++pos;
403       Constraint_id aux = hierarchy.split2(cid,pos);
404       remove_constraint(aux, out);
405       return pos;
406     }
407 
408     Vertices_in_constraint_iterator it = vertices_in_constraint_end(cid);
409     it--;
410     if(pos == it){
411       --pos;
412       Constraint_id aux = hierarchy.split(cid, pos);
413       remove_constraint(aux, out);
414       return vertices_in_constraint_end(cid);
415     }
416 
417     Vertices_in_constraint_iterator pp = pos;
418     --pp;
419     Vertex_handle a = *pp;
420     pp = pos;
421     ++pp;
422     Vertex_handle b = *pp;
423     --it;
424     Vertices_in_constraint_iterator beg = vertices_in_constraint_begin(cid);
425     ++beg;
426     Face_container<Constrained_triangulation_plus_2> fc(*this);
427 
428     Constraint_id head = nullptr, tail = nullptr;
429     if(pos != beg){
430       // split off head
431       --pos;
432       head = hierarchy.split2(cid, pos);
433       ++pos;
434     }
435     if(pos != it){
436       // split off tail
437       ++pos;
438       tail = hierarchy.split(cid,pos);
439     }
440 
441     Constraint_id aux = insert_constraint(a, b, std::back_inserter(fc));
442     pos = vertices_in_constraint_end(aux);
443     --pos;
444     --pos; // this is not necessarily == vertices_in_constraint_begin(aux);
445     hierarchy.swap(cid, aux);
446     remove_constraint(aux, std::back_inserter(fc));
447 
448     if(head.vl_ptr()){
449       hierarchy.concatenate2(head, cid);
450     }
451 
452     if(tail.vl_ptr()){
453       hierarchy.concatenate(cid, tail);
454     }
455     fc.write_faces(out);
456     ++pos; // we went one too far back because the last vertex gets removed by concatenate
457     return pos;
458   }
459 
460   // Inserts vh before pos
461   // Returns an iterator pointing on the newly inserted vertex
462   // Writes the modified faces to out
463   template <class OutputIterator>
464   Vertices_in_constraint_iterator
insert_vertex_in_constraint(Constraint_id cid,Vertices_in_constraint_iterator pos,Vertex_handle vh,OutputIterator out)465   insert_vertex_in_constraint(Constraint_id cid, Vertices_in_constraint_iterator pos,
466                               Vertex_handle vh, OutputIterator out)
467   {
468     // Insertion before the first vertex
469     if(pos == vertices_in_constraint_begin(cid)){
470       //std::cout << "insertion before first vertex" << std::endl;
471       Constraint_id head = insert_constraint(vh, *pos, out);
472       hierarchy.concatenate2(head, cid);
473       return vertices_in_constraint_begin(cid);
474     }
475 
476     // Insertion after the last vertex
477     if(pos == vertices_in_constraint_end(cid)){
478       //std::cout << "insertion after last vertex" << std::endl;
479       pos--;
480       Constraint_id tail = insert_constraint(*pos, vh, out);
481       pos = vertices_in_constraint_end(tail);
482       --pos;
483       hierarchy.concatenate(cid, tail);
484       return pos;
485     }
486     Vertex_handle b = *pos;
487     --pos;
488     Vertex_handle a = *pos;
489     ++pos;
490     Face_container<Constrained_triangulation_plus_2> fc(*this);
491     Vertices_in_constraint_iterator beg = vertices_in_constraint_begin(cid), vcit;
492     ++beg;
493     vcit = beg;
494     ++beg;
495     // If the constraint consists only of a segment, and we want to insert
496     // in the middle
497     if((pos == vcit) && (beg == vertices_in_constraint_end(cid))){
498       //std::cout << "insertion in constraint which is a segment" << std::endl;
499       Constraint_id aux1 = insert_constraint(a, vh, std::back_inserter(fc));
500       Constraint_id aux2 = insert_constraint(vh, b, std::back_inserter(fc));
501       pos = vertices_in_constraint_begin(aux2);
502       concatenate(aux1, aux2);
503       hierarchy.swap(cid, aux1);
504       remove_constraint(aux1, std::back_inserter(fc));
505       fc.write_faces(out);
506       return pos;
507 
508     }
509     Constraint_id head = nullptr, tail = nullptr;
510     Vertices_in_constraint_iterator bit = vertices_in_constraint_begin(cid);
511     Vertices_in_constraint_iterator pred = pos;
512     --pred;
513     ++bit;
514     if(pos != bit){
515       //std::cout << "split head" << std::endl;
516       head = split(cid, pred);
517       std::swap(head,cid); // split2 does the job
518       pred = vertices_in_constraint_begin(cid);
519       pos = pred;
520       ++pos;
521     }
522     Vertices_in_constraint_iterator eit = vertices_in_constraint_end(cid);
523     --eit;
524     if(pos != eit){
525       //std::cout << "split tail" << std::endl;
526       tail = split(cid, pos);
527     }
528 
529     // make the new constraint
530     Constraint_id aux1 = insert_constraint(a, vh, std::back_inserter(fc));
531     Constraint_id aux2 = insert_constraint(vh, b, std::back_inserter(fc));
532     pos = vertices_in_constraint_begin(aux2);
533     concatenate(aux1, aux2);
534 
535     if(head.vl_ptr()){
536       //std::cout << "concatenate head" << std::endl;
537       remove_constraint(cid, std::back_inserter(fc));
538       hierarchy.concatenate(head, aux1);
539     } else {
540       hierarchy.swap(cid, aux1);
541       remove_constraint(aux1, std::back_inserter(fc));
542       head = cid;
543     }
544 
545     if(tail.vl_ptr()){
546       //std::cout << "concatenate tail" << std::endl;
547       concatenate(head, tail);
548     }
549     fc.write_faces(out);
550     return pos;
551   }
552 
553   template < class InputIterator, class OutputIterator>
insert_constraint(InputIterator first,InputIterator last,OutputIterator out)554   Constraint_id insert_constraint(InputIterator first, InputIterator last, OutputIterator out)
555   {
556     Face_handle hint;
557     Face_container<Constrained_triangulation_plus_2> fc(*this);
558     std::vector<Vertex_handle> vertices;
559     for(;first!= last; first++){
560       Vertex_handle vh = insert(*first, hint);
561       hint = vh->face();
562       // no duplicates
563       if(vertices.empty() || (vertices.back() != vh)){
564         vertices.push_back(vh);
565       }
566     }
567     int n = vertices.size();
568     if(n == 1){
569       return nullptr;
570     }
571     Constraint_id ca = hierarchy.insert_constraint(vertices[0],vertices[1]);
572     insert_subconstraint(vertices[0],vertices[1], std::back_inserter(fc));
573 
574     if(n>2){
575       for(int j=1; j<n-1; j++){
576         hierarchy.append_constraint(ca, vertices[j], vertices[j+1]);
577         insert_subconstraint(vertices[j], vertices[j+1], std::back_inserter(fc));
578       }
579     }
580     for(Vertices_in_constraint_iterator vcit = vertices_in_constraint_begin(ca);
581         vcit != vertices_in_constraint_end(ca);
582         vcit++){
583       insert_incident_faces(vcit, out);
584     }
585     //AF    vertices_in_constraint_begin(ca)->fixed() = true;
586     // Vertices_in_constraint_iterator end = boost::prior(vertices_in_constraint_end(ca));
587     // end->fixed() = true;
588     fc.write_faces(out);
589 
590     return ca;
591   }
592 
593 
594 private:
595   template < class InputIterator>
insert_constraint_seq_impl(InputIterator first,InputIterator last,bool is_polygon)596   Constraint_id insert_constraint_seq_impl(InputIterator first, InputIterator last, bool is_polygon)
597   {
598     Face_handle hint;
599     std::vector<Vertex_handle> vertices;
600     for(;first!= last; first++){
601       Vertex_handle vh = insert(*first, hint);
602       hint = vh->face();
603       // no duplicates
604       if(vertices.empty() || (vertices.back() != vh)){
605         vertices.push_back(vh);
606       }
607     }
608     if(is_polygon && (vertices.size()>1) && (vertices.front() != vertices.back())){
609       vertices.push_back(vertices.front());
610     }
611 
612     std::size_t n = vertices.size();
613     if(n == 1){
614       return nullptr;
615     }
616     CGAL_assertion(n >= 2);
617 
618     Constraint_id ca = hierarchy.insert_constraint(vertices[0],vertices[1]);
619     insert_subconstraint(vertices[0],vertices[1]);
620 
621     if(n>2){
622       for(std::size_t j=1; j<n-1; j++){
623         hierarchy.append_constraint(ca, vertices[j], vertices[j+1]);
624         insert_subconstraint(vertices[j], vertices[j+1]);
625       }
626     }
627 
628     // fix first and last, one is redundant for is_polygon == true
629     // vertices.front()->fixed() = true;
630     // vertices.back()->fixed() = true;
631 
632     return ca;
633   }
634 
635 public:
636 
637   void
file_output(std::ostream & os)638   file_output(std::ostream& os) const
639   {
640     os << static_cast<const Tr&>(*this);
641     Unique_hash_map<Vertex_handle,int> V;
642     int inum = 0;
643     for(Vertex_iterator vit = vertices_begin(); vit != vertices_end() ; ++vit){
644       if(! is_infinite(vit)){
645         V[vit] = inum++;
646       }
647     }
648 
649     for(Constraint_iterator cit = constraints_begin(); cit != constraints_end(); ++cit){
650       os << (*cit).second->all_size();
651       for(Vertex_handle vh : vertices_in_constraint(*cit)){
652          os << " " << V[vh];
653        }
654        os << std::endl;
655     }
656   }
657 
658 
file_input(std::istream & is)659   void file_input(std::istream& is)
660   {
661 
662     is >> static_cast<Tr&>(*this);
663 
664     std::vector<Vertex_handle> V;
665     V.reserve(number_of_vertices());
666     for(Vertex_iterator vit = vertices_begin(); vit != vertices_end() ; ++vit){
667       if(! is_infinite(vit)){
668         V.push_back(vit);
669       }
670     }
671     Constraint_id cid;
672     int n, i0, i1;
673     while(is >> n){
674       is >> i0 >> i1;
675       cid = insert_constraint(V[i0],V[i1]);
676 
677       for(int i = 2; i < n; i++){
678         i0 = i1;
679         is >> i1;
680         Constraint_id cid2 = insert_constraint(V[i0],V[i1]);
681         cid = concatenate(cid, cid2);
682       }
683     }
684   }
685 
686 
687   template <class OutputIterator>
688   typename Constrained_triangulation_plus_2<Tr>::Constraint_id
insert_constraint(Vertex_handle va,Vertex_handle vb,OutputIterator out)689   insert_constraint(Vertex_handle va, Vertex_handle vb, OutputIterator out)
690   {
691     // protects against inserting a zero length constraint
692     if(va == vb){
693     return Constraint_id(nullptr);
694     }
695     // protects against inserting twice the same constraint
696     Constraint_id cid = hierarchy.insert_constraint(va, vb);
697     if (va != vb && (cid != nullptr) )  insert_subconstraint(va,vb,out);
698 
699     for(Vertices_in_constraint_iterator vcit = vertices_in_constraint_begin(cid);
700         vcit != vertices_in_constraint_end(cid);
701         vcit++){
702       insert_incident_faces(vcit, out);
703     }
704     return cid;
705   }
706 
707   virtual Vertex_handle intersect(Face_handle f, int i,
708                                   Vertex_handle vaa,
709                                   Vertex_handle vbb);
710   Vertex_handle intersect(Face_handle f, int i,
711                           Vertex_handle vaa,
712                           Vertex_handle vbb,
713                           No_constraint_intersection_tag);
714   Vertex_handle intersect(Face_handle f, int i,
715                           Vertex_handle vaa,
716                           Vertex_handle vbb,
717                           No_constraint_intersection_requiring_constructions_tag);
718   Vertex_handle intersect(Face_handle f, int i,
719                           Vertex_handle vaa,
720                           Vertex_handle vbb,
721                           Exact_intersections_tag);
722   Vertex_handle intersect(Face_handle f, int i,
723                           Vertex_handle vaa,
724                           Vertex_handle vbb,
725                           Exact_predicates_tag);
726 
727   // REMOVAL
728 
729   template <class OutputIterator>
remove_constraint(Constraint_id cid,OutputIterator out)730   void remove_constraint(Constraint_id cid, OutputIterator out)
731   {
732     std::list<Vertex_handle> vertices(hierarchy.vertices_in_constraint_begin(cid),
733                                       hierarchy.vertices_in_constraint_end(cid));
734 
735     hierarchy.remove_constraint(cid);
736     for(typename std::list<Vertex_handle>::iterator it = vertices.begin(),
737           succ = it;
738         ++succ != vertices.end();
739         ++it){
740       if(! is_subconstraint(*it, *succ)){ // this checks whether other constraints pass
741         Face_handle fh;
742         int i;
743         bool b = Triangulation::is_edge(*it, *succ, fh, i);
744         CGAL_assume(b);
745         Triangulation::remove_constrained_edge(fh,i, out); // this does also flipping if necessary.
746       }
747     }
748   }
remove_constraint(Constraint_id cid)749   void remove_constraint(Constraint_id cid)
750   {
751     remove_constraint(cid, Emptyset_iterator());
752   }
753 
754 
simplify(Vertices_in_constraint_iterator v)755   void simplify(Vertices_in_constraint_iterator v)
756   {
757     Vertices_in_constraint_iterator u = boost::prior(v);
758     Vertices_in_constraint_iterator w = boost::next(v);
759     bool unew = (*u != *w);
760     hierarchy.simplify(u,v,w);
761 
762     Triangulation::remove_incident_constraints(*v);
763 
764     Triangulation::remove(*v);
765 
766     if(unew){
767       Triangulation::insert_constraint(*u, *w);
768     }
769   }
770 
remove_points_without_corresponding_vertex(Constraint_id cid)771   std::size_t remove_points_without_corresponding_vertex(Constraint_id cid)
772   {
773     return hierarchy.remove_points_without_corresponding_vertex(cid);
774   }
remove_points_without_corresponding_vertex()775   std::size_t remove_points_without_corresponding_vertex()
776   {
777     return hierarchy.remove_points_without_corresponding_vertex();
778   }
779 
780 
781   // CONCATENATE AND SPLIT
782 
783   // concatenates two constraints
784   Constraint_id
785   concatenate(Constraint_id first, Constraint_id second);
786 
787   // split a constraint in two constraints, so that vcit becomes the first
788   // vertex of the new constraint
789   // returns the new constraint
790   Constraint_id
791   split(Constraint_id first, Vertices_in_constraint_iterator vcit);
792 
793   // Query of the constraint hierarchy
794   Constraint_iterator constraints_begin() const;
795   Constraint_iterator constraints_end()   const;
constraints()796   Constraints constraints() const
797   {
798     return Constraints(constraints_begin(),constraints_end());
799   }
800 
801   Subconstraint_iterator subconstraints_begin() const;
802   Subconstraint_iterator subconstraints_end() const;
803 
subconstraints()804   Subconstraints subconstraints() const
805   {
806     return Subconstraints(subconstraints_begin(),subconstraints_end());
807   }
808 
809   Context   context(Vertex_handle va, Vertex_handle vb); //AF: const;
810 
811   bool is_subconstraint(Vertex_handle va,
812                         Vertex_handle vb);
813   size_type number_of_enclosing_constraints(Vertex_handle va,
814                                             Vertex_handle vb) const;
815   Context_iterator   contexts_begin(Vertex_handle va,
816                                     Vertex_handle vb) const;
817   Context_iterator   contexts_end(Vertex_handle va,
818                                   Vertex_handle vb) const;
819 
contexts(Vertex_handle va,Vertex_handle vb)820   Contexts contexts(Vertex_handle va, Vertex_handle vb) const
821   {
822     return Contexts(contexts_begin(va,vb),contexts_end(va,vb));
823   }
824 
825   Vertices_in_constraint_iterator vertices_in_constraint_begin(Constraint_id cid) const;
826   Vertices_in_constraint_iterator vertices_in_constraint_end(Constraint_id cid) const;
827 
vertices_in_constraint(Constraint_id cid)828   Vertices_in_constraint vertices_in_constraint(Constraint_id cid) const
829   {
830     return Vertices_in_constraint(vertices_in_constraint_begin(cid), vertices_in_constraint_end(cid));
831   }
832 
833   Points_in_constraint_iterator points_in_constraint_begin(Constraint_id cid) const;
834   Points_in_constraint_iterator points_in_constraint_end(Constraint_id cid) const ;
835 
points_in_constraint(Constraint_id cid)836   Points_in_constraint points_in_constraint(Constraint_id cid) const
837   {
838     return Points_in_constraint(points_in_constraint_begin(cid), points_in_constraint_end(cid));
839   }
840 
number_of_constraints()841   size_type number_of_constraints() {
842     return static_cast<size_type> (hierarchy.number_of_constraints());}
number_of_subconstraints()843   size_type number_of_subconstraints(){
844     return static_cast<size_type> (hierarchy.number_of_subconstraints());}
845 
846   // public member, used by Mesh_2::Refine_edges
split_constraint(Vertex_handle v1,Vertex_handle v2,Vertex_handle va)847   void split_constraint(Vertex_handle v1, Vertex_handle v2,
848                         Vertex_handle va) {
849     hierarchy.split_constraint(v1,v2,va);
850   }
851 
852 protected:
853   template <class OutputItertator>
insert_incident_faces(Vertices_in_constraint_iterator vcit,OutputItertator out)854   void insert_incident_faces(Vertices_in_constraint_iterator vcit, OutputItertator out)
855   {
856     Vertex_handle vh = *vcit;
857     Face_circulator fc = incident_faces(vh), done = fc;
858     Face_circulator null ;
859     if ( fc != null )
860     {
861       do {
862         Face_handle fh = fc;
863         out = fh;
864         out++;
865         fc++;
866       }while(fc != done);
867     }
868   }
869 
870 
871 void
insert_subconstraint(Vertex_handle vaa,Vertex_handle vbb)872 insert_subconstraint(Vertex_handle vaa,
873                      Vertex_handle vbb)
874   {
875     insert_subconstraint(vaa,vbb,Emptyset_iterator());
876   }
877 
878 
879 
880 
881 template <class OutputItertator>
882 void
insert_subconstraint(Vertex_handle vaa,Vertex_handle vbb,OutputItertator out)883 insert_subconstraint(Vertex_handle vaa,
884                      Vertex_handle vbb,
885                      OutputItertator out)
886   // insert the subconstraint [vaa vbb]
887   // it will eventually be split into several subconstraints
888 {
889 #ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS
890   std::cerr << CGAL::internal::cdt_2_indent_level
891             << "CT_plus_2::insert_subconstraint( #" << vaa->time_stamp() << "= " << vaa->point()
892             << " , #" << vbb->time_stamp() << "= " << vbb->point()
893             << " )\n";
894   internal::Indentation_level::Exit_guard exit_guard = CGAL::internal::cdt_2_indent_level.open_new_scope();
895   std::cerr << CGAL::internal::cdt_2_indent_level
896             << "CT_plus_2::insert_constraint stack push [va, vb] ( #" << vaa->time_stamp() << "= " << vaa->point()
897             << " , #" << vbb->time_stamp() << "= " << vbb->point()
898             << " )\n";
899 #endif // CGAL_CDT_2_DEBUG_INTERSECTIONS
900   std::stack<std::pair<Vertex_handle, Vertex_handle> > stack;
901   stack.push(std::make_pair(vaa,vbb));
902 
903   while(! stack.empty()){
904     boost::tie(vaa,vbb) = stack.top();
905     stack.pop();
906     CGAL_triangulation_precondition( vaa != vbb);
907 #ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS
908     std::cerr << CGAL::internal::cdt_2_indent_level
909               << "CT_plus_2::insert_subconstraint, stack pop=( #" << vaa->time_stamp() << "= " << vaa->point()
910               << " , #" << vbb->time_stamp() << "= " << vbb->point()
911               << " ) remaining stack size: "
912               << stack.size() << '\n';
913     CGAL_assertion(this->is_valid());
914 #endif // CGAL_CDT_2_DEBUG_INTERSECTIONS
915     Vertex_handle vi;
916 
917     Face_handle fr;
918     int i;
919     if(this->includes_edge(vaa,vbb,vi,fr,i)) {
920 #ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS
921     std::cerr << CGAL::internal::cdt_2_indent_level
922               << "CT_plus_2::insert_subconstraint, the segment ( #" << vaa->time_stamp() << "= " << vaa->point()
923               << " , #" << vbb->time_stamp() << "= " << vbb->point()
924               << " ) is an edge with #"
925               << vi->time_stamp() << "= " << vi->point()
926               << '\n';
927 #endif // CGAL_CDT_2_DEBUG_INTERSECTIONS
928       this->mark_constraint(fr,i);
929       if (vi != vbb)  {
930         hierarchy.split_constraint(vaa,vbb,vi);
931 #ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS
932   std::cerr << CGAL::internal::cdt_2_indent_level
933             << "CT_plus_2::insert_constraint (includes_edge) stack push [vi, vbb] ( #" << vi->time_stamp() << "= " << vi->point()
934             << " , #" << vbb->time_stamp() << "= " << vbb->point()
935             << " )\n";
936 #endif // CGAL_CDT_2_DEBUG_INTERSECTIONS
937         stack.push(std::make_pair(vi,vbb));
938       }
939       continue;
940     }
941 
942     List_faces intersected_faces;
943     List_edges conflict_boundary_ab, conflict_boundary_ba;
944 
945     bool intersection  = this->find_intersected_faces(
946                                                       vaa, vbb,
947                                                       intersected_faces,
948                                                       conflict_boundary_ab,
949                                                       conflict_boundary_ba,
950                                                       vi);
951 
952     if ( intersection) {
953       if (vi != vaa && vi != vbb) {
954         hierarchy.split_constraint(vaa,vbb,vi);
955 #ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS
956   std::cerr << CGAL::internal::cdt_2_indent_level
957             << "CT_plus_2::insert_constraint stack push [vaa, vi] ( #" << vaa->time_stamp() << "= " << vaa->point()
958             << " , #" << vi->time_stamp() << "= " << vi->point()
959             << " )\n";
960   std::cerr << CGAL::internal::cdt_2_indent_level
961             << "CT_plus_2::insert_constraint stack push [vi, vbb] ( #" << vi->time_stamp() << "= " << vi->point()
962             << " , #" << vbb->time_stamp() << "= " << vbb->point()
963             << " )\n";
964 #endif // CGAL_CDT_2_DEBUG_INTERSECTIONS
965         stack.push(std::make_pair(vaa,vi));
966         stack.push(std::make_pair(vi,vbb));
967       }
968       else {
969 #ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS
970   std::cerr << CGAL::internal::cdt_2_indent_level
971             << "CT_plus_2::insert_constraint stack push [vaa, vbb]( #" << vaa->time_stamp() << "= " << vaa->point()
972             << " , #" << vbb->time_stamp() << "= " << vbb->point()
973             << " )\n";
974 #endif // CGAL_CDT_2_DEBUG_INTERSECTIONS
975         stack.push(std::make_pair(vaa,vbb));
976       }
977 
978       continue;
979     }
980 
981 
982     //no intersection
983 
984     List_edges edges(conflict_boundary_ab);
985     std::copy(conflict_boundary_ba.begin(), conflict_boundary_ba.end(), std::back_inserter(edges));
986 
987     // edges may contain mirror edges. They no longer exist after triangulate_hole
988     // so we have to remove them before calling get_bounded_faces
989     if(! edges.empty()){
990 
991 #if defined(BOOST_MSVC) && (BOOST_VERSION == 105500)
992       std::set<Face_handle> faces(intersected_faces.begin(), intersected_faces.end());
993 #else
994       boost::container::flat_set<Face_handle> faces(intersected_faces.begin(), intersected_faces.end());
995 #endif
996       for(typename List_edges::iterator it = edges.begin(); it!= edges.end();){
997         if(faces.find(it->first) != faces.end()){
998           typename List_edges::iterator it2 = it;
999           ++it;
1000           edges.erase(it2);
1001         }else {
1002           ++it;
1003         }
1004       }
1005     }
1006 
1007     this->triangulate_hole(intersected_faces,
1008                            conflict_boundary_ab,
1009                            conflict_boundary_ba);
1010 
1011     this->get_bounded_faces(edges.begin(),
1012                             edges.end(),
1013                             out);
1014 
1015     if (vi != vbb) {
1016       hierarchy.split_constraint(vaa,vbb,vi);
1017       stack.push(std::make_pair(vi,vbb));
1018     }
1019   }
1020 }
1021 
1022 
1023 
1024   //to debug
1025 public:
print_hierarchy()1026   void print_hierarchy() { hierarchy.print(); }
1027 
1028   //template member functions
1029 public:
1030   template < class InputIterator >
1031 #if defined(_MSC_VER)
1032   std::ptrdiff_t insert(InputIterator first, InputIterator last, int i = 0)
1033 #else
1034     std::ptrdiff_t insert(InputIterator first, InputIterator last)
1035 #endif
1036   {
1037 #if defined(_MSC_VER)
1038     CGAL_USE(i);
1039 #endif
1040     size_type n = this->number_of_vertices();
1041 
1042     std::vector<Point> points (first, last);
1043 
1044     spatial_sort (points.begin(), points.end(), geom_traits());
1045 
1046     Face_handle hint;
1047     for (typename std::vector<Point>::const_iterator p = points.begin(), end = points.end();
1048             p != end; ++p)
1049         hint = insert (*p, hint)->face();
1050 
1051     return this->number_of_vertices() - n;
1052   }
1053 
1054 };
1055 
1056 template <class Tr>
1057 void
1058 Constrained_triangulation_plus_2<Tr>::
copy_triangulation(const Constrained_triangulation_plus_2 & ctp)1059 copy_triangulation(const Constrained_triangulation_plus_2 &ctp)
1060 {
1061   Base::copy_triangulation(ctp);
1062   //the following assumes that the triangulation and its copy
1063   // iterate on their vertices in the same order
1064   std::map<Vertex_handle,Vertex_handle> vmap;
1065   Vertex_iterator vit = ctp.vertices_begin();
1066   Vertex_iterator vvit = this->vertices_begin();
1067   for( ; vit != ctp.vertices_end(); ++vit, ++vvit) {
1068     CGAL_triangulation_assertion(vit->point() == vvit->point());
1069     vmap[vit] = vvit;
1070   }
1071   hierarchy.copy(ctp.hierarchy, vmap);
1072 }
1073 
1074 template <class Tr>
1075 void
1076 Constrained_triangulation_plus_2<Tr>::
swap(Constrained_triangulation_plus_2 & ctp)1077 swap(Constrained_triangulation_plus_2 &ctp)
1078 {
1079   Base::swap(ctp);
1080   hierarchy.swap(ctp.hierarchy);
1081 }
1082 
1083 template < class Tr >
1084 inline
1085 typename Constrained_triangulation_plus_2<Tr>::Vertex_handle
1086 Constrained_triangulation_plus_2<Tr>::
insert(const Point & a,Face_handle start)1087 insert(const Point& a, Face_handle start)
1088 {
1089   Locate_type lt;
1090   int li;
1091   Face_handle loc = this->locate(a, lt, li, start);
1092   return insert(a,lt,loc,li);
1093 }
1094 
1095 template < class Tr>
1096 typename Constrained_triangulation_plus_2<Tr>::Vertex_handle
1097 Constrained_triangulation_plus_2<Tr>::
insert(const Point & a,Locate_type lt,Face_handle loc,int li)1098 insert(const Point& a, Locate_type lt, Face_handle loc, int li)
1099 {
1100   Vertex_handle v1, v2;
1101   bool insert_in_constrained_edge = false;
1102 
1103   if ( lt == Triangulation::EDGE && loc->is_constrained(li) )
1104   {
1105     if(boost::is_same<typename Tr::Itag, No_constraint_intersection_tag>::value)
1106       throw typename Tr::Intersection_of_constraints_exception();
1107 
1108     insert_in_constrained_edge = true;
1109     v1=loc->vertex(ccw(li)); //endpoint of the constraint
1110     v2=loc->vertex(cw(li)); // endpoint of the constraint
1111   }
1112 
1113   Vertex_handle va = Triangulation::insert(a,lt,loc,li);
1114   // update the hierarchy
1115   if (insert_in_constrained_edge) {
1116 #ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS
1117     std::cerr << CGAL::internal::cdt_2_indent_level
1118               << "  CT_plus_2::insert(" << a << ") = #"
1119               << va->time_stamp()
1120               << "   insert in constrained edge:  #" << v1->time_stamp() << "= " << v1->point()
1121               << " , #" << v2->time_stamp() << "= " << v2->point()
1122               << std::endl;
1123 #endif
1124     hierarchy.split_constraint(v1,v2,va);
1125   }
1126   return va;
1127 }
1128 
1129 template <class Tr>
1130 typename Constrained_triangulation_plus_2<Tr>:: Vertex_handle
1131 Constrained_triangulation_plus_2<Tr>::
intersect(Face_handle f,int i,Vertex_handle vaa,Vertex_handle vbb)1132 intersect(Face_handle f, int i,
1133           Vertex_handle vaa,
1134           Vertex_handle vbb)
1135 {
1136   return intersect(f, i, vaa, vbb, Intersection_tag());
1137 }
1138 
1139 template <class Tr>
1140 typename Constrained_triangulation_plus_2<Tr>:: Vertex_handle
1141 Constrained_triangulation_plus_2<Tr>::
intersect(Face_handle,int,Vertex_handle,Vertex_handle,No_constraint_intersection_tag)1142 intersect(Face_handle, int,
1143           Vertex_handle,
1144           Vertex_handle,
1145           No_constraint_intersection_tag)
1146 {
1147   throw typename Tr::Intersection_of_constraints_exception();
1148   return Vertex_handle();
1149 }
1150 
1151 template <class Tr>
1152 typename Constrained_triangulation_plus_2<Tr>:: Vertex_handle
1153 Constrained_triangulation_plus_2<Tr>::
intersect(Face_handle,int,Vertex_handle,Vertex_handle,No_constraint_intersection_requiring_constructions_tag)1154 intersect(Face_handle, int,
1155           Vertex_handle,
1156           Vertex_handle,
1157           No_constraint_intersection_requiring_constructions_tag)
1158 {
1159   throw typename Tr::Intersection_of_constraints_exception();
1160   return Vertex_handle();
1161 }
1162 
1163 template <class Tr>
1164 typename Constrained_triangulation_plus_2<Tr>:: Vertex_handle
1165 Constrained_triangulation_plus_2<Tr>::
intersect(Face_handle f,int i,Vertex_handle vaa,Vertex_handle vbb,Exact_intersections_tag)1166 intersect(Face_handle f, int i,
1167           Vertex_handle vaa,
1168           Vertex_handle vbb,
1169           Exact_intersections_tag)
1170 // compute the intersection of the constraint edge (f,i)
1171 // with the subconstraint (vaa,vbb) being inserted
1172 // insert the intersection point
1173 // (the  constraint edge (f,i) will be split in hierarchy by insert)
1174 // and return the Vertex_handle of the new Vertex
1175 {
1176   Vertex_handle  vc, vd, va, vb;
1177   Vertex_handle  vcc, vdd;
1178   vcc = f->vertex(cw(i));
1179   vdd = f->vertex(ccw(i));
1180   CGAL_triangulation_assertion_code( bool b1 = )
1181   hierarchy.enclosing_constraint(vcc,vdd,vc,vd);
1182   CGAL_triangulation_assertion_code( bool b2 = )
1183   hierarchy.enclosing_constraint(vaa,vbb,va,vb);
1184   CGAL_triangulation_assertion(b1);
1185   CGAL_triangulation_assertion(b2);
1186 
1187   const Point& pa = va->point();
1188   const Point& pb = vb->point();
1189   const Point& pc = vc->point();
1190   const Point& pd = vd->point();
1191 #ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS
1192   std::cerr << CGAL::internal::cdt_2_indent_level
1193             << "CT_plus_2::intersect segment ( #" << va->time_stamp() << "= " << va->point()
1194             << " , #" << vb->time_stamp() << "= " << vb->point()
1195             << " ) with edge ( #"<< vc->time_stamp() << "= " << vc->point()
1196             << " , #" << vd->time_stamp() << "= " << vd->point()
1197             << " , Exact_intersections_tag)\n";
1198 #endif // CGAL_CDT_2_DEBUG_INTERSECTIONS
1199   Point pi;
1200   Intersection_tag itag = Intersection_tag();
1201   CGAL_triangulation_assertion_code( bool ok = )
1202   intersection(geom_traits(), pa, pb, pc, pd, pi, itag );
1203   CGAL_triangulation_assertion(ok);
1204 
1205   Vertex_handle vi = insert(pi, Triangulation::EDGE, f, i);
1206 #ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS
1207   std::cerr << CGAL::internal::cdt_2_indent_level
1208             << "CT_plus_2::intersect, `vi` is ( #" << vi->time_stamp() << "= " << vi->point()
1209             << " )\n";
1210 #endif // CGAL_CDT_2_DEBUG_INTERSECTIONS
1211   return vi;
1212 }
1213 
1214 template <class Tr>
1215 typename Constrained_triangulation_plus_2<Tr>::Vertex_handle
1216 Constrained_triangulation_plus_2<Tr>::
intersect(Face_handle f,int i,Vertex_handle vaa,Vertex_handle vbb,Exact_predicates_tag)1217 intersect(Face_handle f, int i,
1218           Vertex_handle vaa,
1219           Vertex_handle vbb,
1220           Exact_predicates_tag)
1221 {
1222   Vertex_handle  vcc, vdd;
1223   vcc = f->vertex(cw(i));
1224   vdd = f->vertex(ccw(i));
1225 
1226   const Point& pa = vaa->point();
1227   const Point& pb = vbb->point();
1228   const Point& pc = vcc->point();
1229   const Point& pd = vdd->point();
1230 #ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS
1231   std::cerr << CGAL::internal::cdt_2_indent_level
1232             << "CT_plus_2::intersect segment ( #" << vaa->time_stamp() << "= " << vaa->point()
1233             << " , #" << vbb->time_stamp() << "= " << vbb->point()
1234             << " ) with edge ( #"<< vcc->time_stamp() << "= " << vcc->point()
1235             << " , #" << vdd->time_stamp() << "= " << vdd->point()
1236             << " , Exact_predicates_tag)\n";
1237 #endif // CGAL_CDT_2_DEBUG_INTERSECTIONS
1238 
1239   Point pi; //creator for point is required here
1240   Intersection_tag itag = Intersection_tag();
1241   bool ok  = intersection(geom_traits(), pa, pb, pc, pd, pi, itag );
1242 
1243   Vertex_handle vi;
1244   if ( !ok) {  //intersection detected but not computed
1245     int i = limit_intersection(geom_traits(), pa, pb, pc, pd, itag);
1246     switch(i){
1247     case 0 : vi = vaa; break;
1248     case 1 : vi = vbb; break;
1249     case 2 : vi = vcc; break;
1250     case 3 : vi = vdd; break;
1251     }
1252     if(vi == vaa || vi == vbb) {
1253       Triangulation::remove_constrained_edge(f, i);
1254     }
1255   }
1256   else{ //computed
1257     Triangulation::remove_constrained_edge(f, i);
1258     vi = insert(pi, f);
1259   }
1260 #ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS
1261   std::cerr << CGAL::internal::cdt_2_indent_level
1262             << "CT_plus_2::intersect, `vi` is ( #" << vi->time_stamp() << "= " << vi->point()
1263             << " )\n";
1264 #endif // CGAL_CDT_2_DEBUG_INTERSECTIONS
1265 
1266   // vi == vc or vi == vd may happen even if intersection==true
1267   // due to approximate construction of the intersection
1268   if (vi != vcc && vi != vdd) {
1269     hierarchy.split_constraint(vcc,vdd,vi);
1270     insert_subconstraint(vcc,vi);
1271     insert_subconstraint(vi, vdd);
1272   }
1273   else {
1274     insert_subconstraint(vcc,vdd);
1275   }
1276   return vi;
1277 }
1278 
1279   // CONCATENATE AND SPLIT
1280 
1281   // concatenates two constraints
1282 template <class Tr>
1283 typename Constrained_triangulation_plus_2<Tr>::Constraint_id
concatenate(Constraint_id first,Constraint_id second)1284 Constrained_triangulation_plus_2<Tr>::concatenate(Constraint_id first, Constraint_id second)
1285 {
1286   return hierarchy.concatenate(first,second);
1287 }
1288 
1289   // split a constraint in two constraints, so that vcit becomes the first
1290   // vertex of the new constraint
1291   // returns the new constraint
1292 template <class Tr>
1293 typename Constrained_triangulation_plus_2<Tr>::Constraint_id
split(Constraint_id first,Vertices_in_constraint_iterator vcit)1294 Constrained_triangulation_plus_2<Tr>::split(Constraint_id first, Vertices_in_constraint_iterator vcit)
1295 {
1296   return hierarchy.split(first, vcit);
1297 }
1298 
1299 
1300 template <class Tr>
1301 std::ostream &
1302 operator<<(std::ostream& os,
1303            const Constrained_triangulation_plus_2<Tr> &ct)
1304 {
1305   ct.file_output(os);
1306   return os ;
1307 }
1308 
1309 template <class Tr>
1310 std::istream &
1311 operator>>(std::istream& is,
1312            Constrained_triangulation_plus_2<Tr> &ct)
1313 {
1314   ct.file_input(is);
1315   return is ;
1316 }
1317 
1318 // Constraint Hierarchy Queries
1319 
1320 template <class Tr>
1321 inline
1322 typename
1323 Constrained_triangulation_plus_2<Tr>::Constraint_iterator
1324 Constrained_triangulation_plus_2<Tr>::
constraints_begin()1325 constraints_begin() const
1326 {
1327   return hierarchy.c_begin();
1328 }
1329 
1330 template <class Tr>
1331 inline
1332 typename
1333 Constrained_triangulation_plus_2<Tr>::Constraint_iterator
1334 Constrained_triangulation_plus_2<Tr>::
constraints_end()1335 constraints_end() const
1336 {
1337   return hierarchy.c_end();
1338 }
1339 
1340 template <class Tr>
1341 inline
1342 typename
1343 Constrained_triangulation_plus_2<Tr>::Subconstraint_iterator
1344 Constrained_triangulation_plus_2<Tr>::
subconstraints_begin()1345 subconstraints_begin() const
1346 {
1347   return hierarchy.subconstraint_begin();
1348 }
1349 
1350 template <class Tr>
1351 inline
1352 typename
1353 Constrained_triangulation_plus_2<Tr>::Subconstraint_iterator
1354 Constrained_triangulation_plus_2<Tr>::
subconstraints_end()1355 subconstraints_end() const
1356 {
1357   return hierarchy.subconstraint_end();
1358 }
1359 
1360 
1361 template <class Tr>
1362 inline
1363 typename Constrained_triangulation_plus_2<Tr>::Context
1364 Constrained_triangulation_plus_2<Tr>::
context(Vertex_handle va,Vertex_handle vb)1365 context(Vertex_handle va, Vertex_handle vb) // AF: const
1366 {
1367   return hierarchy.context(va,vb);
1368 }
1369 
1370 
1371 template <class Tr>
1372 inline
1373 typename Constrained_triangulation_plus_2<Tr>::size_type
1374 Constrained_triangulation_plus_2<Tr>::
number_of_enclosing_constraints(Vertex_handle va,Vertex_handle vb)1375 number_of_enclosing_constraints(Vertex_handle va, Vertex_handle vb) const
1376 {
1377  return static_cast<size_type>
1378    (hierarchy.number_of_enclosing_constraints(va,vb));
1379 }
1380 
1381 template <class Tr>
1382 inline bool
1383 Constrained_triangulation_plus_2<Tr>::
is_subconstraint(Vertex_handle va,Vertex_handle vb)1384 is_subconstraint(Vertex_handle va, Vertex_handle vb)
1385 {
1386  return hierarchy.is_subconstrained_edge(va,vb);
1387 }
1388 
1389 
1390 template <class Tr>
1391 inline
1392 typename Constrained_triangulation_plus_2<Tr>::Context_iterator
1393 Constrained_triangulation_plus_2<Tr>::
contexts_begin(Vertex_handle va,Vertex_handle vb)1394 contexts_begin(Vertex_handle va, Vertex_handle vb) const
1395 {
1396   return hierarchy.contexts_begin(va,vb);
1397 }
1398 
1399 template <class Tr>
1400 inline
1401 typename Constrained_triangulation_plus_2<Tr>::Context_iterator
1402 Constrained_triangulation_plus_2<Tr>::
contexts_end(Vertex_handle va,Vertex_handle vb)1403 contexts_end(Vertex_handle va, Vertex_handle vb) const
1404 {
1405   return hierarchy.contexts_end(va,vb);
1406 }
1407 
1408 template <class Tr>
1409 inline
1410 typename Constrained_triangulation_plus_2<Tr>::Vertices_in_constraint_iterator
1411 Constrained_triangulation_plus_2<Tr>::
vertices_in_constraint_begin(Constraint_id cid)1412 vertices_in_constraint_begin(Constraint_id cid) const
1413 {
1414   return  hierarchy.vertices_in_constraint_begin(cid);
1415 }
1416 
1417 template <class Tr>
1418 inline
1419 typename Constrained_triangulation_plus_2<Tr>::Vertices_in_constraint_iterator
1420 Constrained_triangulation_plus_2<Tr>::
vertices_in_constraint_end(Constraint_id cid)1421 vertices_in_constraint_end(Constraint_id cid) const
1422 {
1423   return  hierarchy.vertices_in_constraint_end(cid);
1424 }
1425 
1426 template <class Tr>
1427 inline
1428 typename Constrained_triangulation_plus_2<Tr>::Points_in_constraint_iterator
1429 Constrained_triangulation_plus_2<Tr>::
points_in_constraint_begin(Constraint_id cid)1430 points_in_constraint_begin(Constraint_id cid) const
1431 {
1432   return  hierarchy.points_in_constraint_begin(cid);
1433 }
1434 
1435 template <class Tr>
1436 inline
1437 typename Constrained_triangulation_plus_2<Tr>::Points_in_constraint_iterator
1438 Constrained_triangulation_plus_2<Tr>::
points_in_constraint_end(Constraint_id cid)1439 points_in_constraint_end(Constraint_id cid) const
1440 {
1441   return  hierarchy.points_in_constraint_end(cid);
1442 }
1443 
1444 } //namespace CGAL
1445 
1446 #include <CGAL/enable_warnings.h>
1447 
1448 #endif //CGAL_CONSTRAINED_TRIANGULATION_PLUS_2_H
1449