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