BWAPI
|
00001 // Copyright (c) 2006 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_planar_topology_traits_base_2.h $ 00015 // $Id: Arr_planar_topology_traits_base_2.h 50366 2009-07-05 12:56:48Z 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_TOPOLOGY_TRAITS_BASE_2_H 00022 #define CGAL_ARR_PLANAR_TOPOLOGY_TRAITS_BASE_2_H 00023 00028 #include <CGAL/Arr_enums.h> 00029 #include <CGAL/Arr_default_dcel.h> 00030 #include <CGAL/Arr_walk_along_line_point_location.h> 00031 #include <CGAL/Arrangement_2/Arr_traits_adaptor_2.h> 00032 #include <CGAL/Sweep_line_2/Arr_construction_event.h> 00033 #include <CGAL/Sweep_line_2/Arr_construction_subcurve.h> 00034 #include <CGAL/Sweep_line_2/Arr_construction_sl_visitor.h> 00035 #include <CGAL/Sweep_line_2/Arr_basic_insertion_traits_2.h> 00036 #include <CGAL/Sweep_line_2/Arr_basic_insertion_sl_visitor.h> 00037 #include <CGAL/Sweep_line_2/Arr_insertion_traits_2.h> 00038 #include <CGAL/Sweep_line_2/Arr_insertion_sl_visitor.h> 00039 #include <CGAL/Sweep_line_2/Arr_overlay_subcurve.h> 00040 #include <CGAL/Sweep_line_2/Arr_overlay_traits_2.h> 00041 #include <CGAL/Sweep_line_2/Arr_overlay_sl_visitor.h> 00042 #include <CGAL/Sweep_line_2/Arr_batched_pl_sl_visitor.h> 00043 #include <CGAL/Sweep_line_2/Arr_vert_decomp_sl_visitor.h> 00044 #include <CGAL/Arr_point_location/Arr_batched_point_location_traits_2.h> 00045 00046 CGAL_BEGIN_NAMESPACE 00047 00052 template <class GeomTraits_, 00053 class Dcel_ = Arr_default_dcel<GeomTraits_> > 00054 class Arr_planar_topology_traits_base_2 00055 { 00056 public: 00057 00059 00060 typedef GeomTraits_ Geometry_traits_2; 00061 typedef typename Geometry_traits_2::Point_2 Point_2; 00062 typedef typename Geometry_traits_2::X_monotone_curve_2 X_monotone_curve_2; 00064 00066 00067 typedef Dcel_ Dcel; 00068 typedef typename Dcel::Size Size; 00069 typedef typename Dcel::Vertex Vertex; 00070 typedef typename Dcel::Halfedge Halfedge; 00071 typedef typename Dcel::Face Face; 00072 typedef typename Dcel::Outer_ccb Outer_ccb; 00073 typedef typename Dcel::Inner_ccb Inner_ccb; 00074 typedef typename Dcel::Isolated_vertex Isolated_vertex; 00076 00077 typedef Arr_planar_topology_traits_base_2<Geometry_traits_2, 00078 Dcel> Self; 00079 00080 protected: 00081 00082 typedef Arr_traits_basic_adaptor_2<Geometry_traits_2> Traits_adaptor_2; 00083 00084 // Data members: 00085 Dcel m_dcel; // The DCEL. 00086 00087 const Traits_adaptor_2 * traits; // The geometry-traits adaptor. 00088 bool own_traits; // Inidicate whether we should evetually 00089 // free the traits object. 00090 00091 // Copy constructor and assignment operator - not supported. 00092 Arr_planar_topology_traits_base_2 (const Self& ); 00093 Self& operator= (const Self& ); 00094 00095 public: 00096 00098 00099 00101 Arr_planar_topology_traits_base_2 () : 00102 own_traits (true) 00103 { 00104 traits = new Traits_adaptor_2; 00105 } 00106 00108 Arr_planar_topology_traits_base_2 (const Geometry_traits_2 * geom_traits) : 00109 own_traits (false) 00110 { 00111 traits = static_cast<const Traits_adaptor_2*>(geom_traits); 00112 } 00113 00115 void assign (const Self& other); 00116 00118 virtual ~Arr_planar_topology_traits_base_2 () 00119 { 00120 // Clear the DCEL. 00121 m_dcel.delete_all(); 00122 00123 if (own_traits) 00124 delete traits; 00125 } 00127 00129 00130 00132 const Dcel& dcel () const 00133 { 00134 return (m_dcel); 00135 } 00136 00138 Dcel& dcel () 00139 { 00140 return (m_dcel); 00141 } 00142 00152 void notify_on_boundary_vertex_creation (Vertex *, 00153 const X_monotone_curve_2& , 00154 Arr_curve_end, 00155 Arr_parameter_space /* ps_x */, 00156 Arr_parameter_space /* ps_y */) 00157 { 00158 // In the planar-topology traits this function should never be invoked: 00159 return; 00160 } 00161 00174 std::pair<bool, bool> 00175 face_split_after_edge_insertion(const Halfedge * 00176 CGAL_precondition_code(prev1), 00177 const Halfedge * 00178 CGAL_precondition_code(prev2), 00179 const X_monotone_curve_2 & /* cv */) const 00180 { 00181 CGAL_precondition (prev1->is_on_inner_ccb()); 00182 CGAL_precondition (prev2->is_on_inner_ccb()); 00183 CGAL_precondition (prev1->inner_ccb() == prev2->inner_ccb()); 00184 00185 // In case of a planar topology, connecting two vertices on the same 00186 // inner CCB closes a new face that becomes a hole in the original face: 00187 return (std::make_pair (true, true)); 00188 } 00189 00190 #if CGAL_NEW_FACE_SPLIT_STRATEGY 00191 00203 std::pair<bool, bool> 00204 face_update_upon_edge_insertion(const Halfedge * 00205 CGAL_precondition_code(prev1), 00206 const Halfedge * 00207 CGAL_precondition_code(prev2), 00208 const X_monotone_curve_2 & cv) const 00209 { 00210 // In case of a planar topology, connecting two vertices on the same 00211 // CCB closes a new face that becomes a hole in the original face: 00212 return (std::make_pair (true, true)); 00213 } 00214 #endif 00215 00216 00224 bool hole_creation_after_edge_removal (const Halfedge *he) const 00225 { 00226 CGAL_precondition (! he->is_on_inner_ccb()); 00227 CGAL_precondition (! he->opposite()->is_on_inner_ccb()); 00228 00229 // Check whether the halfedge and its twin belong to the same outer CCB 00230 // (and are therefore incident to the same face). 00231 if (he->outer_ccb() == he->opposite()->outer_ccb()) 00232 { 00233 // In this case we cut an antenna, therefore we seperate a new hole 00234 // from the outer CCB of the face. 00235 return (true); 00236 } 00237 else 00238 { 00239 // The edge separates two faces. When we remove it, these two faces will 00240 // be merged, but no new hole will be created. 00241 return (false); 00242 } 00243 } 00244 00261 bool is_on_new_perimetric_face_boundary (const Halfedge *, 00262 const Halfedge *, 00263 const X_monotone_curve_2&) const 00264 { 00265 // We can never have perimetric faces in a planar topology: 00266 CGAL_error(); 00267 return (false); 00268 } 00269 00278 bool boundaries_of_same_face (const Halfedge *, 00279 const Halfedge *) const 00280 { 00281 // This predicate is only used for case 3.3.2 of the insertion process, 00282 // therefore it should never be invoked in the planar case. 00283 CGAL_error(); 00284 return (false); 00285 } 00286 00287 00288 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE || CGAL_NEW_FACE_SPLIT_STRATEGY 00289 00296 CGAL::Sign _sign_of_subpath(const Halfedge* he1, const Halfedge* he2) 00297 const { 00298 return CGAL::ZERO; 00299 } 00300 00309 CGAL::Sign _sign_of_subpath(const Halfedge* he1, 00310 const bool target, 00311 const X_monotone_curve_2& cv2, 00312 const CGAL::Arr_curve_end& end2) const { 00313 return CGAL::ZERO; 00314 } 00315 #endif 00316 00325 bool is_in_face (const Face *f, const Point_2& p, const Vertex *v) const; 00327 00329 00330 00332 virtual const Face* initial_face () const = 0; 00334 00336 00337 00344 virtual Comparison_result compare_x (const Point_2& p, 00345 const Vertex* v) const = 0; 00346 00353 virtual Comparison_result compare_xy (const Point_2& p, 00354 const Vertex* v) const = 0; 00355 00364 virtual Comparison_result compare_y_at_x (const Point_2& p, 00365 const Halfedge* he) const = 0; 00367 }; 00368 00369 //----------------------------------------------------------------------------- 00370 // Memeber-function definitions: 00371 //----------------------------------------------------------------------------- 00372 00373 //----------------------------------------------------------------------------- 00374 // Assign the contents of another topology-traits class. 00375 // 00376 template <class GeomTraits, class Dcel_> 00377 void Arr_planar_topology_traits_base_2<GeomTraits, Dcel_>::assign 00378 (const Self& other) 00379 { 00380 // Clear the current DCEL and duplicate the other DCEL. 00381 m_dcel.delete_all(); 00382 m_dcel.assign (other.m_dcel); 00383 00384 // Take care of the traits object. 00385 if (own_traits && traits != NULL) 00386 delete traits; 00387 00388 if (other.own_traits) 00389 traits = new Traits_adaptor_2; 00390 else 00391 traits = other.traits; 00392 own_traits = other.own_traits; 00393 00394 return; 00395 } 00396 00397 //----------------------------------------------------------------------------- 00398 // Determine whether the given vertex lies in the interior of the given face. 00399 // 00400 template <class GeomTraits, class Dcel_> 00401 bool Arr_planar_topology_traits_base_2<GeomTraits, Dcel_>:: 00402 is_in_face(const Face *f, const Point_2& p, const Vertex *v) const 00403 { 00404 CGAL_precondition (v == NULL || ! v->has_null_point()); 00405 CGAL_precondition (v == NULL || 00406 traits->equal_2_object()(p, v->point())); 00407 00408 // In case the face is unbounded and has no outer ccbs, this is the single 00409 // unbounded face of an arrangement of bounded curves. This face obviously 00410 // contains any point in its interior. 00411 if (f->is_unbounded() && f->number_of_outer_ccbs() == 0) 00412 return (true); 00413 00414 // Keep a counter of the number of x-monotone curves that intersect an upward 00415 // vertical emanating from p (except for some degenerate cases that are 00416 // explained below). 00417 unsigned int n_ray_intersections = 0; 00418 00419 // Get a halfedge along the outer CCB of the given face, go over all curves 00420 // of the boundary component, and count those which are above p. 00421 // We begin by comparing p to the source vertex of the first halfedge. 00422 // Note that if p coincides with this vertex, p is obviously not in the 00423 // interior of the component. 00424 const Halfedge *first = *(f->outer_ccbs_begin()); 00425 const Halfedge *curr = first; 00426 Comparison_result res_source; 00427 Comparison_result res_target; 00428 Comparison_result res_y_at_x; 00429 00430 if (curr->opposite()->vertex() == v) 00431 return (false); 00432 00433 res_source = compare_xy (p, curr->opposite()->vertex()); 00434 00435 do 00436 { 00437 // Compare p to the target vertex of the current halfedge. 00438 // If the vertex v associated with p (if v is given and is not NULL) 00439 // on the boundary of the component, p is obviously not in the interior 00440 // the component. 00441 if (curr->vertex() == v) 00442 return (false); 00443 00444 res_target = compare_xy (p, curr->vertex()); 00445 00446 // In case the current halfedge belongs to an "antenna", namely its 00447 // incident face is the same as its twin's, we can simply skip it 00448 // (in order not to count it twice). 00449 if (! curr->opposite()->is_on_inner_ccb() && 00450 curr->outer_ccb()->face() == curr->opposite()->outer_ccb()->face()) 00451 { 00452 curr = curr->next(); 00453 res_source = res_target; 00454 continue; 00455 } 00456 00457 // Check that if we shoot a "tilted" vertical ray from p upward 00458 // (by "tilted" we mean the angle it forms with the x-axis is 00459 // PI/2 + epsilon, where epsilon is arbitrarily small), then we hit 00460 // the x-monotone curve associated with curr once. 00461 if (res_source != res_target) 00462 { 00463 res_y_at_x = compare_y_at_x (p, curr); 00464 00465 if (res_y_at_x == SMALLER) 00466 { 00467 n_ray_intersections++; 00468 } 00469 else if (res_y_at_x == EQUAL) 00470 { 00471 // In this case p lies on the current edge, so it is obviously not 00472 // contained in the interior of the component. 00473 return (false); 00474 } 00475 } 00476 00477 // Proceed to the next halfedge along the component boundary. 00478 // Note that the source vertex of this halfedge is the current target. 00479 curr = curr->next(); 00480 res_source = res_target; 00481 00482 } while (curr != first); 00483 00484 // The query point lies inside the connected components if and only if the 00485 // ray we shoot from it intersects the boundary an odd number of time. 00486 return ((n_ray_intersections % 2) != 0); 00487 } 00488 00489 CGAL_END_NAMESPACE 00490 00491 #endif