BWAPI
|
00001 // Copyright (c) 2005 Tel-Aviv University (Israel). 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/Arrangement_on_surface_2/include/CGAL/Arr_topology_traits/Arr_inc_insertion_zone_visitor.h $ 00015 // $Id: Arr_inc_insertion_zone_visitor.h 41108 2007-12-06 15:26:30Z efif $ 00016 // 00017 // 00018 // Author(s) : Ron Wein <wein@post.tau.ac.il> 00019 // Efi Fogel <efif@post.tau.ac.il> 00020 00021 #ifndef CGAL_ARR_PLANAR_INC_INSERTION_ZONE_VISITOR_H 00022 #define CGAL_ARR_PLANAR_INC_INSERTION_ZONE_VISITOR_H 00023 00028 #include <CGAL/Arr_accessor.h> 00029 #include <CGAL/Arrangement_2/Arr_traits_adaptor_2.h> 00030 00031 CGAL_BEGIN_NAMESPACE 00032 00040 template <class Arrangement_> 00041 class Arr_inc_insertion_zone_visitor 00042 { 00043 public: 00044 00045 typedef Arrangement_ Arrangement_2; 00046 typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2; 00047 00048 typedef typename Arrangement_2::Vertex_handle Vertex_handle; 00049 typedef typename Arrangement_2::Halfedge_handle Halfedge_handle; 00050 typedef typename Arrangement_2::Face_handle Face_handle; 00051 00052 typedef typename Arrangement_2::Point_2 Point_2; 00053 typedef typename Arrangement_2::X_monotone_curve_2 X_monotone_curve_2; 00054 00055 typedef std::pair<Halfedge_handle, bool> Result; 00056 00057 protected: 00058 00059 typedef Arr_traits_basic_adaptor_2<Geometry_traits_2> Traits_adaptor_2; 00060 00061 private: 00062 00063 Arrangement_2 *p_arr; // The arrangement into which we 00064 // insert the curves. 00065 Traits_adaptor_2 *geom_traits; // The arrangement geometry-traits. 00066 00067 const Vertex_handle invalid_v; // An invalid vertex handle. 00068 const Halfedge_handle invalid_he; // An invalid halfedge handle. 00069 00070 X_monotone_curve_2 sub_cv1; // Auxiliary varibale (for splitting). 00071 X_monotone_curve_2 sub_cv2; // Auxiliary varibale (for splitting). 00072 00073 public: 00074 00076 Arr_inc_insertion_zone_visitor () : 00077 p_arr (NULL), 00078 geom_traits (NULL), 00079 invalid_v (), 00080 invalid_he () 00081 {} 00082 00084 void init (Arrangement_2 *arr) 00085 { 00086 p_arr = arr; 00087 geom_traits = const_cast<Traits_adaptor_2*> 00088 (static_cast<const Traits_adaptor_2*> (p_arr->geometry_traits())); 00089 } 00090 00106 Result found_subcurve (const X_monotone_curve_2& cv, 00107 Face_handle face, 00108 Vertex_handle left_v, Halfedge_handle left_he, 00109 Vertex_handle right_v, Halfedge_handle right_he); 00110 00122 Result found_overlap (const X_monotone_curve_2& cv, 00123 Halfedge_handle he, 00124 Vertex_handle left_v, Vertex_handle right_v); 00125 00126 private: 00127 00134 void _split_edge (Halfedge_handle he, 00135 const Point_2& p, 00136 Arr_accessor<Arrangement_2>& arr_access); 00137 00138 }; 00139 00140 //----------------------------------------------------------------------------- 00141 // Memeber-function definitions: 00142 //----------------------------------------------------------------------------- 00143 00144 //----------------------------------------------------------------------------- 00145 // Handle the a subcurve located in the interior of a given face. 00146 // 00147 template <class Arrangement> 00148 typename Arr_inc_insertion_zone_visitor<Arrangement>::Result 00149 Arr_inc_insertion_zone_visitor<Arrangement>:: 00150 found_subcurve (const X_monotone_curve_2& cv, Face_handle face, 00151 Vertex_handle left_v, Halfedge_handle left_he, 00152 Vertex_handle right_v, Halfedge_handle right_he) 00153 { 00154 // Create an arrangement accessor. 00155 Arr_accessor<Arrangement_2> arr_access (*p_arr); 00156 00157 // Get the boundary conditions of the curve ends. 00158 const Arr_parameter_space bx_l = 00159 geom_traits->parameter_space_in_x_2_object()(cv, ARR_MIN_END); 00160 const Arr_parameter_space by_l = 00161 geom_traits->parameter_space_in_y_2_object()(cv, ARR_MIN_END); 00162 00163 const Arr_parameter_space bx_r = 00164 geom_traits->parameter_space_in_x_2_object()(cv, ARR_MAX_END); 00165 const Arr_parameter_space by_r = 00166 geom_traits->parameter_space_in_y_2_object()(cv, ARR_MAX_END); 00167 00168 // Check if the left and the right endpoints of cv should be associated 00169 // with arrangement vertices. 00170 const bool vertex_for_left = 00171 (left_v != invalid_v) || (left_he != invalid_he); 00172 const bool vertex_for_right = 00173 (right_v != invalid_v) || (right_he != invalid_he); 00174 00175 // Find the previous halfedges for the left and right endpoints (if any). 00176 Halfedge_handle prev_he_left; 00177 Halfedge_handle prev_he_right; 00178 00179 if (vertex_for_left) 00180 { 00181 // If we are given the previous halfedge, use it. Otherwise, we are given 00182 // the vertex and we should locate cv around it. 00183 if (left_he != invalid_he) 00184 prev_he_left = left_he; 00185 else if (! left_v->is_isolated()) 00186 prev_he_left = arr_access.locate_around_vertex (left_v, cv); 00187 00188 // In case the vertex does not exist, split left_he at cv's left endpoint 00189 // and create the vertex. 00190 if (left_v == invalid_v) 00191 { 00192 _split_edge (left_he, 00193 geom_traits->construct_min_vertex_2_object() (cv), 00194 arr_access); 00195 00196 // Check if we have just split the halfedge that right_he refers to, 00197 // and if this halfedge is directed from left to right. 00198 // If so, right_he's target is now the new vertex, and we have to 00199 // proceed to the next halfedge (which is going to be split). 00200 if (right_he == left_he && left_he->direction() == ARR_LEFT_TO_RIGHT) 00201 right_he = right_he->next(); 00202 } 00203 } 00204 else 00205 { 00206 // Check if the left end of cv is bounded of not. 00207 if ((bx_l == ARR_LEFT_BOUNDARY) || (by_l != ARR_INTERIOR)) { 00208 // Use the arrangement accessor and obtain a vertex associated with 00209 // the unbounded left end (possibly with a predecessor halfedge). 00210 std::pair<Vertex_handle, Halfedge_handle> pos = 00211 arr_access.place_and_set_curve_end (face, cv, ARR_MIN_END, bx_l, by_l); 00212 00213 if (pos.second != invalid_he) 00214 // Use the predecessor halfedge, if possible: 00215 prev_he_left = pos.second; 00216 else 00217 // Use just the isolated vertex: 00218 left_v = pos.first; 00219 } 00220 } 00221 00222 if (vertex_for_right) 00223 { 00224 // If we are given the previous halfedge, use it. Otherwise, we are given 00225 // the vertex and we should locate cv around it. 00226 if (right_he != invalid_he) 00227 prev_he_right = right_he; 00228 else if (! right_v->is_isolated()) 00229 prev_he_right = arr_access.locate_around_vertex (right_v, cv); 00230 00231 // In case the vertex does not exist, split right_he at cv's right 00232 // endpoint and create the vertex. 00233 if (right_v == invalid_v) 00234 { 00235 _split_edge (right_he, 00236 geom_traits->construct_max_vertex_2_object() (cv), 00237 arr_access); 00238 00239 // Check if we have just split the halfedge that left_he refers to. 00240 // If so, prev_he_right's target is now the new vertex, and we have to 00241 // proceed to the next halfedge (whose target is right_v). 00242 if (right_he == prev_he_left) 00243 { 00244 prev_he_left = prev_he_left->next(); 00245 } 00246 } 00247 } 00248 else 00249 { 00250 // Check if the right end of cv is bounded of not. 00251 if ((bx_r == ARR_RIGHT_BOUNDARY) || (by_r != ARR_INTERIOR)) { 00252 // Use the arrangement accessor and obtain a vertex associated with 00253 // the unbounded right end (possibly with a predecessor halfedge). 00254 std::pair<Vertex_handle, Halfedge_handle> pos = 00255 arr_access.place_and_set_curve_end (face, cv, ARR_MAX_END, bx_r, by_r); 00256 00257 if (pos.second != invalid_he) 00258 // Use the predecessor halfedge, if possible: 00259 prev_he_right = pos.second; 00260 else 00261 // Use just the isolated vertex: 00262 right_v = pos.first; 00263 } 00264 } 00265 00266 // Insert the curve into the arrangement. 00267 Halfedge_handle inserted_he; 00268 00269 if (prev_he_left == invalid_he) 00270 { 00271 // The left endpoint is associated with an isolated vertex, or is not 00272 // associated with any vertex. In the latter case, we create such a vertex 00273 // now. 00274 if (left_v == invalid_v) 00275 { 00276 if (bx_l == ARR_INTERIOR && by_l == ARR_INTERIOR) 00277 { 00278 left_v = arr_access.create_vertex 00279 (geom_traits->construct_min_vertex_2_object() (cv)); 00280 } 00281 else 00282 { 00283 left_v = 00284 arr_access.create_boundary_vertex (cv, ARR_MIN_END, bx_l, by_l); 00285 } 00286 } 00287 00288 if (prev_he_right == invalid_he) 00289 { 00290 // The right endpoint is associated with an isolated vertex, or is not 00291 // associated with any vertex. In the latter case, we create such a 00292 // vertex now. 00293 if (right_v == invalid_v) 00294 { 00295 if (bx_r == ARR_INTERIOR && by_r == ARR_INTERIOR) 00296 { 00297 right_v = arr_access.create_vertex 00298 (geom_traits->construct_max_vertex_2_object() (cv)); 00299 } 00300 else 00301 { 00302 right_v = arr_access.create_boundary_vertex (cv, ARR_MAX_END, 00303 bx_r, by_r); 00304 } 00305 } 00306 00307 // We should insert the curve in the interior of the face. 00308 inserted_he = arr_access.insert_in_face_interior_ex (cv, face, 00309 left_v, right_v, 00310 SMALLER); 00311 } 00312 else 00313 { 00314 // The right endpoint is associated with an arrangement vertex, and 00315 // we have the predecessor halfedge for the insertion. 00316 inserted_he = arr_access.insert_from_vertex_ex (cv, prev_he_right, 00317 left_v, LARGER); 00318 00319 // The returned halfedge is directed to the newly created vertex 00320 // (the left one), so we take its twin. 00321 inserted_he = inserted_he->twin(); 00322 } 00323 } 00324 else 00325 { 00326 // We have a vertex associated with the left end of the curve, along 00327 // with a predecessor halfedge. 00328 if (prev_he_right == invalid_he) 00329 { 00330 // The right endpoint is associated with an isolated vertex, or is not 00331 // associated with any vertex. In the latter case, we create such a 00332 // vertex now. 00333 if (right_v == invalid_v) 00334 { 00335 if (bx_r == ARR_INTERIOR && by_r == ARR_INTERIOR) 00336 { 00337 right_v = arr_access.create_vertex 00338 (geom_traits->construct_max_vertex_2_object() (cv)); 00339 } 00340 else 00341 { 00342 right_v = 00343 arr_access.create_boundary_vertex (cv, ARR_MAX_END, bx_r, by_r); 00344 } 00345 } 00346 00347 // Use the left predecessor for the insertion. 00348 inserted_he = arr_access.insert_from_vertex_ex (cv, prev_he_left, 00349 right_v, SMALLER); 00350 } 00351 else 00352 { 00353 // The right endpoint is associated with an arrangement vertex, and 00354 // we have the predecessor halfedge for the insertion. 00355 CGAL_assertion (prev_he_right != invalid_he); 00356 00357 // Perform the insertion using the predecessor halfedges. 00358 inserted_he = p_arr->insert_at_vertices (cv, 00359 prev_he_left, 00360 prev_he_right); 00361 } 00362 } 00363 00364 // Return the inserted halfedge, and indicate we should not halt the 00365 // zone-computation process. 00366 Result res = Result (inserted_he, false); 00367 00368 return (res); 00369 } 00370 00371 //----------------------------------------------------------------------------- 00372 // Handle the a subcurve located in the interior of a given face. 00373 // 00374 template <class Arrangement> 00375 typename Arr_inc_insertion_zone_visitor<Arrangement>::Result 00376 Arr_inc_insertion_zone_visitor<Arrangement>:: 00377 found_overlap (const X_monotone_curve_2& cv, 00378 Halfedge_handle he, 00379 Vertex_handle left_v, Vertex_handle right_v) 00380 { 00381 // Get the boundary conditions of the curve ends. 00382 const Arr_parameter_space bx_l = 00383 geom_traits->parameter_space_in_x_2_object()(cv, ARR_MIN_END); 00384 const Arr_parameter_space by_l = 00385 geom_traits->parameter_space_in_y_2_object()(cv, ARR_MIN_END); 00386 00387 const Arr_parameter_space bx_r = 00388 geom_traits->parameter_space_in_x_2_object()(cv, ARR_MAX_END); 00389 const Arr_parameter_space by_r = 00390 geom_traits->parameter_space_in_y_2_object()(cv, ARR_MAX_END); 00391 00392 // Modify (perhaps split) the overlapping arrangement edge. 00393 Halfedge_handle updated_he; 00394 00395 if (left_v == invalid_v && 00396 ! ((bx_l == ARR_LEFT_BOUNDARY) || (by_l != ARR_INTERIOR))) 00397 { 00398 // Split the curve associated with he at the left endpoint of cv. 00399 geom_traits->split_2_object() 00400 (he->curve(), 00401 geom_traits->construct_min_vertex_2_object() (cv), sub_cv1, sub_cv2); 00402 00403 if (right_v == invalid_v && 00404 ! ((bx_r == ARR_RIGHT_BOUNDARY) || (by_r != ARR_INTERIOR))) 00405 { 00406 // The overlapping curve is contained strictly in the interior of he: 00407 // Split he as an intermediate step. 00408 updated_he = p_arr->split_edge (he, sub_cv1, sub_cv2); 00409 updated_he = updated_he->next(); 00410 00411 // Split the left subcurve at the right endpoint of cv. 00412 geom_traits->split_2_object() 00413 (updated_he->curve(), 00414 geom_traits->construct_max_vertex_2_object() (cv), sub_cv1, sub_cv2); 00415 00416 // Split updated_he once again, so that the left portion corresponds 00417 // to the overlapping curve and the right portion corresponds to 00418 // sub_cv2. 00419 updated_he = p_arr->split_edge (updated_he, cv, sub_cv2); 00420 } 00421 else 00422 { 00423 // Split he, such that the left portion corresponds to sub_cv1 and the 00424 // right portion corresponds to the overlapping curve. 00425 updated_he = p_arr->split_edge (he, sub_cv1, cv); 00426 updated_he = updated_he->next(); 00427 } 00428 } 00429 else 00430 { 00431 if (right_v == invalid_v && 00432 ! ((bx_r == ARR_RIGHT_BOUNDARY) || (by_r != ARR_INTERIOR))) 00433 { 00434 // Split the curve associated with he at the right endpoint of cv. 00435 geom_traits->split_2_object() 00436 (he->curve(), 00437 geom_traits->construct_max_vertex_2_object() (cv), sub_cv1, sub_cv2); 00438 00439 // Split he, such that the left portion corresponds to the overlapping 00440 // curve and the right portion corresponds to sub_cv2. 00441 updated_he = p_arr->split_edge (he, cv, sub_cv2); 00442 } 00443 else 00444 { 00445 // The entire edge is overlapped: Modify the curve associated with cv 00446 // to be the overlapping curve. 00447 updated_he = p_arr->modify_edge (he, cv); 00448 } 00449 } 00450 00451 // Return the updated halfedge, and indicate we should not halt the 00452 // zone-computation process. 00453 Result res = Result (updated_he, false); 00454 00455 return (res); 00456 } 00457 00458 //----------------------------------------------------------------------------- 00459 // Split an arrangement edge. 00460 // 00461 template <class Arrangement> 00462 void Arr_inc_insertion_zone_visitor<Arrangement>:: 00463 _split_edge (Halfedge_handle he, const Point_2& p, 00464 Arr_accessor<Arrangement_2>& arr_access) 00465 { 00466 // Split the curve at the split point. 00467 geom_traits->split_2_object() (he->curve(), p, sub_cv1, sub_cv2); 00468 00469 // sub_cv1 is always to the left of the split point p and sub_cv2 lies to 00470 // its right. Thus, if the split edge is directed from left to right then 00471 // left end of sub_cv1 equals he's source, and if the edge is directed from 00472 // right to left, we have to reverse the subcurve order. 00473 if (he->direction() == ARR_LEFT_TO_RIGHT) 00474 { 00475 arr_access.split_edge_ex (he, p, sub_cv1, sub_cv2); 00476 } 00477 else 00478 { 00479 arr_access.split_edge_ex (he, p, sub_cv2, sub_cv1); 00480 } 00481 00482 return; 00483 } 00484 00485 CGAL_END_NAMESPACE 00486 00487 #endif