// Copyright (c) 1997-2001 Freie Universitaet Berlin (Germany). // All rights reserved. // // This file is part of CGAL (www.cgal.org); you may redistribute it under // the terms of the Q Public License version 1.0. // See the file LICENSE.QPL distributed with CGAL. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ // // // Author(s) : Sven Schoenherr , Bernd Gaertner #ifndef CGAL_MIN_ELLIPSE_2_ADAPTERC2_H #define CGAL_MIN_ELLIPSE_2_ADAPTERC2_H // includes #ifndef CGAL_CONICCPA2_H # include #endif #ifndef CGAL_OPTIMISATION_ASSERTIONS_H # include #endif CGAL_BEGIN_NAMESPACE // Class declarations // ================== template < class Traits_ > class Min_ellipse_2; template < class PT_, class DA_ > class Min_ellipse_2_adapterC2; template < class PT_, class DA_ > class _Min_ellipse_2_adapterC2__Ellipse; // Class interface and implementation // ================================== template < class PT, class DA > bool are_ordered_along_lineC2( const PT& p, const PT& q, const PT& r, const DA& da) { typedef typename DA::FT FT; FT px; FT py; FT qx; FT qy; FT rx; FT ry; da.get( p, px, py); da.get( q, qx, qy); da.get( r, rx, ry); // p,q,r collinear? if ( ! CGAL_NTS is_zero( ( px-rx) * ( qy-ry) - ( py-ry) * ( qx-rx))) return( false); // p,q,r vertical? if ( px != rx) return( ( ( px < qx) && ( qx < rx)) || ( ( rx < qx) && ( qx < px))); else return( ( ( py < qy) && ( qy < ry)) || ( ( ry < qy) && ( qy < py))); // keeps g++ happy return false; } template < class PT_, class DA_ > class Min_ellipse_2_adapterC2 { public: // types typedef PT_ PT; typedef DA_ DA; // nested types typedef PT Point; typedef _Min_ellipse_2_adapterC2__Ellipse Ellipse; private: DA dao; // data accessor object Ellipse ellipse; // current ellipse friend class Min_ellipse_2< Min_ellipse_2_adapterC2 >; public: // creation Min_ellipse_2_adapterC2( const DA& da = DA()) : dao( da), ellipse( da) { } // operations CGAL::Orientation orientation( const Point& p, const Point& q, const Point& r) const { typedef typename DA_::FT FT; FT px; FT py; FT qx; FT qy; FT rx; FT ry; dao.get( p, px, py); dao.get( q, qx, qy); dao.get( r, rx, ry); return( static_cast< CGAL::Orientation>( CGAL_NTS sign( ( px-rx) * ( qy-ry) - ( py-ry) * ( qx-rx)))); } }; // Nested type `Ellipse' template < class PT_, class DA_ > std::ostream& operator << ( std::ostream& os, const _Min_ellipse_2_adapterC2__Ellipse& c); template < class PT_, class DA_ > std::istream& operator >> ( std::istream& is, _Min_ellipse_2_adapterC2__Ellipse& c); template < class PT_, class DA_ > class _Min_ellipse_2_adapterC2__Ellipse { public: // typedefs typedef PT_ PT; typedef DA_ DA; typedef ConicCPA2< PT, DA> CT; typedef typename DA_::FT FT; private: // data members int n_boundary_points; // number of boundary points PT boundary_point1, boundary_point2; // two boundary points CT conic1, conic2; // two conics FT dr, ds, dt, du, dv, dw; // the gradient vector friend std::ostream& operator << <> ( std::ostream& os, const _Min_ellipse_2_adapterC2__Ellipse& c); friend std::istream& operator >> <> ( std::istream& is, _Min_ellipse_2_adapterC2__Ellipse& c); public: // types typedef PT Point; // creation _Min_ellipse_2_adapterC2__Ellipse( const DA& da) : conic1( da), conic2( da) { } void set( ) { n_boundary_points = 0; } void set( const Point& p) { n_boundary_points = 1; boundary_point1 = p; } void set( const Point& p, const Point& q) { n_boundary_points = 2; boundary_point1 = p; boundary_point2 = q; } void set( const Point& p1, const Point& p2, const Point& p3) { n_boundary_points = 3; conic1.set_ellipse( p1, p2, p3); } void set( const Point& p1, const Point& p2, const Point& p3, const Point& p4) { n_boundary_points = 4; CT::set_two_linepairs( p1, p2, p3, p4, conic1, conic2); dr = FT( 0); ds = conic1.r() * conic2.s() - conic2.r() * conic1.s(), dt = conic1.r() * conic2.t() - conic2.r() * conic1.t(), du = conic1.r() * conic2.u() - conic2.r() * conic1.u(), dv = conic1.r() * conic2.v() - conic2.r() * conic1.v(), dw = conic1.r() * conic2.w() - conic2.r() * conic1.w(); } void set( const Point&, const Point&, const Point&, const Point&, const Point& p5) { n_boundary_points = 5; conic1.set( conic1, conic2, p5); conic1.analyse(); } // predicates CGAL::Bounded_side bounded_side( const Point& p) const { switch ( n_boundary_points) { case 0: return( CGAL::ON_UNBOUNDED_SIDE); case 1: return( ( p == boundary_point1) ? CGAL::ON_BOUNDARY : CGAL::ON_UNBOUNDED_SIDE); case 2: return( ( p == boundary_point1) || ( p == boundary_point2) || ( CGAL::are_ordered_along_lineC2( boundary_point1, p, boundary_point2, conic1.da())) ? CGAL::ON_BOUNDARY : CGAL::ON_UNBOUNDED_SIDE); case 3: case 5: return( conic1.convex_side( p)); case 4: { CT c( conic1.da()); c.set( conic1, conic2, p); c.analyse(); if ( ! c.is_ellipse()) { c.set_ellipse( conic1, conic2); c.analyse(); return( c.convex_side( p)); } else { int tau_star = c.vol_derivative( dr, ds, dt, du, dv, dw); return( CGAL::Bounded_side( CGAL_NTS sign( tau_star))); } } default: CGAL_optimisation_assertion( ( n_boundary_points >= 0) && ( n_boundary_points <= 5) ); } // keeps g++ happy return( CGAL::Bounded_side( 0)); } bool has_on_bounded_side( const Point& p) const { return( bounded_side( p) == CGAL::ON_BOUNDED_SIDE); } bool has_on_boundary( const Point& p) const { return( bounded_side( p) == CGAL::ON_BOUNDARY); } bool has_on_unbounded_side( const Point& p) const { return( bounded_side( p) == CGAL::ON_UNBOUNDED_SIDE); } bool is_empty( ) const { return( n_boundary_points == 0); } bool is_degenerate( ) const { return( n_boundary_points < 3); } // additional operations for checking bool operator == ( const CGAL::_Min_ellipse_2_adapterC2__Ellipse& e) const { if ( n_boundary_points != e.n_boundary_points) return( false); switch ( n_boundary_points) { case 0: return( true); case 1: return( boundary_point1 == e.boundary_point1); case 2: return( ( ( boundary_point1 == e.boundary_point1) && ( boundary_point2 == e.boundary_point2)) || ( ( boundary_point1 == e.boundary_point2) && ( boundary_point2 == e.boundary_point1))); case 3: case 5: return( conic1 == e.conic1); case 4: return( ( ( conic1 == e.conic1) && ( conic2 == e.conic2)) || ( ( conic1 == e.conic2) && ( conic2 == e.conic1))); default: CGAL_optimisation_assertion( ( n_boundary_points >= 0) && ( n_boundary_points <= 5)); } // keeps g++ happy return( false); } bool operator != ( const CGAL::_Min_ellipse_2_adapterC2__Ellipse& e) const { return( ! ( *this == e)); } }; // I/O template < class PT_, class DA_ > std::ostream& operator << ( std::ostream& os, const CGAL::_Min_ellipse_2_adapterC2__Ellipse& e) { const char* const empty = ""; const char* const pretty_head = "CGAL::Min_ellipse_2_adapterC2::Ellipse( "; const char* const pretty_sep = ", "; const char* const pretty_tail = ")"; const char* const ascii_sep = " "; const char* head = empty; const char* sep = empty; const char* tail = empty; switch ( CGAL::get_mode( os)) { case CGAL::IO::PRETTY: head = pretty_head; sep = pretty_sep; tail = pretty_tail; break; case CGAL::IO::ASCII: sep = ascii_sep; break; case CGAL::IO::BINARY: break; default: CGAL_optimisation_assertion_msg( false, "CGAL::get_mode( os) invalid!"); break; } os << head << e.n_boundary_points; switch ( e.n_boundary_points) { case 0: break; case 1: os << sep << e.boundary_point1; break; case 2: os << sep << e.boundary_point1 << sep << e.boundary_point2; break; case 3: case 5: os << sep << e.conic1; break; case 4: os << sep << e.conic1 << sep << e.conic2; break; } os << tail; return( os); } template < class PT_, class DA_ > std::istream& operator >> ( std::istream& is, CGAL::_Min_ellipse_2_adapterC2__Ellipse& e) { switch ( CGAL::get_mode( is)) { case CGAL::IO::PRETTY: std::cerr << std::endl; std::cerr << "Stream must be in ascii or binary mode" << std::endl; break; case CGAL::IO::ASCII: case CGAL::IO::BINARY: CGAL::read( is, e.n_boundary_points); switch ( e.n_boundary_points) { case 0: break; case 1: is >> e.boundary_point1; break; case 2: is >> e.boundary_point1 >> e.boundary_point2; break; case 3: case 5: is >> e.conic1; break; case 4: is >> e.conic1 >> e.conic2; break; } break; default: CGAL_optimisation_assertion_msg( false, "CGAL::IO::mode invalid!"); break; } return( is); } CGAL_END_NAMESPACE #endif // CGAL_MIN_ELLIPSE_2_ADAPTERC2_H // ===== EOF ==================================================================