\( \newcommand{\E}{\mathrm{E}} \) \( \newcommand{\A}{\mathrm{A}} \) \( \newcommand{\R}{\mathrm{R}} \) \( \newcommand{\N}{\mathrm{N}} \) \( \newcommand{\Q}{\mathrm{Q}} \) \( \newcommand{\Z}{\mathrm{Z}} \) \( \def\ccSum #1#2#3{ \sum_{#1}^{#2}{#3} } \def\ccProd #1#2#3{ \sum_{#1}^{#2}{#3} }\)
CGAL 4.14.1 - Optimal Distances
CGAL::Width_3< Traits > Class Template Reference

#include <CGAL/Width_3.h>

Definition

Given a set of points \( \mathcal{S}=\left\{p_1,\ldots , p_n\right\}\) in \( \mathbb{R}^3\).

The width of \( \mathcal{S}\), denoted as \( \mathcal{W(S)}\), is defined as the minimum distance between two parallel planes of support of \( \mathit{conv(\mathcal{S})}\); where \( \mathit{conv(\mathcal{S})}\) denotes the convex hull of \( \mathcal{S}\). The width in direction \( \mathbf{d}\), denoted as \( \mathcal{W}_d\mathcal{(S)}\), is the distance between two parallel planes of support of \( \mathit{conv(\mathcal{S})}\), which are orthogonal to \( \mathbf{d}\).

Subject to the applications of the width algorithm, several objects might be interesting:

  1. The two parallel planes of support such that the distance between them is as small as possible. These planes are called width-planes in further considerations.
  2. The width \( \mathcal{W(S)}\), i.e., the distance between the width-planes.
  3. The direction \( \mathbf{d}_{opt}\) such that \( \mathcal{W(S)}=\mathcal{W}_{d_{opt}}\mathcal{(S)}\)

Note: There might be several optimal build directions. Hence neither the width-planes nor the direction \( \mathbf{d}_{opt}\) are unique - only the width is.

Template Parameters
Traitsmust be a model for WidthTraits_3.

We provide the model Width_default_traits_3<Kernel> based on a three-dimensional CGAL kernel.

See also
CGAL::Width_default_traits_3<K>
WidthTraits_3

Implementation

Since the width of the point set \( \mathcal{S}\) and the width of the convex hull of \( \mathcal{S}\) ( \( \mathit{conv(\mathcal{S})}\)) is the same, the algorithm uses the 3D convex hull algorithm CGAL provides.

The width-algorithm is not incremental and therefore inserting and erasing points cause not an 'automatic' update of the width. Instead you have to run the width-algorithm again even if the point set is extended by only one new point.

Large Numbers.

Because there is no need for dividing values during the algorithm, the numbers can get really huge (all the computations are made using a lot of multiplications). Therefore it is strongly recommended to use a number type that can handle numbers of arbitrary length (e.g., leda_integer in combination with the homogeneous representation of the points). But these large numbers have a disadvantage: Operations on them are slower as greater the number gets. Therefore it is possible to shorten the numbers by using the compiler flag -Dsimplify. For using this option it is required that the underlying number type provides the 'modulo' operation.

Information Output during the Computations.

If during the algorithm the program should output some information (e.g., during the debugging phase) you can turn on the output information by giving the compiler flag debug. In the file width_assertions.h you can turn on/off the output of some functions and additional informations by changing the defined values from 0 (no output) to 1 (output available). But then it is required that the operator<<() has to been overloaded for Point_3, Plane_3, Vector_3 and RT.

Example


File Polytope_distance_d/width_simplex.cpp

#include <CGAL/Homogeneous.h>
#include <CGAL/Width_default_traits_3.h>
#include <CGAL/Width_3.h>
#include <iostream>
#include <vector>
#if defined(CGAL_USE_GMP)
#include <CGAL/Gmpz.h>
typedef CGAL::Gmpz RT;
#elif defined (CGAL_USE_LEDA)
#include <CGAL/leda_integer.h>
typedef leda_integer RT;
#else
#include <CGAL/MP_Float.h>
typedef CGAL::MP_Float RT;
#endif
int main() {
// Create a simplex using homogeneous integer coordinates
std::vector<Point_3> points;
points.push_back( Point_3(2,0,0,1));
points.push_back( Point_3(0,1,0,1));
points.push_back( Point_3(0,0,1,1));
points.push_back( Point_3(0,0,0,1));
// Compute width of simplex
Width simplex( points.begin(), points.end());
// Output of squared width, width-planes, and optimal direction
RT wnum, wdenom;
simplex.get_squared_width( wnum, wdenom);
std::cout << "Squared Width: " << wnum << "/" << wdenom << std::endl;
std::cout << "Direction: " << simplex.get_build_direction() << std::endl;
Plane_3 e1, e2;
simplex.get_width_planes (e1, e2);
std::cout << "Planes: E1: " << e1 << ". E2: " << e2 <<std::endl;
std::cout << "Number of optimal solutions: "
<< simplex.get_number_of_optimal_solutions() << std::endl;
return(0);
}
Examples:
Polytope_distance_d/width_simplex.cpp.

Types

typedef Traits::Point_3 Point_3
 point type.
 
typedef Traits::Plane_3 Plane_3
 plane type.
 
typedef Traits::Vector_3 Vector_3
 vector type.
 
typedef Traits::RT RT
 algebraic ring type.
 
typedef Traits::ChullTraits ChullTraits
 traits class for the 3D convex hull algorithm.
 

Creation

template<class InputIterator >
 Width_3 (InputIterator first, InputIterator beyond)
 creates a variable width initialized to the width of \( \mathcal{S}\) - with \( \mathcal{S}\) being the set of points in the range [first,beyond). More...
 
template<class Polyhedron >
 Width_3 (Polyhedron &P)
 creates a variable width initialized to the width of the polyhedron \( P\). More...
 

Access Functions

void get_squared_width (RT &width_num, RT &width_denom)
 returns the squared width. More...
 
void get_width_planes (Plane_3 &e1, Plane_3 &e2)
 The planes e1 and e2 are the two parallel supporting planes, which distance is minimal (among all such planes).
 
void get_width_coefficients (RT &A, RT &B, RT &C, RT &D, RT &K)
 The returned coefficients A,B,C,D,K have the property that width-plane e1 is given by the equation \( Ax+By+Cz+D=0\) and width-plane e2 by \( Ax+By+Cz+K=0\).
 
Vector_3 get_build_direction ()
 returns a direction \( \mathbf{d}_{opt}\) such that the width-planes e1 and e2 are perpendicular to \( \mathbf{d}_{opt}\). More...
 
void get_all_build_directions (std::vector< Vector_3 > &dir)
 All the build directions are stored in the vector dir. More...
 
int get_number_of_optimal_solutions ()
 returns the number of optimal solutions, i.e., the number of optimal build directions.
 

Constructor & Destructor Documentation

◆ Width_3() [1/2]

template<typename Traits >
template<class InputIterator >
CGAL::Width_3< Traits >::Width_3 ( InputIterator  first,
InputIterator  beyond 
)

creates a variable width initialized to the width of \( \mathcal{S}\) - with \( \mathcal{S}\) being the set of points in the range [first,beyond).

Template Parameters
InputIteratorhas Point_3 as value type.

◆ Width_3() [2/2]

template<typename Traits >
template<class Polyhedron >
CGAL::Width_3< Traits >::Width_3 ( Polyhedron &  P)

creates a variable width initialized to the width of the polyhedron \( P\).

Note that the vertex point coordinates are altered!

Precondition
\( P\) is a convex polyhedron.
Template Parameters
Polyhedronis a CGAL::Polyhedron_3 with facets supporting plane equations where Polyhedron::Point_3 \( \equiv\) Point_3 and Polyhedron::Plane_3 \( \equiv\) Plane_3.

Member Function Documentation

◆ get_all_build_directions()

template<typename Traits >
void CGAL::Width_3< Traits >::get_all_build_directions ( std::vector< Vector_3 > &  dir)

All the build directions are stored in the vector dir.

It might happen that a certain body has several different build directions, but it is also possible to have only one build direction.

◆ get_build_direction()

template<typename Traits >
Vector_3 CGAL::Width_3< Traits >::get_build_direction ( )

returns a direction \( \mathbf{d}_{opt}\) such that the width-planes e1 and e2 are perpendicular to \( \mathbf{d}_{opt}\).

The width of the point set is minimal in this direction.

◆ get_squared_width()

template<typename Traits >
void CGAL::Width_3< Traits >::get_squared_width ( RT width_num,
RT width_denom 
)

returns the squared width.

For the reason of exact computation not the width itself is stored, but the squared width as a fraction: The numerator in width_num and the denominator in width_denom. The width of the point set \( \mathcal{S}\) is \( \sqrt{\frac{width\_num}{width\_denom}}\).