
/*!
\ingroup PkgPolytopeDistanceDConcepts
\cgalConcept

This concept defines the requirements for traits classes of
`CGAL::Width_3<Traits>`.

\cgalHeading{Operations}

Whatever the coordinates of the points are, it is required for the
width-algorithm to have access to the homogeneous representation of
points.

\cgalHasModelsBegin
\cgalHasModels{CGAL::Width_default_traits_3}
\cgalHasModelsEnd

\sa `CGAL::Width_3<Traits>`

*/

class WidthTraits_3 {
public:

/// \name Types
/// \note If you want to compute the width of a <I>polyhedron</I> then you have to make sure that the point type in the traits class and the point type in the polyhedron class are the same! The same holds for `Traits::Plane_3` and `Polyhedron::Plane_3`.
/// @{

/*!
The point type. The (in)equality tests must be
available. Access to the point coordinates is done via the `get_...()`
functions. Constructing a point is done with the `make_point( )`
operation.
*/
typedef unspecified_type Point_3;

/*!
The plane type. Access to the coefficients of the
plane is made via the `get_...()` functions. Constructing a plane is
done with the `make_plane()` operation.
*/
typedef unspecified_type Plane_3;

/*!
The vector type. There is no need to access the
coefficients of a vector; only constructing is required and is done with
the `make_vector` operation.
*/
typedef unspecified_type Vector_3;

/*!
The traits class for using the convex hull
algorithm. It must be a model of the concept ConvexHullTraits_3.
This class is used only if the width is computed from a set
of points.
*/
typedef unspecified_type ChullTraits;

/*!
Ring type numbers. Internally all numbers are treated as
ring type numbers, i.e., neither \f$ /\f$-operator nor \f$ \sqrt{.}\f$ nor other
inexact operations are used. But because the algorithm does not use any
divisions, but multiplication instead, the numbers can get really big.
Therefore it is recommended to use a ring type number, that provides
values of arbitrary length. Furthermore it is assumed that the underlying
number type of `Point_3`, `Plane_3` and `Vector_3` equals
`RT`.
*/
typedef unspecified_type RT;

/// @}

/// \name Creation
/// Only a default constructor is required.
/// @{

/*!

*/
WidthTraits_3( );

/*!
returns the
homogeneous \f$ x\f$-coordinate of point \f$ p\f$.
*/
RT get_hx(const Point_3& p) const;

/*!
returns the
homogeneous \f$ y\f$-coordinate of point \f$ p\f$.
*/
RT get_hy(const Point_3& p) const;

/*!
returns the
homogeneous \f$ z\f$-coordinate of point \f$ p\f$.
*/
RT get_hz(const Point_3& p) const;

/*!
returns the
homogenizing coordinate of point \f$ p\f$.
*/
RT get_hw(const Point_3& p) const;

/*!
returns all homogeneous coordinates
of point \f$ p\f$ at once.
*/
void get_point_coordinates(const Point_3& p, RT& px,
RT& py, RT& pz, RT& ph) const;

/*!
returns the first
coefficient of plane \f$ f\f$.
*/
RT get_a(const Plane_3& f) const;

/*!
returns the second
coefficient of plane \f$ f\f$.
*/
RT get_b(const Plane_3& f) const;

/*!
returns the third
coefficient of plane \f$ f\f$.
*/
RT get_c(const Plane_3& f) const;

/*!
returns the fourth
coefficient of plane \f$ f\f$.
*/
RT get_d(const Plane_3& f) const;

/*!
returns all four plane coefficients of \f$ f\f$ at once.
*/
void get_plane_coefficients(const Plane_3& f,
RT& a, RT& b, RT& c, RT& d)
const;

/// @}

}; /* end WidthTraits_3 */

/*!
returns a point of type
`Point_3` with homogeneous coordinates \f$ hx\f$, \f$ hy\f$, \f$ hz\f$ and \f$ hw\f$.
\relates WidthTraits_3
*/
Point_3 make_point(const RT& hx, const RT& hy, const RT& hz,
const RT& hw) const;

/*!
returns a plane of type `Plane_3`
with coefficients \f$ a\f$, \f$ b\f$, \f$ c\f$ and \f$ d\f$.
\relates WidthTraits_3
*/
Plane_3 make_plane(const RT& a, const RT& b, const
RT& c, const RT& d) const;

/*!
returns a vector of type `Vector_3` with the four
homogeneous coefficients \f$ a\f$, \f$ b\f$, \f$ c\f$ and 1.
\relates WidthTraits_3
*/
Vector_3 make_vector(const RT& a, const RT& b, const
RT& c) const;
