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