BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Nef_S2/SM_point_locator.h
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines