BWAPI
|
00001 // Copyright (c) 2005 Tel-Aviv University (Israel). 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/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h $ 00015 // $Id: Arr_conic_traits_2.h 50366 2009-07-05 12:56:48Z efif $ 00016 // 00017 // 00018 // Author(s) : Ron Wein <wein@post.tau.ac.il> 00019 00020 #ifndef CGAL_ARR_CONIC_TRAITS_2_H 00021 #define CGAL_ARR_CONIC_TRAITS_2_H 00022 00027 #include <CGAL/tags.h> 00028 #include <CGAL/Arr_tags.h> 00029 #include <CGAL/Arr_geometry_traits/Conic_arc_2.h> 00030 #include <CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h> 00031 #include <CGAL/Arr_geometry_traits/Conic_point_2.h> 00032 00033 #include <fstream> 00034 00035 CGAL_BEGIN_NAMESPACE 00036 00050 template <class Rat_kernel_, class Alg_kernel_, class Nt_traits_> 00051 class Arr_conic_traits_2 00052 { 00053 public: 00054 00055 typedef Rat_kernel_ Rat_kernel; 00056 typedef Alg_kernel_ Alg_kernel; 00057 typedef Nt_traits_ Nt_traits; 00058 00059 typedef typename Rat_kernel::FT Rational; 00060 typedef typename Rat_kernel::Point_2 Rat_point_2; 00061 typedef typename Rat_kernel::Segment_2 Rat_segment_2; 00062 typedef typename Rat_kernel::Line_2 Rat_line_2; 00063 typedef typename Rat_kernel::Circle_2 Rat_circle_2; 00064 00065 typedef typename Alg_kernel::FT Algebraic; 00066 00067 typedef typename Nt_traits::Integer Integer; 00068 00069 typedef Arr_conic_traits_2<Rat_kernel, Alg_kernel, Nt_traits> Self; 00070 00071 // Category tags: 00072 typedef Tag_true Has_left_category; 00073 typedef Tag_true Has_merge_category; 00074 00075 typedef Arr_oblivious_side_tag Arr_left_side_tag; 00076 typedef Arr_oblivious_side_tag Arr_bottom_side_tag; 00077 typedef Arr_oblivious_side_tag Arr_top_side_tag; 00078 typedef Arr_oblivious_side_tag Arr_right_side_tag; 00079 00080 // Traits objects: 00081 typedef _Conic_arc_2<Rat_kernel, Alg_kernel, Nt_traits> Curve_2; 00082 typedef _Conic_x_monotone_arc_2<Curve_2> X_monotone_curve_2; 00083 typedef _Conic_point_2<Alg_kernel> Point_2; 00084 typedef unsigned int Multiplicity; 00085 00086 private: 00087 00088 // Type definition for the intersection points mapping. 00089 typedef typename X_monotone_curve_2::Conic_id Conic_id; 00090 typedef typename X_monotone_curve_2::Intersection_point_2 00091 Intersection_point_2; 00092 typedef typename X_monotone_curve_2::Intersection_map Intersection_map; 00093 00094 mutable Intersection_map inter_map; // Mapping conic pairs to their 00095 // intersection points. 00096 00097 public: 00098 00102 Arr_conic_traits_2 () 00103 {} 00104 00106 static unsigned int get_index () 00107 { 00108 static unsigned int index = 0; 00109 return (++index); 00110 } 00111 00113 00114 00115 class Compare_x_2 00116 { 00117 public: 00126 Comparison_result operator() (const Point_2 & p1, const Point_2 & p2) const 00127 { 00128 Alg_kernel ker; 00129 return (ker.compare_x_2_object() (p1, p2)); 00130 } 00131 }; 00132 00134 Compare_x_2 compare_x_2_object () const 00135 { 00136 return Compare_x_2(); 00137 } 00138 00139 class Compare_xy_2 00140 { 00141 public: 00150 Comparison_result operator() (const Point_2& p1, const Point_2& p2) const 00151 { 00152 Alg_kernel ker; 00153 return (ker.compare_xy_2_object() (p1, p2)); 00154 } 00155 }; 00156 00158 Compare_xy_2 compare_xy_2_object () const 00159 { 00160 return Compare_xy_2(); 00161 } 00162 00163 class Construct_min_vertex_2 00164 { 00165 public: 00171 const Point_2& operator() (const X_monotone_curve_2 & cv) const 00172 { 00173 return (cv.left()); 00174 } 00175 }; 00176 00178 Construct_min_vertex_2 construct_min_vertex_2_object () const 00179 { 00180 return Construct_min_vertex_2(); 00181 } 00182 00183 class Construct_max_vertex_2 00184 { 00185 public: 00191 const Point_2& operator() (const X_monotone_curve_2 & cv) const 00192 { 00193 return (cv.right()); 00194 } 00195 }; 00196 00198 Construct_max_vertex_2 construct_max_vertex_2_object () const 00199 { 00200 return Construct_max_vertex_2(); 00201 } 00202 00203 class Is_vertical_2 00204 { 00205 public: 00211 bool operator() (const X_monotone_curve_2& cv) const 00212 { 00213 return (cv.is_vertical()); 00214 } 00215 }; 00216 00218 Is_vertical_2 is_vertical_2_object () const 00219 { 00220 return Is_vertical_2(); 00221 } 00222 00223 class Compare_y_at_x_2 00224 { 00225 public: 00235 Comparison_result operator() (const Point_2 & p, 00236 const X_monotone_curve_2 & cv) const 00237 { 00238 Alg_kernel ker; 00239 00240 if (cv.is_vertical()) 00241 { 00242 // A special treatment for vertical segments: 00243 // In case p has the same x c-ordinate of the vertical segment, compare 00244 // it to the segment endpoints to determine its position. 00245 Comparison_result res1 = ker.compare_y_2_object() (p, cv.left()); 00246 Comparison_result res2 = ker.compare_y_2_object() (p, cv.right()); 00247 00248 if (res1 == res2) 00249 return (res1); 00250 else 00251 return (EQUAL); 00252 } 00253 00254 // Check whether the point is exactly on the curve. 00255 if (cv.contains_point(p)) 00256 return (EQUAL); 00257 00258 // Get a point q on the x-monotone arc with the same x coordinate as p. 00259 Comparison_result x_res; 00260 Point_2 q; 00261 00262 if ((x_res = ker.compare_x_2_object() (p, cv.left())) == EQUAL) 00263 { 00264 q = cv.left(); 00265 } 00266 else 00267 { 00268 CGAL_precondition (x_res != SMALLER); 00269 00270 if ((x_res = ker.compare_x_2_object() (p, cv.right())) == EQUAL) 00271 { 00272 q = cv.right(); 00273 } 00274 else 00275 { 00276 CGAL_precondition (x_res != LARGER); 00277 00278 q = cv.point_at_x (p); 00279 } 00280 } 00281 00282 // Compare p with the a point of the curve with the same x coordinate. 00283 return (ker.compare_y_2_object() (p, q)); 00284 } 00285 }; 00286 00288 Compare_y_at_x_2 compare_y_at_x_2_object () const 00289 { 00290 return Compare_y_at_x_2(); 00291 } 00292 00293 class Compare_y_at_x_left_2 00294 { 00295 public: 00307 Comparison_result operator() (const X_monotone_curve_2& cv1, 00308 const X_monotone_curve_2& cv2, 00309 const Point_2& p) const 00310 { 00311 // Make sure that p lies on both curves, and that both are defined to its 00312 // left (so their left endpoint is lexicographically smaller than p). 00313 CGAL_precondition (cv1.contains_point (p) && 00314 cv2.contains_point (p)); 00315 00316 CGAL_precondition_code ( 00317 Alg_kernel ker; 00318 ); 00319 CGAL_precondition (ker.compare_xy_2_object() (p, 00320 cv1.left()) == LARGER && 00321 ker.compare_xy_2_object() (p, 00322 cv2.left()) == LARGER); 00323 00324 // If one of the curves is vertical, it is below the other one. 00325 if (cv1.is_vertical()) 00326 { 00327 if (cv2.is_vertical()) 00328 // Both are vertical: 00329 return (EQUAL); 00330 else 00331 return (SMALLER); 00332 } 00333 else if (cv2.is_vertical()) 00334 { 00335 return (LARGER); 00336 } 00337 00338 // Compare the two curves immediately to the left of p: 00339 return (cv1.compare_to_left (cv2, p)); 00340 } 00341 }; 00342 00344 Compare_y_at_x_left_2 compare_y_at_x_left_2_object () const 00345 { 00346 return Compare_y_at_x_left_2(); 00347 } 00348 00349 class Compare_y_at_x_right_2 00350 { 00351 public: 00363 Comparison_result operator() (const X_monotone_curve_2& cv1, 00364 const X_monotone_curve_2& cv2, 00365 const Point_2& p) const 00366 { 00367 // Make sure that p lies on both curves, and that both are defined to its 00368 // left (so their left endpoint is lexicographically smaller than p). 00369 CGAL_precondition (cv1.contains_point (p) && 00370 cv2.contains_point (p)); 00371 00372 CGAL_precondition_code ( 00373 Alg_kernel ker; 00374 ); 00375 00376 CGAL_precondition (ker.compare_xy_2_object() (p, 00377 cv1.right()) == SMALLER && 00378 ker.compare_xy_2_object() (p, 00379 cv2.right()) == SMALLER); 00380 00381 // If one of the curves is vertical, it is above the other one. 00382 if (cv1.is_vertical()) 00383 { 00384 if (cv2.is_vertical()) 00385 // Both are vertical: 00386 return (EQUAL); 00387 else 00388 return (LARGER); 00389 } 00390 else if (cv2.is_vertical()) 00391 { 00392 return (SMALLER); 00393 } 00394 00395 // Compare the two curves immediately to the right of p: 00396 return (cv1.compare_to_right (cv2, p)); 00397 } 00398 }; 00399 00401 Compare_y_at_x_right_2 compare_y_at_x_right_2_object () const 00402 { 00403 return Compare_y_at_x_right_2(); 00404 } 00405 00406 class Equal_2 00407 { 00408 public: 00415 bool operator() (const X_monotone_curve_2& cv1, 00416 const X_monotone_curve_2& cv2) const 00417 { 00418 if (&cv1 == &cv2) 00419 return (true); 00420 00421 return (cv1.equals (cv2)); 00422 } 00423 00430 bool operator() (const Point_2& p1, const Point_2& p2) const 00431 { 00432 if (&p1 == &p2) 00433 return (true); 00434 00435 Alg_kernel ker; 00436 return (ker.compare_xy_2_object() (p1, p2) == EQUAL); 00437 } 00438 }; 00439 00441 Equal_2 equal_2_object () const 00442 { 00443 return Equal_2(); 00444 } 00446 00448 00449 00450 class Make_x_monotone_2 00451 { 00452 typedef Arr_conic_traits_2 <Rat_kernel_, Alg_kernel_, Nt_traits_> Self; 00453 public: 00454 00463 template<class OutputIterator> 00464 OutputIterator operator() (const Curve_2& cv, OutputIterator oi) const 00465 { 00466 // Increment the serial number of the curve cv, which will serve as its 00467 // unique identifier. 00468 unsigned int index = Self::get_index(); 00469 Conic_id conic_id (index); 00470 00471 // Find the points of vertical tangency to cv and act accordingly. 00472 typename Curve_2::Point_2 vtan_ps[2]; 00473 int n_vtan_ps; 00474 00475 n_vtan_ps = cv.vertical_tangency_points (vtan_ps); 00476 00477 if (n_vtan_ps == 0) 00478 { 00479 // In case the given curve is already x-monotone: 00480 *oi = make_object (X_monotone_curve_2 (cv, conic_id)); 00481 ++oi; 00482 return (oi); 00483 } 00484 00485 // Split the conic arc into x-monotone sub-curves. 00486 if (cv.is_full_conic()) 00487 { 00488 // Make sure we have two vertical tangency points. 00489 CGAL_assertion(n_vtan_ps == 2); 00490 00491 // In case the curve is a full conic, split it into two x-monotone 00492 // arcs, one going from ps[0] to ps[1], and the other from ps[1] to 00493 // ps[0]. 00494 *oi = make_object (X_monotone_curve_2 (cv, vtan_ps[0], vtan_ps[1], 00495 conic_id)); 00496 ++oi; 00497 *oi = make_object (X_monotone_curve_2 (cv, vtan_ps[1], vtan_ps[0], 00498 conic_id)); 00499 ++oi; 00500 } 00501 else 00502 { 00503 if (n_vtan_ps == 1) 00504 { 00505 // Split the arc into two x-monotone sub-curves: one going from the 00506 // arc source to ps[0], and the other from ps[0] to the target. 00507 *oi = make_object (X_monotone_curve_2 (cv, cv.source(), vtan_ps[0], 00508 conic_id)); 00509 ++oi; 00510 *oi = make_object (X_monotone_curve_2 (cv, vtan_ps[0], cv.target(), 00511 conic_id)); 00512 ++oi; 00513 } 00514 else 00515 { 00516 CGAL_assertion (n_vtan_ps == 2); 00517 00518 // Identify the first point we encounter when going from cv's source 00519 // to its target, and the second point we encounter. Note that the 00520 // two endpoints must both be below the line connecting the two 00521 // tangnecy points (or both lies above it). 00522 int ind_first = 0; 00523 int ind_second = 1; 00524 Alg_kernel_ ker; 00525 typename Alg_kernel_::Line_2 line = 00526 ker.construct_line_2_object() (vtan_ps[0], vtan_ps[1]); 00527 const Comparison_result start_pos = 00528 ker.compare_y_at_x_2_object() (cv.source(), line); 00529 const Comparison_result order_vpts = 00530 ker.compare_x_2_object() (vtan_ps[0], vtan_ps[1]); 00531 00532 CGAL_assertion (start_pos != EQUAL && 00533 ker.compare_y_at_x_2_object() (cv.target(), 00534 line) == start_pos); 00535 CGAL_assertion (order_vpts != EQUAL); 00536 00537 if ((cv.orientation() == COUNTERCLOCKWISE && 00538 start_pos == order_vpts) || 00539 (cv.orientation() == CLOCKWISE && 00540 start_pos != order_vpts)) 00541 { 00542 ind_first = 1; 00543 ind_second = 0; 00544 } 00545 00546 // Split the arc into three x-monotone sub-curves. 00547 *oi = make_object (X_monotone_curve_2 (cv, 00548 cv.source(), 00549 vtan_ps[ind_first], 00550 conic_id)); 00551 ++oi; 00552 00553 *oi = make_object (X_monotone_curve_2 (cv, 00554 vtan_ps[ind_first], 00555 vtan_ps[ind_second], 00556 conic_id)); 00557 ++oi; 00558 00559 *oi = make_object (X_monotone_curve_2 (cv, 00560 vtan_ps[ind_second], 00561 cv.target(), 00562 conic_id)); 00563 ++oi; 00564 } 00565 } 00566 00567 return (oi); 00568 } 00569 }; 00570 00572 Make_x_monotone_2 make_x_monotone_2_object () const 00573 { 00574 return Make_x_monotone_2(); 00575 } 00576 00577 class Split_2 00578 { 00579 public: 00588 void operator() (const X_monotone_curve_2& cv, const Point_2 & p, 00589 X_monotone_curve_2& c1, X_monotone_curve_2& c2) const 00590 { 00591 cv.split (p, c1, c2); 00592 return; 00593 } 00594 }; 00595 00597 Split_2 split_2_object () const 00598 { 00599 return Split_2(); 00600 } 00601 00602 class Intersect_2 00603 { 00604 private: 00605 00606 Intersection_map& _inter_map; // The map of intersection points. 00607 00608 public: 00609 00611 Intersect_2 (Intersection_map& map) : 00612 _inter_map (map) 00613 {} 00614 00624 template<class OutputIterator> 00625 OutputIterator operator() (const X_monotone_curve_2& cv1, 00626 const X_monotone_curve_2& cv2, 00627 OutputIterator oi) const 00628 { 00629 return (cv1.intersect (cv2, _inter_map, oi)); 00630 } 00631 }; 00632 00634 Intersect_2 intersect_2_object () const 00635 { 00636 return (Intersect_2 (inter_map)); 00637 } 00638 00639 class Are_mergeable_2 00640 { 00641 public: 00649 bool operator() (const X_monotone_curve_2& cv1, 00650 const X_monotone_curve_2& cv2) const 00651 { 00652 return (cv1.can_merge_with (cv2)); 00653 } 00654 }; 00655 00657 Are_mergeable_2 are_mergeable_2_object () const 00658 { 00659 return Are_mergeable_2(); 00660 } 00661 00662 class Merge_2 00663 { 00664 public: 00673 void operator() (const X_monotone_curve_2& cv1, 00674 const X_monotone_curve_2& cv2, 00675 X_monotone_curve_2& c) const 00676 { 00677 c = cv1; 00678 c.merge (cv2); 00679 00680 return; 00681 } 00682 }; 00683 00685 Merge_2 merge_2_object () const 00686 { 00687 return Merge_2(); 00688 } 00689 00691 00693 00694 typedef double Approximate_number_type; 00695 00696 class Approximate_2 00697 { 00698 public: 00699 00708 Approximate_number_type operator() (const Point_2& p, 00709 int i) const 00710 { 00711 CGAL_precondition (i == 0 || i == 1); 00712 00713 if (i == 0) 00714 return (CGAL::to_double(p.x())); 00715 else 00716 return (CGAL::to_double(p.y())); 00717 } 00718 }; 00719 00721 Approximate_2 approximate_2_object () const 00722 { 00723 return Approximate_2(); 00724 } 00725 00726 class Construct_x_monotone_curve_2 00727 { 00728 public: 00729 00737 X_monotone_curve_2 operator() (const Point_2& p, 00738 const Point_2& q) const 00739 { 00740 return (X_monotone_curve_2 (p, q)); 00741 } 00742 }; 00743 00745 Construct_x_monotone_curve_2 construct_x_monotone_curve_2_object () const 00746 { 00747 return Construct_x_monotone_curve_2(); 00748 } 00750 00752 00753 00754 class Compare_endpoints_xy_2 00755 { 00756 public: 00757 00765 Comparison_result operator() (const X_monotone_curve_2& cv) const 00766 { 00767 if (cv.is_directed_right()) 00768 return (SMALLER); 00769 else 00770 return (LARGER); 00771 } 00772 }; 00773 00775 Compare_endpoints_xy_2 compare_endpoints_xy_2_object() const 00776 { 00777 return Compare_endpoints_xy_2(); 00778 } 00779 00780 class Construct_opposite_2 00781 { 00782 public: 00783 00789 X_monotone_curve_2 operator() (const X_monotone_curve_2& cv) const 00790 { 00791 return (cv.flip()); 00792 } 00793 }; 00794 00796 Construct_opposite_2 construct_opposite_2_object() const 00797 { 00798 return Construct_opposite_2(); 00799 } 00801 }; 00802 00803 CGAL_END_NAMESPACE 00804 00805 #endif