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