BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Nef_S2/Sphere_segment.h
Go to the documentation of this file.
00001 // Copyright (c) 1997-2002  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/Sphere_segment.h $
00015 // $Id: Sphere_segment.h 44480 2008-07-26 20:26:48Z hachenb $
00016 // 
00017 //
00018 // Author(s)     : Michael Seel  <seel@mpi-sb.mpg.de>
00019 
00020 #ifndef CGAL_SPHERE_SEGMENT_H
00021 #define CGAL_SPHERE_SEGMENT_H
00022 
00023 #include <CGAL/basic.h>
00024 #include <CGAL/Handle_for.h>
00025 #include <vector>
00026 
00027 CGAL_BEGIN_NAMESPACE
00028 
00029 template <class R_> class Sphere_segment_rep 
00030 { 
00031   typedef typename R_::Point_3 Point_3;
00032   typedef typename R_::Plane_3 Plane_3;
00033   typedef Sphere_point<R_>  Point;
00034   typedef Sphere_circle<R_> Circle;
00035   typedef Sphere_segment_rep<R_> Rep;
00036   friend class Sphere_segment<R_>;
00037 public:
00038 Sphere_segment_rep() { ps_ = pt_ = Point(); c_ = Circle(); }
00039 
00040 Sphere_segment_rep(const Point& p1, const Point& p2,
00041                    bool shorter_arc=true) :
00042   ps_(p1), pt_(p2), c_(Plane_3(p1,p2,Point_3(0,0,0))) 
00043 { // warning stays as reminder that one gets an arbitrary plane equation
00044   // in this degenerate case
00045   CGAL_warning(p1 != p2.antipode());
00046   CGAL_assertion(p1 != p2.antipode());
00047   if ( p1 == p2 ) { 
00048     Plane_3 h(Point_3(0,0,0),(p1-CGAL::ORIGIN));
00049     c_ = Sphere_circle<R_>(Plane_3(Point_3(0,0,0),h.base1()));
00050   }
00051   if (!shorter_arc) c_ = c_.opposite(); 
00052   CGAL_exactness_assertion(c_.has_on(p1) && c_.has_on(p2));
00053 }
00054 
00055 Sphere_segment_rep(const Point& p1, const Point& p2, const Circle& c) :
00056   ps_(p1), pt_(p2), c_(c) 
00057 { CGAL_assertion(c.has_on(p1)&&c.has_on(p2)); }
00058 
00059 Sphere_segment_rep(const Circle& c1, 
00060                    const Circle& c2) : c_(c1) 
00061 { CGAL_assertion(!equal_as_sets(c1,c2)); 
00062   ps_ = intersection(c1,c2);
00063   pt_ = ps_.antipode();
00064   if ( R_::orientation(Point_3(0,0,0),ps_,pt_,
00065                    CGAL::ORIGIN + c_.orthogonal_vector()) !=
00066        CGAL::POSITIVE ) std::swap(ps_,pt_);
00067 }
00068 
00069 Sphere_segment_rep(const Rep& r) : 
00070   ps_(r.ps_), pt_(r.pt_), c_(r.c_) {}
00071 
00072 Rep& operator=(const Rep& r) 
00073 { ps_=r.ps_; pt_=r.pt_; c_=r.c_; return *this; }
00074 
00075 protected:
00076   Sphere_point<R_>  ps_,pt_;
00077   Sphere_circle<R_> c_;
00078 };
00079 
00080 
00081 /*{\Moptions print_title=yes }*/ 
00082 /*{\Manpage{Sphere_segment}{R}{Segments on the unit sphere}{s}}*/
00083 
00084 template <class R_> 
00085 class Sphere_segment : 
00086   public Handle_for< Sphere_segment_rep<R_> > {
00087 
00088 /*{\Mdefinition An object |\Mvar| of type |\Mname| is a segment in the
00089 surface of a unit sphere that is part of a great circle trough the
00090 origin. Sphere segments are represented by two sphere points $p$ and
00091 $q$ plus an oriented plane $h$ that contains $p$ and $q$. The plane
00092 determines the sphere segment. Let $c$ be the circle in the
00093 intersection of $h$ and $S_2$. Then $s$ is that part of $c$ that is
00094 swept, when we rotate $p$ into $q$ in counterclockwise rotation around
00095 the normal vector of $h$ as seen from the positive halfspace.}*/  
00096 
00097 public:
00098 
00099 /*{\Mtypes 6}*/
00100 
00101 typedef R_ R;
00102 /*{\Mtypemember representation class.}*/
00103 typedef typename R_::RT RT;
00104 /*{\Mtypemember ring number type.}*/
00105 
00106 typedef Sphere_segment_rep<R_> Rep;
00107 typedef Handle_for<Rep>        Base;
00108 
00109 typedef typename R_::Point_3  Point_3;
00110 typedef typename R_::Vector_3 Vector_3;
00111 typedef typename R_::Plane_3  Plane_3;
00112 typedef typename R_::Line_3   Line_3;
00113 typedef Sphere_segment<R_> Self;
00114 
00115 /*{\Mcreation 4}*/
00116 
00117 Sphere_segment() : Base() {}
00118 
00119 Sphere_segment(const Sphere_point<R>& p1, const Sphere_point<R>& p2,
00120                bool shorter_arc=true) :  Base(Rep(p1,p2,shorter_arc)) {}
00121 /*{\Mcreate creates a spherical segment spanning the shorter arc
00122 from |p1| to |p2| if |shorter_arc == true|. Otherwise the longer
00123 arc is created. \precond |p1 != p2| and |p1 != p2.antipode()|.}*/
00124 
00125 
00126 Sphere_segment(const Sphere_point<R>& p1, const Sphere_point<R>& p2,
00127                const Sphere_circle<R>& c) : Base(Rep(p1,p2,c)) {}
00128 /*{\Mcreate creates a spherical segment spanning the arc
00129 from |p1| to |p2| as part of the oriented circle |c| 
00130 (|p1 == p2| or |p1 == p2.antipode()| are possible.)
00131 \precond |p1| and |p2| are contained in |c|.}*/
00132 
00133 Sphere_segment(const Sphere_circle<R>& c1, 
00134                const Sphere_circle<R>& c2) : Base(Rep(c1,c2)) {}
00135 /*{\Mcreate creates the spherical segment as part of |c1|
00136 that is part of the halfsphere left of the oriented circle |c2|.
00137 \precond |c1 != c2| as unoriented circles.}*/
00138 
00139 Sphere_segment(const Self& s) : Base(s) {}
00140 
00141 /*{\Moperations 4 2}*/
00142 
00143 const Sphere_point<R>& source() const { return this->ptr()->ps_; }
00144 /*{\Mop the source point of |\Mvar|.}*/
00145 const Sphere_point<R>& target() const { return this->ptr()->pt_; }
00146 /*{\Mop the target point of |\Mvar|.}*/
00147 const Sphere_circle<R>& sphere_circle() const { return this->ptr()->c_; }
00148 /*{\Mop the great circle supporting |\Mvar|.}*/
00149 
00150 Sphere_segment<R> opposite() const 
00151 /*{\Mop returns the sperical segment oriented from |target()|
00152   to |source()| with the same point set as |\Mvar|. }*/
00153 { return Sphere_segment<R>(
00154     target(),source(),sphere_circle().opposite()); }
00155   
00156 Sphere_segment<R> complement() const 
00157 /*{\Mop returns the sperical segment oriented from |target()|
00158   to |source()| with the point set completing |\Mvar| to a
00159   full circle. }*/
00160 { return Sphere_segment<R>(target(),source(),sphere_circle()); }
00161 
00162 
00163 int intersection(const Sphere_circle<R>& c,
00164                  std::vector<Sphere_segment<R> >& s) const;
00165 
00166 int intersection(const Sphere_circle<R>& c,
00167                  Sphere_segment<R>& s1, Sphere_segment<R>& s2) const;
00168 /*{\Mop returns the number of non-trivial connected components
00169 of the intersection of |\Mvar| and the closed halfsphere left of
00170 |c|.}*/
00171 
00172 Sphere_point<R> intersection(const Sphere_segment<R>& so) const;
00173 /*{\Mop returns the point of intersection of |\Mvar| and
00174 |so|. \precond |\Mvar| and |so| do intersect.}*/
00175 
00176 void split_halfcircle(Sphere_segment<R>& s1, 
00177                       Sphere_segment<R>& s2) const
00178 /*{\Mop splits a halfcircle into two equally sized segments.
00179 \precond |\Mvar| is a halfcircle.}*/
00180 { CGAL_assertion( is_halfcircle() );
00181   Plane_3 h(Point_3(0,0,0),(target()-CGAL::ORIGIN));
00182   Sphere_point<R> p = 
00183     CGAL::intersection(sphere_circle(),Sphere_circle<R>(h));
00184   if ( !has_on(p) ) p = p.antipode();
00185   s1 = Sphere_segment<R>(this->ptr()->ps_,p,this->ptr()->c_);
00186   s2 = Sphere_segment<R>(p,this->ptr()->pt_,this->ptr()->c_);
00187 }
00188 
00189 bool is_short() const 
00190 /*{\Mop a segment is short iff it is shorter than a halfcircle.}*/
00191 { 
00192   return R().orientation_3_object()(Point_3(0,0,0), source(), target(),
00193                                     CGAL::ORIGIN + this->ptr()->c_.orthogonal_vector()) 
00194     == CGAL::POSITIVE; }
00195 
00196 bool is_long() const 
00197 /*{\Mop a segment is long iff it is longer than a halfcircle.}*/
00198 { return R().orientation_3_object()(Point_3(0,0,0), source(), target(),
00199                                     CGAL::ORIGIN + this->ptr()->c_.orthogonal_vector()) 
00200     == CGAL::NEGATIVE; }
00201 
00202 bool is_degenerate() const { return source() == target(); }
00203 /*{\Mop return true iff |\Mvar| is degenerate.}*/
00204 
00205 bool is_halfcircle() const { return source().antipode() == target(); }
00206 /*{\Mop return true iff |\Mvar| is a halfcircle.}*/
00207 
00208 bool has_on(const Sphere_point<R>& p) const;
00209 /*{\Mop return true iff |\Mvar| contains |p|.}*/
00210 bool has_on_after_intersection(const Sphere_point<R>& p) const;
00211 
00212 bool has_in_relative_interior(const Sphere_point<R>& p) const;
00213 /*{\Mop return true iff |\Mvar| contains |p| in
00214 its relative interior.}*/
00215 
00216 bool operator==(const Sphere_segment<R>& so) const
00217 { return source() == so.source() && target() == so.target() && 
00218          (source() == target() || 
00219           sphere_circle() == so.sphere_circle()); }
00220 
00221 bool operator!=(const Sphere_segment<R>& so) const
00222 { return !operator==(so); }
00223 
00224 };
00225 
00226 template <typename R>
00227 bool do_intersect_internally(const Sphere_segment<R>& s1,
00228                              const Sphere_segment<R>& s2,
00229                              Sphere_point<R>& p);
00230 /*{\Mfunc return true iff |s1| and |s2| intersect internally
00231 (non-degenerately).  If |true| the parameter |p| returns the point of
00232 intersection.}*/
00233 
00234 
00235 template <typename R>
00236 std::ostream& operator<<(std::ostream& os, 
00237                          const CGAL::Sphere_segment<R>& s)
00238 { os << s.source()<<" "<<s.target()<<" "<<
00239   s.sphere_circle().plane()<<" "; return os; }
00240 
00241 template <typename R>
00242 std::istream& operator>>(std::istream& is, 
00243                          CGAL::Sphere_segment<R>& s)
00244 { CGAL::Sphere_point<R>  p1,p2;
00245   CGAL::Sphere_circle<R> c;
00246   if ( !(is >> p1 >> p2 >> c) ) return is; 
00247   s = CGAL::Sphere_segment<R>(p1,p2,c); 
00248   return is; }
00249 
00250 
00251 template <typename R>
00252 std::pair< Sphere_segment<R>,Sphere_segment<R> >
00253 Sphere_circle<R>::split_at(const Sphere_point<R>& p) const
00254 { CGAL_assertion(has_on(p));
00255   Sphere_point<R> q(p.antipode());
00256   return Sphere_segment_pair(
00257     Sphere_segment<R>(p,q,*this),
00258     Sphere_segment<R>(p,q,this->opposite()));
00259 }
00260 
00261 template <typename R>
00262 std::pair< Sphere_segment<R>,Sphere_segment<R> >
00263 Sphere_circle<R>::split_at_xy_plane() const
00264 { Self xycircle(0,0,1), yzcircle(1,0,0);
00265   if ( !equal_as_sets(xycircle,*this) )
00266     return split_at(intersection(*this,xycircle));
00267   else 
00268     return split_at(intersection(*this,yzcircle));
00269 }
00270 
00271 
00272 /* Contains maps to two orientation checks with the wedge
00273 spanned by the source and the target with planes orthogonal
00274 to the supporting plane of $p$ and $q$. The logic depends on
00275 the segments length: long or short. */
00276 
00277 template <typename R> 
00278 bool Sphere_segment<R>::
00279 has_on(const CGAL::Sphere_point<R>& p) const 
00280 { if ( !sphere_circle().has_on(p) ) return false;
00281   if ( !is_long() ) { 
00282     return orientation(Point_3(0,0,0),
00283                        CGAL::ORIGIN + sphere_circle().orthogonal_vector(),
00284                        source(),p) !=
00285            CGAL::NEGATIVE &&
00286            orientation(Point_3(0,0,0),target(),
00287                        CGAL::ORIGIN + 
00288                        sphere_circle().orthogonal_vector(),p) !=
00289            CGAL::NEGATIVE;
00290   } else { 
00291     return orientation(Point_3(0,0,0),
00292                        CGAL::ORIGIN + sphere_circle().orthogonal_vector(),
00293                        source(),p) !=
00294            CGAL::NEGATIVE ||
00295            orientation(Point_3(0,0,0),target(),
00296                        CGAL::ORIGIN + 
00297                        sphere_circle().orthogonal_vector(),p) !=
00298            CGAL::NEGATIVE;
00299   }
00300 }
00301 
00302 template <typename R> 
00303 bool Sphere_segment<R>::
00304 has_on_after_intersection(const CGAL::Sphere_point<R>& p) const {
00305     return orientation(Point_3(0,0,0),
00306                        CGAL::ORIGIN + sphere_circle().orthogonal_vector(),
00307                        source(),p) !=
00308            CGAL::NEGATIVE &&
00309            orientation(Point_3(0,0,0),target(),
00310                        CGAL::ORIGIN + 
00311                        sphere_circle().orthogonal_vector(),p) !=
00312            CGAL::NEGATIVE;
00313 }
00314 
00315 template <typename R> 
00316 bool Sphere_segment<R>::
00317 has_in_relative_interior(const CGAL::Sphere_point<R>& p) const 
00318 { if ( !sphere_circle().has_on(p) ) return false;
00319   if ( !is_long() ) { 
00320     return orientation(Point_3(0,0,0),
00321                        CGAL::ORIGIN + sphere_circle().orthogonal_vector(),
00322                        source(),p) == CGAL::POSITIVE &&
00323            orientation(Point_3(0,0,0),target(),
00324                        CGAL::ORIGIN + 
00325                        sphere_circle().orthogonal_vector(),p) ==
00326            CGAL::POSITIVE;
00327   } else { 
00328     return orientation(Point_3(0,0,0),
00329                        CGAL::ORIGIN + sphere_circle().orthogonal_vector(),
00330                        source(),p) == CGAL::POSITIVE ||
00331            orientation(Point_3(0,0,0),target(),
00332                        CGAL::ORIGIN + 
00333                        sphere_circle().orthogonal_vector(),p) ==
00334            CGAL::POSITIVE;
00335   }
00336 }
00337 
00338 
00339 
00340 /* Intersection of two sphere segments. It does not work if the two
00341    involved planes are equal as sets. */
00342 
00343 template <typename R> 
00344 Sphere_point<R> Sphere_segment<R>::
00345 intersection(const Sphere_segment<R>& s) const
00346 {
00347   CGAL_assertion(!equal_as_sets(sphere_circle(),s.sphere_circle()));
00348   Sphere_point<R> res = 
00349     CGAL::intersection(sphere_circle(),s.sphere_circle());
00350   if ( has_on(res) && s.has_on(res) ) return res;
00351   return res.antipode();
00352 }
00353 
00354 template <typename R> 
00355 bool do_intersect_internally(const Sphere_segment<R>& s1,
00356                              const Sphere_segment<R>& s2,
00357                              Sphere_point<R>& p)
00358 {
00359   if ( equal_as_sets(s1.sphere_circle(),s2.sphere_circle()) )
00360     return false;
00361   p = CGAL::intersection(s1.sphere_circle(),s2.sphere_circle());
00362   if ( s1.has_in_relative_interior(p) && 
00363        s2.has_in_relative_interior(p) ) return true;
00364   p = p.antipode();
00365   if ( s1.has_in_relative_interior(p) && 
00366        s2.has_in_relative_interior(p) ) return true;
00367   return false;
00368 }
00369 
00370 
00371 template <typename R> 
00372 bool do_intersect_internally(const Sphere_circle<R>& c1,
00373                              const Sphere_segment<R>& s2,
00374                              Sphere_point<R>& p)
00375 {
00376   if ( equal_as_sets(c1,s2.sphere_circle()) )
00377     return false;
00378   p = CGAL::intersection(c1,s2.sphere_circle());
00379   if ( s2.has_in_relative_interior(p) ) return true;
00380   p = p.antipode();
00381   if ( s2.has_in_relative_interior(p) ) return true;
00382   return false;
00383 }
00384 
00385 
00386 CGAL_END_NAMESPACE
00387 #endif //CGAL_SPHERE_SEGMENT_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines