BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Segment_Delaunay_graph_2/Vertex_conflict_C2.h
Go to the documentation of this file.
00001 // Copyright (c) 2003,2004,2005,2006  INRIA Sophia-Antipolis (France) and
00002 // Notre Dame University (U.S.A.).  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/Segment_Delaunay_graph_2/include/CGAL/Segment_Delaunay_graph_2/Vertex_conflict_C2.h $
00015 // $Id: Vertex_conflict_C2.h 45094 2008-08-22 16:10:06Z spion $
00016 // 
00017 //
00018 // Author(s)     : Menelaos Karavelas <mkaravel@cse.nd.edu>
00019 
00020 
00021 
00022 #ifndef CGAL_SEGMENT_DELAUNAY_GRAPH_2_VERTEX_CONFLICT_C2_H
00023 #define CGAL_SEGMENT_DELAUNAY_GRAPH_2_VERTEX_CONFLICT_C2_H
00024 
00025 #include <CGAL/Segment_Delaunay_graph_2/Voronoi_vertex_C2.h>
00026 #include <CGAL/Segment_Delaunay_graph_2/Are_same_points_C2.h>
00027 #include <CGAL/Segment_Delaunay_graph_2/Are_same_segments_C2.h>
00028 
00029 CGAL_BEGIN_NAMESPACE
00030 
00031 CGAL_SEGMENT_DELAUNAY_GRAPH_2_BEGIN_NAMESPACE
00032 
00033 //---------------------------------------------------------------------
00034 
00035 template<class K, class Method_tag>
00036 class Vertex_conflict_C2
00037 {
00038 private:
00039   typedef typename K::Point_2                Point_2;
00040   typedef typename K::Segment_2              Segment_2;
00041   typedef typename K::Site_2                 Site_2;
00042   typedef typename K::FT                     FT;
00043   typedef typename K::RT                     RT;
00044   typedef typename K::Orientation            Orientation;
00045   typedef typename K::Sign                   Sign;
00046 
00047   typedef Voronoi_vertex_C2<K,Method_tag>    Voronoi_vertex_2;
00048 
00049   typedef Are_same_points_C2<K>              Are_same_points_2;
00050   typedef Are_same_segments_C2<K>            Are_same_segments_2;
00051 
00052   typedef typename K::Intersections_tag      ITag;
00053 
00054 private:
00055   Are_same_points_2    same_points;
00056   Are_same_segments_2  same_segments;
00057 
00058   bool is_on_common_support(const Site_2& s1, const Site_2& s2,
00059                             const Point_2& p) const
00060   {
00061     CGAL_precondition( !s1.is_input() && !s2.is_input() );
00062 
00063     if (  same_segments(s1.supporting_site(0),
00064                         s2.supporting_site(0)) ||
00065           same_segments(s1.supporting_site(0),
00066                         s2.supporting_site(1))  ) {
00067       Site_2 support = s1.supporting_site(0);
00068       Site_2 tp = Site_2::construct_site_2(p);
00069 
00070       return (  same_points(support.source_site(), tp) ||
00071                 same_points(support.target_site(), tp)  );
00072     } else if (  same_segments(s1.supporting_site(1),
00073                                s2.supporting_site(1)) ||
00074                  same_segments(s1.supporting_site(1),
00075                                s2.supporting_site(0))  ) {
00076       Site_2 support = s1.supporting_site(1);
00077       Site_2 tp = Site_2::construct_site_2(p);
00078 
00079       return (  same_points(support.source_site(), tp) ||
00080                 same_points(support.target_site(), tp)  );      
00081     }
00082     return false;
00083   }
00084 
00085   bool have_common_support(const Site_2& p, const Site_2& q) const
00086   {
00087     CGAL_precondition( !p.is_input() && !q.is_input() );
00088 
00089     return
00090       same_segments(p.supporting_site(0), q.supporting_site(0)) ||
00091       same_segments(p.supporting_site(0), q.supporting_site(1)) ||
00092       same_segments(p.supporting_site(1), q.supporting_site(1)) ||
00093       same_segments(p.supporting_site(1), q.supporting_site(0));
00094   }
00095 
00096   bool have_common_support(const Site_2& s, const Point_2& p1,
00097                            const Point_2& p2) const
00098   {
00099     CGAL_precondition( !s.is_input() );
00100 
00101     Site_2 t = Site_2::construct_site_2(p1, p2);
00102 
00103     return ( same_segments(s.supporting_site(0), t) ||
00104              same_segments(s.supporting_site(1), t) );
00105   }
00106 
00107 private:
00108   Sign incircle_ppp(const Site_2& p, const Site_2& q,
00109                     const Site_2& t, const Tag_false&) const
00110   {
00111     Point_2 pp = p.point(), qp = q.point(), tp = t.point();
00112 
00113     // MK::ERROR: here I should call a kernel object, not a
00114     // function...; actually here (and everywhere in this class)
00115     // use the orientation predicate for sites; it does some
00116     // geometric filtering...
00117     Orientation o = orientation(pp, qp, tp);
00118 
00119     if ( o != COLLINEAR ) {
00120       return (o == LEFT_TURN) ? POSITIVE : NEGATIVE;
00121     }
00122 
00123     // MK::ERROR: change the following code to use the compare_x_2
00124     // and compare_y_2 stuff...
00125     RT dtpx = pp.x() - tp.x();
00126     RT dtpy = pp.y() - tp.y();
00127     RT dtqx = qp.x() - tp.x();
00128     RT minus_dtqy = -qp.y() + tp.y();
00129     
00130     Sign s = sign_of_determinant(dtpx, dtpy, minus_dtqy, dtqx);
00131 
00132     CGAL_assertion( s != ZERO );
00133 
00134     return s;
00135   }
00136 
00137   Sign incircle_ppp(const Site_2& p, const Site_2& q,
00138                     const Site_2& t, const Tag_true&) const
00139   {
00140     Orientation o = COLLINEAR; // the initialization was done in
00141                                // order a compiler warning
00142 
00143     // do some geometric filtering...
00144     bool p_exact = p.is_input();
00145     bool q_exact = q.is_input();
00146     bool t_exact = t.is_input();
00147     bool filtered = false;
00148     // the following if-statement does the gometric filtering...
00149     // maybe it is not so important since this will only be
00150     // activated if a lot of intersection points appear on the
00151     // convex hull
00152     if ( !p_exact || !q_exact || !t_exact ) {
00153       if ( !p_exact && !q_exact && !t_exact ) {
00154         if ( have_common_support(p, q) &&
00155              have_common_support(q, t) ) {
00156           o = COLLINEAR;
00157           filtered = true;
00158         }
00159       } else if ( !p_exact && !q_exact && t_exact ) {
00160         if ( is_on_common_support(p, q, t.point()) ) {
00161           o = COLLINEAR;
00162           filtered = true;
00163         }
00164       } else if ( !p_exact && q_exact && !t_exact ) {
00165         if ( is_on_common_support(p, t, q.point()) ) {
00166           o = COLLINEAR;
00167           filtered = true;
00168         }
00169       } else if ( p_exact && !q_exact && !t_exact ) {
00170         if ( is_on_common_support(t, q, p.point()) ) {
00171           o = COLLINEAR;
00172           filtered = true;
00173         }
00174       } else if ( !p_exact && q_exact && t_exact ) {
00175         if ( have_common_support(p, q.point(), t.point()) ) {
00176           o = COLLINEAR;
00177           filtered = true;
00178         }
00179       } else if ( p_exact && !q_exact && t_exact ) {
00180         if ( have_common_support(q, p.point(), t.point()) ) {
00181           o = COLLINEAR;
00182           filtered = true;
00183         }
00184       } else if ( p_exact && q_exact && !t_exact ) {
00185         if ( have_common_support(t, p.point(), q.point()) ) {
00186           o = COLLINEAR;
00187           filtered = true;
00188         }
00189       }
00190     }
00191 
00192     Point_2 pp = p.point(), qp = q.point(), tp = t.point();
00193 
00194     if ( !filtered ) {
00195       // MK::ERROR: here I should call a kernel object, not a
00196       // function...; actually here (and everywhere in this class)
00197       // use the orientation predicate for sites; it does some
00198       // geometric filtering...
00199       o = orientation(pp, qp, tp);
00200     }
00201 
00202     if ( o != COLLINEAR ) {
00203       return (o == LEFT_TURN) ? POSITIVE : NEGATIVE;
00204     }
00205 
00206     // MK::ERROR: change the following code to use the compare_x_2
00207     // and compare_y_2 stuff...
00208     RT dtpx = pp.x() - tp.x();
00209     RT dtpy = pp.y() - tp.y();
00210     RT dtqx = qp.x() - tp.x();
00211     RT minus_dtqy = -qp.y() + tp.y();
00212     
00213     Sign s = sign_of_determinant(dtpx, dtpy, minus_dtqy, dtqx);
00214     
00215     CGAL_assertion( s != ZERO );
00216 
00217     return s;
00218   }
00219 
00220 
00221   Sign incircle_p(const Site_2& p, const Site_2& q,
00222                   const Site_2& t) const
00223   {
00224     CGAL_precondition( t.is_point() );
00225 
00226     if ( p.is_point() && q.is_point() ) {
00227 
00228 #if 1
00229       return incircle_ppp(p, q, t, ITag());
00230 
00231 #else
00232       Orientation o = COLLINEAR; // the initialization was done in
00233                                  // order a compiler warning
00234 
00235       // do some geometric filtering...
00236       bool p_exact = p.is_input();
00237       bool q_exact = q.is_input();
00238       bool t_exact = t.is_input();
00239       bool filtered = false;
00240       // the following if-statement does the gometric filtering...
00241       // maybe it is not so important since this will only be
00242       // activated if a lot of intersection points appear on the
00243       // convex hull
00244       if ( !p_exact || !q_exact || !t_exact ) {
00245         if ( !p_exact && !q_exact && !t_exact ) {
00246           if ( have_common_support(p, q) &&
00247                have_common_support(q, t) ) {
00248             o = COLLINEAR;
00249             filtered = true;
00250           }
00251         } else if ( !p_exact && !q_exact && t_exact ) {
00252           if ( is_on_common_support(p, q, t.point()) ) {
00253             o = COLLINEAR;
00254             filtered = true;
00255           }
00256         } else if ( !p_exact && q_exact && !t_exact ) {
00257           if ( is_on_common_support(p, t, q.point()) ) {
00258             o = COLLINEAR;
00259             filtered = true;
00260           }
00261         } else if ( p_exact && !q_exact && !t_exact ) {
00262           if ( is_on_common_support(t, q, p.point()) ) {
00263             o = COLLINEAR;
00264             filtered = true;
00265           }
00266         } else if ( !p_exact && q_exact && t_exact ) {
00267           if ( have_common_support(p, q.point(), t.point()) ) {
00268             o = COLLINEAR;
00269             filtered = true;
00270           }
00271         } else if ( p_exact && !q_exact && t_exact ) {
00272           if ( have_common_support(q, p.point(), t.point()) ) {
00273             o = COLLINEAR;
00274             filtered = true;
00275           }
00276         } else if ( p_exact && q_exact && !t_exact ) {
00277           if ( have_common_support(t, p.point(), q.point()) ) {
00278             o = COLLINEAR;
00279             filtered = true;
00280           }
00281         }
00282       }
00283 
00284       Point_2 pp = p.point(), qp = q.point(), tp = t.point();
00285 
00286       if ( !filtered ) {
00287         // MK::ERROR: here I should call a kernel object, not a
00288         // function...; actually here (and everywhere in this class)
00289         // use the orientation predicate for sites; it does some
00290         // geometric filtering...
00291         o = orientation(pp, qp, tp);
00292       }
00293 
00294       if ( o != COLLINEAR ) {
00295         return (o == LEFT_TURN) ? POSITIVE : NEGATIVE;
00296       }
00297 
00298       // MK::ERROR: change the following code to use the compare_x_2
00299       // and compare_y_2 stuff...
00300       RT dtpx = pp.x() - tp.x();
00301       RT dtpy = pp.y() - tp.y();
00302       RT dtqx = qp.x() - tp.x();
00303       RT minus_dtqy = -qp.y() + tp.y();
00304       
00305       Sign s = sign_of_determinant(dtpx, dtpy, minus_dtqy, dtqx);
00306 
00307       CGAL_assertion( s != ZERO );
00308 
00309       return s;
00310 #endif
00311     }
00312 
00313     CGAL_assertion( p.is_point() || q.is_point() );
00314 
00315     Orientation o;
00316     if ( p.is_point() && q.is_segment() ) {
00317       Point_2 pq = same_points(p, q.source_site()) ? q.target() : q.source();
00318       o = orientation(p.point(), pq, t.point());
00319     } else { // p is a segment and q is a point
00320       Point_2 pp = same_points(q, p.source_site()) ? p.target() : p.source();
00321       o = orientation(pp, q.point(), t.point());
00322     }
00323     if ( CGAL::is_certain(o == RIGHT_TURN) )
00324         return CGAL::get_certain( o == RIGHT_TURN ) ? NEGATIVE : POSITIVE;
00325     return CGAL::Uncertain<CGAL::Sign>::indeterminate();
00326   }
00327 
00328   //-----------------------------------------------------------------------
00329 
00330 
00331   Sign incircle_pps(const Site_2& p, const Site_2& q,
00332                     const Site_2& t) const
00333   {
00334     CGAL_precondition( p.is_point() && q.is_point() );
00335 
00336     bool is_p_tsrc = same_points(p, t.source_site());
00337     bool is_p_ttrg = same_points(p, t.target_site());
00338 
00339     bool is_q_tsrc = same_points(q, t.source_site());
00340     bool is_q_ttrg = same_points(q, t.target_site());
00341 
00342     bool is_p_on_t = is_p_tsrc || is_p_ttrg;
00343     bool is_q_on_t = is_q_tsrc || is_q_ttrg;
00344 
00345     if ( is_p_on_t && is_q_on_t ) {
00346         // if t is the segment joining p and q then t must be a vertex
00347         // on the convex hull
00348         return NEGATIVE;
00349     } else if ( is_p_on_t ) {
00350       // p is an endpoint of t
00351       // in this case the p,q,oo vertex is destroyed only if the
00352       // other endpoint of t is beyond
00353       Point_2 pt = is_p_tsrc ? t.target() : t.source();
00354       Orientation o = orientation(p.point(), q.point(), pt);
00355 
00356       return (o == RIGHT_TURN) ? NEGATIVE : POSITIVE;
00357     } else if ( is_q_on_t ) {
00358       Point_2 pt = is_q_tsrc ? t.target() : t.source();
00359       Orientation o = orientation(p.point(), q.point(), pt);
00360 
00361       return (o == RIGHT_TURN) ? NEGATIVE : POSITIVE;
00362     } else {
00363       // maybe here I should immediately return POSITIVE;
00364       // since we insert endpoints of segments first, p and q cannot
00365       // be consecutive points on the convex hull if one of the
00366       // endpoints of t is to the right of the line pq.
00367       Point_2 pp = p.point(), qq = q.point();
00368       Orientation o1 = orientation(pp, qq, t.source());
00369       Orientation o2 = orientation(pp, qq, t.target());
00370 
00371       if ( o1 == RIGHT_TURN || o2 == RIGHT_TURN ) {
00372         return NEGATIVE;
00373       }
00374       return POSITIVE;
00375     }
00376   }
00377 
00378 
00379   Sign incircle_sps(const Site_2& p, const Site_2& q,
00380                     const Site_2& t) const
00381   {
00382     CGAL_precondition( p.is_segment() && q.is_point() );
00383 
00384     bool is_q_tsrc = same_points(q, t.source_site());
00385     bool is_q_ttrg = same_points(q, t.target_site());
00386 
00387     bool is_q_on_t = is_q_tsrc || is_q_ttrg;
00388 
00389     if ( is_q_on_t ) {
00390       Point_2 pp = same_points(q, p.source_site()) ? p.target() : p.source();
00391       Point_2 pt = is_q_tsrc ? t.target() : t.source();
00392 
00393       Orientation o = orientation(pp, q.point(), pt);
00394 
00395       return (o == RIGHT_TURN) ? NEGATIVE : POSITIVE;
00396     } else {
00397       return POSITIVE;
00398     }
00399   }
00400 
00401 
00402   Sign incircle_pss(const Site_2& p, const Site_2& q,
00403                     const Site_2& t) const
00404   {
00405     CGAL_precondition( p.is_point() && q.is_segment() );
00406 
00407     bool is_p_tsrc = same_points(p, t.source_site());
00408     bool is_p_ttrg = same_points(p, t.target_site());
00409 
00410     bool is_p_on_t = is_p_tsrc || is_p_ttrg;
00411 
00412     if ( is_p_on_t ) {
00413       Point_2 pq = same_points(p, q.source_site()) ? q.target() : q.source();
00414       Point_2 pt = is_p_tsrc ? t.target() : t.source();
00415 
00416       Orientation o = orientation(p.point(), pq, pt);
00417 
00418       return (o == RIGHT_TURN) ? NEGATIVE : POSITIVE;
00419     } else {
00420       // if p is not an endpoint of t, then either p and q should
00421       // not be on the convex hull or t does not affect the vertex
00422       // of p and q.
00423       return POSITIVE;
00424     }
00425   }
00426 
00427 
00428   Sign incircle_s(const Site_2& p, const Site_2& q,
00429                   const Site_2& t) const
00430   {
00431     CGAL_precondition( t.is_segment() );
00432 
00433     if ( p.is_point() && q.is_point() ) {
00434       return incircle_pps(p, q, t);
00435     } else if ( p.is_point() && q.is_segment() ) {
00436       return incircle_pss(p, q, t);
00437     } else { // p is a segment and q is a point
00438       return incircle_sps(p, q, t);
00439     }
00440   }
00441 
00442 
00443 public:
00444   typedef Site_2      argument_type;
00445   typedef Sign        result_type;
00446 
00447 
00448   Sign operator()(const Site_2& p, const Site_2& q,
00449                   const Site_2& r, const Site_2& t) const
00450   {
00451     Voronoi_vertex_2 v(p, q, r);
00452 
00453     return v.incircle(t);
00454   }
00455 
00456 
00457   
00458 
00459   Sign operator()(const Site_2& p, const Site_2& q,
00460                   const Site_2& t) const
00461   {
00462     CGAL_assertion( !(p.is_segment() && q.is_segment()) );
00463 
00464     if ( p.is_point() && q.is_segment() ) {
00465       // p must be an endpoint of q
00466       CGAL_assertion( same_points(p, q.source_site()) ||
00467                       same_points(p, q.target_site()) );
00468     } else if ( p.is_segment() && q.is_point() ) {
00469       // q must be an endpoint of p
00470       CGAL_assertion( same_points(p.source_site(), q) ||
00471                       same_points(p.target_site(), q) );
00472     }
00473 
00474     if ( t.is_point() ) {
00475       //      return incircle_p(p, q, t);
00476       return incircle_p(q, p, t);
00477     }
00478 
00479     // MK::ERROR: do geometric filtering when orientation is called.
00480     //    return incircle_s(p, q, t);
00481     return incircle_s(q, p, t);
00482   }
00483 
00484 
00485 };
00486 
00487 //---------------------------------------------------------------------
00488 
00489 CGAL_SEGMENT_DELAUNAY_GRAPH_2_END_NAMESPACE
00490 
00491 CGAL_END_NAMESPACE
00492 
00493 #endif // CGAL_SEGMENT_DELAUNAY_GRAPH_2_VERTEX_CONFLICT_C2_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines