dust3d/thirdparty/cgal/CGAL-5.1/include/CGAL/Min_ellipse_2.h

594 lines
16 KiB
C
Raw Normal View History

2020-10-13 12:44:25 +00:00
// Copyright (c) 1997-2001
// ETH Zurich (Switzerland). All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
2020-10-13 12:44:25 +00:00
// $URL: https://github.com/CGAL/cgal/blob/v5.1/Bounding_volumes/include/CGAL/Min_ellipse_2.h $
// $Id: Min_ellipse_2.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Sven Schoenherr <sven@inf.ethz.ch>, Bernd Gaertner
#ifndef CGAL_MIN_ELLIPSE_2_H
#define CGAL_MIN_ELLIPSE_2_H
#include <CGAL/license/Bounding_volumes.h>
#include <CGAL/Optimisation/basic.h>
#include <CGAL/Random.h>
#include <CGAL/algorithm.h>
#include <list>
#include <vector>
#include <algorithm>
#include <iostream>
namespace CGAL {
// Class declaration
// =================
template < class Traits_ >
class Min_ellipse_2;
// Class interface
// ===============
template < class Traits_ >
class Min_ellipse_2 {
public:
// types
typedef Traits_ Traits;
typedef typename Traits_::Point Point;
typedef typename Traits_::Ellipse Ellipse;
typedef typename std::list<Point>::const_iterator Point_iterator;
typedef const Point * Support_point_iterator;
2020-10-13 12:44:25 +00:00
/**************************************************************************
WORKAROUND: Some compilers are unable to match member functions defined
outside the class template. Therefore, all member functions are implemented
in the class interface.
2020-10-13 12:44:25 +00:00
// creation
template < class InputIterator >
Min_ellipse_2( InputIterator first,
InputIterator last,
bool randomize = false,
Random& random = get_default_random(),
const Traits& traits = Traits());
2020-10-13 12:44:25 +00:00
Min_ellipse_2( const Traits& traits = Traits());
Min_ellipse_2( const Point& p,
const Traits& traits = Traits());
Min_ellipse_2( Point p,
Point q,
const Traits& traits = Traits());
Min_ellipse_2( const Point& p1,
const Point& p2,
const Point& p3,
const Traits& traits = Traits());
Min_ellipse_2( const Point& p1,
const Point& p2,
const Point& p3,
const Point& p4,
const Traits& traits = Traits());
Min_ellipse_2( const Point& p1,
const Point& p2,
const Point& p3,
const Point& p4,
const Point& p5,
const Traits& traits = Traits());
~Min_ellipse_2( );
2020-10-13 12:44:25 +00:00
// access functions
int number_of_points ( ) const;
int number_of_support_points( ) const;
2020-10-13 12:44:25 +00:00
Point_iterator points_begin( ) const;
Point_iterator points_end ( ) const;
2020-10-13 12:44:25 +00:00
Support_point_iterator support_points_begin( ) const;
Support_point_iterator support_points_end ( ) const;
2020-10-13 12:44:25 +00:00
const Point& support_point( int i) const;
2020-10-13 12:44:25 +00:00
const Ellipse& ellipse( ) const;
2020-10-13 12:44:25 +00:00
// predicates
CGAL::Bounded_side bounded_side( const Point& p) const;
bool has_on_bounded_side ( const Point& p) const;
bool has_on_boundary ( const Point& p) const;
bool has_on_unbounded_side ( const Point& p) const;
2020-10-13 12:44:25 +00:00
bool is_empty ( ) const;
bool is_degenerate( ) const;
2020-10-13 12:44:25 +00:00
// modifiers
void insert( const Point& p);
void insert( const Point* first,
const Point* last );
void insert( std::list<Point>::const_iterator first,
std::list<Point>::const_iterator last );
void insert( std::istream_iterator<Point,std::ptrdiff_t> first,
std::istream_iterator<Point,std::ptrdiff_t> last );
void clear( );
2020-10-13 12:44:25 +00:00
// validity check
bool is_valid( bool verbose = false, int level = 0) const;
2020-10-13 12:44:25 +00:00
// miscellaneous
const Traits& traits( ) const;
**************************************************************************/
private:
// private data members
Traits tco; // traits class object
std::list<Point> points; // doubly linked list of points
int n_support_points; // number of support points
Point* support_points; // array of support points
2020-10-13 12:44:25 +00:00
// copying and assignment not allowed!
Min_ellipse_2( const Min_ellipse_2<Traits_>&);
Min_ellipse_2<Traits_>& operator = ( const Min_ellipse_2<Traits_>&);
// ============================================================================
// Class implementation
// ====================
public:
// Access functions and predicates
// -------------------------------
// #points and #support points
inline
std::size_t
number_of_points( ) const
{
return( points.size());
}
2020-10-13 12:44:25 +00:00
inline
std::size_t
number_of_support_points( ) const
{
return( n_support_points);
}
// is_... predicates
inline
bool
is_empty( ) const
{
return( number_of_support_points() == 0);
}
2020-10-13 12:44:25 +00:00
inline
bool
is_degenerate( ) const
{
return( number_of_support_points() < 3);
}
// access to points and support points
inline
Point_iterator
points_begin( ) const
{
return( points.begin());
}
2020-10-13 12:44:25 +00:00
inline
Point_iterator
points_end( ) const
{
return( points.end());
}
2020-10-13 12:44:25 +00:00
inline
Support_point_iterator
support_points_begin( ) const
{
return( support_points);
}
2020-10-13 12:44:25 +00:00
inline
Support_point_iterator
support_points_end( ) const
{
return( support_points+n_support_points);
}
2020-10-13 12:44:25 +00:00
// random access for support points
inline
const Point&
support_point( std::size_t i) const
{
CGAL_optimisation_precondition(i < number_of_support_points());
return( support_points[ i]);
}
// ellipse
inline
const Ellipse&
ellipse( ) const
{
return( tco.ellipse);
}
2020-10-13 12:44:25 +00:00
// in-ellipse test predicates
inline
CGAL::Bounded_side
bounded_side( const Point& p) const
{
return( tco.ellipse.bounded_side( p));
}
2020-10-13 12:44:25 +00:00
inline
bool
has_on_bounded_side( const Point& p) const
{
return( tco.ellipse.has_on_bounded_side( p));
}
2020-10-13 12:44:25 +00:00
inline
bool
has_on_boundary( const Point& p) const
{
return( tco.ellipse.has_on_boundary( p));
}
2020-10-13 12:44:25 +00:00
inline
bool
has_on_unbounded_side( const Point& p) const
{
return( tco.ellipse.has_on_unbounded_side( p));
}
private:
// Private member functions
// ------------------------
// compute_ellipse
inline
void
compute_ellipse( )
{
switch ( n_support_points) {
case 5:
tco.ellipse.set( support_points[ 0],
support_points[ 1],
support_points[ 2],
support_points[ 3],
support_points[ 4]);
break;
case 4:
tco.ellipse.set( support_points[ 0],
support_points[ 1],
support_points[ 2],
support_points[ 3]);
break;
case 3:
tco.ellipse.set( support_points[ 0],
support_points[ 1],
support_points[ 2]);
break;
case 2:
tco.ellipse.set( support_points[ 0], support_points[ 1]);
break;
case 1:
tco.ellipse.set( support_points[ 0]);
break;
case 0:
tco.ellipse.set( );
break;
default:
CGAL_optimisation_assertion( ( n_support_points >= 0) &&
( n_support_points <= 5) ); }
}
void
me( const Point_iterator& last, int n_sp)
{
// compute ellipse through support points
n_support_points = n_sp;
compute_ellipse();
if ( n_sp == 5) return;
2020-10-13 12:44:25 +00:00
// test first n points
typename std::list<Point>::iterator point_iter = points.begin();
for ( ; last != point_iter; ) {
const Point& p = *point_iter;
2020-10-13 12:44:25 +00:00
// p not in current ellipse?
if ( has_on_unbounded_side( p)) {
2020-10-13 12:44:25 +00:00
// recursive call with p as additional support point
support_points[ n_sp] = p;
me( point_iter, n_sp+1);
2020-10-13 12:44:25 +00:00
// move current point to front
points.splice( points.begin(), points, point_iter++); }
2020-10-13 12:44:25 +00:00
else
++point_iter; }
}
public:
// Constructors
// ------------
// STL-like constructor (member template)
template < class InputIterator >
Min_ellipse_2( InputIterator first,
InputIterator last,
bool randomize
#if !defined(_MSC_VER) || _MSC_VER > 1300
= false
#endif
,
Random& random = get_default_random(),
const Traits& traits = Traits())
: tco( traits)
{
// allocate support points' array
support_points = new Point[ 5];
2020-10-13 12:44:25 +00:00
// range of points not empty?
if ( first != last) {
2020-10-13 12:44:25 +00:00
// store points
if ( randomize) {
2020-10-13 12:44:25 +00:00
// shuffle points at random
std::vector<Point> v( first, last);
CGAL::cpp98::random_shuffle( v.begin(), v.end(), random);
std::copy( v.begin(), v.end(),
std::back_inserter( points)); }
else
std::copy( first, last, std::back_inserter( points)); }
2020-10-13 12:44:25 +00:00
// compute me
me( points.end(), 0);
}
2020-10-13 12:44:25 +00:00
// default constructor
inline
2020-10-13 12:44:25 +00:00
Min_ellipse_2()
: n_support_points( 0)
{
// allocate support points' array
support_points = new Point[ 5];
// initialize ellipse
tco.ellipse.set();
CGAL_optimisation_postcondition( is_empty());
}
inline
Min_ellipse_2( const Traits& traits )
: tco( traits), n_support_points( 0)
{
// allocate support points' array
support_points = new Point[ 5];
2020-10-13 12:44:25 +00:00
// initialize ellipse
tco.ellipse.set();
2020-10-13 12:44:25 +00:00
CGAL_optimisation_postcondition( is_empty());
}
2020-10-13 12:44:25 +00:00
// constructor for one point
inline
Min_ellipse_2( const Point& p, const Traits& traits = Traits())
: tco( traits), points( 1, p), n_support_points( 1)
{
// allocate support points' array
support_points = new Point[ 5];
2020-10-13 12:44:25 +00:00
// initialize ellipse
support_points[ 0] = p;
tco.ellipse.set( p);
2020-10-13 12:44:25 +00:00
CGAL_optimisation_postcondition( is_degenerate());
}
2020-10-13 12:44:25 +00:00
// constructor for two points
2020-10-13 12:44:25 +00:00
// This was const Point& but then Intel 7.0/.net2003 messes it up
// with the constructor taking an iterator range
inline
Min_ellipse_2( Point p1, Point p2,
const Traits& traits = Traits())
: tco( traits)
{
// allocate support points' array
support_points = new Point[ 5];
2020-10-13 12:44:25 +00:00
// store points
points.push_back( p1);
points.push_back( p2);
2020-10-13 12:44:25 +00:00
// compute me
me( points.end(), 0);
2020-10-13 12:44:25 +00:00
CGAL_optimisation_postcondition( is_degenerate());
}
2020-10-13 12:44:25 +00:00
// constructor for three points
inline
Min_ellipse_2( const Point& p1, const Point& p2, const Point& p3,
const Traits& traits = Traits())
: tco( traits)
{
// allocate support points' array
support_points = new Point[ 5];
2020-10-13 12:44:25 +00:00
// store points
points.push_back( p1);
points.push_back( p2);
points.push_back( p3);
2020-10-13 12:44:25 +00:00
// compute me
me( points.end(), 0);
}
2020-10-13 12:44:25 +00:00
// constructor for four points
inline
Min_ellipse_2( const Point& p1, const Point& p2,
const Point& p3, const Point& p4,
const Traits& traits = Traits())
: tco( traits)
{
// allocate support points' array
support_points = new Point[ 5];
2020-10-13 12:44:25 +00:00
// store points
points.push_back( p1);
points.push_back( p2);
points.push_back( p3);
points.push_back( p4);
2020-10-13 12:44:25 +00:00
// compute me
me( points.end(), 0);
}
2020-10-13 12:44:25 +00:00
// constructor for five points
inline
Min_ellipse_2( const Point& p1, const Point& p2, const Point& p3,
const Point& p4, const Point& p5,
const Traits& traits = Traits())
: tco( traits)
{
// allocate support points' array
support_points = new Point[ 5];
2020-10-13 12:44:25 +00:00
// store points
points.push_back( p1);
points.push_back( p2);
points.push_back( p3);
points.push_back( p4);
points.push_back( p5);
2020-10-13 12:44:25 +00:00
// compute me
me( points.end(), 0);
}
2020-10-13 12:44:25 +00:00
// Destructor
// ----------
inline
~Min_ellipse_2( )
{
// free support points' array
delete[] support_points;
}
// Modifiers
// ---------
void
insert( const Point& p)
{
// p not in current ellipse?
if ( has_on_unbounded_side( p)) {
2020-10-13 12:44:25 +00:00
// p new support point
support_points[ 0] = p;
2020-10-13 12:44:25 +00:00
// recompute me
me( points.end(), 1);
2020-10-13 12:44:25 +00:00
// store p as the first point in list
points.push_front( p); }
else
2020-10-13 12:44:25 +00:00
// append p to the end of the list
points.push_back( p);
}
template < class InputIterator >
void
insert( InputIterator first, InputIterator last)
{
for ( ; first != last; ++first)
insert( *first);
}
void
clear( )
{
points.erase( points.begin(), points.end());
n_support_points = 0;
tco.ellipse.set();
}
2020-10-13 12:44:25 +00:00
// Validity check
// --------------
bool
is_valid( bool verbose = false, int level = 0) const
{
using namespace std;
2020-10-13 12:44:25 +00:00
CGAL::Verbose_ostream verr( verbose);
verr << endl;
verr << "CGAL::Min_ellipse_2<Traits>::" << endl;
verr << "is_valid( true, " << level << "):" << endl;
verr << " |P| = " << number_of_points()
<< ", |S| = " << number_of_support_points() << endl;
2020-10-13 12:44:25 +00:00
// containment check (a)
verr << " a) containment check..." << flush;
Point_iterator point_iter;
for ( point_iter = points_begin();
point_iter != points_end();
++point_iter)
if ( has_on_unbounded_side( *point_iter))
return( CGAL::_optimisation_is_valid_fail( verr,
"ellipse does not contain all points"));
verr << "passed." << endl;
2020-10-13 12:44:25 +00:00
// support set checks (b)+(c) (not yet implemented)
2020-10-13 12:44:25 +00:00
// alternative support set check
verr << " +) support set check..." << flush;
Support_point_iterator support_point_iter;
for ( support_point_iter = support_points_begin();
support_point_iter != support_points_end();
++support_point_iter)
if ( ! has_on_boundary( *support_point_iter))
return( CGAL::_optimisation_is_valid_fail( verr,
"ellipse does not have all \
support points on the boundary"));
verr << "passed." << endl;
2020-10-13 12:44:25 +00:00
verr << " object is valid!" << endl;
return( true);
}
// Miscellaneous
// -------------
inline
const Traits&
traits( ) const
{
return( tco);
}
};
// Function declarations
// =====================
// I/O
// ---
template < class Traits_ >
std::ostream&
operator << ( std::ostream& os, const Min_ellipse_2<Traits_>& me);
template < class Traits_ >
std::istream&
operator >> ( std::istream& is, Min_ellipse_2<Traits_>& me);
} //namespace CGAL
#include <CGAL/Min_ellipse_2/Min_ellipse_2_impl.h>
#endif // CGAL_MIN_ELLIPSE_2_H
// ===== EOF ==================================================================