BWAPI
|
00001 // Copyright (c) 1997 INRIA Sophia-Antipolis (France). 00002 // All rights reserved. 00003 // 00004 // This file is part of CGAL (www.cgal.org); you may redistribute it under 00005 // the terms of the Q Public License version 1.0. 00006 // See the file LICENSE.QPL distributed with CGAL. 00007 // 00008 // Licensees holding a valid commercial license may use this file in 00009 // accordance with the commercial license agreement provided with the software. 00010 // 00011 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00012 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00013 // 00014 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Triangulation_2/include/CGAL/Constrained_triangulation_2.h $ 00015 // $Id: Constrained_triangulation_2.h 48844 2009-04-21 18:28:04Z spion $ 00016 // 00017 // 00018 // Author(s) : Mariette Yvinec, Jean-Daniel Boissonnat 00019 00020 00021 #ifndef CGAL_CONSTRAINED_TRIANGULATION_2_H 00022 #define CGAL_CONSTRAINED_TRIANGULATION_2_H 00023 00024 #include <set> 00025 00026 #include <CGAL/triangulation_assertions.h> 00027 #include <CGAL/Triangulation_2.h> 00028 #include <CGAL/Constrained_triangulation_face_base_2.h> 00029 #include <CGAL/iterator.h> 00030 00031 #include <CGAL/intersections.h> 00032 #include <CGAL/squared_distance_2.h> 00033 00034 CGAL_BEGIN_NAMESPACE 00035 00036 struct No_intersection_tag{}; 00037 struct Exact_intersections_tag{}; // to be used with an exact number type 00038 struct Exact_predicates_tag{}; // to be used with filtered exact number 00039 00040 00041 template < class Gt, 00042 class Tds = Triangulation_data_structure_2 < 00043 Triangulation_vertex_base_2<Gt>, 00044 Constrained_triangulation_face_base_2<Gt> >, 00045 class Itag = No_intersection_tag > 00046 class Constrained_triangulation_2 : public Triangulation_2<Gt,Tds> 00047 { 00048 00049 public: 00050 typedef Triangulation_2<Gt,Tds> Triangulation; 00051 typedef Constrained_triangulation_2<Gt,Tds,Itag> Constrained_triangulation; 00052 00053 typedef typename Triangulation::Edge Edge; 00054 typedef typename Triangulation::Vertex Vertex; 00055 typedef typename Triangulation::Vertex_handle Vertex_handle; 00056 typedef typename Triangulation::Face_handle Face_handle; 00057 typedef typename Triangulation::Locate_type Locate_type; 00058 typedef typename Triangulation::All_faces_iterator All_faces_iterator; 00059 typedef typename Triangulation::Face_circulator Face_circulator; 00060 typedef typename Triangulation::Edge_circulator Edge_circulator; 00061 typedef typename Triangulation::Vertex_circulator Vertex_circulator; 00062 typedef typename Triangulation::Line_face_circulator Line_face_circulator; 00063 00064 #ifndef CGAL_CFG_USING_BASE_MEMBER_BUG_2 00065 using Triangulation::number_of_vertices; 00066 using Triangulation::cw; 00067 using Triangulation::ccw; 00068 using Triangulation::dimension; 00069 using Triangulation::geom_traits; 00070 using Triangulation::all_faces_begin; 00071 using Triangulation::all_faces_end; 00072 using Triangulation::side_of_oriented_circle; 00073 #endif 00074 00075 typedef Gt Geom_traits; 00076 typedef Itag Intersection_tag; 00077 typedef typename Geom_traits::Point_2 Point; 00078 typedef typename Geom_traits::Segment_2 Segment; 00079 typedef std::pair<Point,Point> Constraint; 00080 typedef std::list<Edge> List_edges; 00081 typedef std::list<Face_handle> List_faces; 00082 typedef std::list<Vertex_handle> List_vertices; 00083 typedef std::list<Constraint> List_constraints; 00084 00085 // Tag to mark the presence of a hierarchy of constraints 00086 typedef Tag_false Constraint_hierarchy_tag; 00087 00088 00089 class Less_edge; 00090 typedef std::set<Edge,Less_edge> Edge_set; 00091 00092 00093 Constrained_triangulation_2(const Gt& gt = Gt()) : Triangulation(gt) { } 00094 00095 Constrained_triangulation_2(const Constrained_triangulation_2& ct) 00096 : Triangulation(ct) {} 00097 00098 Constrained_triangulation_2(std::list<Constraint>& lc, const Gt& gt=Gt()) 00099 : Triangulation_2<Gt,Tds>(gt) 00100 { 00101 typename List_constraints::iterator lcit=lc.begin(); 00102 for( ;lcit != lc.end(); lcit++) { 00103 insert( (*lcit).first, (*lcit).second); 00104 } 00105 CGAL_triangulation_postcondition( this->is_valid() ); 00106 } 00107 00108 template<class InputIterator> 00109 Constrained_triangulation_2(InputIterator it, 00110 InputIterator last, 00111 const Gt& gt=Gt() ) 00112 : Triangulation_2<Gt,Tds>(gt) 00113 { 00114 for ( ; it != last; it++) { 00115 insert_constraint((*it).first, (*it).second); 00116 } 00117 CGAL_triangulation_postcondition( this->is_valid() ); 00118 } 00119 00120 //TODO Is that destructor correct ? 00121 virtual ~Constrained_triangulation_2() {} 00122 00123 // INSERTION 00124 Vertex_handle insert(const Point& p, 00125 Face_handle start = Face_handle() ); 00126 Vertex_handle insert(const Point& p, 00127 Locate_type lt, 00128 Face_handle loc, 00129 int li ); 00130 Vertex_handle push_back(const Point& a); 00131 // template < class InputIterator > 00132 // int insert(InputIterator first, InputIterator last); 00133 00134 void insert_constraint(const Point& a, const Point& b); 00135 void insert_constraint(Vertex_handle va, Vertex_handle vb); 00136 void push_back(const Constraint& c); 00137 00138 void remove(Vertex_handle v); 00139 void remove_constrained_edge(Face_handle f, int i); 00140 void remove_incident_constraints(Vertex_handle v); 00141 // to be used by Constrained_triangulation_plus_2 00142 template <class OutputItFaces> 00143 OutputItFaces 00144 remove_constrained_edge(Face_handle f, int i, OutputItFaces out) 00145 { 00146 remove_constrained_edge(f, i); 00147 return out; 00148 } 00149 00150 //for backward compatibility 00151 void remove_constraint(Face_handle f, int i) {remove_constrained_edge(f,i);} 00152 void insert(Point a, Point b) { insert_constraint(a, b);} 00153 void insert(Vertex_handle va, Vertex_handle vb) {insert_constraint(va,vb);} 00154 00155 // QUERY 00156 bool is_constrained(Edge e) const; 00157 bool are_there_incident_constraints(Vertex_handle v) const; 00158 bool is_valid(bool verbose = false, int level = 0) const; 00159 // template<class OutputItEdges> 00160 // OutputItEdges incident_constraints(Vertex_handle v, 00161 // OutputItEdges out) const; 00162 00163 00164 class Less_edge 00165 : public std::binary_function<Edge, Edge, bool> 00166 { 00167 public: 00168 Less_edge() {} 00169 bool operator() (const Edge& e1, const Edge& e2) const 00170 { 00171 int ind1=e1.second, ind2=e2.second; 00172 return( (&(*e1.first) < &(*e2.first)) 00173 || ( (&(*e1.first) == &(*e2.first)) && (ind1 < ind2))); 00174 } 00175 }; 00176 00177 00178 void file_output(std::ostream& os) const; 00179 00180 protected: 00181 virtual Vertex_handle virtual_insert(const Point& a, 00182 Face_handle start = Face_handle()); 00183 virtual Vertex_handle virtual_insert(const Point& a, 00184 Locate_type lt, 00185 Face_handle loc, 00186 int li ); 00187 //Vertex_handle special_insert_in_edge(const Point & a, Face_handle f, int i); 00188 void update_constraints_incident(Vertex_handle va, 00189 Vertex_handle c1, 00190 Vertex_handle c2); 00191 void clear_constraints_incident(Vertex_handle va); 00192 void update_constraints_opposite(Vertex_handle va); 00193 void update_constraints(const List_edges &hole); 00194 00195 void mark_constraint(Face_handle fr, int i); 00196 00197 virtual Vertex_handle intersect(Face_handle f, int i, 00198 Vertex_handle vaa, 00199 Vertex_handle vbb); 00200 Vertex_handle intersect(Face_handle f, int i, 00201 Vertex_handle vaa, 00202 Vertex_handle vbb, 00203 No_intersection_tag); 00204 Vertex_handle intersect(Face_handle f, int i, 00205 Vertex_handle vaa, 00206 Vertex_handle vbb, 00207 Exact_intersections_tag); 00208 Vertex_handle intersect(Face_handle f, int i, 00209 Vertex_handle vaa, 00210 Vertex_handle vbb, 00211 Exact_predicates_tag); 00212 public: 00213 // made public for Laurent to find out deleted faces 00214 // when inserting a constraint with most probably 00215 // no intersection 00216 bool find_intersected_faces(Vertex_handle va, 00217 Vertex_handle vb, 00218 List_faces & intersected_faces, 00219 List_edges & list_ab, 00220 List_edges & list_ba, 00221 Vertex_handle& vi); 00222 protected: 00223 virtual void triangulate_hole(List_faces& intersected_faces, 00224 List_edges& conflict_boundary_ab, 00225 List_edges& conflict_boundary_ba); 00226 00227 void triangulate_hole(List_faces& intersected_faces, 00228 List_edges& conflict_boundary_ab, 00229 List_edges& conflict_boundary_ba, 00230 List_edges& new_edges); 00231 00232 void triangulate_half_hole(List_edges & list_edges, 00233 List_edges & new_edges); 00234 00235 void remove_1D(Vertex_handle v); 00236 void remove_2D(Vertex_handle v); 00237 00238 //templated member function 00239 public: 00240 // the int parameter is a work around for VC7 to compile 00241 template < class InputIterator > 00242 #if defined(_MSC_VER) 00243 int insert(InputIterator first, InputIterator last, int i = 0) 00244 #else 00245 int insert(InputIterator first, InputIterator last) 00246 #endif 00247 { 00248 int n = number_of_vertices(); 00249 00250 std::vector<Point> points (first, last); 00251 std::random_shuffle (points.begin(), points.end()); 00252 CGAL::spatial_sort (points.begin(), points.end(), geom_traits()); 00253 00254 Face_handle hint; 00255 for (typename std::vector<Point>::const_iterator p = points.begin(), end = points.end(); 00256 p != end; ++p) 00257 hint = insert (*p, hint)->face(); 00258 00259 return number_of_vertices() - n; 00260 } 00261 00262 //deprecated 00263 template<class OutputIterator> 00264 bool are_there_incident_constraints(Vertex_handle v, 00265 OutputIterator out) const 00266 { 00267 Edge_circulator ec=incident_edges(v), done(ec); 00268 bool are_there = false; 00269 if (ec == 0) return are_there; 00270 do { 00271 if(is_constrained(*ec)) { 00272 *out++ = *ec; 00273 are_there = true; 00274 } 00275 ec++; 00276 } while (ec != done); 00277 return are_there; 00278 } 00279 00280 00281 template<class OutputItEdges> 00282 OutputItEdges incident_constraints(Vertex_handle v, 00283 OutputItEdges out) const { 00284 Edge_circulator ec=incident_edges(v), done(ec); 00285 if (ec == 0) return out; 00286 do { 00287 if(is_constrained(*ec)) *out++ = *ec; 00288 ec++; 00289 } while (ec != done); 00290 return out; 00291 } 00292 00293 // the following fonctions are overloaded 00294 // to take care of constraint marks 00295 template<class EdgeIt> 00296 Vertex_handle star_hole( const Point& p, 00297 EdgeIt edge_begin, 00298 EdgeIt edge_end) { 00299 std::list<Face_handle> empty_list; 00300 return star_hole(p, 00301 edge_begin, 00302 edge_end, 00303 empty_list.begin(), 00304 empty_list.end()); 00305 } 00306 00307 template<class EdgeIt, class FaceIt> 00308 Vertex_handle star_hole( const Point& p, 00309 EdgeIt edge_begin, 00310 EdgeIt edge_end, 00311 FaceIt face_begin, 00312 FaceIt face_end) 00313 { 00314 Vertex_handle v = Triangulation::star_hole(p, 00315 edge_begin, 00316 edge_end, 00317 face_begin, 00318 face_end); 00319 // restore constraint status for new faces. 00320 int vindex; 00321 Face_handle fh; 00322 int ih; 00323 Face_circulator fc = incident_faces(v), done(fc); 00324 do { 00325 vindex = fc->index(v); 00326 fc->set_constraint(cw(vindex), false); 00327 fc->set_constraint(ccw(vindex), false); 00328 fh = fc->neighbor(vindex); 00329 ih = this->mirror_index(fc,vindex); 00330 fc->set_constraint(vindex, fh->is_constrained(ih)); 00331 } while (++fc != done); 00332 return v; 00333 } 00334 00335 }; 00336 00337 template < class Gt, class Tds, class Itag > 00338 inline 00339 typename Constrained_triangulation_2<Gt,Tds,Itag>::Vertex_handle 00340 Constrained_triangulation_2<Gt,Tds,Itag>:: 00341 virtual_insert(const Point& a, Face_handle start) 00342 // virtual version of insert 00343 { 00344 return insert(a,start); 00345 } 00346 00347 template < class Gt, class Tds, class Itag > 00348 inline 00349 typename Constrained_triangulation_2<Gt,Tds,Itag>::Vertex_handle 00350 Constrained_triangulation_2<Gt,Tds,Itag>:: 00351 virtual_insert(const Point& a, 00352 Locate_type lt, 00353 Face_handle loc, 00354 int li ) 00355 // virtual version of insert 00356 { 00357 return insert(a,lt,loc,li); 00358 } 00359 00360 template < class Gt, class Tds, class Itag > 00361 inline 00362 typename Constrained_triangulation_2<Gt,Tds,Itag>::Vertex_handle 00363 Constrained_triangulation_2<Gt,Tds,Itag>:: 00364 insert(const Point& a, Face_handle start) 00365 // inserts point a 00366 // in addition to what is done for non constrained triangulations 00367 // constrained edges are updated 00368 { 00369 Face_handle loc; 00370 int li; 00371 Locate_type lt; 00372 loc = locate(a, lt, li, start); 00373 return Constrained_triangulation::insert(a,lt,loc,li); 00374 } 00375 00376 template < class Gt, class Tds, class Itag > 00377 typename Constrained_triangulation_2<Gt,Tds,Itag>::Vertex_handle 00378 Constrained_triangulation_2<Gt,Tds,Itag>:: 00379 insert(const Point& a, Locate_type lt, Face_handle loc, int li) 00380 // insert a point p, whose localisation is known (lt, f, i) 00381 // in addition to what is done for non constrained triangulations 00382 // constrained edges are updated 00383 { 00384 Vertex_handle va; 00385 Vertex_handle v1, v2; 00386 bool insert_in_constrained_edge = false; 00387 00388 if ( lt == Triangulation::EDGE && loc->is_constrained(li) ){ 00389 insert_in_constrained_edge = true; 00390 v1=loc->vertex(ccw(li)); //endpoint of the constraint 00391 v2=loc->vertex(cw(li)); // endpoint of the constraint 00392 } 00393 00394 va = Triangulation::insert(a,lt,loc,li); 00395 if (insert_in_constrained_edge) update_constraints_incident(va, v1,v2); 00396 else if(lt != Triangulation::VERTEX) clear_constraints_incident(va); 00397 if (dimension() == 2) update_constraints_opposite(va); 00398 return va; 00399 } 00400 00401 // template < class Gt, class Tds, class Itag > 00402 // typename Constrained_triangulation_2<Gt,Tds,Itag>::Vertex_handle 00403 // Constrained_triangulation_2<Gt, Tds, Itag>:: 00404 // special_insert_in_edge(const Point & a, Face_handle f, int i) 00405 // // insert point p in edge(f,i) 00406 // // bypass the precondition for point a to be in edge(f,i) 00407 // // update constrained status 00408 // { 00409 // Vertex_handle va; 00410 // Vertex_handle c1,c2; 00411 // c1 = f->vertex(cw(i)); //endpoint of edge 00412 // c2 = f->vertex(ccw(i)); //endpoint of edge 00413 // bool insert_in_constrained_edge = f->is_constrained(i); 00414 00415 // va = this->_tds.insert_in_edge(f, i); 00416 // va->set_point(a); 00417 00418 // if (insert_in_constrained_edge) update_constraints_incident(va, c1,c2); 00419 // else clear_constraints_incident(va); 00420 // if (dimension() == 2) update_constraints_opposite(va); 00421 // return va; 00422 // } 00423 00424 00425 template < class Gt, class Tds, class Itag > 00426 inline void 00427 Constrained_triangulation_2<Gt,Tds,Itag>:: 00428 insert_constraint(const Point& a, const Point& b) 00429 // the algorithm first inserts a and b, 00430 // and then forces the constraint [va,vb] 00431 { 00432 Vertex_handle va= virtual_insert(a); 00433 Vertex_handle vb= virtual_insert(b); 00434 if ( va != vb) insert_constraint(va,vb); 00435 } 00436 00437 00438 00439 template <class Gt, class Tds, class Itag > 00440 inline void 00441 Constrained_triangulation_2<Gt,Tds,Itag>:: 00442 insert_constraint(Vertex_handle vaa, Vertex_handle vbb) 00443 // forces the constrained [va,vb] 00444 // [va,vb] will eventually be splitted into several edges 00445 // if a vertex vc of t lies on segment ab 00446 // of if ab intersect some constrained edges 00447 { 00448 CGAL_triangulation_precondition( vaa != vbb); 00449 Vertex_handle vi; 00450 00451 Face_handle fr; 00452 int i; 00453 if(includes_edge(vaa,vbb,vi,fr,i)) { 00454 mark_constraint(fr,i); 00455 if (vi != vbb) { 00456 insert_constraint(vi,vbb); 00457 } 00458 return; 00459 } 00460 00461 List_faces intersected_faces; 00462 List_edges conflict_boundary_ab, conflict_boundary_ba; 00463 bool intersection = find_intersected_faces( vaa, vbb, 00464 intersected_faces, 00465 conflict_boundary_ab, 00466 conflict_boundary_ba, 00467 vi); 00468 if ( intersection) { 00469 if (vi != vaa && vi != vbb) { 00470 insert_constraint(vaa,vi); 00471 insert_constraint(vi,vbb); 00472 } 00473 else insert_constraint(vaa,vbb); 00474 return; 00475 } 00476 00477 triangulate_hole(intersected_faces, 00478 conflict_boundary_ab, 00479 conflict_boundary_ba); 00480 00481 if (vi != vbb) { 00482 insert_constraint(vi,vbb); 00483 } 00484 return; 00485 00486 } 00487 00488 template <class Gt, class Tds, class Itag > 00489 bool 00490 Constrained_triangulation_2<Gt,Tds,Itag>:: 00491 find_intersected_faces(Vertex_handle vaa, 00492 Vertex_handle vbb, 00493 List_faces & intersected_faces, 00494 List_edges & list_ab, 00495 List_edges & list_ba, 00496 Vertex_handle & vi) 00497 // vi is set to the first vertex of the triangulation on [vaa,vbb]. 00498 // Return true if an intersection with a constrained edge is 00499 // encountered, false otherwise 00500 // When false : 00501 // intersected_faces contains the list if faces intersected by [va,vi] 00502 // list_ab and list_ba represents the boundary of the union 00503 // of the intersected faces oriented cw 00504 // list_ab consists of the edges from vaa to vi (i.e. on the left of a->b) 00505 // list_ba " " from vi to vaa (i.e. on the right of a->b) 00506 { 00507 const Point& aa = vaa->point(); 00508 const Point& bb = vbb->point(); 00509 Line_face_circulator current_face=Line_face_circulator(vaa, this, bb); 00510 int ind=current_face->index(vaa); 00511 00512 // to deal with the case where the first crossed edge 00513 // is constrained 00514 if(current_face->is_constrained(ind)) { 00515 vi=intersect(current_face, ind, vaa, vbb); 00516 return true; 00517 } 00518 00519 Face_handle lf= current_face->neighbor(ccw(ind)); 00520 Face_handle rf= current_face->neighbor(cw(ind)); 00521 Orientation orient; 00522 Face_handle previous_face; 00523 Vertex_handle current_vertex; 00524 00525 list_ab.push_back(Edge(lf, lf->index(current_face))); 00526 list_ba.push_front(Edge(rf, rf->index(current_face))); 00527 intersected_faces.push_front(current_face); 00528 00529 // initcd 00530 previous_face=current_face; 00531 ++current_face; 00532 ind=current_face->index(previous_face); 00533 current_vertex=current_face->vertex(ind); 00534 00535 // loop over triangles intersected by ab 00536 bool done = false; 00537 while (current_vertex != vbb && !done) { 00538 orient = this->orientation(aa,bb,current_vertex->point()); 00539 int i1, i2; 00540 switch (orient) { 00541 case COLLINEAR : 00542 done = true; // current_vertex is the new endpoint 00543 break; 00544 case LEFT_TURN : 00545 case RIGHT_TURN : 00546 if (orient == LEFT_TURN) { 00547 i1 = ccw(ind) ; //index of second intersected edge of current_face 00548 i2 = cw(ind); //index of non intersected edge of current_face 00549 } 00550 else { 00551 i1 = cw(ind) ; //index of second intersected edge of current_face 00552 i2 = ccw(ind); //index of non intersected edge of current_face 00553 } 00554 if(current_face->is_constrained(i1)) { 00555 vi = intersect(current_face, i1, vaa,vbb); 00556 return true; 00557 } 00558 else { 00559 lf= current_face->neighbor(i2); 00560 intersected_faces.push_front(current_face); 00561 if (orient == LEFT_TURN) 00562 list_ab.push_back(Edge(lf, lf->index(current_face))); 00563 else // orient == RIGHT_TURN 00564 list_ba.push_front(Edge(lf, lf->index(current_face))); 00565 previous_face=current_face; 00566 ++current_face; 00567 ind=current_face->index(previous_face); 00568 current_vertex=current_face->vertex(ind); 00569 } 00570 break; 00571 } 00572 } 00573 00574 // last triangle 00575 vi = current_vertex; 00576 intersected_faces.push_front(current_face); 00577 lf= current_face->neighbor(cw(ind)); 00578 list_ab.push_back(Edge(lf, lf->index(current_face))); 00579 rf= current_face->neighbor(ccw(ind)); 00580 list_ba.push_front(Edge(rf, rf->index(current_face))); 00581 return false; 00582 } 00583 00584 00585 template <class Gt, class Tds, class Itag > 00586 typename Constrained_triangulation_2<Gt,Tds,Itag>::Vertex_handle 00587 Constrained_triangulation_2<Gt,Tds,Itag>:: 00588 intersect(Face_handle f, int i, 00589 Vertex_handle vaa, 00590 Vertex_handle vbb) 00591 { 00592 return intersect(f, i, vaa, vbb, Itag()); 00593 } 00594 00595 template <class Gt, class Tds, class Itag > 00596 typename Constrained_triangulation_2<Gt,Tds,Itag>::Vertex_handle 00597 Constrained_triangulation_2<Gt,Tds,Itag>:: 00598 intersect(Face_handle , int , 00599 Vertex_handle , 00600 Vertex_handle , 00601 No_intersection_tag) 00602 { 00603 std::cerr << " sorry, this triangulation does not deal with" 00604 << std::endl 00605 << " intersecting constraints" << std::endl; 00606 CGAL_triangulation_assertion(false); 00607 return Vertex_handle() ; 00608 } 00609 00610 template <class Gt, class Tds, class Itag > 00611 typename Constrained_triangulation_2<Gt,Tds,Itag>::Vertex_handle 00612 Constrained_triangulation_2<Gt,Tds,Itag>:: 00613 intersect(Face_handle f, int i, 00614 Vertex_handle vaa, 00615 Vertex_handle vbb, 00616 Exact_intersections_tag) 00617 // compute the intersection of the constraint edge (f,i) 00618 // with the subconstraint (vaa,vbb) being inserted 00619 // insert the intersection point 00620 // split constraint edge (f,i) 00621 // and return the Vertex_handle of the new Vertex 00622 { 00623 std::cerr << "You are using an exact number types" << std::endl; 00624 std::cerr << "using a Constrained_triangulation_plus_2 class" << std::endl; 00625 std::cerr << "would avoid cascading intersection computation" << std::endl; 00626 std::cerr << " and be much more efficient" << std::endl; 00627 const Point& pa = vaa->point(); 00628 const Point& pb = vbb->point(); 00629 const Point& pc = f->vertex(cw(i))->point(); 00630 const Point& pd = f->vertex(ccw(i))->point(); 00631 Point pi; 00632 Itag itag = Itag(); 00633 CGAL_triangulation_assertion_code( bool ok = ) 00634 intersection(geom_traits(), pa, pb, pc, pd, pi, itag ); 00635 CGAL_triangulation_assertion(ok); 00636 Vertex_handle vi = virtual_insert(pi, Triangulation::EDGE, f, i); 00637 return vi; 00638 } 00639 00640 template <class Gt, class Tds, class Itag > 00641 typename Constrained_triangulation_2<Gt,Tds,Itag>::Vertex_handle 00642 Constrained_triangulation_2<Gt,Tds,Itag>:: 00643 intersect(Face_handle f, int i, 00644 Vertex_handle vaa, 00645 Vertex_handle vbb, 00646 Exact_predicates_tag) 00647 { 00648 Vertex_handle vcc, vdd; 00649 vcc = f->vertex(cw(i)); 00650 vdd = f->vertex(ccw(i)); 00651 00652 const Point& pa = vaa->point(); 00653 const Point& pb = vbb->point(); 00654 const Point& pc = vcc->point(); 00655 const Point& pd = vdd->point(); 00656 00657 Point pi; //creator for point is required here 00658 Itag itag = Itag(); 00659 bool ok = intersection(geom_traits(), pa, pb, pc, pd, pi, itag ); 00660 00661 Vertex_handle vi; 00662 if ( !ok) { //intersection detected but not computed 00663 int i = limit_intersection(geom_traits(), pa, pb, pc, pd, itag); 00664 switch(i){ 00665 case 0 : vi = vaa; break; 00666 case 1 : vi = vbb; break; 00667 case 2 : vi = vcc; break; 00668 case 3 : vi = vdd; break; 00669 } 00670 } 00671 else{ //intersection computed 00672 remove_constrained_edge(f, i); 00673 vi = virtual_insert(pi, f); 00674 } 00675 00676 // vi == vc or vi == vd may happen even if intersection==true 00677 // due to approximate construction of the intersection 00678 if (vi != vcc && vi != vdd) { 00679 insert_constraint(vcc,vi); 00680 insert_constraint(vi, vdd); 00681 } 00682 else { 00683 insert_constraint(vcc,vdd); 00684 } 00685 return vi; 00686 } 00687 00688 template <class Gt, class Tds, class Itag > 00689 inline 00690 typename Constrained_triangulation_2<Gt,Tds,Itag>::Vertex_handle 00691 Constrained_triangulation_2<Gt,Tds,Itag>:: 00692 push_back(const Point &p) 00693 { 00694 return insert(p); 00695 } 00696 00697 00698 template <class Gt, class Tds, class Itag > 00699 inline 00700 void 00701 Constrained_triangulation_2<Gt,Tds,Itag>:: 00702 push_back(const Constraint &c) 00703 { 00704 insert(c.first, c.second); 00705 } 00706 00707 00708 template < class Gt, class Tds, class Itag > 00709 void 00710 Constrained_triangulation_2<Gt,Tds,Itag>:: 00711 update_constraints_incident(Vertex_handle va, 00712 Vertex_handle c1, 00713 Vertex_handle c2) 00714 // update status of edges incident to a 00715 // after insertion in the constrained edge c1c2 00716 { 00717 if (dimension() == 0) return; 00718 if (dimension()== 1) { 00719 Edge_circulator ec=this->incident_edges(va), done(ec); 00720 do { 00721 ((*ec).first)->set_constraint(2,true); 00722 }while (++ec != done); 00723 } 00724 else{ 00725 //dimension() ==2 00726 int cwi, ccwi, indf; 00727 Face_circulator fc=this->incident_faces(va), done(fc); 00728 CGAL_triangulation_assertion(fc != 0); 00729 do { 00730 indf = fc->index(va); 00731 cwi=cw(indf); 00732 ccwi=ccw(indf); 00733 if ((fc->vertex(cwi) == c1)||(fc->vertex(cwi) == c2)) { 00734 fc->set_constraint(ccwi,true); 00735 fc->set_constraint(cwi,false); 00736 } 00737 else { 00738 fc->set_constraint(ccwi,false); 00739 fc->set_constraint(cwi,true); 00740 } 00741 ++fc; 00742 } while (fc != done); 00743 } 00744 } 00745 00746 template < class Gt, class Tds ,class Itag > 00747 void 00748 Constrained_triangulation_2<Gt,Tds,Itag>:: 00749 clear_constraints_incident(Vertex_handle va) 00750 // make the edges incident to a newly created vertex unconstrained 00751 { 00752 Edge_circulator ec=this->incident_edges(va), done(ec); 00753 Face_handle f; 00754 int indf; 00755 if ( ec != 0){ 00756 do { 00757 f = (*ec).first ; 00758 indf = (*ec).second; 00759 f->set_constraint(indf,false); 00760 if (dimension() == 2) { 00761 f->neighbor(indf)->set_constraint(this->mirror_index(f,indf),false); 00762 } 00763 } while (++ec != done); 00764 } 00765 return; 00766 } 00767 00768 00769 template < class Gt, class Tds, class Itag > 00770 void 00771 Constrained_triangulation_2<Gt,Tds,Itag>:: 00772 update_constraints_opposite(Vertex_handle va) 00773 // update status of edges opposite to a 00774 // after insertion of a 00775 { 00776 CGAL_triangulation_assertion(dimension()==2); 00777 Face_handle f=va->face(), start=f; 00778 int indf; 00779 do { 00780 indf = f->index(va); 00781 if (f->neighbor(indf)->is_constrained(this->mirror_index(f,indf)) ) { 00782 f->set_constraint(indf,true); 00783 } 00784 else { 00785 f->set_constraint(indf,false); 00786 } 00787 f= f->neighbor(ccw(indf)); // turns ccw around va 00788 } while (f != start); 00789 return; 00790 } 00791 00792 template < class Gt, class Tds, class Itag > 00793 void 00794 Constrained_triangulation_2<Gt,Tds,Itag>:: 00795 update_constraints( const List_edges &hole) 00796 { 00797 typename List_edges::const_iterator it = hole.begin(); 00798 Face_handle f; 00799 int i; 00800 for ( ; it != hole.end(); it ++) { 00801 f =(*it).first; 00802 i = (*it).second; 00803 if ( f->is_constrained(i) ) 00804 (f->neighbor(i))->set_constraint(this->mirror_index(f,i),true); 00805 else (f->neighbor(i))->set_constraint(this->mirror_index(f,i),false); 00806 } 00807 } 00808 00809 00810 template < class Gt, class Tds, class Itag > 00811 inline void 00812 Constrained_triangulation_2<Gt,Tds,Itag>:: 00813 mark_constraint(Face_handle fr, int i) 00814 { 00815 if (dimension()==1) fr->set_constraint(2, true); 00816 else{ 00817 fr->set_constraint(i,true); 00818 fr->neighbor(i)->set_constraint(this->mirror_index(fr,i),true); 00819 } 00820 return; 00821 } 00822 00823 template < class Gt, class Tds, class Itag > 00824 inline void 00825 Constrained_triangulation_2<Gt,Tds,Itag>:: 00826 triangulate_hole(List_faces& intersected_faces, 00827 List_edges& conflict_boundary_ab, 00828 List_edges& conflict_boundary_ba) 00829 { 00830 List_edges new_edges; 00831 triangulate_hole(intersected_faces, 00832 conflict_boundary_ab, 00833 conflict_boundary_ba, 00834 new_edges); 00835 } 00836 00837 00838 00839 template < class Gt, class Tds, class Itag > 00840 void 00841 Constrained_triangulation_2<Gt,Tds,Itag>:: 00842 triangulate_hole(List_faces& intersected_faces, 00843 List_edges& conflict_boundary_ab, 00844 List_edges& conflict_boundary_ba, 00845 List_edges& new_edges) 00846 // triangulate the hole limited by conflict_boundary_ab 00847 // and conflict_boundary_ba 00848 // insert the new edges in new-edges 00849 // delete the faces of intersected_faces 00850 { 00851 if ( !conflict_boundary_ab.empty() ) { 00852 triangulate_half_hole(conflict_boundary_ab, new_edges); 00853 triangulate_half_hole(conflict_boundary_ba, new_edges); 00854 00855 // the two faces that share edge ab are neighbors 00856 // their common edge ab is a constraint 00857 Face_handle fr,fl; 00858 fl=(*conflict_boundary_ab.begin()).first; 00859 fr=(*conflict_boundary_ba.begin()).first; 00860 fl->set_neighbor(2, fr); 00861 fr->set_neighbor(2, fl); 00862 fl->set_constraint(2, true); 00863 fr->set_constraint(2, true); 00864 00865 // delete intersected faces 00866 while( ! intersected_faces.empty()) { 00867 fl = intersected_faces.front(); 00868 intersected_faces.pop_front(); 00869 delete_face(fl); 00870 } 00871 } 00872 } 00873 00874 00875 00876 template < class Gt, class Tds, class Itag > 00877 void 00878 Constrained_triangulation_2<Gt,Tds,Itag>:: 00879 remove(Vertex_handle v) 00880 // remove a vertex and updates the constrained edges of the new faces 00881 // precondition : there is no incident constraints 00882 { 00883 CGAL_triangulation_precondition( v != Vertex_handle() ); 00884 CGAL_triangulation_precondition( ! is_infinite(v)); 00885 CGAL_triangulation_precondition( ! are_there_incident_constraints(v)); 00886 00887 if (number_of_vertices() == 1) remove_first(v); 00888 else if (number_of_vertices() == 2) remove_second(v); 00889 else if ( dimension() == 1) remove_1D(v); 00890 else remove_2D(v); 00891 return; 00892 } 00893 00894 00895 template < class Gt, class Tds, class Itag > 00896 void 00897 Constrained_triangulation_2<Gt,Tds,Itag>:: 00898 remove_1D(Vertex_handle v) 00899 { 00900 Edge_circulator ec = incident_edges(v), done(ec); 00901 do { 00902 (*ec).first->set_constraint(2,false); 00903 } while (++ec != done); 00904 Triangulation::remove_1D(v); 00905 } 00906 00907 template < class Gt, class Tds, class Itag > 00908 void 00909 Constrained_triangulation_2<Gt,Tds,Itag>:: 00910 remove_2D(Vertex_handle v) 00911 { 00912 if (test_dim_down(v)) { this->_tds.remove_dim_down(v);} 00913 else { 00914 List_edges hole; 00915 make_hole(v, hole); 00916 List_edges shell=hole; //save hole because it will be emptied by fill_hole 00917 fill_hole(v, hole); 00918 update_constraints(shell); 00919 delete_vertex(v); 00920 } 00921 return; 00922 } 00923 00924 00925 template < class Gt, class Tds, class Itag > 00926 void 00927 Constrained_triangulation_2<Gt,Tds,Itag>:: 00928 remove_constrained_edge(Face_handle f, int i) 00929 { 00930 f->set_constraint(i, false); 00931 if (dimension() == 2) 00932 (f->neighbor(i))->set_constraint(this->mirror_index(f,i), false); 00933 return; 00934 } 00935 00936 template < class Gt, class Tds, class Itag > 00937 void 00938 Constrained_triangulation_2<Gt,Tds,Itag>:: 00939 remove_incident_constraints(Vertex_handle v) 00940 { 00941 Edge_circulator ec=incident_edges(v), done(ec); 00942 if (ec == 0) return; 00943 do { 00944 if(is_constrained(*ec)) { remove_constrained_edge((*ec).first, 00945 (*ec).second);} 00946 ec++; 00947 } while (ec != done); 00948 return; 00949 } 00950 00951 template < class Gt, class Tds, class Itag > 00952 inline bool 00953 Constrained_triangulation_2<Gt,Tds,Itag>:: 00954 are_there_incident_constraints(Vertex_handle v) const 00955 { 00956 return are_there_incident_constraints(v, Emptyset_iterator()); 00957 } 00958 00959 template < class Gt, class Tds, class Itag > 00960 inline bool 00961 Constrained_triangulation_2<Gt,Tds,Itag>:: 00962 is_valid(bool verbose, int level) const 00963 { 00964 bool result = Triangulation::is_valid(verbose,level); 00965 for( All_faces_iterator it = all_faces_begin(); 00966 it != all_faces_end() ; it++) { 00967 for(int i=0; i<3; i++) { 00968 Face_handle n = it->neighbor(i); 00969 result = result && 00970 it->is_constrained(i) == n->is_constrained(n->index(it)); 00971 } 00972 } 00973 return result; 00974 } 00975 00976 template < class Gt, class Tds, class Itag > 00977 inline bool 00978 Constrained_triangulation_2<Gt,Tds,Itag>:: 00979 is_constrained(Edge e) const 00980 { 00981 return (e.first)->is_constrained(e.second); 00982 } 00983 00984 template < class Gt, class Tds, class Itag > 00985 void 00986 Constrained_triangulation_2<Gt,Tds,Itag>:: 00987 triangulate_half_hole(List_edges & list_edges, List_edges & new_edges) 00988 // triangulates the polygon whose boundary consists of list_edges 00989 // plus the edge ab joining the two endpoints of list_edges 00990 // the orientation of the polygon (as provided by list_edges) must 00991 // be cw 00992 // the edges of list_edges are assumed to be edges of a 00993 // triangulation that will be updated by the procedure 00994 // the edges that are created are put in list new_edges 00995 // takes linear time 00996 { 00997 Vertex_handle va,vb; // first and last vertices of list_edges 00998 Face_handle newlf; 00999 Face_handle n1,n2,n; 01000 int ind1, ind2,ind; 01001 Orientation orient; 01002 01003 typename List_edges::iterator current, next, tempo; 01004 current=list_edges.begin(); 01005 tempo=list_edges.end(); 01006 --tempo; 01007 01008 va=((*current).first)->vertex(ccw((*current).second)); 01009 vb=((*tempo).first)->vertex(cw((*tempo).second)); 01010 next=current; 01011 ++next; 01012 01013 do 01014 { 01015 n1=(*current).first; 01016 ind1=(*current).second; 01017 // in case n1 is no longer a triangle of the new triangulation 01018 if ( n1->neighbor(ind1) != Face_handle() ) { 01019 n=n1->neighbor(ind1); 01020 //ind=this->mirror_index(n1,ind1); 01021 // mirror_index does not work in this case 01022 ind = cw(n->index(n1->vertex(cw(ind1)))); 01023 n1=n->neighbor(ind); 01024 ind1= this->mirror_index(n,ind); 01025 } 01026 n2=(*next).first; 01027 ind2=(*next).second; 01028 // in case n2 is no longer a triangle of the new triangulation 01029 if (n2->neighbor(ind2) != Face_handle() ) { 01030 n=n2->neighbor(ind2); 01031 // ind=this->mirror_index(n2,ind2); 01032 // mirror_index does not work in this case 01033 ind = cw(n->index(n2->vertex(cw(ind2)))); 01034 n2=n->neighbor(ind); 01035 ind2= this->mirror_index(n,ind); 01036 } 01037 01038 Vertex_handle v0=n1->vertex(ccw(ind1)); 01039 Vertex_handle v1=n1->vertex(cw(ind1)); 01040 Vertex_handle v2=n2->vertex(cw(ind2)); 01041 orient = this->orientation(v0->point(),v1->point(),v2->point()); 01042 switch (orient) { 01043 case RIGHT_TURN : 01044 // creates the new triangle v0v1v2 01045 // updates the neighbors, the constraints 01046 //and the list of new edges 01047 newlf = create_face(v0,v2,v1); 01048 new_edges.push_back(Edge(newlf,2)); 01049 newlf->set_neighbor(1, n1); 01050 newlf->set_neighbor(0, n2); 01051 n1->set_neighbor(ind1, newlf); 01052 n2->set_neighbor(ind2, newlf); 01053 if (n1->is_constrained(ind1)) { 01054 newlf->set_constraint(1,true); 01055 } 01056 if (n2->is_constrained(ind2)) { 01057 newlf->set_constraint(0,true); 01058 } 01059 // v0, v1 or v2.face() may have been removed 01060 v0->set_face(newlf); 01061 v1->set_face(newlf); 01062 v2->set_face(newlf); 01063 // update list_edges 01064 tempo=current; 01065 current=list_edges.insert(current, Edge(newlf,2)); 01066 list_edges.erase(tempo); 01067 list_edges.erase(next); 01068 next=current; 01069 if (v0 != va) {--current;} 01070 else {++next;} 01071 break; 01072 case LEFT_TURN : 01073 ++current; ++next; 01074 break; 01075 case COLLINEAR : 01076 ++current; ++next; 01077 break; 01078 } 01079 } while (list_edges.size()>1); 01080 } 01081 01082 template < class Gt, class Tds, class Itag > 01083 void 01084 Constrained_triangulation_2<Gt, Tds, Itag>:: 01085 file_output(std::ostream& os) const 01086 { 01087 Triangulation_2<Gt, Tds>::file_output(os); 01088 01089 // write constrained status 01090 typename Tds::Face_iterator ib = this->_tds.face_iterator_base_begin(); 01091 for( ; ib != this->_tds.face_iterator_base_end(); ++ib) { 01092 for(int j = 0; j < 3; ++j){ 01093 if (ib->is_constrained(j)) { os << "C";} 01094 else { os << "N";} 01095 if(is_ascii(os)){ 01096 if(j==2) { 01097 os << "\n"; 01098 } else { 01099 os << ' '; 01100 } 01101 } 01102 } 01103 } 01104 } 01105 01106 template < class Gt, class Tds, class Itag > 01107 std::ostream & 01108 operator<<(std::ostream& os, 01109 const Constrained_triangulation_2<Gt,Tds,Itag> &ct) 01110 { 01111 ct.file_output(os); 01112 return os ; 01113 } 01114 01115 //Helping functions to compute intersections of constrained edges 01116 template<class Gt> 01117 bool 01118 intersection(Gt , 01119 const typename Gt::Point_2& , 01120 const typename Gt::Point_2& , 01121 const typename Gt::Point_2& , 01122 const typename Gt::Point_2& , 01123 typename Gt::Point_2& , 01124 No_intersection_tag) 01125 { 01126 return false; 01127 } 01128 01129 template<class Gt> 01130 bool 01131 intersection(Gt gt, 01132 const typename Gt::Point_2& pa, 01133 const typename Gt::Point_2& pb, 01134 const typename Gt::Point_2& pc, 01135 const typename Gt::Point_2& pd, 01136 typename Gt::Point_2& pi, 01137 Exact_intersections_tag) 01138 { 01139 return compute_intersection(gt,pa,pb,pc,pd,pi); 01140 } 01141 01142 01143 template<class Gt> 01144 inline bool 01145 intersection(Gt gt, 01146 const typename Gt::Point_2& pa, 01147 const typename Gt::Point_2& pb, 01148 const typename Gt::Point_2& pc, 01149 const typename Gt::Point_2& pd, 01150 typename Gt::Point_2& pi, 01151 Exact_predicates_tag) 01152 { 01153 return compute_intersection(gt,pa,pb,pc,pd,pi); 01154 } 01155 01156 template<class Gt> 01157 bool 01158 compute_intersection(Gt gt, 01159 const typename Gt::Point_2& pa, 01160 const typename Gt::Point_2& pb, 01161 const typename Gt::Point_2& pc, 01162 const typename Gt::Point_2& pd, 01163 typename Gt::Point_2& pi) 01164 { 01165 typename Gt::Intersect_2 compute_intersec=gt.intersect_2_object(); 01166 typename Gt::Construct_segment_2 01167 construct_segment=gt.construct_segment_2_object(); 01168 Object result = compute_intersec(construct_segment(pa,pb), 01169 construct_segment(pc,pd)); 01170 return assign(pi, result); 01171 } 01172 01173 01174 template<class Gt> 01175 int 01176 limit_intersection(Gt , 01177 const typename Gt::Point_2& , 01178 const typename Gt::Point_2& , 01179 const typename Gt::Point_2& , 01180 const typename Gt::Point_2& , 01181 No_intersection_tag) 01182 { 01183 return 0; 01184 } 01185 01186 template<class Gt> 01187 int 01188 limit_intersection(Gt , 01189 const typename Gt::Point_2& , 01190 const typename Gt::Point_2& , 01191 const typename Gt::Point_2& , 01192 const typename Gt::Point_2& , 01193 Exact_intersections_tag) 01194 { 01195 return 0; 01196 } 01197 01198 template<class Gt> 01199 int 01200 limit_intersection(Gt gt, 01201 const typename Gt::Point_2& pa, 01202 const typename Gt::Point_2& pb, 01203 const typename Gt::Point_2& pc, 01204 const typename Gt::Point_2& pd, 01205 Exact_predicates_tag) 01206 { 01207 typename Gt::Construct_line_2 line = gt.construct_line_2_object(); 01208 typename Gt::Compute_squared_distance_2 01209 distance = gt.compute_squared_distance_2_object(); 01210 typename Gt::Line_2 l1 = line(pa,pb); 01211 typename Gt::Line_2 l2 = line(pc,pd); 01212 int i = 0; 01213 typename Gt::FT dx = distance(l2,pa); 01214 typename Gt::FT db = distance(l2,pb); 01215 typename Gt::FT dc = distance(l1,pc); 01216 typename Gt::FT dd = distance(l1,pd); 01217 if ( db < dx ) { dx = db; i = 1;} 01218 if ( dc < dx ) { dx = dc; i = 2;} 01219 if ( dd < dx ) { i = 3;} 01220 return i; 01221 } 01222 01223 CGAL_END_NAMESPACE 01224 01225 #endif //CGAL_CONSTRAINED_TRIANGULATION_2_H