BWAPI
|
00001 // Copyright (c) 2000 Utrecht University (The Netherlands), 00002 // ETH Zurich (Switzerland), Freie Universitaet Berlin (Germany), 00003 // INRIA Sophia-Antipolis (France), Martin-Luther-University Halle-Wittenberg 00004 // (Germany), Max-Planck-Institute Saarbruecken (Germany), RISC Linz (Austria), 00005 // and Tel-Aviv University (Israel). All rights reserved. 00006 // 00007 // This file is part of CGAL (www.cgal.org); you can redistribute it and/or 00008 // modify it under the terms of the GNU Lesser General Public License as 00009 // published by the Free Software Foundation; version 2.1 of the License. 00010 // See the file LICENSE.LGPL distributed with CGAL. 00011 // 00012 // Licensees holding a valid commercial license may use this file in 00013 // accordance with the commercial license agreement provided with the software. 00014 // 00015 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00016 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00017 // 00018 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Intersections_2/include/CGAL/Straight_2.h $ 00019 // $Id: Straight_2.h 45075 2008-08-21 12:50:41Z spion $ 00020 // 00021 // 00022 // Author(s) : Geert-Jan Giezeman 00023 00024 00025 #ifndef CGAL_STRAIGHT_2_H 00026 #define CGAL_STRAIGHT_2_H 00027 00028 #include <CGAL/Line_2_Line_2_intersection.h> 00029 #include <CGAL/squared_distance_utils.h> 00030 #include <CGAL/Kernel/global_functions_internal_2.h> 00031 00032 CGAL_BEGIN_NAMESPACE 00033 00034 namespace CGALi { 00035 00036 class Straight_2_base_ { 00037 public: 00038 enum states {EMPTY, POINT, SEGMENT, RAY, LINE}; 00039 enum bound_states {NO_UNBOUNDED=0, MIN_UNBOUNDED=1, MAX_UNBOUNDED=2, 00040 BOTH_UNBOUNDED = 3, LINE_EMPTY = 4}; 00041 protected: 00042 Straight_2_base_() ; 00043 int main_dir_; // support_ is x or y directed (0/1). 00044 int dir_sign_; // sign of main direction coord. 00045 unsigned int bound_state_; // 0, 1, 2, 3, 4. 00046 public: 00047 unsigned int bound_state() const {return bound_state_;} 00048 }; 00049 00050 template <class K> 00051 class Straight_2_: public Straight_2_base_ { 00052 public: 00053 Straight_2_() ; 00054 Straight_2_(typename K::Point_2 const &point) ; 00055 Straight_2_(typename K::Line_2 const &line) ; 00056 Straight_2_(typename K::Ray_2 const &ray) ; 00057 Straight_2_(typename K::Ray_2 const &ray,bool cooriented) ; 00058 Straight_2_(typename K::Segment_2 const &seg) ; 00059 void cut_right_off(typename K::Line_2 const & cutter) ; 00060 int collinear_order(typename K::Point_2 const & p1, 00061 typename K::Point_2 const &p2) const ; 00062 void current(typename K::Line_2 &line) const; 00063 void current(typename K::Ray_2 &ray) const; 00064 void current(typename K::Segment_2 &seg) const; 00065 void current(typename K::Point_2 &point) const; 00066 states current_state() const; 00067 bool operator==(const Straight_2_<K>&) const; 00068 bool operator!=(const Straight_2_<K>&other) const 00069 { return !(*this == other);} 00070 protected: 00071 typename K::Line_2 support_; // The supporting line. 00072 typename K::Point_2 min_; 00073 typename K::Point_2 max_; 00074 }; 00075 00076 00077 00078 inline 00079 Straight_2_base_:: 00080 Straight_2_base_() 00081 { 00082 bound_state_ = LINE_EMPTY; 00083 } 00084 00085 template <class K> 00086 Straight_2_base_::states 00087 Straight_2_<K>:: 00088 current_state() const 00089 { 00090 switch (bound_state_) { 00091 case BOTH_UNBOUNDED: 00092 return LINE; 00093 case MIN_UNBOUNDED: 00094 case MAX_UNBOUNDED: 00095 return RAY; 00096 case NO_UNBOUNDED: 00097 return (collinear_order(min_, max_) == 0) ? POINT : SEGMENT; 00098 case LINE_EMPTY: 00099 default: 00100 return EMPTY; 00101 } 00102 } 00103 00104 template <class K> 00105 Straight_2_<K>:: 00106 Straight_2_() 00107 { 00108 bound_state_ = LINE_EMPTY; 00109 } 00110 00111 template <class K> 00112 Straight_2_<K>:: 00113 Straight_2_(typename K::Line_2 const &line) 00114 { 00115 support_ = line; 00116 typename K::Vector_2 const &dir = support_.direction().to_vector(); 00117 main_dir_ = (CGAL_NTS abs(dir.x()) > CGAL_NTS abs(dir.y()) ) ? 0 : 1; 00118 dir_sign_ = 00119 CGAL_NTS sign(support_.direction().to_vector().cartesian(main_dir_)); 00120 bound_state_ = BOTH_UNBOUNDED; 00121 } 00122 00123 template <class K> 00124 Straight_2_<K>:: 00125 Straight_2_(typename K::Point_2 const &point) 00126 { 00127 typedef typename K::Direction_2 Direction_2; 00128 typedef typename K::Line_2 Line_2; 00129 support_ = Line_2(point, Direction_2(K::RT(1), K::RT(0))); 00130 main_dir_ = 0; 00131 dir_sign_ = 1; 00132 bound_state_ = NO_UNBOUNDED; 00133 min_ = point; 00134 max_ = point; 00135 } 00136 00137 template <class K> 00138 Straight_2_<K>:: 00139 Straight_2_(typename K::Ray_2 const &ray) 00140 { 00141 support_ = ray.supporting_line(); 00142 typename K::Vector_2 const &dir = ray.direction().to_vector(); 00143 main_dir_ = (CGAL_NTS abs(dir.x()) > CGAL_NTS abs(dir.y()) ) ? 0 : 1; 00144 dir_sign_ = 00145 CGAL_NTS sign(support_.direction().to_vector().cartesian(main_dir_)); 00146 bound_state_ = MAX_UNBOUNDED; 00147 min_ = ray.source(); 00148 } 00149 00150 template <class K> 00151 Straight_2_<K>:: 00152 Straight_2_(typename K::Ray_2 const &ray_,bool cooriented) 00153 { 00154 typename K::Ray_2 const &ray = cooriented ? ray_ : ray_.opposite(); 00155 support_ = ray.supporting_line(); 00156 /* the supporting line is cooriented with the input ray iff 00157 cooriented is true */ 00158 typename K::Vector_2 const &dir = ray.direction().to_vector(); 00159 main_dir_ = (CGAL_NTS abs(dir.x()) > CGAL_NTS abs(dir.y()) ) ? 0 : 1; 00160 dir_sign_ = 00161 CGAL_NTS sign(support_.direction().to_vector().cartesian(main_dir_)); 00162 if (cooriented) 00163 { 00164 bound_state_ = MAX_UNBOUNDED; 00165 min_ = ray.source(); 00166 } 00167 else 00168 { 00169 bound_state_ = MIN_UNBOUNDED; 00170 max_ = ray.source(); 00171 } 00172 } 00173 00174 template <class K> 00175 Straight_2_<K>:: 00176 Straight_2_(typename K::Segment_2 const &seg) 00177 { 00178 support_ = seg.supporting_line(); 00179 typename K::Vector_2 const &dir = support_.direction().to_vector(); 00180 main_dir_ = (CGAL_NTS abs(dir.x()) > CGAL_NTS abs(dir.y()) ) ? 0 : 1; 00181 dir_sign_ = 00182 CGAL_NTS sign(support_.direction().to_vector().cartesian(main_dir_)); 00183 bound_state_ = NO_UNBOUNDED; 00184 min_ = seg.source(); 00185 max_ = seg.target(); 00186 } 00187 00188 00189 template <class K> 00190 void 00191 Straight_2_<K>:: 00192 current(typename K::Line_2 &line) const 00193 { 00194 CGAL_kernel_assertion(bound_state_ == BOTH_UNBOUNDED); 00195 line = support_; 00196 } 00197 00198 template <class K> 00199 void 00200 Straight_2_<K>:: 00201 current(typename K::Ray_2 &ray) const 00202 { 00203 typedef typename K::Ray_2 Ray_2; 00204 CGAL_kernel_assertion(bound_state_ == MIN_UNBOUNDED 00205 || bound_state_ == MAX_UNBOUNDED); 00206 if (bound_state_ == MIN_UNBOUNDED) { 00207 ray = Ray_2(max_, -support_.direction()); 00208 } else { 00209 ray = Ray_2(min_, support_.direction()); 00210 } 00211 } 00212 00213 template <class K> 00214 void 00215 Straight_2_<K>:: 00216 current(typename K::Segment_2 &seg) const 00217 { 00218 typedef typename K::Segment_2 Segment_2; 00219 CGAL_kernel_assertion(bound_state_ == NO_UNBOUNDED 00220 && collinear_order(min_, max_) != 0); 00221 seg = Segment_2(min_, max_); 00222 } 00223 00224 template <class K> 00225 void 00226 Straight_2_<K>:: 00227 current(typename K::Point_2 &pt) const 00228 { 00229 CGAL_kernel_assertion(bound_state_ == NO_UNBOUNDED 00230 && collinear_order(min_, max_) == 0); 00231 pt = min_; 00232 } 00233 00234 00235 template <class K> 00236 bool Straight_2_<K>::operator==(const Straight_2_<K>& s) const 00237 { 00238 typedef Straight_2_<K> Straight_2; 00239 // enum bound_states {NO_UNBOUNDED=0, MIN_UNBOUNDED=1, MAX_UNBOUNDED=2, 00240 // BOTH_UNBOUNDED = 3, LINE_EMPTY = 4}; 00241 if (bound_state_!=s.bound_state()) return false; 00242 if (bound_state_==Straight_2::LINE_EMPTY) return true; // empty 00243 if (support_!=s.support_) 00244 return false; // on different lines, even if both are points. 00245 switch (bound_state_) 00246 { 00247 case Straight_2::NO_UNBOUNDED: 00248 return min_==s.min_ && max_==s.max_; 00249 case Straight_2::MAX_UNBOUNDED: 00250 return min_==s.min_; 00251 case Straight_2::MIN_UNBOUNDED: 00252 return max_==s.max_; 00253 case Straight_2::BOTH_UNBOUNDED: 00254 return true; 00255 } 00256 return false; 00257 } 00258 00259 00260 00261 00262 template <class K> 00263 int 00264 sign_of_cross(typename K::Direction_2 const &dir1, 00265 typename K::Direction_2 const &dir2, 00266 const K&) 00267 { 00268 return static_cast<int>(CGALi::orientation(dir1.to_vector(), 00269 dir2.to_vector(), K())); 00270 } 00271 00272 template <class K> 00273 void 00274 Straight_2_<K>:: 00275 cut_right_off(typename K::Line_2 const & cutter) 00276 // cut off any part of this straight that is to the right of the cutter. 00277 { 00278 if (bound_state_ == LINE_EMPTY) 00279 return; 00280 Line_2_Line_2_pair<K> pair(&support_, &cutter); 00281 switch (pair.intersection_type()) { 00282 case Line_2_Line_2_pair<K>::NO_INTERSECTION: 00283 if (cutter.has_on_negative_side(support_.point())) 00284 bound_state_ = LINE_EMPTY; 00285 break; 00286 case Line_2_Line_2_pair<K>::LINE: 00287 break; 00288 case Line_2_Line_2_pair<K>::POINT: 00289 typename K::Point_2 ispoint = pair.intersection_point(); 00290 bool new_point = false; 00291 switch (sign_of_cross(support_.direction(), cutter.direction(), K())) { 00292 case -1: // new minimum. 00293 if (bound_state_ & MIN_UNBOUNDED) { 00294 new_point = true; 00295 bound_state_ ^= MIN_UNBOUNDED; // exclusive or removes flag. 00296 } else { 00297 if (collinear_order(ispoint, min_) == -1) 00298 new_point = true; 00299 } 00300 if (new_point) { 00301 if (!(bound_state_ & MAX_UNBOUNDED) 00302 && collinear_order(ispoint, max_) == -1) 00303 bound_state_ = LINE_EMPTY; 00304 else 00305 min_ = ispoint; 00306 } 00307 break; 00308 case 0: // should not happen 00309 CGAL_kernel_warning_msg(false, "Internal CGAL error."); 00310 break; 00311 case 1: // new maximum 00312 if (bound_state_ & MAX_UNBOUNDED) { 00313 new_point = true; 00314 bound_state_ ^= MAX_UNBOUNDED; // exclusive or removes flag. 00315 } else { 00316 if (collinear_order(ispoint, max_) == 1) 00317 new_point = true; 00318 } 00319 if (new_point) { 00320 if (!(bound_state_ & MIN_UNBOUNDED) 00321 && collinear_order(ispoint, min_) == 1) 00322 bound_state_ = LINE_EMPTY; 00323 else 00324 max_ = ispoint; 00325 } 00326 break; 00327 } 00328 break; 00329 } 00330 } 00331 00332 template <class K> 00333 int 00334 Straight_2_<K>:: 00335 collinear_order(typename K::Point_2 const &pt1, typename K::Point_2 const & pt2) const 00336 // Compare two points on the support_ line. 00337 // If the second point lies in the direction of the direction vector from 00338 // the first point, the result is 1. 00339 // Other results are -1 (other side) and 0 (coincidence). 00340 { 00341 typename K::Construct_cartesian_const_iterator_2 construct_cccit; 00342 typename K::Cartesian_const_iterator_2 ccit1 = construct_cccit(pt1) + main_dir_; 00343 typename K::Cartesian_const_iterator_2 ccit2 = construct_cccit(pt2) + main_dir_; 00344 int diffsign; 00345 diffsign = CGAL_NTS sign(*ccit2 - *ccit1); 00346 if (diffsign == 0) 00347 return 0; 00348 return (diffsign == dir_sign_) ? 1 : -1; 00349 } 00350 00351 } // namespace CGALi 00352 00353 CGAL_END_NAMESPACE 00354 00355 00356 00357 00358 00359 00360 #endif