BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/constructions/Straight_skeleton_cons_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/constructions/Straight_skeleton_cons_ftC2.h $
00014 // $Id: Straight_skeleton_cons_ftC2.h 45683 2008-09-22 20:23:41Z fcacciola $
00015 //
00016 // Author(s)     : Fernando Cacciola <fernando_cacciola@ciudad.com.ar>
00017 //
00018 #ifndef CGAL_STRAIGHT_SKELETON_CONS_FTC2_H
00019 #define CGAL_STRAIGHT_SKELETON_CONS_FTC2_H 1
00020 
00021 CGAL_BEGIN_NAMESPACE 
00022 
00023 namespace CGAL_SS_i
00024 {
00025 
00026 #ifdef CGAL_USE_CORE  
00027 
00028 template<class NT>
00029 inline CORE::BigFloat to_BigFloat( NT const& n )
00030 {
00031   return CORE::BigFloat( CGAL::to_double(n) ) ;
00032 }
00033 
00034 template<>
00035 inline CORE::BigFloat to_BigFloat<MP_Float>( MP_Float const& b )
00036 {
00037   if (b.is_zero())
00038     return CORE::BigFloat::getZero();
00039     
00040   typedef MP_Float::exponent_type exponent_type;
00041 
00042   const int                    log_limb         = 8 * sizeof(MP_Float::limb);
00043   const MP_Float::V::size_type limbs_per_double = 2 + 53/log_limb;
00044     
00045   exponent_type exp = b.max_exp();
00046   int steps = (std::min)(limbs_per_double, b.v.size());
00047   
00048   CORE::BigFloat d_exp_1 = CORE::BigFloat::exp2(-log_limb);
00049   
00050   CORE::BigFloat d_exp   = CORE::BigFloat::getOne() ;
00051   
00052   CORE::BigFloat d       = CORE::BigFloat::getZero();
00053 
00054   for ( exponent_type i = exp - 1; i > exp - 1 - steps; i--) 
00055   {
00056     d_exp *= d_exp_1;
00057     d += d_exp * CORE::BigFloat(b.of_exp(i));
00058   }
00059 
00060   return d * CORE::BigFloat::exp2( static_cast<int>(exp * log_limb) );
00061 }
00062 
00063 
00064 #endif
00065 
00066 
00067 
00068 template<class NT> 
00069 inline NT inexact_sqrt_implementation( NT const& n, CGAL::Null_functor no_sqrt )
00070 {
00071 
00072 #ifdef CGAL_USE_CORE
00073 
00074   CORE::BigFloat nn = to_BigFloat(n) ;
00075   CORE::BigFloat s  = CORE::sqrt(nn);
00076   return NT(s.doubleValue());
00077   
00078 #else
00079 
00080   double nn = CGAL::to_double(n) ;
00081   
00082   if ( !CGAL_NTS is_valid(nn) || ! CGAL_NTS is_finite(nn) )
00083     nn = std::numeric_limits<double>::max BOOST_PREVENT_MACRO_SUBSTITUTION () ;
00084     
00085   CGAL_precondition(nn > 0);
00086   
00087   double s = CGAL_NTS sqrt(nn);
00088   
00089   return NT(s);
00090   
00091 #endif
00092 }
00093 
00094 template<class NT, class Sqrt>
00095 inline NT inexact_sqrt_implementation( NT const& n, Sqrt sqrt_f )
00096 {
00097   return sqrt_f(n);
00098 }
00099 
00100 template<class NT>
00101 inline NT inexact_sqrt( NT const& n )
00102 {
00103   typedef CGAL::Algebraic_structure_traits<NT> AST;
00104   typedef typename AST::Sqrt Sqrt; 
00105   return inexact_sqrt_implementation(n,Sqrt());
00106 }
00107 
00108 inline Quotient<MP_Float> inexact_sqrt( Quotient<MP_Float> const& q )
00109 {
00110   CGAL_precondition(q > 0);
00111   return Quotient<MP_Float>(CGAL_SS_i::inexact_sqrt(q.numerator()*q.denominator()), q.denominator() );
00112 }
00113 
00114 
00115 // Given an oriented 2D straight line segment 'e', computes the normalized coefficients (a,b,c) of the
00116 // supporting line.
00117 // POSTCONDITION: [a,b] is the leftward normal _unit_ (a�+b�=1) vector.
00118 // POSTCONDITION: In case of overflow, an empty optional<> is returned.
00119 template<class K>
00120 optional< Line_2<K> > compute_normalized_line_ceoffC2( Segment_2<K> const& e )
00121 {
00122   bool finite = true ;
00123   
00124   typedef typename K::FT FT ;
00125   
00126   FT a (0.0),b (0.0) ,c(0.0)  ;
00127 
00128   if(e.source().y() == e.target().y())
00129   {
00130     a = 0 ;
00131     if(e.target().x() > e.source().x())
00132     {
00133       b = 1;
00134       c = -e.source().y();
00135     }
00136     else if(e.target().x() == e.source().x())
00137     {
00138       b = 0;
00139       c = 0;
00140     }
00141     else
00142     {
00143       b = -1;
00144       c = e.source().y();
00145     }
00146 
00147     CGAL_STSKEL_TRAITS_TRACE("Line coefficients for HORIZONTAL line:\n" 
00148                             << s2str(e) 
00149                             << "\na="<< n2str(a) << ", b=" << n2str(b) << ", c=" << n2str(c)
00150                            ) ;
00151   }
00152   else if(e.target().x() == e.source().x())
00153   {
00154     b = 0;
00155     if(e.target().y() > e.source().y())
00156     {
00157       a = -1;
00158       c = e.source().x();
00159     }
00160     else if (e.target().y() == e.source().y())
00161     {
00162       a = 0;
00163       c = 0;
00164     }
00165     else
00166     {
00167       a = 1;
00168       c = -e.source().x();
00169     }
00170 
00171     CGAL_STSKEL_TRAITS_TRACE("Line coefficients for VERTICAL line:\n"
00172                             << s2str(e) 
00173                             << "\na="<< n2str(a) << ", b=" << n2str(b) << ", c=" << n2str(c)
00174                            ) ;
00175   }
00176   else
00177   {
00178     FT sa = e.source().y() - e.target().y();
00179     FT sb = e.target().x() - e.source().x();
00180     FT l2 = (sa*sa) + (sb*sb) ;
00181 
00182     if ( CGAL_NTS is_finite(l2) )
00183     {
00184       FT l = CGAL_SS_i :: inexact_sqrt(l2);
00185   
00186       a = sa / l ;
00187       b = sb / l ;
00188   
00189       c = -e.source().x()*a - e.source().y()*b;
00190       
00191       CGAL_STSKEL_TRAITS_TRACE("Line coefficients for line:\n"
00192                                << s2str(e) 
00193                                << "\nsa="<< n2str(sa) << "\nsb=" << n2str(sb) << "\nl2=" << n2str(l2) << "\nl=" << n2str(l)
00194                                << "\na="<< n2str(a) << "\nb=" << n2str(b) << "\nc=" << n2str(c)
00195                                ) ;
00196     }
00197     else finite = false ;
00198     
00199   }
00200   
00201   if ( finite )
00202     if ( !CGAL_NTS is_finite(a) || !CGAL_NTS is_finite(b) || !CGAL_NTS is_finite(c) ) 
00203       finite = false ;
00204 
00205   return cgal_make_optional( finite, K().construct_line_2_object()(a,b,c) ) ;
00206 }
00207 
00208 template<class FT>
00209 Rational<FT> squared_distance_from_point_to_lineC2( FT const& px, FT const& py, FT const& sx, FT const& sy, FT const& tx, FT const& ty )
00210 {
00211   FT ldx = tx - sx ;
00212   FT ldy = ty - sy ;
00213   FT rdx = sx - px ;
00214   FT rdy = sy - py ;
00215   
00216   FT n = CGAL_NTS square(ldx * rdy - rdx * ldy);
00217   FT d = CGAL_NTS square(ldx) + CGAL_NTS square(ldy);
00218   
00219   return Rational<FT>(n,d) ;
00220 }
00221 
00222 //
00223 // Constructs a Trisegment_2 which stores 3 oriented straight line segments e0,e1,e2 along with their collinearity.
00224 //
00225 // NOTE: If the collinearity cannot be determined reliably, a null trisegment is returned.
00226 //
00227 template<class K>
00228 intrusive_ptr< Trisegment_2<K> > construct_trisegment ( Segment_2<K> const& e0
00229                                                       , Segment_2<K> const& e1
00230                                                       , Segment_2<K> const& e2
00231                                                       )
00232 {
00233   typedef Trisegment_2<K>                 Trisegment_2 ;
00234   typedef typename Trisegment_2::Self_ptr Trisegment_2_ptr ;
00235   
00236   Uncertain<Trisegment_collinearity> lCollinearity = certified_trisegment_collinearity(e0,e1,e2);
00237   
00238   if (is_certain(lCollinearity) ) 
00239        return Trisegment_2_ptr( new Trisegment_2(e0, e1, e2, lCollinearity) ) ;
00240   else return Trisegment_2_ptr();
00241 }
00242 
00243 // Given 3 oriented straight line segments: e0, e1, e2 
00244 // returns the OFFSET DISTANCE (n/d) at which the offsetted lines
00245 // intersect at a single point, IFF such intersection exist.
00246 // If the lines intersect to the left, the returned distance is positive.
00247 // If the lines intersect to the right, the returned distance is negative.
00248 // If the lines do not intersect, for example, for collinear edges, or parallel edges but with the same orientation,
00249 // returns 0 (the actual distance is undefined in this case, but 0 is a usefull return)
00250 //
00251 // NOTE: The result is a explicit rational number returned as a tuple (num,den); the caller must check that den!=0 manually
00252 // (a predicate for instance should return indeterminate in this case)
00253 //
00254 // PRECONDITION: None of e0, e1 and e2 are collinear (but two of them can be parallel)
00255 //
00256 // POSTCONDITION: In case of overflow an empty optional is returned.
00257 //
00258 // NOTE: The segments (e0,e1,e2) are stored in the argument as the trisegment st.event()
00259 //
00260 template<class K>
00261 optional< Rational< typename K::FT> > compute_normal_offset_lines_isec_timeC2 ( intrusive_ptr< Trisegment_2<K> > const& tri )
00262 {
00263   typedef typename K::FT  FT ;
00264   
00265   typedef Line_2<K> Line_2 ;
00266   
00267   typedef optional<Line_2> Optional_line_2 ;
00268   
00269   CGAL_STSKEL_TRAITS_TRACE("Computing normal offset lines isec time for: " << tri ) ;
00270   
00271   FT num(0.0), den(0.0) ;
00272   
00273   // DETAILS:
00274   //
00275   // An offset line is given by:
00276   //
00277   //   a*x(t) + b*y(t) + c - t = 0
00278   //
00279   // were 't > 0' being to the left of the line.
00280   // If 3 such offset lines intersect at the same offset distance, the intersection 't',
00281   // or 'time', can be computed solving for 't' in the linear system formed by 3 such equations.
00282   // The result is :
00283   //
00284   //  t = a2*b0*c1 - a2*b1*c0 - b2*a0*c1 + b2*a1*c0 + b1*a0*c2 - b0*a1*c2
00285   //      ---------------------------------------------------------------
00286   //             -a2*b1 + a2*b0 + b2*a1 - b2*a0 + b1*a0 - b0*a1 ;
00287 
00288   bool ok = false ;
00289   
00290   Optional_line_2 l0 = compute_normalized_line_ceoffC2(tri->e0()) ;
00291   Optional_line_2 l1 = compute_normalized_line_ceoffC2(tri->e1()) ;
00292   Optional_line_2 l2 = compute_normalized_line_ceoffC2(tri->e2()) ;
00293 
00294   if ( l0 && l1 && l2 )
00295   {
00296     num = (l2->a()*l0->b()*l1->c())
00297          -(l2->a()*l1->b()*l0->c())
00298          -(l2->b()*l0->a()*l1->c())
00299          +(l2->b()*l1->a()*l0->c())
00300          +(l1->b()*l0->a()*l2->c())
00301          -(l0->b()*l1->a()*l2->c());
00302       
00303     den = (-l2->a()*l1->b())
00304          +( l2->a()*l0->b())
00305          +( l2->b()*l1->a())
00306          -( l2->b()*l0->a())
00307          +( l1->b()*l0->a())
00308          -( l0->b()*l1->a());
00309          
00310     ok = CGAL_NTS is_finite(num) && CGAL_NTS is_finite(den);     
00311   }
00312   
00313   CGAL_STSKEL_TRAITS_TRACE("Event time (normal): n=" << num << " d=" << den << " n/d=" << Rational<FT>(num,den)  )
00314 
00315   return cgal_make_optional(ok,Rational<FT>(num,den)) ;
00316 }
00317 
00318 // Given two oriented straight line segments e0 and e1 such that e-next follows e-prev, returns
00319 // the coordinates of the midpoint of the segment between e-prev and e-next.
00320 // NOTE: the edges can be oriented e0->e1 or e1->e0
00321 //
00322 // POSTCONDITION: In case of overflow an empty optional is returned.
00323 //
00324 template<class K>
00325 optional< Point_2<K> > compute_oriented_midpoint ( Segment_2<K> const& e0, Segment_2<K> const& e1 )
00326 {
00327   bool ok = false ;
00328   
00329   typedef typename K::FT FT ;
00330   
00331   FT delta01 = CGAL::squared_distance(e0.target(),e1.source());
00332   FT delta10 = CGAL::squared_distance(e1.target(),e0.source());
00333   
00334   Point_2<K> mp ;
00335    
00336   if ( CGAL_NTS is_finite(delta01) &&  CGAL_NTS is_finite(delta10) )
00337   {
00338     if ( delta01 <= delta10 )
00339          mp = CGAL::midpoint(e0.target(),e1.source());
00340     else mp = CGAL::midpoint(e1.target(),e0.source());
00341     
00342     CGAL_STSKEL_TRAITS_TRACE("Computing oriented midpoint between:"
00343                              << "\ne0: " << s2str(e0)
00344                              << "\ne1: " << s2str(e1)
00345                              << "\nmp=" << p2str(mp)
00346                             );
00347                             
00348     ok = CGAL_NTS is_finite(mp.x()) && CGAL_NTS is_finite(mp.y());
00349   }
00350   
00351   return cgal_make_optional(ok,mp);
00352 }
00353 
00354 
00355 //
00356 // Given 3 oriented straight line segments: e0, e1, e2 and the corresponding offseted segments: e0*, e1* and e2*,
00357 // returns the point of the left or right seed (offset vertex) (e0*,e1*) or (e1*,e2*) 
00358 // 
00359 // If the current event (defined by e0,e1,e2) is a propagated event, that is, it follows from a previous event,
00360 // the seeds are skeleten nodes and are given by non-null trisegments.
00361 // If the current event is an initial event the seeds are contour vertices and are given by null trisegmets.
00362 //
00363 // If a seed is a skeleton node, its point has to be computed from the trisegment that defines it.
00364 // That trisegment is exactly the trisegment tree that defined the previous event which produced the skeleton node
00365 // (so the trisegment tree is basically a lazy representation of the seed point).
00366 //
00367 // If a seed is a contour vertex, its point is then simply the target endoint of e0 or e1 (for the left/right seed).
00368 //
00369 // This method returns the specified seed point (left or right)
00370 //
00371 // NOTE: Split events involve 3 edges but only one seed, the left (that is, only e0*,e1* is connected before the event).
00372 // The trisegment tree for a split event has always a null right child even if the event is not an initial event
00373 // (in which case its left child won't be null).
00374 // If you ask for the right child point for a trisegment tree corresponding to a split event you will just get e1.target()
00375 // which is nonsensical for a non initial split event.
00376 //
00377 // NOTE: There is an abnormal collinearity case which ocurrs when e0 and e2 are collinear.
00378 // In this case, these lines do not correspond to an offset vertex (because e0* and e2* are never consecutive before the event),
00379 // so the degenerate seed is neither the left or the right seed. In this case, the SEED ID for the degenerate pseudo seed is UNKOWN.
00380 // If you request the point of such degenerate pseudo seed the oriented midpoint bettwen e0 and e2 is returned.
00381 //
00382 template<class K>
00383 optional< Point_2<K> > compute_seed_pointC2 ( intrusive_ptr< Trisegment_2<K> > const& tri, typename Trisegment_2<K>::SEED_ID sid )
00384 {
00385   optional< Point_2<K> > p ;
00386 
00387   typedef Trisegment_2<K> Trisegment_2 ;
00388     
00389   switch ( sid )
00390   {
00391     case Trisegment_2::LEFT :
00392          
00393        p = tri->child_l() ? construct_offset_lines_isecC2(tri->child_l())  // this can recurse
00394                           : compute_oriented_midpoint(tri->e0(),tri->e1()) ;
00395        break ;                     
00396              
00397     case Trisegment_2::RIGHT : 
00398     
00399       p = tri->child_r() ? construct_offset_lines_isecC2(tri->child_r()) // this can recurse
00400                          : compute_oriented_midpoint(tri->e1(),tri->e2()) ;
00401       break ;        
00402              
00403     case Trisegment_2::UNKNOWN : 
00404     
00405       p = compute_oriented_midpoint(tri->e0(),tri->e2());
00406       
00407       break ;
00408   }
00409   
00410   return p ;  
00411 }
00412 
00413 //
00414 // Given the trisegment tree for an event which is known to have a normal collinearity returns the seed point
00415 // of the degenerate seed.
00416 // A normal collinearity occurs when e0,e1 or e1,e2 are collinear.
00417 template<class K>
00418 optional< Point_2<K> > compute_degenerate_seed_pointC2 ( intrusive_ptr< Trisegment_2<K> > const& tri )
00419 {
00420   return compute_seed_pointC2( tri, tri->degenerate_seed_id() ) ;
00421 }
00422 
00423 // Given 3 oriented straight line segments: e0, e1, e2 
00424 // such that two and only two of these edges are collinear, not neccesarily consecutive but with the same orientaton;
00425 // returns the OFFSET DISTANCE (n/d) at which a line perpendicular to the collinear edge passing through
00426 // the degenerate seed point intersects the offset line of the non collinear edge
00427 //
00428 // NOTE: The result is a explicit rational number returned as a tuple (num,den); the caller must check that den!=0 manually
00429 // (a predicate for instance should return indeterminate in this case)
00430 //
00431 // POSTCONDITION: In case of overflow an empty optional is returned.
00432 //
00433 template<class K>
00434 optional< Rational< typename K::FT> > compute_degenerate_offset_lines_isec_timeC2 ( intrusive_ptr< Trisegment_2<K> > const& tri )
00435 {
00436   typedef typename K::FT FT ;
00437   
00438   typedef Point_2<K> Point_2 ;
00439   typedef Line_2 <K> Line_2 ;
00440   
00441   typedef optional<Point_2> Optional_point_2 ;
00442   typedef optional<Line_2>  Optional_line_2 ;
00443   
00444   CGAL_STSKEL_TRAITS_TRACE("Computing degenerate offset lines isec time for: " << tri ) ;
00445   
00446   // DETAILS:
00447   //
00448   // For simplicity, assume e0,e1 are the collinear edges.
00449   //
00450   //   (1)
00451   //   The bisecting line of e0 and e1 is a line perpendicular to e0 (and e1)
00452   //   which passes through 'q': the degenerate offset vertex (e0*,e1*)
00453   //   This "degenerate" bisecting line is given by:
00454   //
00455   //     B0(t) = p + t*[l0.a,l0.b]
00456   //
00457   //   where p is the projection of q along l0 and l0.a,l0.b are the _normalized_ line coefficients for e0 (or e1 which is the same)
00458   //   Since [a,b] is a _unit_ vector pointing perpendicularly to the left of e0 (and e1);
00459   //   any point B0(k) is at a distance k from the line supporting e0 and e1.
00460   //
00461   //   (2)
00462   //   The bisecting line of e0 and e2 is given by the following SEL
00463   //
00464   //    l0.a*x(t) + l0.b*y(t) + l0.c + t = 0
00465   //    l2.a*x(t) + l2.b*y(t) + l2.c + t = 0
00466   //
00467   //   where (l0.a,l0.b,l0.c) and (l2.a,l2.b,l0.c) are the normalized line coefficientes of e0 and e2 resp.
00468   //
00469   //     B1(t)=[x(t),y(t)]
00470   //
00471   //   (3)
00472   //   These two bisecting lines B0(t) and B1(t) intersect (if they do) in a single point 'p' whose distance
00473   //   to the lines supporting the 3 edges is exactly 't' (since those expressions are precisely parametrized in a distance)
00474   //   Solving the following vectorial equation:
00475   //
00476   //     [x(y),y(t)] = q + t*[l0.a,l0.b]
00477   //
00478   //   for t gives the result we want.
00479   //
00480   //
00481   bool ok = false ;
00482 
00483   Optional_line_2 l0 = compute_normalized_line_ceoffC2(tri->collinear_edge    ()) ;
00484   Optional_line_2 l2 = compute_normalized_line_ceoffC2(tri->non_collinear_edge()) ;
00485 
00486   Optional_point_2 q = compute_degenerate_seed_pointC2(tri);
00487   
00488   FT num(0.0), den(0.0) ;
00489 
00490   if ( l0 && l2 && q )
00491   {
00492     FT px, py ;
00493     line_project_pointC2(l0->a(),l0->b(),l0->c(),q->x(),q->y(),px,py); 
00494     
00495     CGAL_STSKEL_TRAITS_TRACE("Seed point: " << p2str(*q) << ".\nProjected seed point: (" << n2str(px) << "," << n2str(py) << ")" ) ;
00496     
00497     if ( ! CGAL_NTS is_zero(l0->b()) ) // Non-vertical
00498     {
00499       num = (l2->a() * l0->b() - l0->a() * l2->b() ) * px + l0->b() * l2->c() - l2->b() * l0->c() ;
00500       den = (l0->a() * l0->a() - 1) * l2->b() + ( 1 - l2->a() * l0->a() ) * l0->b() ;
00501       
00502       CGAL_STSKEL_TRAITS_TRACE("Event time (degenerate, non-vertical) n=" << n2str(num) << " d=" << n2str(den) << " n/d=" << Rational<FT>(num,den) )
00503     }
00504     else
00505     {
00506       num = (l2->a() * l0->b() - l0->a() * l2->b() ) * py - l0->a() * l2->c() + l2->a() * l0->c() ;
00507       den = l0->a() * l0->b() * l2->b() - l0->b() * l0->b() * l2->a() + l2->a() - l0->a() ;
00508       
00509       CGAL_STSKEL_TRAITS_TRACE("Event time (degenerate, vertical) n=" << n2str(num) << " d=" << n2str(den) << " n/d=" << Rational<FT>(num,den) )
00510     }
00511     
00512     ok = CGAL_NTS is_finite(num) && CGAL_NTS is_finite(den);     
00513   }
00514   
00515 
00516   return cgal_make_optional(ok,Rational<FT>(num,den)) ;
00517 }
00518 
00519 //
00520 // Calls the appropiate function depending on the collinearity of the edges.
00521 //
00522 template<class K>
00523 optional< Rational< typename K::FT > > compute_offset_lines_isec_timeC2 ( intrusive_ptr< Trisegment_2<K> > const& tri )
00524 {
00525   CGAL_precondition ( tri->collinearity() != TRISEGMENT_COLLINEARITY_ALL ) ;
00526  
00527   return tri->collinearity() == TRISEGMENT_COLLINEARITY_NONE ? compute_normal_offset_lines_isec_timeC2    (tri)
00528                                                              : compute_degenerate_offset_lines_isec_timeC2(tri);
00529 }
00530 
00531 
00532 // Given 3 oriented line segments e0, e1 and e2 
00533 // such that their offsets at a certian distance intersect in a single point, 
00534 // returns the coordinates (x,y) of such a point.
00535 //
00536 // PRECONDITIONS:
00537 // None of e0, e1 and e2 are collinear (but two of them can be parallel)
00538 // The line coefficients must be normalized: a�+b�==1 and (a,b) being the leftward normal vector
00539 // The offsets at a certain distance do intersect in a single point.
00540 //
00541 // POSTCONDITION: In case of overflow an empty optional is returned.
00542 //
00543 template<class K>
00544 optional< Point_2<K> > construct_normal_offset_lines_isecC2 ( intrusive_ptr< Trisegment_2<K> > const& tri )
00545 {
00546   typedef typename K::FT  FT ;
00547   
00548   typedef Point_2<K> Point_2 ;
00549   typedef Line_2<K>  Line_2 ;
00550   
00551   typedef optional<Line_2>  Optional_line_2 ;
00552   
00553   CGAL_STSKEL_TRAITS_TRACE("Computing normal offset lines isec point for: " << tri ) ;
00554   
00555   FT x(0.0),y(0.0) ;
00556   
00557   Optional_line_2 l0 = compute_normalized_line_ceoffC2(tri->e0()) ;
00558   Optional_line_2 l1 = compute_normalized_line_ceoffC2(tri->e1()) ;
00559   Optional_line_2 l2 = compute_normalized_line_ceoffC2(tri->e2()) ;
00560 
00561   bool ok = false ;
00562   
00563   if ( l0 && l1 && l2 )
00564   {
00565     FT den = l0->a()*l2->b() - l0->a()*l1->b() - l1->a()*l2->b() + l2->a()*l1->b() + l0->b()*l1->a() - l0->b()*l2->a();
00566   
00567     CGAL_STSKEL_TRAITS_TRACE("den=" << n2str(den) )
00568   
00569     if ( ! CGAL_NTS certified_is_zero(den) ) 
00570     {
00571       FT numX = l0->b()*l2->c() - l0->b()*l1->c() - l1->b()*l2->c() + l2->b()*l1->c() + l1->b()*l0->c() - l2->b()*l0->c();
00572       FT numY = l0->a()*l2->c() - l0->a()*l1->c() - l1->a()*l2->c() + l2->a()*l1->c() + l1->a()*l0->c() - l2->a()*l0->c();
00573     
00574       if ( CGAL_NTS is_finite(den) && CGAL_NTS is_finite(numX) && CGAL_NTS is_finite(numY)  )
00575       {
00576         ok = true ;
00577         
00578         x =  numX / den ;
00579         y = -numY / den ;
00580         
00581        CGAL_STSKEL_TRAITS_TRACE("numX=" << n2str(numX) << "\nnumY=" << n2str(numY)
00582                                << "\nx=" << n2str(x) << "\ny=" << n2str(y)
00583                                )
00584       }
00585     }
00586   }
00587     
00588     
00589   return cgal_make_optional(ok,K().construct_point_2_object()(x,y)) ;
00590 }
00591 
00592 // Given 3 oriented line segments e0, e1 and e2
00593 // such that their offsets at a certian distance intersect in a single point, 
00594 // returns the coordinates (x,y) of such a point.
00595 // two and only two of the edges are collinear, not neccesarily consecutive but with the same orientaton
00596 //
00597 // PRECONDITIONS:
00598 // The line coefficients must be normalized: a�+b�==1 and (a,b) being the leftward normal vector
00599 // The offsets at a certain distance do intersect in a single point.
00600 //
00601 // POSTCONDITION: In case of overflow an empty optional is returned.
00602 //
00603 template<class K>
00604 optional< Point_2<K> > construct_degenerate_offset_lines_isecC2 ( intrusive_ptr< Trisegment_2<K> > const& tri )
00605 {
00606   typedef typename K::FT FT ;
00607   
00608   typedef Point_2<K> Point_2 ;
00609   typedef Line_2<K>  Line_2 ;
00610   
00611   typedef optional<Point_2> Optional_point_2 ;
00612   typedef optional<Line_2>  Optional_line_2 ;
00613   
00614   CGAL_STSKEL_TRAITS_TRACE("Computing degenerate offset lines isec point for: " << tri )  ;
00615   
00616   FT x(0.0),y(0.0) ;
00617 
00618   Optional_line_2 l0 = compute_normalized_line_ceoffC2(tri->collinear_edge    ()) ;
00619   Optional_line_2 l2 = compute_normalized_line_ceoffC2(tri->non_collinear_edge()) ;
00620   
00621   Optional_point_2 q = compute_degenerate_seed_pointC2(tri);
00622 
00623   bool ok = false ;
00624   
00625   if ( l0 && l2 && q )
00626   {
00627     FT num, den ;
00628     
00629     FT px, py ;
00630     line_project_pointC2(l0->a(),l0->b(),l0->c(),q->x(),q->y(),px,py); 
00631     
00632     CGAL_STSKEL_TRAITS_TRACE("Seed point: " << p2str(*q) << ". Projected seed point: (" << n2str(px) << "," << n2str(py) << ")" ) ;
00633     
00634     if ( ! CGAL_NTS is_zero(l0->b()) ) // Non-vertical
00635     {
00636       num = (l2->a() * l0->b() - l0->a() * l2->b() ) * px + l0->b() * l2->c() - l2->b() * l0->c() ;
00637       den = (l0->a() * l0->a() - 1) * l2->b() + ( 1 - l2->a() * l0->a() ) * l0->b() ;
00638     }
00639     else
00640     {
00641       num = (l2->a() * l0->b() - l0->a() * l2->b() ) * py - l0->a() * l2->c() + l2->a() * l0->c() ;
00642       den = l0->a() * l0->b() * l2->b() - l0->b() * l0->b() * l2->a() + l2->a() - l0->a() ;
00643     }
00644   
00645     if ( ! CGAL_NTS certified_is_zero(den) && CGAL_NTS is_finite(den) && CGAL_NTS is_finite(num) )
00646     {
00647       x = px + l0->a() * num / den  ;
00648       y = py + l0->b() * num / den  ;
00649       
00650       ok = CGAL_NTS is_finite(x) && CGAL_NTS is_finite(y) ;
00651     }
00652   }
00653   
00654 
00655   CGAL_STSKEL_TRAITS_TRACE("\nDegenerate " << (CGAL_NTS is_zero(l0->b()) ? "(vertical)" : "") << " event point:  x=" << n2str(x) << " y=" << n2str(y) )
00656 
00657   return cgal_make_optional(ok,K().construct_point_2_object()(x,y)) ;
00658 }
00659 
00660 //
00661 // Calls the appropiate function depending on the collinearity of the edges.
00662 //
00663 template<class K>
00664 optional< Point_2<K> > construct_offset_lines_isecC2 ( intrusive_ptr< Trisegment_2<K> > const& tri )
00665 {
00666   CGAL_precondition ( tri->collinearity() != TRISEGMENT_COLLINEARITY_ALL ) ;
00667   
00668   return tri->collinearity() == TRISEGMENT_COLLINEARITY_NONE ? construct_normal_offset_lines_isecC2    (tri)
00669                                                              : construct_degenerate_offset_lines_isecC2(tri) ;
00670 }
00671 
00672 } // namnepsace CGAIL_SS_i
00673 
00674 CGAL_END_NAMESPACE
00675 
00676 #endif // CGAL_STRAIGHT_SKELETON_CONS_FTC2_H //
00677 // EOF //
00678 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines