cgal/Polytope_distance_d/include/CGAL/Polytope_distance_d.h

883 lines
32 KiB
C++

// Copyright (c) 1997-2001 ETH Zurich (Switzerland).
// 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>
#ifndef CGAL_POLYTOPE_DISTANCE_D_H
#define CGAL_POLYTOPE_DISTANCE_D_H
// includes
// --------
#include <CGAL/Optimisation/basic.h>
#include <CGAL/function_objects.h>
#include <CGAL/QP_solver.h>
#include <CGAL/QP_partial_filtered_pricing.h>
#include <CGAL/QP_partial_exact_pricing.h>
CGAL_BEGIN_NAMESPACE
// A functor whose operator(int i) provides access to the i-th element
// of a random access iterator.
template < typename RndAccIt, typename ArgType >
class Access_by_index {
public:
typedef typename std::iterator_traits<RndAccIt>::value_type result_type;
Access_by_index(RndAccIt it = RndAccIt()) : a(it) {}
result_type operator () (ArgType i) const { return a[i]; }
private:
RndAccIt a;
};
// Class declarations
// ==================
template < class Traits_ >
class Polytope_distance_d;
template < class ET_, class NT_, class Point, class Point_iterator,
class Access_coord, class Access_dim >
struct QP_rep_poly_dist_d;
template < class NT >
struct QP_rep_row_of_a {
typedef std::vector<NT> argument_type;
typedef typename argument_type::const_iterator result_type;
result_type
operator ( ) ( const argument_type& v) const { return v.begin(); }
};
template < class Point, class Point_iterator >
struct QP_rep_signed_point_iterator;
template < class NT, class Point,
class Access_coord, class Access_dim >
class QP_rep_signed_inner_product;
template < class NT, class Point, class Point_iterator,
class Access_coord, class Access_dim >
struct QP_rep_row_of_d;
// Class interfaces
// ================
template < class Traits_ >
class Polytope_distance_d {
public:
// self
typedef Traits_ Traits;
typedef Polytope_distance_d<Traits>
Self;
// types from the traits class
typedef typename Traits::Point_d Point;
typedef typename Traits::Rep_tag Rep_tag;
typedef typename Traits::RT RT;
typedef typename Traits::FT FT;
typedef typename Traits::Access_dimension_d
Access_dimension_d;
typedef typename Traits::Access_coordinates_begin_d
Access_coordinates_begin_d;
typedef typename Traits::Construct_point_d
Construct_point_d;
typedef typename Traits::ET ET;
typedef typename Traits::NT NT;
private:
// QP solver
typedef CGAL::QP_rep_poly_dist_d<
ET, NT, Point, typename std::vector<Point>::const_iterator,
Access_coordinates_begin_d, Access_dimension_d >
QP_rep;
typedef CGAL::QP_solver< QP_rep > Solver;
typedef typename Solver::Pricing_strategy
Pricing_strategy;
// private types
typedef std::vector<Point> Point_vector;
typedef std::vector<ET> ET_vector;
typedef std::vector<int> Index_vector;
typedef CGAL::Access_by_index<typename std::vector<Point>::const_iterator,
int> Point_by_index;
typedef std::vector<NT> NT_vector;
typedef std::vector<NT_vector> NT_matrix;
public:
// public types
typedef typename Point_vector::const_iterator
Point_iterator;
typedef typename Index_vector::const_iterator IVCI;
typedef CGAL::Join_input_iterator_1< IVCI, Point_by_index >
Support_point_iterator;
typedef typename ET_vector::const_iterator
Coordinate_iterator;
// creation
Polytope_distance_d( const Traits& traits = Traits())
: tco( traits), d( -1), solver(0), strategy(0) {}
template < class InputIterator1, class InputIterator2 >
Polytope_distance_d( InputIterator1 p_first,
InputIterator1 p_last,
InputIterator2 q_first,
InputIterator2 q_last,
const Traits& traits = Traits())
: tco( traits), solver(0), strategy(0)
{
set( p_first, p_last, q_first, q_last);
}
~Polytope_distance_d() {
if (solver)
delete solver;
if (strategy)
delete strategy;
}
// access to point sets
int ambient_dimension( ) const { return d; }
int number_of_points( ) const { return p_points.size()+q_points.size();}
int number_of_points_p( ) const { return p_points.size(); }
int number_of_points_q( ) const { return q_points.size(); }
Point_iterator points_p_begin( ) const { return p_points.begin(); }
Point_iterator points_p_end ( ) const { return p_points.end (); }
Point_iterator points_q_begin( ) const { return q_points.begin(); }
Point_iterator points_q_end ( ) const { return q_points.end (); }
// access to support points
int
number_of_support_points( ) const
{ return is_finite() ? solver->number_of_basic_variables() : 0; }
int number_of_support_points_p() const { return p_support_indices.size();}
int number_of_support_points_q() const { return q_support_indices.size();}
Support_point_iterator
support_points_p_begin() const
{ return Support_point_iterator(
p_support_indices.begin(),
Point_by_index( p_points.begin())); }
Support_point_iterator
support_points_p_end() const
{ return Support_point_iterator(
is_finite() ? p_support_indices.end()
: p_support_indices.begin(),
Point_by_index( p_points.begin())); }
Support_point_iterator
support_points_q_begin() const
{ return Support_point_iterator(
q_support_indices.begin(),
Point_by_index( q_points.begin())); }
Support_point_iterator
support_points_q_end() const
{ return Support_point_iterator(
is_finite() ? q_support_indices.end()
: q_support_indices.begin(),
Point_by_index( q_points.begin())); }
// access to realizing points (rational representation)
Coordinate_iterator
realizing_point_p_coordinates_begin( ) const { return p_coords.begin(); }
Coordinate_iterator
realizing_point_p_coordinates_end ( ) const { return p_coords.end (); }
Coordinate_iterator
realizing_point_q_coordinates_begin( ) const { return q_coords.begin(); }
Coordinate_iterator
realizing_point_q_coordinates_end ( ) const { return q_coords.end (); }
// access to squared distance (rational representation)
ET squared_distance_numerator ( ) const
{ return solver->solution_numerator(); }
ET squared_distance_denominator( ) const
{ return solver->solution_denominator(); }
// access to realizing points and squared distance
// NOTE: an implicit conversion from ET to RT must be available!
Point
realizing_point_p( ) const
{ CGAL_optimisation_precondition( is_finite());
return tco.construct_point_d_object()( ambient_dimension(),
realizing_point_p_coordinates_begin(),
realizing_point_p_coordinates_end ()); }
Point
realizing_point_q( ) const
{ CGAL_optimisation_precondition( is_finite());
return tco.construct_point_d_object()( ambient_dimension(),
realizing_point_q_coordinates_begin(),
realizing_point_q_coordinates_end ()); }
FT
squared_distance( ) const
{
return FT( squared_distance_numerator ()) /
FT( squared_distance_denominator()); }
bool is_finite( ) const
{ return ( number_of_points_p() > 0) && ( number_of_points_q() > 0); }
bool is_zero( ) const
{ return CGAL_NTS is_zero( squared_distance_numerator()); }
bool is_degenerate( ) const { return ( ! is_finite()); }
// modifiers
template < class InputIterator1, class InputIterator2 >
void
set( InputIterator1 p_first, InputIterator1 p_last,
InputIterator2 q_first, InputIterator2 q_last)
{ if ( p_points.size() > 0)
p_points.erase( p_points.begin(), p_points.end());
if ( q_points.size() > 0)
q_points.erase( q_points.begin(), q_points.end());
std::copy( p_first, p_last, std::back_inserter( p_points));
std::copy( q_first, q_last, std::back_inserter( q_points));
set_dimension();
CGAL_optimisation_precondition_msg(
check_dimension( p_points.begin(), p_points.end())
&& check_dimension( q_points.begin(), q_points.end()),
"Not all points have the same dimension.");
compute_distance(); }
template < class InputIterator >
void
set_p( InputIterator p_first, InputIterator p_last)
{ if ( p_points.size() > 0)
p_points.erase( p_points.begin(), p_points.end());
std::copy( p_first, p_last, std::back_inserter( p_points));
set_dimension();
CGAL_optimisation_precondition_msg(
check_dimension( p_points.begin(), p_points.end()),
"Not all points have the same dimension.");
compute_distance(); }
template < class InputIterator >
void
set_q( InputIterator q_first, InputIterator q_last)
{ if ( q_points.size() > 0)
q_points.erase( q_points.begin(), q_points.end());
std::copy( q_first, q_last, std::back_inserter( q_points));
set_dimension();
CGAL_optimisation_precondition_msg(
check_dimension( q_points.begin(), q_points.end()),
"Not all points have the same dimension.");
compute_distance(); }
void
insert_p( const Point& p)
{ CGAL_optimisation_precondition( ( ! is_finite()) ||
( tco.access_dimension_d_object()( p) == d));
p_points.push_back( p);
compute_distance(); }
void
insert_q( const Point& q)
{ CGAL_optimisation_precondition( ( ! is_finite()) ||
( tco.access_dimension_d_object()( q) == d));
q_points.push_back( q);
compute_distance(); }
template < class InputIterator1, class InputIterator2 >
void
insert( InputIterator1 p_first, InputIterator1 p_last,
InputIterator2 q_first, InputIterator2 q_last)
{ CGAL_optimisation_precondition_code( int old_r = p_points.size());
CGAL_optimisation_precondition_code( int old_s = q_points.size());
p_points.insert( p_points.end(), p_first, p_last);
q_points.insert( q_points.end(), q_first, q_last);
set_dimension();
CGAL_optimisation_precondition_msg(
check_dimension( p_points.begin()+old_r, p_points.end())
&& check_dimension( q_points.begin()+old_s, q_points.end()),
"Not all points have the same dimension.");
compute_distance(); }
template < class InputIterator >
void
insert_p( InputIterator p_first, InputIterator p_last)
{ CGAL_optimisation_precondition_code( int old_r = p_points.size());
p_points.insert( p_points.end(), p_first, p_last);
set_dimension();
CGAL_optimisation_precondition_msg(
check_dimension( p_points.begin()+old_r, p_points.end()),
"Not all points have the same dimension.");
compute_distance(); }
template < class InputIterator >
void
insert_q( InputIterator q_first, InputIterator q_last)
{ CGAL_optimisation_precondition_code( int old_s = q_points.size());
q_points.insert( q_points.end(), q_first, q_last);
set_dimension();
CGAL_optimisation_precondition_msg(
check_dimension( q_points.begin()+old_s, q_points.end()),
"Not all points have the same dimension.");
compute_distance(); }
void
clear( )
{ p_points.erase( p_points.begin(), p_points.end());
q_points.erase( q_points.begin(), q_points.end());
compute_distance(); }
// validity check
bool is_valid( bool verbose = false, int level = 0) const;
// traits class access
const Traits& traits( ) const { return tco; }
private:
Traits tco; // traits class object
Point_vector p_points; // points of P
Point_vector q_points; // points of Q
int d; // dimension of input points
ET_vector p_coords; // realizing point of P
ET_vector q_coords; // realizing point of Q
Solver *solver; // quadratic programming solver
Pricing_strategy *strategy; // ...and its pricing strategy
Index_vector p_support_indices;
Index_vector q_support_indices;
NT_matrix a_matrix; // matrix `A' of QP
private:
// set dimension of input points
void
set_dimension( )
{ d = ( p_points.size() > 0 ?
tco.access_dimension_d_object()( p_points[ 0]) :
q_points.size() > 0 ?
tco.access_dimension_d_object()( q_points[ 0]) :
-1); }
// check dimension of input points
template < class InputIterator >
bool
check_dimension( InputIterator first, InputIterator last)
{ return ( std::find_if( first, last,
CGAL::compose1_1( std::bind2nd(
std::not_equal_to<int>(), d),
tco.access_dimension_d_object()))
== last); }
// compute (squared) distance
void
compute_distance( )
{
// clear support points
p_support_indices.erase( p_support_indices.begin(),
p_support_indices.end());
q_support_indices.erase( q_support_indices.begin(),
q_support_indices.end());
if ( ( p_points.size() == 0) || ( q_points.size() == 0)) return;
// set up and solve QP
int i, j;
NT nt_0 = 0, nt_1 = 1;
// matrix A
a_matrix.erase( a_matrix.begin(), a_matrix.end());
a_matrix.insert( a_matrix.end(),
number_of_points(), NT_vector( 2, nt_0));
for ( j = 0; j < number_of_points_p(); ++j) a_matrix[ j][ 0] = nt_1;
for ( ; j < number_of_points (); ++j) a_matrix[ j][ 1] = nt_1;
// set-up
typedef QP_rep_signed_point_iterator< Point, Point_iterator >
Signed_point_iterator;
Signed_point_iterator
signed_pts_it(p_points.begin(), p_points.size(), q_points.begin());
QP_rep_row_of_d< NT, Point, Signed_point_iterator,
Access_coordinates_begin_d, Access_dimension_d >
row_of_d( signed_pts_it,
tco.access_coordinates_begin_d_object(),
tco.access_dimension_d_object());
typedef typename QP_rep::A_iterator A_it;
typedef typename QP_rep::B_iterator B_it;
typedef typename QP_rep::C_iterator C_it;
typedef typename QP_rep::D_iterator D_it;
typedef typename QP_rep::Row_type_iterator Row_it;
strategy = pricing_strategy(NT());
solver = new Solver(number_of_points(), 2,
A_it( a_matrix.begin()), B_it( 1), C_it( 0),
D_it( signed_pts_it, row_of_d),
Row_it(QP_rep::EQUAL), strategy);
// compute support and realizing points
ET et_0 = 0;
int r = number_of_points_p();
p_coords.resize( ambient_dimension()+1);
q_coords.resize( ambient_dimension()+1);
std::fill( p_coords.begin(), p_coords.end(), et_0);
std::fill( q_coords.begin(), q_coords.end(), et_0);
for ( i = 0; i < solver->number_of_basic_variables(); ++i) {
ET value = solver->basic_original_variables_numerator_begin()[ i];
int index = solver->basic_original_variables_index_begin()[ i];
if ( index < r) {
for ( int j = 0; j < d; ++j) {
p_coords[ j]
+= value * tco.access_coordinates_begin_d_object()(
p_points[ index ])[ j];
}
p_support_indices.push_back( index);
} else {
for ( int j = 0; j < d; ++j) {
q_coords[ j]
+= value * tco.access_coordinates_begin_d_object()(
q_points[ index-r])[ j];
}
q_support_indices.push_back( index-r);
}
}
p_coords[ d] = q_coords[ d] = solver->variables_common_denominator();
}
template < class NT >
Pricing_strategy *pricing_strategy( NT) {
return new QP_partial_filtered_pricing<QP_rep>;
}
Pricing_strategy *pricing_strategy( ET) {
return new QP_partial_exact_pricing<QP_rep>;
}
};
template < class Point, class PointIterator >
struct QP_rep_signed_point_iterator {
public:
typedef std::pair<Point,CGAL::Sign> value_type;
typedef ptrdiff_t difference_type;
typedef value_type* pointer;
typedef value_type& reference;
typedef std::random_access_iterator_tag iterator_category;
typedef QP_rep_signed_point_iterator<Point,PointIterator> Self;
typedef value_type Val;
typedef difference_type Dist;
typedef pointer Ptr;
// forward operations
QP_rep_signed_point_iterator() {}
QP_rep_signed_point_iterator(const PointIterator& it_p, Dist n_p,
const PointIterator& it_q)
: p_it( it_p), q_it( it_q), n( n_p), curr( 0) { }
bool operator == ( const Self& it) const { return (curr == it.curr);}
bool operator != ( const Self& it) const { return (curr != it.curr);}
Val operator * ( ) const
{ return ( curr < n) ? std::make_pair( *p_it, CGAL::POSITIVE)
: std::make_pair( *q_it, CGAL::NEGATIVE); }
Self& operator ++ ( )
{ if ( ++curr <= n) ++p_it; else ++q_it; return *this; }
Self operator ++ ( int)
{ Self tmp = *this; operator++(); return tmp; }
// bidirectional operations
Self& operator -- ( )
{ if ( --curr < n) --p_it; else --q_it; return *this; }
Self operator -- ( int)
{ Self tmp = *this; operator--(); return tmp; }
// random access operations
Self& operator += ( Dist i)
{
if ( curr+i <= n) {
curr += i;
p_it += i;
} else {
if ( curr < n) p_it += n-curr;
curr += i;
q_it += curr-n;
}
return *this;
}
Self& operator -= ( Dist i)
{
if ( curr-i < n) {
if ( curr > n) q_it -= curr-n;
curr -= i;
p_it -= n-curr;
} else {
curr -= i;
q_it -= i;
}
return *this;
}
Self operator + ( Dist i) const { Self tmp = *this; return tmp+=i; }
Self operator - ( Dist i) const { Self tmp = *this; return tmp-=i; }
Dist operator - ( const Self& it) const { return curr - it.curr; }
Val operator [] ( int i) const
{ return ( curr+i < n)
? std::make_pair( p_it[ i ], CGAL::POSITIVE)
: std::make_pair( q_it[ i-n], CGAL::NEGATIVE); }
bool operator < ( const Self& it) const { return ( curr < it.curr); }
bool operator > ( const Self& it) const { return ( curr > it.curr); }
bool operator <= ( const Self& it) const { return ( curr <= it.curr); }
bool operator >= ( const Self& it) const { return ( curr >= it.curr); }
private:
PointIterator p_it;
PointIterator q_it;
Dist n;
Dist curr;
};
template < class NT, class Point,
class Access_coord, class Access_dim >
class QP_rep_signed_inner_product {
Point p_i;
CGAL::Sign s_i;
Access_coord da_coord;
Access_dim da_dim;
public:
typedef std::pair<Point,CGAL::Sign> argument_type;
typedef NT result_type;
QP_rep_signed_inner_product( ) { }
QP_rep_signed_inner_product( const argument_type& p_signed,
const Access_coord& ac,
const Access_dim& ad)
: p_i( p_signed.first), s_i( p_signed.second),
da_coord( ac), da_dim( ad) { }
NT operator( ) ( const argument_type& p_signed) const
{ NT ip = std::inner_product( da_coord( p_i),
da_coord( p_i)+da_dim( p_i),
da_coord( p_signed.first), NT( 0),
std::plus<NT>(),
std::multiplies<NT>());
return ( s_i*p_signed.second == CGAL::POSITIVE) ? ip : -ip; }
};
template < class NT, class Point, class Signed_point_iterator,
class Access_coord, class Access_dim >
class QP_rep_row_of_d {
Signed_point_iterator signed_pts_it;
Access_coord da_coord;
Access_dim da_dim;
public:
typedef CGAL::QP_rep_signed_inner_product<
NT, Point, Access_coord, Access_dim >
Signed_inner_product;
typedef CGAL::Join_input_iterator_1<
Signed_point_iterator, Signed_inner_product >
Row_of_d;
typedef std::pair<Point,CGAL::Sign>
argument_type;
typedef Row_of_d result_type;
QP_rep_row_of_d( ) { }
QP_rep_row_of_d( const Signed_point_iterator& it,
const Access_coord& ac,
const Access_dim& ad)
: signed_pts_it( it), da_coord( ac), da_dim( ad) { }
Row_of_d operator( ) ( const argument_type& p_signed) const
{ return Row_of_d( signed_pts_it,
Signed_inner_product( p_signed, da_coord, da_dim));}
};
template < class ET_, class NT_, class Point, class Point_iterator,
class Access_coord, class Access_dim >
struct QP_rep_poly_dist_d {
// (possibly inexact) number type for the pricing:
typedef NT_ NT;
// helper types:
typedef std::vector< std::vector<NT> > NT_matrix;
typedef CGAL::QP_rep_signed_point_iterator< Point, Point_iterator>
Signed_point_iterator;
// stuff required by concept QPSolverTraits:
typedef ET_ ET;
typedef CGAL::Join_input_iterator_1<
typename NT_matrix::const_iterator,
QP_rep_row_of_a<NT> > A_iterator;
typedef CGAL::Const_oneset_iterator<NT> B_iterator;
typedef CGAL::Const_oneset_iterator<NT> C_iterator;
typedef CGAL::Join_input_iterator_1<
Signed_point_iterator,
QP_rep_row_of_d< NT, Point, Signed_point_iterator,
Access_coord, Access_dim > > D_iterator;
typedef Const_oneset_iterator<bool> FU_iterator;
typedef Const_oneset_iterator<bool> FL_iterator;
typedef Const_oneset_iterator<NT> U_iterator;
typedef Const_oneset_iterator<NT> L_iterator;
enum Row_type { LESS_EQUAL = -1, EQUAL, GREATER_EQUAL};
typedef Const_oneset_iterator<Row_type> Row_type_iterator;
typedef Tag_false Is_linear;
typedef Tag_true Is_symmetric;
typedef Tag_true Has_equalities_only_and_full_rank;
typedef Tag_true Is_in_standard_form;
};
// Function declarations
// =====================
// I/O operators
template < class Traits_ >
std::ostream&
operator << ( std::ostream& os,
const Polytope_distance_d<Traits_>& poly_dist);
template < class Traits_ >
std::istream&
operator >> ( std::istream& is,
Polytope_distance_d<Traits_>& poly_dist);
// ============================================================================
// Class implementation
// ====================
// validity check
template < class Traits_ >
bool
Polytope_distance_d<Traits_>::
is_valid( bool verbose, int level) const
{
using namespace std;
CGAL::Verbose_ostream verr( verbose);
verr << "CGAL::Polytope_distance_d<Traits>::" << endl;
verr << "is_valid( true, " << level << "):" << endl;
verr << " |P+Q| = " << number_of_points_p()
<< '+' << number_of_points_q()
<< ", |S| = " << number_of_support_points_p()
<< '+' << number_of_support_points_q() << endl;
if ( is_finite()) {
// check QP solver
CGAL_optimisation_assertion(solver);
if (!solver->is_valid())
return CGAL::_optimisation_is_valid_fail(
verr,
"underlying QP_solver is in invalid state");
// compute normal vector
ET_vector normal( d), diff( d);
ET et_0 = 0, den = solver->variables_common_denominator();
int i, j;
for ( j = 0; j < d; ++j) normal[ j] = p_coords[ j] - q_coords[ j];
// check P
// -------
verr << " checking P..." << flush;
// check point set
for ( i = 0; i < number_of_points_p(); ++i) {
for ( j = 0; j < d; ++j) {
diff[ j] = p_coords[ j] - den
* tco.access_coordinates_begin_d_object()( p_points[ i])[ j];
}
if ( std::inner_product( diff.begin(), diff.end(),
normal.begin(), et_0) > et_0)
return CGAL::_optimisation_is_valid_fail( verr,
"polytope P is not separated by its hyperplane");
}
verr << "passed." << endl;
// check Q
// -------
verr << " checking Q..." << flush;
// check point set
for ( i = 0; i < number_of_points_q(); ++i) {
for ( j = 0; j < d; ++j) {
diff[ j] = q_coords[ j] - den
* tco.access_coordinates_begin_d_object()( q_points[ i])[ j];
}
if ( std::inner_product( diff.begin(), diff.end(),
normal.begin(), et_0) < et_0)
return CGAL::_optimisation_is_valid_fail( verr,
"polytope Q is not separated by its hyperplane");
}
verr << "passed." << endl;
}
verr << " object is valid!" << endl;
return( true);
}
// output operator
template < class Traits_ >
std::ostream&
operator << ( std::ostream& os,
const Polytope_distance_d<Traits_>& poly_dist)
{
using namespace std;
typedef typename Polytope_distance_d<Traits_>::Point Point;
typedef ostream_iterator<Point> Os_it;
typedef typename Traits_::ET ET;
typedef ostream_iterator<ET> Et_it;
switch ( CGAL::get_mode( os)) {
case CGAL::IO::PRETTY:
os << "CGAL::Polytope_distance_d( |P+Q| = "
<< poly_dist.number_of_points_p() << '+'
<< poly_dist.number_of_points_q() << ", |S| = "
<< poly_dist.number_of_support_points_p() << '+'
<< poly_dist.number_of_support_points_q() << endl;
os << " P = {" << endl;
os << " ";
copy( poly_dist.points_p_begin(), poly_dist.points_p_end(),
Os_it( os, ",\n "));
os << "}" << endl;
os << " Q = {" << endl;
os << " ";
copy( poly_dist.points_q_begin(), poly_dist.points_q_end(),
Os_it( os, ",\n "));
os << "}" << endl;
os << " S_P = {" << endl;
os << " ";
copy( poly_dist.support_points_p_begin(),
poly_dist.support_points_p_end(),
Os_it( os, ",\n "));
os << "}" << endl;
os << " S_Q = {" << endl;
os << " ";
copy( poly_dist.support_points_q_begin(),
poly_dist.support_points_q_end(),
Os_it( os, ",\n "));
os << "}" << endl;
os << " p = ( ";
copy( poly_dist.realizing_point_p_coordinates_begin(),
poly_dist.realizing_point_p_coordinates_end(),
Et_it( os, " "));
os << ")" << endl;
os << " q = ( ";
copy( poly_dist.realizing_point_q_coordinates_begin(),
poly_dist.realizing_point_q_coordinates_end(),
Et_it( os, " "));
os << ")" << endl;
os << " squared distance = "
<< poly_dist.squared_distance_numerator() << " / "
<< poly_dist.squared_distance_denominator() << endl;
break;
case CGAL::IO::ASCII:
os << poly_dist.number_of_points_p() << endl;
copy( poly_dist.points_p_begin(),
poly_dist.points_p_end(),
Os_it( os, "\n"));
os << poly_dist.number_of_points_q() << endl;
copy( poly_dist.points_q_begin(),
poly_dist.points_q_end(),
Os_it( os, "\n"));
break;
case CGAL::IO::BINARY:
os << poly_dist.number_of_points_p() << endl;
copy( poly_dist.points_p_begin(),
poly_dist.points_p_end(),
Os_it( os));
os << poly_dist.number_of_points_q() << endl;
copy( poly_dist.points_q_begin(),
poly_dist.points_q_end(),
Os_it( os));
break;
default:
CGAL_optimisation_assertion_msg( false,
"CGAL::get_mode( os) invalid!");
break; }
return( os);
}
// input operator
template < class Traits_ >
std::istream&
operator >> ( std::istream& is,
CGAL::Polytope_distance_d<Traits_>& poly_dist)
{
using namespace std;
/*
switch ( CGAL::get_mode( is)) {
case CGAL::IO::PRETTY:
cerr << endl;
cerr << "Stream must be in ascii or binary mode" << endl;
break;
case CGAL::IO::ASCII:
case CGAL::IO::BINARY:
typedef CGAL::Polytope_distance_d<Traits_>::Point Point;
typedef istream_iterator<Point> Is_it;
poly_dist.set( Is_it( is), Is_it());
break;
default:
CGAL_optimisation_assertion_msg( false, "CGAL::IO::mode invalid!");
break; }
*/
return( is);
}
CGAL_END_NAMESPACE
#endif // CGAL_POLYTOPE_DISTANCE_D_H
// ===== EOF ==================================================================