mirror of https://github.com/CGAL/cgal
430 lines
11 KiB
C++
430 lines
11 KiB
C++
// 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 <sven@inf.ethz.ch>, Bernd Gaertner
|
|
|
|
#ifndef CGAL_MIN_ELLIPSE_2_ADAPTERC2_H
|
|
#define CGAL_MIN_ELLIPSE_2_ADAPTERC2_H
|
|
|
|
// includes
|
|
#ifndef CGAL_CONICCPA2_H
|
|
# include <CGAL/ConicCPA2.h>
|
|
#endif
|
|
#ifndef CGAL_OPTIMISATION_ASSERTIONS_H
|
|
# include <CGAL/Optimisation/assertions.h>
|
|
#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<PT,DA> Ellipse;
|
|
|
|
private:
|
|
DA dao; // data accessor object
|
|
Ellipse ellipse; // current ellipse
|
|
friend class Min_ellipse_2< Min_ellipse_2_adapterC2<PT,DA> >;
|
|
|
|
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<PT_,DA_>& c);
|
|
|
|
template < class PT_, class DA_ >
|
|
std::istream& operator >> ( std::istream& is,
|
|
_Min_ellipse_2_adapterC2__Ellipse<PT_,DA_>& 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<PT_,DA_>& c);
|
|
|
|
friend
|
|
std::istream& operator >> <> ( std::istream& is,
|
|
_Min_ellipse_2_adapterC2__Ellipse<PT_,DA_>& 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<PT_,DA_>& 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<PT_,DA_>& 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<PT_,DA_>& 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<PT_,DA_>& 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 ==================================================================
|