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