BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/predicates/Straight_skeleton_pred_ftC2.h
Go to the documentation of this file.
00001 // Copyright (c) 2006 Fernando Luis Cacciola Carballal. All rights reserved.
00002 //
00003 // This file is part of CGAL (www.cgal.org); you may redistribute it under
00004 // the terms of the Q Public License version 1.0.
00005 // See the file LICENSE.QPL distributed with CGAL.
00006 //
00007 // Licensees holding a valid commercial license may use this file in
00008 // accordance with the commercial license agreement provided with the software.
00009 //
00010 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00011 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00012 //
00013 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Straight_skeleton_2/include/CGAL/predicates/Straight_skeleton_pred_ftC2.h $
00014 // $Id: Straight_skeleton_pred_ftC2.h 46494 2008-10-27 16:30:51Z afabri $
00015 //
00016 // Author(s)     : Fernando Cacciola <fernando_cacciola@ciudad.com.ar>
00017 //
00018 #ifndef CGAL_STRAIGHT_SKELETON_PREDICATES_FTC2_H 
00019 #define CGAL_STRAIGHT_SKELETON_PREDICATES_FTC2_H 1
00020 
00021 #include <CGAL/constructions/Straight_skeleton_cons_ftC2.h>
00022 #include <CGAL/Uncertain.h>
00023 #include <CGAL/certified_quotient_predicates.h>
00024 
00025 CGAL_BEGIN_NAMESPACE
00026 
00027 namespace CGAL_SS_i
00028 {
00029 
00030 // Just like the uncertified collinear() returns true IFF r lies in the line p->q
00031 // NOTE: r might be in the ray from p or q containing q or p, that is, there is no ordering implied, just that
00032 // the three points are along the same line, in any order.
00033 template<class K>
00034 inline
00035 Uncertain<bool> certified_collinearC2( Point_2<K> const& p
00036                                      , Point_2<K> const& q
00037                                      , Point_2<K> const& r 
00038                                      )
00039 {
00040   return CGAL_NTS certified_is_equal( ( q.x() - p.x() ) * ( r.y() - p.y() )
00041                                     , ( r.x() - p.x() ) * ( q.y() - p.y() )
00042                                     );
00043 }
00044 
00045 
00046 // Just like the uncertified collinear_are_ordered_along_lineC2() returns true IFF, given p,q,r along the same line,
00047 // q is in the closed segment [p,r].
00048 template<class K>
00049 inline
00050 Uncertain<bool> certified_collinear_are_ordered_along_lineC2( Point_2<K> const& p
00051                                                             , Point_2<K> const& q
00052                                                             , Point_2<K> const& r 
00053                                                             )
00054 {
00055   if ( CGAL_NTS certainly(p.x() < q.x()) ) return !(r.x() < q.x());
00056   if ( CGAL_NTS certainly(q.x() < p.x()) ) return !(q.x() < r.x());
00057   if ( CGAL_NTS certainly(p.y() < q.y()) ) return !(r.y() < q.y());
00058   if ( CGAL_NTS certainly(q.y() < p.y()) ) return !(q.y() < r.y());
00059   
00060   if ( CGAL_NTS certainly(p.x() == q.x()) && CGAL_NTS certainly(p.y() == q.y())  ) return true;
00061   
00062   return Uncertain<bool>::indeterminate();
00063 }
00064 
00065 // Returns true IFF segments e0,e1 share the same supporting line
00066 template<class K>
00067 Uncertain<bool> are_edges_collinearC2( Segment_2<K> const& e0, Segment_2<K> const& e1 )
00068 {
00069   return   certified_collinearC2(e0.source(),e0.target(),e1.source())
00070          & certified_collinearC2(e0.source(),e0.target(),e1.target()) ;
00071 }
00072 
00073 // Returns true IFF the supporting lines for segments e0,e1 are parallel (or the same)
00074 template<class K>
00075 inline
00076 Uncertain<bool> are_edges_parallelC2( Segment_2<K> const& e0, Segment_2<K> const& e1 )
00077 {
00078   Uncertain<Sign> s = certified_sign_of_determinant2x2(e0.target().x() - e0.source().x()
00079                                                       ,e0.target().y() - e0.source().y()
00080                                                       ,e1.target().x() - e1.source().x()
00081                                                       ,e1.target().y() - e1.source().y()
00082                                                      ) ;
00083                                                      
00084   return ( s == Uncertain<Sign>(ZERO) ) ;
00085 }
00086 
00087 
00088 // Returns true IFF the parallel segments are equally oriented.
00089 // Precondition: the segments must be parallel.
00090 // the three points are along the same line, in any order.
00091 template<class K>
00092 inline
00093 Uncertain<bool> are_parallel_edges_equally_orientedC2( Segment_2<K> const& e0, Segment_2<K> const& e1 )
00094 {
00095   return CGAL_NTS certified_sign( (e0.target() - e0.source()) * (e1.target() - e1.source()) ) == POSITIVE;
00096 }
00097 
00098 
00099 // Returns true IFF segments e0,e1 share the same supporting line but do not overlap except at the vetices, and have the same orientation.
00100 // NOTE: If e1 goes back over e0 (a degenerate antenna or alley) this returns false.
00101 template<class K>
00102 Uncertain<bool> are_edges_orderly_collinearC2( Segment_2<K> const& e0, Segment_2<K> const& e1 )
00103 {
00104   return are_edges_collinearC2(e0,e1) & are_parallel_edges_equally_orientedC2(e0,e1);
00105 }
00106 
00107 template <class FT>
00108 inline
00109 Uncertain<Sign> certified_side_of_oriented_lineC2(const FT &a, const FT &b, const FT &c, const FT &x, const FT &y)
00110 {
00111   return CGAL_NTS certified_sign(a*x+b*y+c);
00112 }
00113 
00114 
00115 //
00116 // Constructs a Trisegment_2 which stores 3 edges (segments) such that
00117 // if two of them are collinear, they are put first, as e0, e1.
00118 // Stores also the number of collinear edges. which should be 0 or 2.
00119 //
00120 // If the collinearity test is indeterminate for any pair of edges the
00121 // resulting sorted trisegment is itself indeterminate 
00122 // (encoded as a collinear count of -1)
00123 //
00124 template<class K>
00125 Uncertain<Trisegment_collinearity> certified_trisegment_collinearity ( Segment_2<K> const& e0
00126                                                                      , Segment_2<K> const& e1
00127                                                                      , Segment_2<K> const& e2
00128                                                                      )
00129 {
00130   Uncertain<bool> is_01 = are_edges_orderly_collinearC2(e0,e1);
00131   if ( is_certain(is_01) )
00132   {
00133     Uncertain<bool> is_02 = are_edges_orderly_collinearC2(e0,e2);
00134     if ( is_certain(is_02) )
00135     {
00136       Uncertain<bool> is_12 = are_edges_orderly_collinearC2(e1,e2);
00137       if ( is_certain(is_12) )
00138       {
00139         if ( CGAL_NTS logical_and(is_01 , !is_02 , !is_12 ) )
00140           return TRISEGMENT_COLLINEARITY_01;
00141         else if ( CGAL_NTS logical_and(is_02 , !is_01 , !is_12 ) )
00142           return TRISEGMENT_COLLINEARITY_02;
00143         else if ( CGAL_NTS logical_and(is_12 , !is_01 , !is_02 ) )
00144           return TRISEGMENT_COLLINEARITY_12;
00145         else if ( CGAL_NTS logical_and(!is_01 , !is_02, !is_12  ) )
00146           return TRISEGMENT_COLLINEARITY_NONE;
00147         else 
00148           return TRISEGMENT_COLLINEARITY_ALL;
00149       }
00150     }
00151   }
00152 
00153   return Uncertain<Trisegment_collinearity>::indeterminate();
00154 }
00155 
00156 
00157 
00158 // Given 3 oriented straight line segments: e0, e1, e2 
00159 // returns true if there exist some positive offset distance 't' for which the
00160 // leftward-offsets of their supporting lines intersect at a single point.
00161 //
00162 // NOTE: This function can handle the case of collinear and/or parallel segments.
00163 //
00164 // If two segments are collinear but equally oriented (that is, they share a degenerate vertex) the event exists and
00165 // is well defined, In that case, the degenerate vertex can be even a contour vertex or a skeleton node. If it is a skeleton
00166 // node, it is properly defined by the trisegment tree that corresponds to the node.
00167 // A trisegment tree stores not only the "current event" trisegment but also the trisegments for the left/right seed vertices,
00168 // recursivey in case the seed vertices are skeleton nodes as well.
00169 // Those seeds are used to determine the actual position of the degenerate vertex in case of collinear edges (since that point is
00170 // not given by the collinear edges alone)
00171 //
00172 template<class K, class FT>
00173 Uncertain<bool> exist_offset_lines_isec2 ( intrusive_ptr< Trisegment_2<K> > const& tri, optional<FT> const& aMaxTime )
00174 {
00175   
00176   typedef Rational<FT>       Rational ;
00177   typedef optional<Rational> Optional_rational ;
00178   typedef Quotient<FT>       Quotient ;
00179   
00180   Uncertain<bool> rResult = Uncertain<bool>::indeterminate();
00181 
00182   if ( tri->collinearity() != TRISEGMENT_COLLINEARITY_ALL ) 
00183   {
00184     CGAL_STSKEL_TRAITS_TRACE( ( tri->collinearity() == TRISEGMENT_COLLINEARITY_NONE ? " normal edges" : " collinear edges" ) ) ;
00185 
00186     Optional_rational t = compute_offset_lines_isec_timeC2(tri) ;
00187     if ( t )
00188     {
00189       Uncertain<bool> d_is_zero = CGAL_NTS certified_is_zero(t->d()) ;
00190       if ( is_certain(d_is_zero) )
00191       {
00192         if ( !d_is_zero )
00193         {
00194           Quotient tq = t->to_quotient() ;
00195           
00196           rResult = CGAL_NTS certified_is_positive(tq) ;
00197           
00198           if ( aMaxTime && CGAL_NTS certainly(rResult) )
00199             rResult = CGAL_NTS certified_is_smaller_or_equal(tq,Quotient(*aMaxTime));
00200           
00201           CGAL_STSKEL_TRAITS_TRACE("\nEvent time: " << *t << ". Event " << ( rResult ? "exist." : "doesn't exist." ) ) ;
00202         }
00203         else
00204         {
00205           CGAL_STSKEL_TRAITS_TRACE("\nDenominator exactly zero, Event doesn't exist." ) ;
00206           rResult = false;
00207         }
00208       }
00209       else
00210         CGAL_STSKEL_TRAITS_TRACE("\nDenominator is probably zero (but not exactly), event existance is indeterminate." ) ;
00211     }
00212     else
00213       CGAL_STSKEL_TRAITS_TRACE("\nEvent time overflowed, event existance is indeterminate." ) ;
00214   }
00215   else
00216   {
00217     CGAL_STSKEL_TRAITS_TRACE("\nAll the edges are collinear. Event doesn't exist." ) ;
00218     rResult = false;
00219   }
00220 
00221   return rResult ;
00222 }
00223 
00224 // Given 2 triples of oriented straight line segments: (m0,m1,m2) and (n0,n1,n2), such that
00225 // for each triple there exists distances 'mt' and 'nt' for which the offsets lines (at mt and nt resp.),
00226 // (m0',m1',m2') and (n0',n1',n2') intersect each in a single point; returns the relative order of mt w.r.t nt.
00227 // That is, indicates which offset triple intersects first (closer to the source lines)
00228 // PRECONDITION: There exist distances mt and nt for which each offset triple intersect at a single point.
00229 template<class K>
00230 Uncertain<Comparison_result> compare_offset_lines_isec_timesC2 ( intrusive_ptr< Trisegment_2<K> > const& m
00231                                                                , intrusive_ptr< Trisegment_2<K> > const& n 
00232                                                                )
00233 {
00234   typedef typename K::FT FT ;
00235   
00236   typedef Trisegment_2<K> Trisegment_2 ;
00237   
00238   typedef Rational<FT>       Rational ;
00239   typedef Quotient<FT>       Quotient ;
00240   typedef optional<Rational> Optional_rational ;
00241   
00242   Uncertain<Comparison_result> rResult = Uncertain<Comparison_result>::indeterminate();
00243 
00244   Optional_rational mt_ = compute_offset_lines_isec_timeC2(m);
00245   Optional_rational nt_ = compute_offset_lines_isec_timeC2(n);
00246   
00247   if ( mt_ && nt_ )
00248   {
00249     Quotient mt = mt_->to_quotient();
00250     Quotient nt = nt_->to_quotient();
00251    
00252     if ( CGAL_NTS certified_is_positive(mt) && CGAL_NTS certified_is_positive(nt) ) 
00253       rResult = CGAL_NTS certified_compare(mt,nt);
00254   }
00255   
00256   return rResult ;
00257 
00258 }
00259 
00260 
00261 // Returns true if the point aP is on the positive side of the line supporting the edge
00262 //
00263 template<class K>
00264 Uncertain<bool> is_edge_facing_pointC2 ( optional< Point_2<K> > const& aP, Segment_2<K> const& aEdge )
00265 {
00266   typedef typename K::FT FT ;
00267   
00268   Uncertain<bool> rResult = Uncertain<bool>::indeterminate();
00269   if ( aP )
00270   {
00271     FT a,b,c ;
00272     line_from_pointsC2(aEdge.source().x(),aEdge.source().y(),aEdge.target().x(),aEdge.target().y(),a,b,c); 
00273     rResult = certified_side_of_oriented_lineC2(a,b,c,aP->x(),aP->y()) == make_uncertain(POSITIVE) ;
00274   }
00275   return rResult ;
00276 }
00277 
00278 // Given a triple of oriented straight line segments: (e0,e1,e2) such that their offsets
00279 // at some distance intersects in a point (x,y), returns true if (x,y) is on the positive side of the line supporting aEdge
00280 //
00281 template<class K>
00282 inline Uncertain<bool> is_edge_facing_offset_lines_isecC2 ( intrusive_ptr< Trisegment_2<K> > const& tri, Segment_2<K> const& aEdge )
00283 {
00284   return is_edge_facing_pointC2(construct_offset_lines_isecC2(tri),aEdge);
00285 }
00286 
00287 // Given an event trisegment and two oriented straight line segments e0 and e1, returns the oriented side of the event point 
00288 // w.r.t the (positive) bisector [e0,e1].
00289 //
00290 // The (positive) bisector [e0,e1] is a ray starting at the vertex (e0,e1) (called "v01")
00291 // 
00292 // If e0,e1 are consecutive in the input polygon, v01 = e0.target() = e1.source().
00293 // If they are not consecutive in the input polygon they must had become consecutive at some known previous event. In this
00294 // case, the point of the "v01_event" trisegment intersection determines v01 which is to the position of the very first
00295 // vertex shared between e0,e1 (at the time they first become consecutive).
00296 //
00297 // A point *exactly on* the bisector is an offset vertex (e0*,e1*) (that is, belongs to both e0* and e1*). 
00298 // A point to the positive side of the bisector belongs to e0* but not e1*
00299 // A point to the negative side of the bisector belongs to e1* but not e0*
00300 //
00301 // If e0,e1 intersect in a single point the bisector is an angular bisector.
00302 //
00303 // One of e0 or e1 is considered the primary edge.
00304 //
00305 // If e0,e1 are parallel a line perpendicular to the primary edge passing through "v01" is used "as bisector". 
00306 //
00307 // If e0,e1 are collinear then this perpendicular line is a perpendicular bisector of the two segments.
00308 // 
00309 // If e0,e1 are parallel but not collinear then the actual bisector is an equidistant line parallel to e0 and e1.
00310 // e0* and e1* overlap and are known to be connected sharing a known vertex v01, which is somewhere along the parallel
00311 // line which is the bisector of e0 and e1. 
00312 // Given a line perpendicular to e0 through v01, a point to its positive side belongs to e0* while a point to its negative side does not.
00313 // Given a line perpendicular to e1 through v01, a point to its negative side belongs to e1* while a point to its positive side does not.
00314 //
00315 // This predicate is used to determine the validity of a split or edge event.
00316 // 
00317 // A split event is the coallision of a reflex wavefront and some opposite offset egde. Unless the three segments
00318 // don't actually collide (there is no event), the split point is along the supporting line of the offset edge.
00319 // Testing its validity amounts to determining if the split point is inside the closed offset segment instead of 
00320 // the two open rays before and after the offset segment endpoints.
00321 // The offset edge is bounded by its previous and next adjacent edges at the time of the event. Thus, the bisectors
00322 // of this edge and its previous/next adjacent edges (at the time of the event) detemine the offset vertices that
00323 // bound the opposite edge.
00324 // If the opposite edge is 'e' and its previous/next edges are "preve"/"nexte" then the split point is inside the offset
00325 // egde if it is NOT to the positive side of [preve,e] *and* NOT to the negative side o [e,nexte].
00326 // (so this predicate answer half the question, at one and other side independenty).
00327 // If the split point is exacty over any of this bisectors then the split point ocurres exactly and one (or both) endpoints
00328 // of the opposite edge (so it is a pseudo-split event since the opposite edge is not itself split in two halfeves)
00329 // When this predicate is called to test (prev,e), e is the primary edge but since it is  pass as e1, primary_is_0=false. 
00330 // This causes the case of parallel but not collinear edges to return positive when the split point is before the source point of e*
00331 // (a positive result means invalid split).
00332 // Likewise, primary_is_0 must be true when testing (e,nexte) to return negative if the split point is past the target endpoint of e*.
00333 // (in the other cases there is no need to discrminate which is 'e' in the call since the edjes do not overlap).
00334 //
00335 // An edge event is a coallision of three *consecutive* edges, say, e1,e2 and e3.
00336 // The coallision causes e2 (the edge in the middle) to collapse and e1,e3 to become consecutive and form a new vertex.
00337 // In all cases there is an edge before e1, say e0, and after e3, say e4.
00338 // Testing for the validity of an edge event amounts to determine that (e1,e3) (the new vertex) is not before (e0,e1) nor
00339 // past (e3,e4). 
00340 // Thus, and edge event is valid if the new vertex NOT to the positive side of [e0,e1] *and* NOT to the negative side o [e3,e4].
00341 //
00342 // PRECONDITIONS:
00343 //   There exist a single point 'p' corresponding to the event as given by the trisegment
00344 //   e0 and e1 are known to be consectuve at the time of the event (even if they are not consecutive in the input polygon)
00345 //   If e0 and e1 are not consecutive in the input, v01_event is the event that defined they very first offset vertex.
00346 //   If e0 and e1 are consecutive, v01_event is null.
00347 //
00348 template<class K>
00349 Uncertain<Oriented_side>
00350 oriented_side_of_event_point_wrt_bisectorC2 ( intrusive_ptr< Trisegment_2<K> > const& event
00351                                             , Segment_2<K>                     const& e0
00352                                             , Segment_2<K>                     const& e1
00353                                             , intrusive_ptr< Trisegment_2<K> > const& v01_event // can be null
00354                                             , bool                                    primary_is_0
00355                                             )
00356 {
00357   typedef typename K::FT FT ;
00358   
00359   typedef Point_2     <K> Point_2 ;
00360   typedef Line_2      <K> Line_2 ;
00361   typedef Trisegment_2<K> Trisegment_2 ;
00362   
00363   Uncertain<Oriented_side> rResult = Uncertain<Oriented_side>::indeterminate();
00364   
00365   try
00366   {
00367     Point_2 p = validate(construct_offset_lines_isecC2(event));
00368     
00369     Line_2 l0 = validate(compute_normalized_line_ceoffC2(e0)) ;
00370     Line_2 l1 = validate(compute_normalized_line_ceoffC2(e1)) ;
00371   
00372     CGAL_STSKEL_TRAITS_TRACE("Getting oriented side of point " << p2str(p)
00373                             << " w.r.t bisector ["
00374                             << s2str(e0) << ( primary_is_0 ? "*" : "" )
00375                             << "," 
00376                             << s2str(e1) << ( primary_is_0 ? "" : "*" )
00377                             << "]"
00378                             ) ; 
00379       
00380     // Degenerate bisector?   
00381     if ( certainly( are_edges_parallelC2(e0,e1) ) )
00382     { 
00383       CGAL_STSKEL_TRAITS_TRACE("Bisector is not angular." ) ;
00384       
00385       // b01 is degenerate so we don't have an *angular bisector* but a *perpendicular* bisector.
00386       // We need to compute the actual bisector line.
00387       CGAL_assertion( v01_event || ( !v01_event && e0.target() == e1.source() ) ) ;
00388       
00389       Point_2 v01 = v01_event ? validate( construct_offset_lines_isecC2(v01_event) ) : e1.source() ;
00390       
00391       CGAL_STSKEL_TRAITS_TRACE("v01=" << p2str(v01) << ( v01_event ? " (from skelton node)" : "" ) ) ;      
00392       
00393       // (a,b,c) is a line perpedincular to the primary edge through v01.
00394       // If e0 and e1 are collinear this line is the actual perpendicular bisector.
00395       //
00396       // If e0 and e1 are parallel but not collinear (then neccesarrily facing each other) this line
00397       // is NOT the bisector, but the serves to determine the side of the point (projected along the primary ege) w.r.t vertex v01.
00398       
00399       FT a, b, c ;
00400       perpendicular_through_pointC2( primary_is_0 ? l0.a() : l1.a()
00401                                    , primary_is_0 ? l0.b() : l1.b()
00402                                    , v01.x(), v01.y()
00403                                    , a, b, c
00404                                    );
00405       
00406       rResult = certified_side_of_oriented_lineC2(a,b,c,p.x(),p.y());
00407       
00408       CGAL_STSKEL_TRAITS_TRACE("Point is at " << rResult << " side of degenerate bisector through v01 " << p2str(v01)) ;
00409     }
00410     else // Valid (non-degenerate) angular bisector
00411     {
00412       // Scale distance from to the lines.
00413       FT sd_p_l0 = validate(l0.a() * p.x() + l0.b() * p.y() + l0.c()) ;
00414       FT sd_p_l1 = validate(l1.a() * p.x() + l1.b() * p.y() + l1.c()) ;
00415       
00416       CGAL_STSKEL_TRAITS_TRACE("sd_p_l1=" << n2str(sd_p_l1) ) ;
00417       CGAL_STSKEL_TRAITS_TRACE("sd_p_l0=" << n2str(sd_p_l0) ) ;
00418         
00419       Uncertain<bool> equal = CGAL_NTS certified_is_equal(sd_p_l0,sd_p_l1) ;   
00420       if ( is_certain(equal) )
00421       {
00422         if ( equal )
00423         {
00424           CGAL_STSKEL_TRAITS_TRACE("Point is exactly at bisector"); 
00425           
00426           rResult = ON_ORIENTED_BOUNDARY;
00427         }
00428         else
00429         {
00430           Uncertain<bool> smaller = CGAL_NTS certified_is_smaller( validate(l0.a()*l1.b()), validate(l1.a()*l0.b()) ) ;
00431           if ( is_certain(smaller) )
00432           {
00433             // Reflex bisector?
00434             if ( smaller )
00435             {
00436               rResult = CGAL_NTS certified_is_smaller(sd_p_l0,sd_p_l1) ? ON_NEGATIVE_SIDE 
00437                                                                        : ON_POSITIVE_SIDE ;
00438                                                                       
00439               CGAL_STSKEL_TRAITS_TRACE("\nEvent point is at " << rResult << " side of reflex bisector" ) ;
00440             }
00441             else
00442             {
00443               rResult = CGAL_NTS certified_is_larger (sd_p_l0,sd_p_l1) ? ON_NEGATIVE_SIDE
00444                                                                        : ON_POSITIVE_SIDE ; 
00445                               
00446               CGAL_STSKEL_TRAITS_TRACE("\nEvent point is at " << rResult << " side of convex bisector" ) ;
00447             }
00448           }
00449         }
00450       }
00451     }
00452   }
00453   catch( std::overflow_error const& )
00454   {
00455     CGAL_STSKEL_TRAITS_TRACE("Unable to compute value due to overflow.");
00456   }
00457   catch( CGAL::Uncertain_conversion_exception const& )
00458   {
00459     CGAL_STSKEL_TRAITS_TRACE("Indeterminate boolean expression.");
00460   }
00461   
00462   return rResult ;
00463 
00464 }
00465 
00466 
00467 // Given 2 triples of oriented straight line segments (l0,l1,l2) and (r0,r1,r2), such that 
00468 // the offsets at time 'tl' for triple 'l' intersects in a point (lx,ly) and 
00469 // the offsets at time 'tr' for triple 'r' intersects in a point (rx,ry) 
00470 // returns true if "tl==tr" and "(lx,ly)==(rx,ry)" 
00471 // PRECONDITIONS:
00472 //   There exist single points at which the offset lines for 'l' and 'r' at 'tl', 'tr' intersect.
00473 //
00474 template<class K>
00475 Uncertain<bool> are_events_simultaneousC2 ( intrusive_ptr< Trisegment_2<K> > const& l, intrusive_ptr< Trisegment_2<K> > const& r )
00476 {
00477   typedef typename K::FT FT ;
00478   
00479   typedef Point_2<K> Point_2 ;
00480   typedef Line_2<K>  Line_2 ;
00481   
00482   typedef Trisegment_2<K> Trisegment_2 ;
00483   
00484   typedef Rational<FT> Rational ;
00485   typedef Quotient<FT> Quotient ;
00486   
00487   typedef optional<Rational> Optional_rational ;
00488   typedef optional<Point_2>  Optional_point_2 ;
00489   
00490   Uncertain<bool> rResult = Uncertain<bool>::indeterminate();
00491 
00492   Optional_rational lt_ = compute_offset_lines_isec_timeC2(l);
00493   Optional_rational rt_ = compute_offset_lines_isec_timeC2(r);
00494   
00495   if ( lt_ && rt_ )
00496   {
00497     Quotient lt = lt_->to_quotient();
00498     Quotient rt = rt_->to_quotient();
00499 
00500     if ( CGAL_NTS certified_is_positive(lt) && CGAL_NTS certified_is_positive(rt) ) 
00501     {
00502       Uncertain<bool> equal_times = CGAL_NTS certified_is_equal(lt,rt);
00503       
00504       if ( is_certain(equal_times) )
00505       {
00506         if ( equal_times )
00507         {
00508           Optional_point_2 li = construct_offset_lines_isecC2(l);
00509           Optional_point_2 ri = construct_offset_lines_isecC2(r);
00510   
00511           if ( li && ri )
00512             rResult = CGAL_NTS logical_and( CGAL_NTS certified_is_equal(li->x(),ri->x())
00513                                           , CGAL_NTS certified_is_equal(li->y(),ri->y())
00514                                           ) ;
00515         }
00516         else rResult = false;
00517       }
00518     }
00519 
00520   }
00521   return rResult;
00522 }
00523 
00524 } // namespace CGAL_SS_i
00525 
00526 CGAL_END_NAMESPACE
00527 
00528 #endif // CGAL_STRAIGHT_SKELETON_PREDICATES_FTC2_H //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines