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_S2/include/CGAL/Nef_S2/SM_point_locator.h $ 00015 // $Id: SM_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_SM_POINT_LOCATOR_H 00020 #define CGAL_SM_POINT_LOCATOR_H 00021 00022 #include <vector> 00023 #include <CGAL/basic.h> 00024 #include <CGAL/Unique_hash_map.h> 00025 #include <CGAL/Nef_2/geninfo.h> 00026 #include <CGAL/Nef_2/Object_handle.h> 00027 #include <CGAL/Nef_S2/SM_decorator_traits.h> 00028 #undef CGAL_NEF_DEBUG 00029 #define CGAL_NEF_DEBUG 47 00030 #include <CGAL/Nef_2/debug.h> 00031 00032 00033 CGAL_BEGIN_NAMESPACE 00034 00035 /*{\Moptions print_title=yes }*/ 00036 00037 /*{\Manpage {SM_point_locator}{Decorator} 00038 {Naive point location in plane maps}{PL}}*/ 00039 /*{\Mdefinition An instance |\Mvar| of data type |\Mname| 00040 encapsulates naive point location queries within a sphere map |M|. The 00041 two template parameters are specified via concepts. |SM_decorator_| 00042 must be a model of the concept |SMDecorator| as described in the 00043 appendix. |Geometry_| must be a model of the concept 00044 |AffineGeometryTraits_2| as described in the appendix. For a 00045 specification of plane maps see also the concept of 00046 |SMConstDecorator|.}*/ 00047 00048 /*{\Mgeneralization Decorator}*/ 00049 00050 template <class SM_decorator> 00051 class SM_point_locator : public SM_decorator { 00052 protected: 00053 typedef SM_decorator Base; 00054 typedef SM_point_locator<SM_decorator> Self; 00055 typedef typename SM_decorator::Sphere_map Sphere_map; 00056 00057 public: 00058 /*{\Mtypes 5}*/ 00059 00060 typedef typename SM_decorator::Decorator_traits Decorator_traits; 00061 00062 typedef typename Base::Mark Mark; 00063 /*{\Mtypemember the attribute of all objects (vertices, edges, loops, 00064 faces).}*/ 00065 00066 typedef typename SM_decorator::Sphere_kernel Sphere_kernel; 00067 /*{\Mtypemember the sphere kernel.}*/ 00068 typedef typename Sphere_kernel::Sphere_point Sphere_point; 00069 /*{\Mtypemember points.}*/ 00070 typedef typename Sphere_kernel::Sphere_segment Sphere_segment; 00071 /*{\Mtypemember segments.}*/ 00072 typedef typename Sphere_kernel::Sphere_circle Sphere_circle; 00073 /*{\Mtypemember circles.}*/ 00074 typedef typename Sphere_kernel::Sphere_direction Sphere_direction; 00075 /*{\Mtypemember directions.}*/ 00076 00077 /*{\Mtext Local types are handles, iterators and circulators of the 00078 following kind: |SVertex_const_handle|, |SVertex_const_iterator|, 00079 |SHalfedge_const_handle|, |SHalfedge_const_iterator|, 00080 |SHalfloop_const_handle|, |SHalfloop_const_iterator|, 00081 |SFace_const_handle|, |SFace_const_iterator|.}*/ 00082 00083 typedef CGAL::Object_handle Object_handle; 00084 /*{\Mtypemember a generic handle to an object of the underlying plane 00085 map. The kind of the object |(vertex, halfedge,face)| can be determined and 00086 the object assigned by the three functions:\\ 00087 |bool assign(SVertex_const_handle& h, Object_handle o)|\\ 00088 |bool assign(SHalfedge_const_handle& h, Object_handle o)|\\ 00089 |bool assign(SFace_const_handle& h, Object_handle o)|\\ where each 00090 function returns |true| iff the assignment of |o| to |h| was valid.}*/ 00091 00092 typedef typename Decorator_traits::SVertex_handle SVertex_handle; 00093 typedef typename Decorator_traits::SHalfedge_handle SHalfedge_handle; 00094 typedef typename Decorator_traits::SHalfloop_handle SHalfloop_handle; 00095 typedef typename Decorator_traits::SFace_handle SFace_handle; 00096 00097 typedef typename Decorator_traits::SVertex_iterator SVertex_iterator; 00098 typedef typename Decorator_traits::SHalfedge_iterator SHalfedge_iterator; 00099 typedef typename Decorator_traits::SHalfloop_iterator SHalfloop_iterator; 00100 typedef typename Decorator_traits::SFace_iterator SFace_iterator; 00101 00102 typedef typename Decorator_traits::SHalfedge_around_svertex_circulator 00103 SHalfedge_around_svertex_circulator; 00104 typedef typename Decorator_traits::SHalfedge_around_sface_circulator 00105 SHalfedge_around_sface_circulator; 00106 00107 Sphere_segment segment(SHalfedge_handle e) const 00108 { return Sphere_segment(e->source()->point(), e->twin()->source()->point(), e->circle()); } 00109 00110 Sphere_direction direction(SHalfedge_handle e) const 00111 { return Sphere_direction(e->circle()); } 00112 00113 SHalfedge_handle out_wedge(SVertex_handle v, const Sphere_direction& d, 00114 bool& collinear) const 00115 /*{\Xop returns a halfedge |e| bounding a wedge in between two 00116 neighbored edges in the adjacency list of |v| which contains |d|. 00117 If |d| extends along a edge then |e| is this edge. If |d| extends 00118 into the interior of such a wedge then |e| is the first edge hit 00119 when |d| is rotated clockwise. \precond |v| is not isolated.}*/ 00120 { CGAL_NEF_TRACEN("out_wedge "<<PH(v)); 00121 CGAL_assertion(!is_isolated(v)); 00122 collinear=false; 00123 Sphere_point p = v->point(); 00124 SHalfedge_handle e_res = first_out_edge(v); 00125 Sphere_direction d_res = direction(e_res); 00126 SHalfedge_around_svertex_circulator el(e_res),ee(el); 00127 if(direction(el) == d) { 00128 collinear = true; 00129 CGAL_NEF_TRACEN(" determined "<<PH(el) << el->circle()); 00130 return el; 00131 } 00132 CGAL_For_all(el,ee) { 00133 if(direction(cyclic_adj_succ(el)) == d) { 00134 collinear = true; 00135 CGAL_NEF_TRACEN(" equal "<<PH(cyclic_adj_succ(el)) << cyclic_adj_succ(el)->circle()); 00136 return cyclic_adj_succ(el); 00137 } 00138 else { 00139 CGAL_NEF_TRACEN("strictly_ordered_ccw " << direction(el) << " ? " << d << " ? " << direction(cyclic_adj_succ(el))); 00140 // if ( strictly_ordered_ccw_at(p,d_res, direction(el), d) ) { 00141 if ( strictly_ordered_ccw_at(p,direction(el), d, direction(cyclic_adj_succ(el))) ) { 00142 CGAL_NEF_TRACEN("strictly_ordered_ccw " << direction(el) << " - " << d << " - " << direction(cyclic_adj_succ(el))); 00143 e_res = el; d_res = direction(e_res); break; 00144 } 00145 } 00146 } 00147 CGAL_NEF_TRACEN(" finally determined "<<PH(e_res) << e_res->circle()); 00148 return e_res; 00149 } 00150 00151 /*{\Mcreation 3}*/ 00152 00153 SM_point_locator() : Base() {} 00154 00155 /*{\Moptions constref=yes}*/ 00156 SM_point_locator(Sphere_map* cp) : Base(cp) {} 00157 /*{\Mcreate constructs a point locator working on |P|.}*/ 00158 /*{\Moptions constref=no}*/ 00159 /*{\Moperations 2.5 0.5}*/ 00160 00161 const Mark& mark(Object_handle h) const 00162 /*{\Mop returns the mark associated to the object |h|.}*/ 00163 { SVertex_handle v; 00164 SHalfedge_handle e; 00165 SHalfloop_handle l; 00166 SFace_handle f; 00167 if ( CGAL::assign(v,h) ) return v->mark(); 00168 if ( CGAL::assign(e,h) ) return e->mark(); 00169 if ( CGAL::assign(l,h) ) return l->mark(); 00170 CGAL_assertion_msg(CGAL::assign(f,h), 00171 "PM_point_locator::mark: Object_handle holds no object."); 00172 CGAL::assign(f,h); 00173 return f->mark(); 00174 } 00175 00176 enum SOLUTION { is_vertex_, is_edge_, is_loop_ }; 00177 // enumeration for internal use 00178 00179 Object_handle locate(const Sphere_point& p, bool skipVEL = false) 00180 /*{\Mop returns a generic handle |h| to an object (vertex, halfedge, 00181 face) of the underlying plane map |P| which contains the point |p = 00182 s.source()| in its relative interior. |s.target()| must be a point 00183 such that |s| intersects the $1$-skeleton of |P|.}*/ 00184 { CGAL_NEF_TRACEN("locate naivly "<< normalized(p)); 00185 SVertex_iterator v; 00186 SHalfedge_iterator e; 00187 00188 if(!skipVEL) { 00189 CGAL_forall_svertices(v,*this) { 00190 if ( p == v->point() ) { 00191 CGAL_NEF_TRACEN( " on point"); 00192 return make_object(v); 00193 } 00194 } 00195 00196 CGAL_forall_sedges(e,*this) { 00197 if ( segment(e).has_on(p) || 00198 (e->source() == e->twin()->source() && e->circle().has_on(p))) { 00199 CGAL_NEF_TRACEN( " on segment " << segment(e)); 00200 return make_object(e); 00201 } 00202 } 00203 00204 if ( this->has_shalfloop() && this->shalfloop()->circle().has_on(p)) { 00205 CGAL_NEF_TRACEN( " on loop"); 00206 return make_object(SHalfloop_handle(this->shalfloop())); 00207 } 00208 } 00209 00210 00211 // now in face: 00212 00213 if(this->number_of_sfaces() == 1) { 00214 CGAL_NEF_TRACEN(" on unique face"); 00215 SFace_handle f = this->sfaces_begin(); 00216 return make_object(f); 00217 } 00218 00219 SVertex_handle v_res; 00220 SHalfedge_handle e_res; 00221 SHalfloop_handle l_res(this->shalfloop()); 00222 SOLUTION solution; 00223 00224 CGAL_NEF_TRACEN(" on face..."); 00225 Sphere_segment s; // we shorten the segment iteratively 00226 if ( this->has_shalfloop() ) { 00227 Sphere_circle c(this->shalfloop()->circle(),p); // orthogonal through p 00228 s = Sphere_segment(p,intersection(c,this->shalfloop()->circle())); 00229 l_res = this->shalfloop()->circle().has_on_positive_side(p) ? 00230 this->shalfloop() : this->shalfloop()->twin(); 00231 solution = is_loop_; 00232 CGAL_NEF_TRACEN("has loop, initial ray "<<s); 00233 CGAL_NEF_TRACEN(l_res->circle()); 00234 } else { // has vertices ! 00235 CGAL_assertion( this->number_of_svertices()!=0 ); 00236 SVertex_iterator vi = this->svertices_begin(); 00237 if( p == vi->point().antipode()) { 00238 ++vi; 00239 CGAL_assertion( vi != this->svertices_end()); 00240 } 00241 CGAL_NEF_TRACEN("initial segment: "<<p<<","<<vi->point()); 00242 CGAL_assertion( p != vi->point().antipode()); 00243 s = Sphere_segment( p, vi->point()); 00244 v_res = vi; 00245 solution = is_vertex_; 00246 CGAL_NEF_TRACEN("has vertices, initial ray "<<s); 00247 } 00248 00249 // s now initialized 00250 00251 Sphere_direction dso(s.sphere_circle().opposite()); 00252 Unique_hash_map<SHalfedge_handle,bool> visited(false); 00253 CGAL_forall_svertices(v,*this) { 00254 Sphere_point vp = v->point(); 00255 if ( s.has_on(vp) ) { 00256 CGAL_NEF_TRACEN(" location via vertex at "<<vp); 00257 s = Sphere_segment(p,vp,s.sphere_circle()); // we shrink the segment 00258 if ( is_isolated(v) ) { 00259 CGAL_NEF_TRACEN("is_vertex_"); 00260 v_res = v; solution = is_vertex_; 00261 } else { // not isolated 00262 bool dummy; 00263 e_res = out_wedge(v,dso,dummy); 00264 SHalfedge_around_svertex_circulator el(e_res),ee(el); 00265 CGAL_For_all(el,ee) 00266 visited[el] = visited[el->twin()] = true; 00267 /* e_res is now the counterclockwise maximal halfedge out 00268 of v just before s */ 00269 if ( e_res->circle().has_on_negative_side(p) ) 00270 e_res = e_res->sprev(); 00271 // correction to make e_res visible from p 00272 solution = is_edge_; 00273 CGAL_NEF_TRACEN(" determined "<<PH(e_res)); 00274 } 00275 } 00276 } 00277 00278 CGAL_forall_sedges(e,*this) { 00279 if ( visited[e] ) continue; 00280 Sphere_segment se = segment(e); 00281 Sphere_point p_res; 00282 if(e->source() == e->twin()->source()) { 00283 Sphere_point p_res = intersection(e->circle(), s.sphere_circle()); 00284 if(!s.has_in_relative_interior(p_res)) { 00285 p_res = p_res.antipode(); 00286 if(!s.has_in_relative_interior(p_res)) 00287 continue; 00288 } 00289 s = Sphere_segment(p,p_res,s.sphere_circle()); 00290 e_res = ( e->circle().has_on_positive_side(p) ? e : e->twin() ); 00291 visited[e] = visited[e->twin()] = true; 00292 solution = is_edge_; 00293 CGAL_NEF_TRACEN(" determined "<<PH(e_res)<<" "<< e_res->incident_sface()->mark()); 00294 } 00295 else if ( do_intersect_internally(se,s,p_res) ) { 00296 CGAL_NEF_TRACEN(" location via halfedge "<<se); 00297 s = Sphere_segment(p,p_res,s.sphere_circle()); 00298 e_res = ( e->circle().has_on_positive_side(p) ? e : e->twin() ); 00299 visited[e] = visited[e->twin()] = true; 00300 solution = is_edge_; 00301 CGAL_NEF_TRACEN(" determined "<<PH(e_res)<<" "<< e_res->incident_sface()->mark()); 00302 } 00303 } 00304 00305 switch ( solution ) { 00306 case is_edge_: 00307 return make_object(SFace_handle(e_res->incident_sface())); 00308 case is_loop_: 00309 return make_object(SFace_handle(l_res->incident_sface())); 00310 case is_vertex_: 00311 return make_object(SFace_handle(v_res->incident_sface())); 00312 default: CGAL_error_msg("missing solution."); 00313 } 00314 return Object_handle(); // never reached! 00315 } 00316 00317 template <typename Object_predicate> 00318 Object_handle ray_shoot(const Sphere_point& p, 00319 const Sphere_direction& d, 00320 const Object_predicate& M) const 00321 /*{\Mop returns an |Object_handle o| which can be converted to a 00322 |SVertex_handle|, |SHalfedge_handle|, |SFace_handle| 00323 |h| as described above. The object predicate |M| has to have 00324 function operators \\ |bool operator() (const 00325 SVertex_/SHalfedge_/SHalfloop_/SFace_handle&)|.\\ The object 00326 returned is intersected by |d.circle()|, has minimal distance to 00327 |p|, and |M(h)| holds on the converted object. The operation returns 00328 the null handle |NULL| if the ray shoot along |s| does not hit any 00329 object |h| of |M| with |M(h)|.}*/ 00330 { 00331 Sphere_circle c(d.circle()); 00332 Sphere_segment s; 00333 bool s_init(false); 00334 Object_handle h = locate(p); 00335 SVertex_handle v; 00336 SHalfedge_handle e; 00337 SHalfloop_handle l; 00338 SFace_handle f; 00339 if ( CGAL::assign(v,h) && M(v) || 00340 CGAL::assign(e,h) && M(e) || 00341 CGAL::assign(l,h) && M(l) || 00342 CGAL::assign(f,h) && M(f) ) return h; 00343 h = Object_handle(); 00344 CGAL_NEF_TRACEN("not contained"); 00345 #if 0 00346 HASEN: s am anfang circle, ab wann segment ? 00347 wo loop ? 00348 00349 CGAL_forall_svertices (v,*this) { 00350 Point pv = v->point(); 00351 if ( !(s_init && s.has_on(pv) || 00352 !s_init && c.has_on(pv)) ) continue; 00353 CGAL_NEF_TRACEN("candidate "<<pv); 00354 if ( M(v) ) { 00355 h = make_object(v); // store vertex 00356 s = Sphere_segment(p,pv,c); // shorten 00357 continue; 00358 } 00359 // now we know that v is not marked but on s 00360 bool collinear; 00361 SHalfedge_handle e = out_wedge(v,d,collinear); 00362 if ( collinear ) { 00363 if ( M(e) ) { 00364 h = make_object(e); 00365 s = Sphere_segment(p,pv,c); 00366 } 00367 continue; 00368 } 00369 if ( M(e->incident_sface()) ) { 00370 h = make_object(e->incident_sface()); 00371 s = Sphere_segment(p,pv,c); 00372 } 00373 } // all vertices 00374 00375 CGAL::Unique_hash_map<SHalfedge_handle,bool> visited(false); 00376 SHalfedge_iterator e_res; 00377 CGAL_forall_sedges(e,*this) { 00378 Sphere_segment se = segment(e); 00379 Sphere_point p_res; 00380 if ( do_intersect_internally(se,s,p_res) ) { 00381 // internal intersection 00382 CGAL_NEF_TRACEN("candidate "<<se); 00383 e_res = e; 00384 Sphere_segment s_cand = Sphere_segment(p,p_res,c); 00385 if ( s_cand.is_short() && e->circle().has_on_negative_side(p) || 00386 s_cand.is_long() && e->circle().has_on_positive_side(p) || 00387 s_cand.is_halfcircle() && 00388 strictly_ordered_ccw_at(p.antipode(), 00389 direction(e),d,direction(e->twin())) ) 00390 e_res = e->twin(); 00391 if ( M(e_res) ) { 00392 h = make_object(e_res); s = s_cand; 00393 } else if ( M(face(twin(e_res))) ) { 00394 h = make_object(face(twin(e_res))); s = s_cand; 00395 } 00396 } 00397 } 00398 #endif 00399 CGAL_error_msg("not yet correct"); 00400 return h; 00401 } 00402 00403 Object_handle ray_shoot(const Sphere_point& p, 00404 const Sphere_circle& c, 00405 Sphere_point& ip, 00406 bool start_inclusive = false) { 00407 Sphere_segment seg(p, p.antipode(), c); 00408 return ray_shoot(seg, ip, start_inclusive); 00409 } 00410 00411 Object_handle ray_shoot(const Sphere_segment& d, 00412 Sphere_point& ip, 00413 bool start_inclusive = false, 00414 bool beyond_end = true, 00415 bool end_inclusive = false) { 00416 00417 // TODO: end_inclusive=true does not work properly for sedges and sloops 00418 00419 CGAL_NEF_TRACEN("ray shoot"); 00420 Sphere_circle c(d.sphere_circle()); 00421 Sphere_point p(d.source()); 00422 Sphere_segment s; 00423 bool s_init(false); 00424 00425 if(!beyond_end) { 00426 s = d; 00427 s_init = true; 00428 } 00429 00430 Object_handle h = Object_handle(); 00431 00432 if(s_init) { 00433 CGAL_NEF_TRACEN(" at begin " << s_init << ":" << s); 00434 } else { 00435 CGAL_NEF_TRACEN(" at begin " << s_init << ":" << c); 00436 } 00437 00438 SVertex_iterator vi; 00439 CGAL_forall_svertices (vi,*this) { 00440 Sphere_point pv = vi->point(); 00441 if ((s_init && !s.has_on(pv)) || 00442 (!s_init && !c.has_on(pv))) continue; 00443 CGAL_NEF_TRACEN("candidate "<<pv); 00444 CGAL_NEF_TRACEN("p =?= pv: " << p << ", " << pv); 00445 if ((start_inclusive || p != pv) && 00446 (end_inclusive || !s_init || s.target() != pv)) { 00447 h = make_object(vi); // store vertex 00448 s = Sphere_segment(p,pv,c); // shorten 00449 ip = pv; 00450 s_init = true; 00451 } 00452 } 00453 00454 // TODO: edges on the ray. 00455 00456 SHalfedge_iterator ei; 00457 CGAL_forall_sedges(ei,*this) { 00458 Sphere_segment se = segment(ei); 00459 CGAL_NEF_TRACEN("ray_shoot " << s_init); 00460 if(s_init) 00461 CGAL_NEF_TRACEN(" " << s.source() << "->" << s.target() << " | " << s.sphere_circle() << " is long " << s.is_long()); 00462 CGAL_NEF_TRACEN(" " << se.source() << "->" << se.target() << " | " << se.sphere_circle() << " is long " << se.is_long()); 00463 00464 // TODO: start-end point of s on se or c 00465 00466 Sphere_point p_res; 00467 if(se.source() == se.target()) { 00468 00469 if(s_init) { 00470 if(s.is_long()) { 00471 Sphere_segment first_half(p,p.antipode(),c); 00472 Sphere_segment second_part(p.antipode(), s.target(), c); 00473 if(!do_intersect_internally(ei->circle(), first_half, p_res) && 00474 !do_intersect_internally(ei->circle(), second_part, p_res)) { 00475 if(se.has_on(p.antipode())) { 00476 p_res = p.antipode(); 00477 } else { 00478 continue; 00479 } 00480 } 00481 } else { 00482 if(!do_intersect_internally(ei->circle(), s, p_res)) continue; 00483 } 00484 } else { 00485 Sphere_segment first_half(p,p.antipode(),c); 00486 Sphere_segment second_part(p.antipode(),p,c); 00487 if(!do_intersect_internally(ei->circle(), first_half, p_res)) { 00488 do_intersect_internally(ei->circle(), second_part, p_res); 00489 } 00490 } 00491 00492 } else { 00493 if(s_init) { 00494 if(s.is_long() && se.is_long()) { 00495 Sphere_segment first_half(p,p.antipode(),c); 00496 Sphere_segment second_part(p.antipode(), s.target(), c); 00497 if(!do_intersect_internally(se, first_half, p_res) && 00498 !do_intersect_internally(se, second_part, p_res)) { 00499 if(se.has_on(p.antipode())) 00500 p_res = p.antipode(); 00501 else 00502 continue; 00503 } 00504 } else { 00505 if(!do_intersect_internally(se, s, p_res)) continue; 00506 } 00507 } else { 00508 if(se.is_long()) { 00509 Sphere_segment first_half(p,p.antipode(),c); 00510 Sphere_segment second_half(p.antipode(),p,c); 00511 if(!do_intersect_internally(se, first_half, p_res)) { 00512 if(!do_intersect_internally(se, second_half, p_res)) { 00513 if(start_inclusive) 00514 p_res = p; 00515 else 00516 p_res = p.antipode(); 00517 } 00518 } 00519 } else { 00520 if(!do_intersect_internally(c, se, p_res)) continue; 00521 } 00522 } 00523 } 00524 00525 CGAL_NEF_TRACEN("candidate "<<se); 00526 if (start_inclusive || p != p_res) { 00527 h = make_object(ei); 00528 s = Sphere_segment(p,p_res,c); 00529 ip = p_res; 00530 s_init = true; 00531 } 00532 } 00533 00534 // TODO: start-end point of s on cl 00535 00536 if(this->has_shalfloop()) { 00537 Sphere_circle cl(this->shalfloop()->circle()); 00538 if(!s_init || s.is_long()) { 00539 if(cl.has_on(p)) { 00540 ip = p.antipode(); 00541 return make_object(SHalfloop_handle(this->shalfloop())); 00542 } else 00543 s = Sphere_segment(p,p.antipode(),c); 00544 } 00545 Sphere_point p_res; 00546 CGAL_NEF_TRACEN("do intersect " << cl << ", " << s); 00547 if(!do_intersect_internally(cl,s,p_res)) 00548 return h; 00549 /* 00550 if(p_res == p.antipode()) // does this happen ? test has_on for p/p.antipode ? 00551 p_res = p; 00552 */ 00553 CGAL_NEF_TRACEN("found intersection point " << p_res); 00554 CGAL_assertion_code(Sphere_segment testseg(p,p_res,c)); 00555 CGAL_assertion(!testseg.is_long()); 00556 if (start_inclusive || p != p_res) { 00557 ip = p_res; 00558 return make_object(SHalfloop_handle(this->shalfloop())); 00559 } 00560 } 00561 00562 return h; 00563 } 00564 00565 void marks_of_halfspheres(std::vector<Mark>& mohs, int offset, 00566 int axis=2); 00567 void marks_of_halfspheres(Mark& unten, Mark& oben, int axis=2); 00568 00569 /*{\Mimplementation Naive query operations are realized by checking 00570 the intersection points of the $1$-skeleton of the plane map |P| with 00571 the query segments $s$. This method takes time linear in the size $n$ 00572 of the underlying plane map without any preprocessing.}*/ 00573 }; // SM_point_locator<SM_decorator> 00574 00575 template <typename D> 00576 void SM_point_locator<D>:: 00577 marks_of_halfspheres(std::vector<Mark>& mohs, int offset, int axis) { 00578 Mark lower, upper; 00579 marks_of_halfspheres(lower, upper, axis); 00580 mohs[offset] = lower; 00581 mohs[offset+1] = upper; 00582 } 00583 00584 template <typename D> 00585 void SM_point_locator<D>:: 00586 marks_of_halfspheres(Mark& lower, Mark& upper, int axis) { 00587 00588 CGAL_NEF_TRACEN("marks_of_halfspheres "); 00589 00590 Sphere_point y_minus; 00591 if(axis!=1) 00592 y_minus = Sphere_point(0,-1,0); 00593 else 00594 y_minus = Sphere_point(0,0,1); 00595 Object_handle h = locate(y_minus); 00596 SFace_handle f; 00597 if ( CGAL::assign(f,h) ) { 00598 CGAL_NEF_TRACEN("on face " << mark(make_object(f))); 00599 lower = upper = mark(make_object(f)); 00600 return; 00601 } 00602 00603 SHalfedge_handle e; 00604 if ( CGAL::assign(e,h) ) { 00605 CGAL_assertion(e->circle().has_on(y_minus)); 00606 Sphere_point op(CGAL::ORIGIN+e->circle().orthogonal_vector()); 00607 CGAL_NEF_TRACEN("on edge "<<op); 00608 if (axis==0 && ((op.z() < 0) || ((op.z() == 0) && (op.x() < 0)))) e = e->twin(); 00609 if (axis==1 && ((op.x() > 0) || ((op.x() == 0) && (op.y() < 0)))) e = e->twin(); 00610 if (axis==2 && ((op.x() > 0) || ((op.x() == 0) && (op.z() < 0)))) e = e->twin(); 00611 upper = e->incident_sface()->mark(); 00612 lower = e->twin()->incident_sface()->mark(); 00613 return; 00614 } 00615 00616 SHalfloop_handle l; 00617 if ( CGAL::assign(l,h) ) { 00618 CGAL_assertion(l->circle().has_on(y_minus)); 00619 Sphere_point op(CGAL::ORIGIN+l->circle().orthogonal_vector()); 00620 CGAL_NEF_TRACEN("on loop "<<op); 00621 if (axis==0 && ((op.z() < 0) || ((op.z() == 0) && (op.x() < 0)))) l = l->twin(); 00622 if (axis==1 && ((op.x() > 0) || ((op.x() == 0) && (op.y() < 0)))) l = l->twin(); 00623 if (axis==2 && ((op.x() > 0) || ((op.x() == 0) && (op.z() < 0)))) l = l->twin(); 00624 upper = l->incident_sface()->mark(); 00625 lower = l->twin()->incident_sface()->mark(); 00626 return; 00627 } 00628 00629 Sphere_circle c; 00630 switch(axis) { 00631 case 0: c = Sphere_circle(1,0,0); break; 00632 case 1: c = Sphere_circle(0,1,0); break; 00633 case 2: c = Sphere_circle(0,0,1); break; 00634 } 00635 Sphere_direction right(c),left(c.opposite()); 00636 bool collinear(false); 00637 SVertex_handle v; 00638 if ( CGAL::assign(v,h) ) { 00639 CGAL_assertion(v->point()==y_minus); 00640 if(is_isolated(v)) 00641 upper = lower = mark(make_object(v->incident_sface())); 00642 else { 00643 e = out_wedge(v,left,collinear); 00644 if ( collinear ) upper = e->twin()->incident_sface()->mark(); 00645 else upper = e->incident_sface()->mark(); 00646 e = out_wedge(v,right,collinear); 00647 if ( collinear ) lower = e->twin()->incident_sface()->mark(); 00648 else lower = e->incident_sface()->mark(); 00649 } 00650 } 00651 } 00652 00653 CGAL_END_NAMESPACE 00654 #endif // CGAL_SM_POINT_LOCATOR_H 00655 00656 00657