BWAPI
|
00001 // Copyright (c) 1997-2000 Max-Planck-Institute Saarbruecken (Germany). 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/Nef_2/include/CGAL/Nef_2/PM_point_locator.h $ 00015 // $Id: PM_point_locator.h 45448 2008-09-09 16:03:25Z spion $ 00016 // 00017 // 00018 // Author(s) : Michael Seel <seel@mpi-sb.mpg.de> 00019 #ifndef CGAL_PM_POINT_LOCATOR_H 00020 #define CGAL_PM_POINT_LOCATOR_H 00021 00022 #include <CGAL/basic.h> 00023 #include <CGAL/Unique_hash_map.h> 00024 #include <CGAL/Nef_2/Constrained_triang_traits.h> 00025 #include <CGAL/Nef_2/Object_handle.h> 00026 #include <CGAL/Circulator_project.h> 00027 #include <CGAL/Polygon_2_algorithms.h> 00028 #undef CGAL_NEF_DEBUG 00029 #define CGAL_NEF_DEBUG 17 00030 #include <CGAL/Nef_2/debug.h> 00031 #include <CGAL/Nef_2/geninfo.h> 00032 00033 #ifdef CGAL_USE_LEDA 00034 #include <CGAL/LEDA_basic.h> 00035 # if __LEDA__ > 410 && __LEDA__ < 441 00036 # define CGAL_USING_PPL 00037 # include <CGAL/Nef_2/PM_persistent_PL.h> 00038 # endif 00039 #endif 00040 00041 CGAL_BEGIN_NAMESPACE 00042 00043 enum object_kind { VERTEX, EDGE_CROSSING, EDGE_COLLINEAR }; 00044 00045 template < class Node, class Object> 00046 struct Project_halfedge_point { 00047 typedef Node argument_type; 00048 typedef Object result_type; 00049 Object& operator()( Node& x) const { 00050 return x.vertex()->point(); 00051 } 00052 const Object& operator()( const Node& x) const { 00053 return x.vertex()->point(); 00054 } 00055 }; 00056 00057 /*{\Moptions print_title=yes }*/ 00058 /*{\Msubst 00059 PM_decorator_#PMD 00060 Geometry_#GEO 00061 }*/ 00062 /*{\Manpage {PM_naive_point_locator}{PMD,GEO} 00063 {Naive point location in plane maps}{PL}}*/ 00064 /*{\Mdefinition An instance |\Mvar| of data type |\Mname| 00065 encapsulates naive point location queries within a plane map |P|. The 00066 two template parameters are specified via concepts. |PM_decorator_| 00067 must be a model of the concept |PMDecorator| as described in the 00068 appendix. |Geometry_| must be a model of the concept 00069 |AffineGeometryTraits_2| as described in the appendix. For a 00070 specification of plane maps see also the concept of 00071 |PMConstDecorator|.}*/ 00072 00073 /*{\Mgeneralization PMD}*/ 00074 00075 template <typename PM_decorator_, typename Geometry_> 00076 class PM_naive_point_locator : public PM_decorator_ { 00077 protected: 00078 typedef PM_decorator_ Base; 00079 typedef PM_naive_point_locator<PM_decorator_,Geometry_> Self; 00080 00081 const Geometry_& K; 00082 public: 00083 /*{\Mtypes 5}*/ 00084 typedef PM_decorator_ Decorator; 00085 /*{\Mtypemember equals |PM_decorator_|.}*/ 00086 typedef typename Decorator::Plane_map Plane_map; 00087 /*{\Mtypemember the plane map type decorated by |Decorator|.}*/ 00088 typedef typename Decorator::Mark Mark; 00089 /*{\Mtypemember the attribute of all objects (vertices, edges, 00090 faces).}*/ 00091 00092 typedef Geometry_ Geometry; 00093 /*{\Mtypemember equals |Geometry_|.}*/ 00094 typedef typename Geometry_::Point_2 Point; 00095 /*{\Mtypemember the point type of the geometry kernel.\\ 00096 \require |Geometry::Point_2| equals |Plane_map::Point|.}*/ 00097 typedef typename Geometry_::Segment_2 Segment; 00098 /*{\Mtypemember the segment type of the geometry kernel.}*/ 00099 typedef typename Geometry_::Direction_2 Direction; 00100 00101 /*{\Mtext Local types are handles, iterators and circulators of the 00102 following kind: |Vertex_const_handle|, |Vertex_const_iterator|, 00103 |Halfedge_const_handle|, |Halfedge_const_iterator|, |Face_const_handle|, 00104 |Face_const_iterator|.}*/ 00105 00106 typedef CGAL::Object_handle Object_handle; 00107 /*{\Mtypemember a generic handle to an object of the underlying plane 00108 map. The kind of the object |(vertex, halfedge,face)| can be determined and 00109 the object assigned by the three functions:\\ 00110 |bool assign(Vertex_const_handle& h, Object_handle o)|\\ 00111 |bool assign(Halfedge_const_handle& h, Object_handle o)|\\ 00112 |bool assign(Face_const_handle& h, Object_handle o)|\\ where each 00113 function returns |true| iff the assignment of |o| to |h| was valid.}*/ 00114 00115 typedef typename PM_decorator_::Vertex_handle Vertex_handle; 00116 typedef typename PM_decorator_::Halfedge_handle Halfedge_handle; 00117 typedef typename PM_decorator_::Face_handle Face_handle; 00118 typedef typename PM_decorator_::Vertex_const_handle Vertex_const_handle; 00119 typedef typename PM_decorator_::Halfedge_const_handle Halfedge_const_handle; 00120 typedef typename PM_decorator_::Face_const_handle Face_const_handle; 00121 typedef typename PM_decorator_::Vertex_iterator Vertex_iterator; 00122 typedef typename PM_decorator_::Halfedge_iterator Halfedge_iterator; 00123 typedef typename PM_decorator_::Face_iterator Face_iterator; 00124 typedef typename PM_decorator_::Vertex_const_iterator Vertex_const_iterator; 00125 typedef typename PM_decorator_::Halfedge_const_iterator Halfedge_const_iterator; 00126 typedef typename PM_decorator_::Face_const_iterator Face_const_iterator; 00127 typedef typename PM_decorator_::Halfedge_around_vertex_circulator Halfedge_around_vertex_circulator; 00128 typedef typename PM_decorator_::Halfedge_around_vertex_const_circulator Halfedge_around_vertex_const_circulator; 00129 typedef typename PM_decorator_::Halfedge_around_face_circulator Halfedge_around_face_circulator; 00130 typedef typename PM_decorator_::Halfedge_around_face_const_circulator Halfedge_around_face_const_circulator; 00131 00132 using Base::clear; 00133 using Base::vertices_begin; 00134 using Base::vertices_end; 00135 using Base::halfedges_begin; 00136 using Base::halfedges_end; 00137 using Base::faces_begin; 00138 using Base::faces_end; 00139 using Base::number_of_vertices; 00140 using Base::number_of_halfedges; 00141 using Base::number_of_faces; 00142 00143 Halfedge_const_handle out_wedge(Vertex_const_handle v, 00144 const Direction& d, bool& collinear) const 00145 /*{\Xop returns a halfedge |e| bounding a wedge in between two 00146 neighbored edges in the adjacency list of |v| which contains |d|. 00147 If |d| extends along a edge then |e| is this edge. If |d| extends 00148 into the interior of such a wedge then |e| is the first edge hit 00149 when |d| is rotated clockwise. \precond |v| is not isolated.}*/ 00150 { CGAL_NEF_TRACEN("out_wedge "<<PV(v)); 00151 CGAL_assertion(!is_isolated(v)); 00152 collinear=false; 00153 Point p = point(v); 00154 Halfedge_const_handle e_res = first_out_edge(v); 00155 Direction d_res = direction(e_res); 00156 Halfedge_around_vertex_const_circulator el(e_res),ee(el); 00157 CGAL_For_all(el,ee) { 00158 if ( K.strictly_ordered_ccw(d_res, direction(el), d) ) 00159 e_res = el; d_res = direction(e_res); 00160 } 00161 CGAL_NEF_TRACEN(" determined "<<PE(e_res)<<" "<<d_res); 00162 if ( direction(cyclic_adj_succ(e_res)) == d ) { 00163 e_res = cyclic_adj_succ(e_res); 00164 collinear=true; 00165 } 00166 CGAL_NEF_TRACEN(" wedge = "<<PE(e_res)<<" "<<collinear); 00167 return e_res; 00168 } 00169 00170 Segment segment(Halfedge_const_handle e) const 00171 { return K.construct_segment(point(source(e)), point(target(e))); } 00172 00173 Direction direction(Halfedge_const_handle e) const 00174 { return K.construct_direction(point(source(e)),point(target(e))); } 00175 00176 /*{\Mcreation 3}*/ 00177 00178 PM_naive_point_locator() : Base() {} 00179 00180 /*{\Moptions constref=yes}*/ 00181 PM_naive_point_locator(const Plane_map& P, const Geometry& k = Geometry()) : 00182 Base(const_cast<Plane_map&>(P)), K(k) {} 00183 /*{\Mcreate constructs a point locator working on |P|.}*/ 00184 /*{\Moptions constref=no}*/ 00185 /*{\Moperations 2.5 0.5}*/ 00186 00187 const Mark& mark(Object_handle h) const 00188 /*{\Mop returns the mark associated to the object |h|.}*/ 00189 { Vertex_const_handle v; 00190 Halfedge_const_handle e; 00191 Face_const_handle f; 00192 if ( assign(v,h) ) return mark(v); 00193 if ( assign(e,h) ) return mark(e); 00194 if ( assign(f,h) ) return mark(f); 00195 CGAL_error_msg("PM_point_locator::mark: Object_handle holds no object."); 00196 return mark(v); // never reached 00197 } 00198 00199 00200 Object_handle locate(const Segment& s) const 00201 /*{\Mop returns a generic handle |h| to an object (vertex, halfedge, 00202 face) of the underlying plane map |P| which contains the point |p = 00203 s.source()| in its relative interior. |s.target()| must be a point 00204 such that |s| intersects the $1$-skeleton of |P|.}*/ 00205 { CGAL_NEF_TRACEN("locate naivly "<<s); 00206 if (this->number_of_vertices() == 0) 00207 CGAL_error_msg("PM_naive_point_locator: plane map is empty."); 00208 Point p = K.source(s); 00209 Vertex_const_iterator vit; 00210 for(vit = this->vertices_begin(); vit != this->vertices_end(); ++vit) { 00211 if ( p == point(vit) ) return make_object(vit); 00212 } 00213 Halfedge_const_iterator eit; 00214 for(eit = this->halfedges_begin(); eit != this->halfedges_end(); ++(++eit)) { 00215 // we only have to check each second halfedge 00216 if ( K.contains(segment(eit),p) ) 00217 return make_object(eit); 00218 } 00219 Vertex_const_handle v_res; 00220 Halfedge_const_handle e_res; 00221 Segment ss = s; // we shorten the segment iteratively 00222 Direction dso = K.construct_direction(K.target(s),p), d_res; 00223 CGAL::Unique_hash_map<Halfedge_const_handle,bool> visited(false); 00224 for(vit = this->vertices_begin(); vit != this->vertices_end(); ++vit) { 00225 Point p_res, vp = point(vit); 00226 if ( K.contains(ss,vp) ) { 00227 CGAL_NEF_TRACEN(" location via vertex at "<<vp); 00228 ss = K.construct_segment(p,vp); // we shrink the segment 00229 if ( is_isolated(vit) ) { 00230 v_res = vit; e_res = Halfedge_const_handle(); 00231 } else { // not isolated 00232 bool dummy; 00233 e_res = out_wedge(vit,dso,dummy); 00234 Halfedge_around_vertex_const_circulator el(e_res),ee(el); 00235 CGAL_For_all(el,ee) 00236 visited[el] = visited[twin(el)] = true; 00237 /* e_res is now the counterclockwise maximal halfedge out 00238 of v just before s */ 00239 if ( K.orientation(p,vp,point(target(e_res))) < 0 ) // right turn 00240 e_res = previous(e_res); 00241 // correction to make e_res visible from p 00242 CGAL_NEF_TRACEN(" determined "<<PE(e_res)); 00243 } 00244 } 00245 } 00246 00247 for (eit = this->halfedges_begin(); eit != this->halfedges_end(); ++eit) { 00248 if ( visited[eit] ) continue; 00249 Point se = point(source(eit)), 00250 te = point(target(eit)); 00251 int o1 = K.orientation(ss,se); 00252 int o2 = K.orientation(ss,te); 00253 if ( o1 == -o2 && // internal intersection 00254 K.orientation(se,te,K.source(ss)) != 00255 K.orientation(se,te,K.target(ss)) ) { 00256 CGAL_NEF_TRACEN(" location via halfedge "<<segment(eit)); 00257 Point p_res = K.intersection(s,segment(eit)); 00258 ss = K.construct_segment(p,p_res); 00259 e_res = (o2 > 0 ? eit : twin(eit)); 00260 // o2>0 => te left of s and se right of s => p left of e 00261 visited[eit] = visited[twin(eit)] = true; 00262 CGAL_NEF_TRACEN(" determined "<<PE(e_res)<<" "<<mark(e_res)); 00263 CGAL_NEF_TRACEN(" "<<mark(face(e_res))); 00264 } 00265 } 00266 00267 if ( e_res != Halfedge_const_handle() ) 00268 return make_object((Face_const_handle)(face(e_res))); 00269 else 00270 return make_object((Face_const_handle)(face(v_res))); 00271 } 00272 00273 00274 template <typename Object_predicate> 00275 Object_handle ray_shoot(const Segment& s, const Object_predicate& M) const 00276 /*{\Mop returns an |Object_handle o| which can be converted to a 00277 |Vertex_const_handle|, |Halfedge_const_handle|, |Face_const_handle| 00278 |h| as described above. The object predicate |M| has to have function 00279 operators \\ 00280 |bool operator() (const Vertex_/Halfedge_/Face_const_handle&)|.\\ 00281 The object returned is intersected by the segment |s| and has 00282 minimal distance to |s.source()| and |M(h)| holds on the converted 00283 object. The operation returns the null handle |NULL| if the ray shoot 00284 along |s| does not hit any object |h| of |P| with |M(h)|.}*/ 00285 { CGAL_NEF_TRACEN("naive ray_shoot "<<s); 00286 CGAL_assertion( !K.is_degenerate(s) ); 00287 Point p = K.source(s); 00288 Segment ss(s); 00289 Direction d = K.construct_direction(K.source(s),K.target(s)); 00290 Object_handle h = locate(s); 00291 Vertex_const_handle v; 00292 Halfedge_const_handle e; 00293 Face_const_handle f; 00294 if ( assign(v,h) && M(v) || 00295 assign(e,h) && M(e) || 00296 assign(f,h) && M(f) ) return h; 00297 h = Object_handle(); 00298 CGAL_NEF_TRACEN("not contained"); 00299 for (v = this->vertices_begin(); v != this->vertices_end(); ++v) { 00300 Point pv = point(v); 00301 if ( !K.contains(ss,pv) ) continue; 00302 CGAL_NEF_TRACEN("candidate "<<pv); 00303 if ( M(v) ) { 00304 h = make_object(v); // store vertex 00305 ss = K.construct_segment(p,pv); // shorten 00306 continue; 00307 } 00308 // now we know that v is not marked but on s 00309 bool collinear; 00310 Halfedge_const_handle e = out_wedge(v,d,collinear); 00311 if ( collinear ) { 00312 if ( M(e) ) { 00313 h = make_object(e); 00314 ss = K.construct_segment(p,pv); 00315 } 00316 continue; 00317 } 00318 if ( M(face(e)) ) { 00319 h = make_object(face(e)); 00320 ss = K.construct_segment(p,pv); 00321 } 00322 } // all vertices 00323 00324 Halfedge_const_iterator e_res; 00325 for(e = this->halfedges_begin(); e != this->halfedges_end(); ++(++e)) { 00326 Segment es = segment(e); 00327 int o1 = K.orientation(ss,K.source(es)); 00328 int o2 = K.orientation(ss,K.target(es)); 00329 if ( o1 == -o2 && o1 != 0 && 00330 K.orientation(es, K.source(ss)) == 00331 - K.orientation(es, K.target(ss)) ) { 00332 // internal intersection 00333 CGAL_NEF_TRACEN("candidate "<<es); 00334 Point p_res = K.intersection(s,es); 00335 e_res = (o2 > 0 ? e : twin(e)); 00336 // o2 > 0 => te left of s and se right of s => p left of e 00337 if ( M(e_res) ) { 00338 h = make_object(e_res); 00339 ss = K.construct_segment(p,p_res); 00340 } else if ( M(face(twin(e_res))) ) { 00341 h = make_object(face(twin(e_res))); 00342 ss = K.construct_segment(p,p_res); 00343 } 00344 } 00345 } 00346 00347 return h; 00348 } 00349 00350 00351 // C++ is really friendly: 00352 #define USECMARK(t) const Mark& mark(t h) const { return Base::mark(h); } 00353 #define USEMARK(t) Mark& mark(t h) const { return Base::mark(h); } 00354 USEMARK(Vertex_handle) 00355 USEMARK(Halfedge_handle) 00356 USEMARK(Face_handle) 00357 USECMARK(Vertex_const_handle) 00358 USECMARK(Halfedge_const_handle) 00359 USECMARK(Face_const_handle) 00360 #undef USEMARK 00361 #undef USECMARK 00362 /*{\Mimplementation Naive query operations are realized by checking 00363 the intersection points of the $1$-skeleton of the plane map |P| with 00364 the query segments $s$. This method takes time linear in the size $n$ 00365 of the underlying plane map without any preprocessing.}*/ 00366 }; // PM_naive_point_locator<PM_decorator_,Geometry_> 00367 00368 00369 /*{\Moptions print_title=yes }*/ 00370 /*{\Msubst 00371 PM_decorator_#PMD 00372 Geometry_#GEO 00373 }*/ 00374 /*{\Manpage {PM_point_locator}{PMD,GEO} 00375 {Point location in plane maps via LMWT}{PL}}*/ 00376 /*{\Mdefinition An instance |\Mvar| of data type |\Mname| 00377 encapsulates point location queries within a plane map |P|. The two 00378 template parameters are specified via concepts. |PMD| must be a model 00379 of the concept |PMDecorator| as described in the appendix. |GEO| must 00380 be a model of the concept |AffineGeometryTraits_2| as described in the 00381 appendix. For a specification of plane maps see also the concept of 00382 |PMConstDecorator|.}*/ 00383 00384 /*{\Mgeneralization PMD^#PM_naive_point_locator<PMD,GEO>}*/ 00385 00386 template <typename PM_decorator_, typename Geometry_> 00387 class PM_point_locator : public 00388 PM_naive_point_locator<PM_decorator_,Geometry_> { 00389 protected: 00390 typedef PM_naive_point_locator<PM_decorator_,Geometry_> Base; 00391 typedef PM_point_locator<PM_decorator_,Geometry_> Self; 00392 Base CT; 00393 #ifdef CGAL_USING_PPL 00394 typedef PM_persistent_PL_traits<Base> PMPPLT; 00395 typedef PointLocator<PMPPLT> PMPP_locator; 00396 PMPP_locator* pPPL; 00397 #define LOCATE_IN_TRIANGULATION pPPL->locate_down 00398 #else 00399 #define LOCATE_IN_TRIANGULATION walk_in_triangulation 00400 #endif 00401 00402 public: 00403 00404 typedef typename Base::Decorator Decorator; 00405 typedef typename Base::Plane_map Plane_map; 00406 typedef typename Base::Mark Mark; 00407 typedef typename Base::Geometry Geometry; 00408 typedef typename Base::Point Point; 00409 typedef typename Base::Segment Segment; 00410 typedef typename Base::Direction Direction; 00411 typedef typename Base::Object_handle Object_handle; 00412 typedef typename Base::Vertex_handle Vertex_handle; 00413 typedef typename Base::Halfedge_handle Halfedge_handle; 00414 typedef typename Base::Face_handle Face_handle; 00415 typedef typename Base::Vertex_const_handle Vertex_const_handle; 00416 typedef typename Base::Halfedge_const_handle Halfedge_const_handle; 00417 typedef typename Base::Face_const_handle Face_const_handle; 00418 typedef typename Base::Vertex_iterator Vertex_iterator; 00419 typedef typename Base::Halfedge_iterator Halfedge_iterator; 00420 typedef typename Base::Face_iterator Face_iterator; 00421 typedef typename Base::Vertex_const_iterator Vertex_const_iterator; 00422 typedef typename Base::Halfedge_const_iterator Halfedge_const_iterator; 00423 typedef typename Base::Face_const_iterator Face_const_iterator; 00424 typedef typename Base::Halfedge_around_vertex_circulator Halfedge_around_vertex_circulator; 00425 typedef typename Base::Halfedge_around_vertex_const_circulator Halfedge_around_vertex_const_circulator; 00426 typedef typename Base::Halfedge_around_face_circulator Halfedge_around_face_circulator; 00427 typedef typename Base::Halfedge_around_face_const_circulator Halfedge_around_face_const_circulator; 00428 00429 using Base::K; 00430 using Base::number_of_vertices; 00431 using Base::faces_begin; 00432 00433 /*{\Mtypes 2}*/ 00434 /*{\Mtext All local types of |PM_naive_point_locator| are inherited.}*/ 00435 typedef std::pair<Vertex_const_handle,Face_const_handle> VF_pair; 00436 typedef std::pair<Halfedge_const_handle,Face_const_handle> EF_pair; 00437 00438 struct CT_link_to_original : Decorator { // CT decorator 00439 const Decorator& Po; 00440 CT_link_to_original(const Decorator& P, const Decorator& Poi) 00441 : Decorator(P), Po(Poi) {} 00442 void operator()(Vertex_handle vn, Vertex_const_handle vo) const 00443 { Face_const_handle f; 00444 if ( Po.is_isolated(vo) ) f = Po.face(vo); 00445 geninfo<VF_pair>::create(info(vn)); 00446 geninfo<VF_pair>::access(info(vn)) = VF_pair(vo,f); 00447 CGAL_NEF_TRACEN("linking to org "<<PV(vn)); 00448 } 00449 void operator()(Halfedge_handle hn, Halfedge_const_handle ho) const 00450 { geninfo<EF_pair>::create(info(hn)); 00451 geninfo<EF_pair>::access(info(hn)) = EF_pair(ho,Po.face(ho)); 00452 CGAL_NEF_TRACEN("linking to org "<<PE(hn)); 00453 } 00454 }; 00455 00456 protected: 00457 Vertex_const_handle input_vertex(Vertex_const_handle v) const 00458 { return geninfo<VF_pair>::const_access(CT.info(v)).first; } 00459 00460 Halfedge_const_handle input_halfedge(Halfedge_const_handle e) const 00461 { return geninfo<EF_pair>::const_access(CT.info(e)).first; } 00462 00463 Face_const_handle input_face(Halfedge_const_handle e) const 00464 { return geninfo<EF_pair>::const_access(CT.info(e)).second; } 00465 00466 00467 Object_handle input_object(Vertex_const_handle v) const 00468 { return make_object(input_vertex(v)); } 00469 00470 Object_handle input_object(Halfedge_const_handle e) const 00471 { Halfedge_const_handle e_org = input_halfedge(e); 00472 if ( e_org != Halfedge_const_handle() ) 00473 return make_object( e_org ); 00474 // now e_org is not existing 00475 return make_object( input_face(e) ); 00476 } 00477 00478 /*{\Mimplementation 00479 The efficiency of this point location module is mostly based on 00480 heuristics. Therefore worst case bounds are not very expressive. The 00481 query operations take up to linear time for subsequent query 00482 operations though they are better in practise. They trigger a one-time 00483 initialization which needs worst case $O(n^2)$ time though runtime 00484 tests often show subquadratic results. The necessary space for the 00485 query structure is subsumed in the storage space $O(n)$ of the input 00486 plane map. The query times are configuration dependent. If LEDA is 00487 present then point location is done via the slap method based on 00488 persistent dictionaries. Then $T_{pl}(n) = O( \log(n) )$. If CGAL is 00489 not configured to use LEDA then point location is done via a segment 00490 walk in the underlying convex subdivision of $P$. In this case 00491 $T_{pl}(n)$ is the number of triangles crossed by a walk from the 00492 boundary of the structure to the query point. The time for the ray 00493 shooting operation $T_{rs}(n)$ is the time for the point location 00494 $T_{pl}(n)$ plus the time for the walk in the triangulation that is 00495 superimposed to the plane map. Let's consider the plane map edges as 00496 obstacles and the additional triangulation edges as non-obstacle 00497 edges. Let's call the sum of the lengths of all edges of the 00498 triangulation its weight. If the calculated triangulation 00499 approximates\footnote{The calculation of general 00500 minimum-weight-triangulations is conjectured to be NP-complete and 00501 locally-minimum-weight-triangulations that we use are considered good 00502 approximations.} the minimum weight triangulation of the obstacle set 00503 then the stepping quotient\footnote {The number of non-obstacle edges 00504 crossed until an obstacle edge is hit.} for a random direction of the 00505 ray shot is expected to be $O( \sqrt{n} )$.}*/ 00506 00507 00508 struct CT_new_edge : Decorator { 00509 const Decorator& _DP; 00510 CT_new_edge(const Decorator& CT, const Decorator& DP) : 00511 Decorator(CT), _DP(DP) {} 00512 void operator()(Halfedge_handle& e) const 00513 { Halfedge_handle e_from = previous(e); 00514 Face_const_handle f; 00515 if ( is_closed_at_source(e) ) // source(e) was isolated before 00516 f = geninfo<VF_pair>::access(info(source(e))).second; 00517 else 00518 f = geninfo<EF_pair>::access(info(e_from)).second; 00519 mark(e) = _DP.mark(f); 00520 geninfo<EF_pair>::create(info(e)); 00521 geninfo<EF_pair>::create(info(twin(e))); 00522 00523 geninfo<EF_pair>::access(info(e)).first = 00524 geninfo<EF_pair>::access(info(twin(e))).first = 00525 Halfedge_const_handle(); 00526 00527 geninfo<EF_pair>::access(info(e)).second = 00528 geninfo<EF_pair>::access(info(twin(e))).second = f; 00529 CGAL_NEF_TRACEN("CT_new_edge "<<PE(e)); 00530 } 00531 }; 00532 00533 void triangulate_CT() const 00534 { 00535 CGAL_NEF_TRACEN("triangulate_CT"); 00536 typedef CGAL::Constrained_triang_traits< 00537 Decorator,Geometry,CT_new_edge> NCTT; 00538 typedef CGAL::generic_sweep<NCTT> Constrained_triang_sweep; 00539 CT_new_edge NE(CT,*this); 00540 Constrained_triang_sweep T(NE,CT.plane_map(),this->K); T.sweep(); 00541 } 00542 00543 void minimize_weight_CT() const 00544 { CGAL_NEF_TRACEN("minimize_weight_CT"); 00545 if ( this->number_of_vertices() < 2 ) return; 00546 std::list<Halfedge_handle> S; 00547 /* We maintain a stack |S| of edges containing diagonals 00548 which might have to be flipped. */ 00549 int flip_count = 0; 00550 Halfedge_iterator e; 00551 for (e = CT.halfedges_begin(); e != CT.halfedges_end(); ++(++e)) { 00552 Halfedge_const_handle e_org = input_halfedge(e); 00553 if ( e_org != Halfedge_const_handle() ) 00554 continue; 00555 S.push_back(e); 00556 } 00557 00558 while ( !S.empty() ) { 00559 Halfedge_handle e = S.front(); S.pop_front(); 00560 Halfedge_handle r = twin(e); 00561 Halfedge_const_handle e_org = input_halfedge(e); 00562 if ( e_org != Halfedge_const_handle() ) 00563 continue; 00564 Halfedge_handle e1 = next(r); 00565 Halfedge_handle e3 = next(e); 00566 // e1,e3: edges of quadrilateral with diagonal e 00567 00568 Point a = point(source(e1)); 00569 Point b = point(target(e1)); 00570 Point c = point(source(e3)); 00571 Point d = point(target(e3)); 00572 00573 if (! (this->K.orientation(b,d,a) > 0 && // left_turn 00574 this->K.orientation(b,d,c) < 0) ) // right_turn 00575 continue; 00576 00577 if ( this->K.first_pair_closer_than_second(b,d,a,c) ) { // flip 00578 CGAL_NEF_TRACEN("flipping diagonal of quadilateral"<<a<<b<<c<<d); 00579 Halfedge_handle e2 = next(e1); 00580 Halfedge_handle e4 = next(e3); 00581 S.push_back(e1); 00582 S.push_back(e2); 00583 S.push_back(e3); 00584 S.push_back(e4); 00585 flip_diagonal(e); 00586 flip_count++; 00587 } 00588 00589 00590 } 00591 CGAL_NEF_TRACEN(" flipped "<<flip_count); 00592 } 00593 00594 public: 00595 /*{\Mcreation 3}*/ 00596 00597 PM_point_locator() { 00598 #ifdef CGAL_USING_PPL 00599 pPPL = 0; 00600 #endif 00601 00602 } 00603 00604 /*{\Moptions constref=yes}*/ 00605 PM_point_locator(const Plane_map& P, const Geometry& k = Geometry()); 00606 /*{\Mcreate constructs a point locator working on |P|.}*/ 00607 00608 ~PM_point_locator(); 00609 00610 /*{\Moperations 2.5 0.5}*/ 00611 00612 const Decorator& triangulation() const { return CT; } 00613 /*{\Mop access to the constrained triangulation structure that 00614 is superimposed to |P|.}*/ 00615 /*{\Moptions constref=no}*/ 00616 00617 00618 Object_handle locate(const Point& p) const 00619 /*{\Mop returns a generic handle |h| to an object (vertex, halfedge, 00620 face) of |P| which contains the point |p| in its relative 00621 interior.}*/ 00622 { 00623 Object_handle h = LOCATE_IN_TRIANGULATION(p); 00624 Vertex_const_handle v_triang; 00625 if ( assign(v_triang,h) ) { 00626 return input_object(v_triang); 00627 } 00628 Halfedge_const_handle e_triang; 00629 if ( assign(e_triang,h) ) { 00630 Halfedge_const_handle e = input_halfedge(e_triang); 00631 if ( e == Halfedge_const_handle() ) // inserted during triangulation 00632 return make_object(input_face(e_triang)); 00633 int orientation_ = this->K.orientation(segment(e),p); 00634 if ( orientation_ == 0 ) return make_object(e); 00635 if ( orientation_ < 0 ) return make_object(face(twin(e))); 00636 if ( orientation_ > 0 ) return make_object(face(e)); 00637 } 00638 CGAL_assertion(!check_tag(typename Is_extended_kernel<Geometry>::value_type())); 00639 return make_object(Face_const_handle(faces_begin())); 00640 // CGAL_error(); return h; // compiler warning 00641 } 00642 00643 bool ray_shoot_from_outer_facet(Segment& , object_kind& , 00644 Vertex_const_handle &, 00645 Halfedge_const_handle& , 00646 const Tag_true& ) const { 00647 return false; 00648 } 00649 00650 bool ray_shoot_from_outer_facet(Segment& s, object_kind& current, 00651 Vertex_const_handle &v, 00652 Halfedge_const_handle& e, 00653 const Tag_false& ) const { 00654 CGAL_NEF_TRACEN("target on outer facet"); 00655 Point p = this->K.source(s); 00656 Vertex_const_handle v1 = CT.vertices_begin(); 00657 Halfedge_const_handle e1 = CT.twin(CT.first_out_edge(v1)); 00658 Halfedge_around_face_const_circulator circ(e1), end(circ); 00659 Point i; 00660 Segment seg; 00661 bool found = false; 00662 CGAL_For_all(circ, end) { 00663 // std::cerr << s << std::endl; 00664 // std::cerr << point(source(circ)) << "->" << point(target(circ)) << std::endl; 00665 Object o = intersection(s, Segment(point(source(circ)), 00666 point(target(circ)))); 00667 00668 if(assign(i,o)) { 00669 CGAL_NEF_TRACEN("intersection in point " << i); 00670 found = true; 00671 s = Segment(p,i); 00672 if(i == point(source(circ))) { 00673 current = VERTEX; 00674 v = source(circ); 00675 } else if(i == point(target(circ))) { 00676 current = VERTEX; 00677 v = target(circ); 00678 } else { 00679 current = EDGE_CROSSING; 00680 e = circ; 00681 } 00682 } else if(assign(seg,o)) { 00683 found = true; 00684 CGAL_NEF_TRACEN("overlap of segments"); 00685 current = EDGE_COLLINEAR; 00686 e = circ; 00687 } 00688 } 00689 return found; 00690 } 00691 00692 template <typename Object_predicate> 00693 Object_handle ray_shoot(const Segment& ss, const Object_predicate& M) const 00694 /*{\Mop returns an |Object_handle o| which can be converted to a 00695 |Vertex_const_handle|, |Halfedge_const_handle|, |Face_const_handle| 00696 |h| as described above. The object predicate |M| has to have 00697 function operators\\ 00698 |bool operator() (const Vertex_/ Halfedge_/Face_const_handle&) const|.\\ 00699 The object returned is intersected by the segment |s| and has minimal 00700 distance to |s.source()| and |M(h)| holds on the converted object. The 00701 operation returns the null handle |NULL| if the ray shoot along |s| 00702 does not hit any object |h| of |P| with |M(h)|.}*/ 00703 { Segment s(ss); 00704 CGAL_NEF_TRACEN("ray_shoot "<<s); 00705 CGAL_assertion( !this->K.is_degenerate(s) ); 00706 Point p = this->K.source(s); 00707 Direction d = this->K.construct_direction(p,s.target()); 00708 Vertex_const_handle v; 00709 Halfedge_const_handle e; 00710 object_kind current; 00711 Object_handle h = LOCATE_IN_TRIANGULATION(p); 00712 if ( assign(v,h) ) { 00713 CGAL_NEF_TRACEN("located vertex "<<PV(v)); 00714 current = VERTEX; 00715 } else if ( assign(e,h) ) { 00716 CGAL_NEF_TRACEN("located edge "<<PE(e)); 00717 int orientation_ = this->K.orientation( segment(e), p); 00718 if ( orientation_ == 0 ) { // p on segment 00719 CGAL_NEF_TRACEN("on edge "<<PE(e)); 00720 if ( d == CT.direction(e) ) 00721 { current = EDGE_COLLINEAR; } 00722 else if ( d == CT.direction(CT.twin(e)) ) 00723 { e = CT.twin(e); current = EDGE_COLLINEAR; } 00724 else { // crossing 00725 current = EDGE_CROSSING; 00726 if ( !(this->K.orientation(CT.segment(e),s.target())>0) ) // not left_turn 00727 e = CT.twin(e); 00728 } 00729 00730 } else { // p not on segment, thus in triangle 00731 if ( orientation_ < 0 ) e = CT.twin(e); 00732 // now p left of e 00733 CGAL_NEF_TRACEN("in face at "<<PE(e)); 00734 if ( M(input_face(e)) ) // face mark 00735 return make_object(input_face(e)); 00736 00737 Point p1 = CT.point(CT.source(e)), 00738 p2 = CT.point(CT.target(e)), 00739 p3 = CT.point(CT.target(next(e))); 00740 int or1 = this->K.orientation(p,s.target(),p1); 00741 int or2 = this->K.orientation(p,s.target(),p2); 00742 int or3 = this->K.orientation(p,s.target(),p3); 00743 if ( or1 == 0 && !this->K.left_turn(p1,p2,s.target()) ) 00744 { v = CT.source(e); current = VERTEX; } 00745 else if ( or2 == 0 && !this->K.left_turn(p2,p3,s.target()) ) 00746 { v = CT.target(e); current = VERTEX; } 00747 else if ( or3 == 0 && !this->K.left_turn(p3,p1,s.target()) ) 00748 { v = CT.target(CT.next(e)); current = VERTEX; } 00749 else if ( or2 > 0 && or1 < 0 && !this->K.left_turn(p1,p2,s.target()) ) 00750 { e = CT.twin(e); current = EDGE_CROSSING; } 00751 else if ( or3 > 0 && or2 < 0 && !this->K.left_turn(p2,p3,s.target()) ) 00752 { e = CT.twin(CT.next(e)); current = EDGE_CROSSING; } 00753 else if ( or1 > 0 && or3 < 0 && !this->K.left_turn(p3,p1,s.target()) ) 00754 { e = CT.twin(CT.previous(e)); current = EDGE_CROSSING; } 00755 else return Object_handle(); 00756 00757 } 00758 } else { 00759 00760 if(check_tag(typename Is_extended_kernel<Geometry>::value_type())) { 00761 CGAL_error_msg( "code is only for Bounded_kernel"); 00762 } 00763 if(!ray_shoot_from_outer_facet(s,current,v,e,typename Is_extended_kernel<Geometry>::value_type())) 00764 return Object_handle(); 00765 } 00766 00767 CGAL_NEF_TRACEN("current = " << current); 00768 if(current == VERTEX) 00769 CGAL_NEF_TRACEN(point(v)); 00770 00771 while (true) switch ( current ) { 00772 case VERTEX: 00773 { CGAL_NEF_TRACEN("vertex "<<CT.point(v)); 00774 Vertex_const_handle v_org = input_vertex(v); 00775 if ( M(v_org) ) return make_object(v_org); 00776 if ( CT.point(v) == s.target() ) return Object_handle(); 00777 // stop walking at s.target(), or determine next object on s: 00778 bool collinear; 00779 Halfedge_const_handle e_out = CT.out_wedge(v,d,collinear); 00780 if (collinear) // ray shoot via e_out 00781 { e = e_out; current = EDGE_COLLINEAR; } 00782 else { // ray shoot in wedge left of e_out 00783 if ( M(input_face(e_out)) ) 00784 return make_object(input_face(e_out)); 00785 e = CT.twin(CT.next(e_out)); current = EDGE_CROSSING; 00786 } 00787 } 00788 00789 break; 00790 case EDGE_CROSSING: 00791 { CGAL_NEF_TRACEN("crossing edge "<<segment(e)); 00792 if ( this->K.orientation(CT.segment(e),s.target()) == 0 ) 00793 return Object_handle(); 00794 Halfedge_const_handle e_org = input_halfedge(e); 00795 if ( e_org != Halfedge_const_handle() ) { // not a CT edge 00796 if ( M(e_org) ) return make_object(e_org); 00797 if ( M(face(e_org)) ) return make_object(face(e_org)); 00798 } 00799 Vertex_const_handle v_cand = CT.target(CT.next(e)); 00800 CGAL_NEF_TRACEN("v_cand "<<PV(v_cand)); 00801 int orientation_ = this->K.orientation(p,s.target(),CT.point(v_cand)); 00802 switch( orientation_ ) { 00803 case 0: 00804 v = v_cand; current = VERTEX; break; 00805 case +1: 00806 e = CT.twin(CT.next(e)); current = EDGE_CROSSING; break; 00807 case -1: 00808 e = CT.twin(CT.previous(e)); current = EDGE_CROSSING; break; 00809 } 00810 } 00811 00812 break; 00813 case EDGE_COLLINEAR: 00814 { CGAL_NEF_TRACEN("collinear edge "<<CT.segment(e)); 00815 Halfedge_const_handle e_org = input_halfedge(e); 00816 if ( e_org == Halfedge_const_handle() ) { // a CT edge 00817 if ( M(input_face(e)) ) 00818 return make_object(input_face(e)); 00819 } else { // e_org is not a CT edge 00820 if ( M(e_org) ) 00821 return make_object(e_org); 00822 } 00823 if ( this->K.strictly_ordered_along_line( 00824 CT.point(CT.source(e)),s.target(),CT.point(CT.target(e))) ) 00825 return Object_handle(); 00826 v = CT.target(e); current = VERTEX; 00827 } 00828 00829 break; 00830 } 00831 // CGAL_error(); return h; // compiler warning 00832 } 00833 00834 bool within_outer_cycle(Vertex_const_handle , 00835 const Point& , const Tag_true& ) const { 00836 return true; 00837 } 00838 00839 bool within_outer_cycle(Vertex_const_handle v, 00840 const Point& q, const Tag_false& ) const { 00841 typedef Project_halfedge_point<typename Decorator::Halfedge, Point> Project; 00842 typedef Circulator_project<Halfedge_around_face_const_circulator, 00843 Project, const Point&, const Point*> Circulator; 00844 typedef Container_from_circulator<Circulator> Container; 00845 00846 Halfedge_const_handle e_min = CT.twin(CT.first_out_edge(v)); 00847 Halfedge_around_face_const_circulator circ(e_min); 00848 Circulator c(circ); 00849 Container ct(c); 00850 if(is_empty_range(ct.begin(), ct.end()) || 00851 bounded_side_2(ct.begin(), ct.end(),q) == CGAL::ON_UNBOUNDED_SIDE) 00852 return false; 00853 00854 return true; 00855 } 00856 00857 Object_handle walk_in_triangulation(const Point& p) const; 00858 00859 }; // PM_point_locator<PM_decorator_,Geometry_> 00860 00861 00862 #ifdef CGAL_USING_PPL 00863 static const char* const pointlocationversion ="point location via pers dicts"; 00864 #else 00865 static const char* const pointlocationversion ="point location via seg walks"; 00866 #endif 00867 00868 template <typename PMD, typename GEO> 00869 PM_point_locator<PMD,GEO>:: 00870 PM_point_locator(const Plane_map& P, const Geometry& k) : 00871 Base(P,k), CT(*(new Plane_map),k) 00872 00873 { CGAL_NEF_TRACEN("PM_point_locator construction"); 00874 CT.clone_skeleton(P,CT_link_to_original(CT,*this)); 00875 triangulate_CT(); 00876 minimize_weight_CT(); 00877 #ifdef CGAL_USING_PPL 00878 pPPL = new PMPP_locator(CT,PMPPLT(K)); 00879 #endif 00880 00881 } 00882 00883 template <typename PMD, typename GEO> 00884 PM_point_locator<PMD,GEO>:: 00885 ~PM_point_locator() 00886 { CGAL_NEF_TRACEN("clear_static_point_locator"); 00887 Vertex_iterator vit, vend = CT.vertices_end(); 00888 for (vit = CT.vertices_begin(); vit != vend; ++vit) { 00889 geninfo<VF_pair>::clear(CT.info(vit)); 00890 } 00891 Halfedge_iterator eit, eend = CT.halfedges_end(); 00892 for (eit = CT.halfedges_begin(); eit != eend; ++eit) { 00893 geninfo<EF_pair>::clear(CT.info(eit)); 00894 } 00895 CT.clear(); 00896 delete &(CT.plane_map()); 00897 #ifdef CGAL_USING_PPL 00898 delete pPPL; pPPL=0; 00899 #endif 00900 } 00901 00902 template <typename PMD, typename GEO> 00903 typename PM_point_locator<PMD,GEO>::Object_handle 00904 PM_point_locator<PMD,GEO>::walk_in_triangulation(const Point& q) const 00905 { 00906 CGAL_NEF_TRACEN("walk in triangulation "<<q); 00907 00908 Vertex_const_handle v = CT.vertices_begin(); 00909 00910 if(!check_tag(typename Is_extended_kernel<GEO>::value_type())) 00911 if(!within_outer_cycle(v,q,typename Is_extended_kernel<Geometry>::value_type())) 00912 return Object_handle(); 00913 00914 Halfedge_const_handle e; 00915 Point p = CT.point(v); 00916 if ( p == q ) return make_object(v); 00917 // Segment s = this->K.construct_segment(p,q); 00918 Direction dir = this->K.construct_direction(p,q); 00919 object_kind current = VERTEX; 00920 while (true) switch ( current ) { 00921 case VERTEX: 00922 { 00923 CGAL_NEF_TRACEN("vertex "<<CT.point(v)); 00924 if ( CT.point(v) == q ) 00925 return make_object(v); // stop walking at q 00926 bool collinear; 00927 Halfedge_const_handle e_out = CT.out_wedge(v,dir,collinear); 00928 if (collinear) // ray shoot via e_out 00929 { e = e_out; current = EDGE_COLLINEAR; } 00930 else // ray shoot in wedge left of e_out 00931 { e = CT.twin(CT.next(e_out)); current = EDGE_CROSSING; } 00932 } 00933 00934 break; 00935 case EDGE_CROSSING: 00936 { CGAL_NEF_TRACEN("crossing edge "<<CT.segment(e)); 00937 if ( !(this->K.orientation(CT.segment(e),q) > 0) ) // q not left of e 00938 return make_object(e); 00939 Vertex_const_handle v_cand = CT.target(CT.next(e)); 00940 int orientation_ = this->K.orientation(p,q,CT.point(v_cand)); 00941 switch( orientation_ ) { 00942 case 0: // collinear 00943 if ( this->K.strictly_ordered_along_line(p,q,CT.point(v_cand)) ) 00944 return make_object(e); 00945 v = v_cand; current = VERTEX; break; 00946 case +1: // left_turn 00947 e = twin(next(e)); current = EDGE_CROSSING; break; 00948 case -1: 00949 e = twin(previous(e)); current = EDGE_CROSSING; break; 00950 } 00951 } 00952 00953 break; 00954 case EDGE_COLLINEAR: 00955 { CGAL_NEF_TRACEN("collinear edge "<<CT.segment(e)); 00956 if ( this->K.strictly_ordered_along_line( 00957 CT.point(CT.source(e)),q,CT.point(CT.target(e))) ) 00958 return make_object(e); 00959 v = CT.target(e); current = VERTEX; 00960 } 00961 00962 break; 00963 } 00964 return Object_handle(); // never reached warning acceptable 00965 } 00966 00967 CGAL_END_NAMESPACE 00968 00969 #endif // CGAL_PM_POINT_LOCATOR_H