|
BWAPI
|
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
1.7.6.1