mirror of https://github.com/CGAL/cgal
Update code/doc after pre-review
This commit is contained in:
parent
4f56fdff8e
commit
0ae811604a
|
|
@ -1,37 +0,0 @@
|
||||||
namespace CGAL {
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\ingroup PkgOptimalBoundingBoxConcepts
|
|
||||||
\cgalConcept
|
|
||||||
|
|
||||||
The concept `OptimalBoundingBoxTraits` describes the requirements of the traits class
|
|
||||||
used in the function `CGAL::optimal_bounding_box()`, and in particular the need for
|
|
||||||
a 3x3 matrix type with a number of supporting functions (determinant and transposed matrix
|
|
||||||
computations, etc.).
|
|
||||||
|
|
||||||
\cgalRefines `Kernel`
|
|
||||||
|
|
||||||
\cgalHasModel `CGAL::Optimal_bounding_box::Optimal_bounding_box_traits`
|
|
||||||
|
|
||||||
*/
|
|
||||||
class OptimalBoundingBoxTraits
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/// The field number type; must be a model of the concept `FieldNumberType`.
|
|
||||||
typedef unspecified_type FT;
|
|
||||||
|
|
||||||
/// A 3x3 matrix type; must be a model of the concept `SvdTraits::Matrix` and support
|
|
||||||
/// matrix-matrix and scalar-matrix multiplication, as well as matrix-matrix addition.
|
|
||||||
typedef unspecified_type Matrix;
|
|
||||||
|
|
||||||
/// Returns the transpose of a matrix.
|
|
||||||
Matrix transpose(const Matrix& mat) const;
|
|
||||||
|
|
||||||
/// Returns the determinant of a matrix.
|
|
||||||
FT compute_determinant(const Matrix& matrix) const;
|
|
||||||
|
|
||||||
/// Returns the unary matrix Q obtained in the QR decompoisiton of the matrix `A`.
|
|
||||||
Matrix get_Q(const Matrix& A) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace CGAL
|
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
namespace CGAL {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\ingroup PkgOrientedBoundingBoxConcepts
|
||||||
|
\cgalConcept
|
||||||
|
|
||||||
|
The concept `OrientedBoundingBoxTraits` describes the requirements of the traits class
|
||||||
|
used in the function `CGAL::oriented_bounding_box()`, and in particular the need for
|
||||||
|
a 3x3 matrix type with a number of supporting functions (determinant and transposed matrix
|
||||||
|
computations, etc.).
|
||||||
|
|
||||||
|
\cgalRefines `Kernel`
|
||||||
|
|
||||||
|
\cgalHasModel `CGAL::Oriented_bounding_box_traits`
|
||||||
|
|
||||||
|
*/
|
||||||
|
class OrientedBoundingBoxTraits
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// The field number type; must be a model of the concept `FieldNumberType`.
|
||||||
|
typedef unspecified_type FT;
|
||||||
|
|
||||||
|
/// The 3D point type; must be model of `Point_3`
|
||||||
|
typedef unspecified_type Point_3;
|
||||||
|
|
||||||
|
/// A construction object that must provide the function operator:
|
||||||
|
/// `CGAL::Bbox_3 operator()(const Point_3&)`,
|
||||||
|
/// which returns an axis-aligned bounding that contains the point
|
||||||
|
typedef unspecified_type Construct_bbox_3;
|
||||||
|
|
||||||
|
/// A 3x3 matrix type; model of the concept `SvdTraits::Matrix` and which supports
|
||||||
|
/// matrix-matrix and scalar-matrix multiplication, as well as matrix-matrix addition.
|
||||||
|
typedef unspecified_type Matrix;
|
||||||
|
|
||||||
|
/// Returns the transpose of a matrix.
|
||||||
|
Matrix transpose(const Matrix& mat) const;
|
||||||
|
|
||||||
|
/// Returns the determinant of a matrix.
|
||||||
|
FT compute_determinant(const Matrix& matrix) const;
|
||||||
|
|
||||||
|
/// Returns the unary matrix Q obtained in the QR decomposition of the matrix `A`.
|
||||||
|
Matrix get_Q(const Matrix& A) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace CGAL
|
||||||
|
|
@ -45,7 +45,7 @@ is the geometric traits instance in which the mesh processing operation should b
|
||||||
\cgalNPEnd
|
\cgalNPEnd
|
||||||
|
|
||||||
\cgalNPBegin{use_convex_hull} \anchor OBB_use_convex_hull
|
\cgalNPBegin{use_convex_hull} \anchor OBB_use_convex_hull
|
||||||
Parameter used in optimal bounding box construction to indicate whether the algorithm should
|
Parameter used in the construction of oriented bounding box to indicate whether the algorithm should
|
||||||
first extract the extreme points (points that are on the 3D convex hull) of the input data range
|
first extract the extreme points (points that are on the 3D convex hull) of the input data range
|
||||||
to accelerate the computation of the bounding box.
|
to accelerate the computation of the bounding box.
|
||||||
\n
|
\n
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,9 @@
|
||||||
/// \defgroup PkgOptimalBoundingBoxFunctions Optimal Bounding Box Methods
|
/// \defgroup PkgOptimalBoundingBoxFunctions Optimal Bounding Box Methods
|
||||||
/// \ingroup PkgOptimalBoundingBoxRef
|
/// \ingroup PkgOptimalBoundingBoxRef
|
||||||
|
|
||||||
|
/// \defgroup PkgOptimalBoundingBox_Oriented_bounding_box Oriented Bounding Box Methods
|
||||||
|
/// \ingroup PkgOptimalBoundingBoxFunctions
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\addtogroup PkgOptimalBoundingBoxRef
|
\addtogroup PkgOptimalBoundingBoxRef
|
||||||
\cgalPkgDescriptionBegin{Optimal Bounding Box,PkgOptimalBoundingBox}
|
\cgalPkgDescriptionBegin{Optimal Bounding Box,PkgOptimalBoundingBox}
|
||||||
|
|
@ -37,14 +40,14 @@ that are used in this package.
|
||||||
|
|
||||||
\cgalCRPSection{Concepts}
|
\cgalCRPSection{Concepts}
|
||||||
|
|
||||||
- `CGAL::OptimalBoundingBoxTraits`
|
- `CGAL::OrientedBoundingBoxTraits`
|
||||||
|
|
||||||
\cgalCRPSection{Classes}
|
\cgalCRPSection{Classes}
|
||||||
|
|
||||||
- `CGAL::Optimal_bounding_box::Optimal_bounding_box_traits`
|
- `CGAL::Oriented_bounding_box_traits`
|
||||||
|
|
||||||
\cgalCRPSection{Methods}
|
\cgalCRPSection{Methods}
|
||||||
|
|
||||||
- `CGAL::optimal_bounding_box()`
|
- \link PkgOptimalBoundingBox_Oriented_bounding_box `CGAL::oriented_bounding_box()` \endlink
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,14 @@
|
||||||
#include <CGAL/Surface_mesh.h>
|
#include <CGAL/Surface_mesh.h>
|
||||||
|
|
||||||
#include <CGAL/optimal_bounding_box.h>
|
#include <CGAL/optimal_bounding_box.h>
|
||||||
|
#include <CGAL/Real_timer.h>
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
|
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
|
||||||
typedef K::Point_3 Point;
|
typedef K::Point_3 Point;
|
||||||
|
typedef K::Aff_transformation_3 Aff_transformation;
|
||||||
typedef CGAL::Surface_mesh<Point> Surface_mesh;
|
typedef CGAL::Surface_mesh<Point> Surface_mesh;
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
|
|
@ -22,9 +24,21 @@ int main(int argc, char** argv)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// test one
|
Aff_transformation aff;
|
||||||
|
|
||||||
|
// API test
|
||||||
|
CGAL::Real_timer timer;
|
||||||
|
timer.start();
|
||||||
|
|
||||||
|
std::array<Point, 8> obb_points;
|
||||||
|
CGAL::oriented_bounding_box(sm, obb_points);
|
||||||
|
|
||||||
|
std::cout << "Elapsed time: " << timer.time() << std::endl;
|
||||||
|
|
||||||
|
// Make a mesh out of the oriented bounding box
|
||||||
Surface_mesh obb_sm;
|
Surface_mesh obb_sm;
|
||||||
CGAL::optimal_bounding_box(sm, obb_sm);
|
CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3],
|
||||||
|
obb_points[4], obb_points[5], obb_points[6], obb_points[7], obb_sm);
|
||||||
|
|
||||||
std::ofstream("obb.off") << obb_sm;
|
std::ofstream("obb.off") << obb_sm;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,29 +21,36 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace CGAL {
|
namespace CGAL {
|
||||||
namespace Optimal_bounding_box {
|
|
||||||
|
|
||||||
#if defined(CGAL_EIGEN3_ENABLED) || defined(DOXYGEN_RUNNING)
|
#if defined(CGAL_EIGEN3_ENABLED) || defined(DOXYGEN_RUNNING)
|
||||||
|
|
||||||
/// \ingroup PkgOptimalBoundingBoxClasses
|
/// \ingroup PkgOptimalBoundingBoxClasses
|
||||||
///
|
///
|
||||||
/// The class `CGAL::Optimal_bounding_box::Optimal_bounding_box_traits` is a traits type
|
/// The class `CGAL::Oriented_bounding_box_traits` is a traits type
|
||||||
/// to be used with the functions `CGAL::optimal_bounding_box()`.
|
/// to be used with the functions `CGAL::oriented_bounding_box()`.
|
||||||
/// It uses the third party library \ref thirdpartyEigen "Eigen", which must therefore
|
/// It uses the third party library \ref thirdpartyEigen "Eigen", which must therefore
|
||||||
/// be available on the system for this class to be used.
|
/// be available on the system for this class to be used.
|
||||||
///
|
///
|
||||||
/// \tparam K must be a model of `Kernel`
|
/// \tparam K must be a model of `Kernel`
|
||||||
///
|
///
|
||||||
/// \cgalModels `OptimalBoundingBoxTraits`
|
/// \cgalModels `OrientedBoundingBoxTraits`
|
||||||
///
|
///
|
||||||
template <typename K>
|
template <typename K>
|
||||||
class Optimal_bounding_box_traits
|
class Oriented_bounding_box_traits
|
||||||
: public K
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// The field number type
|
/// The field number type
|
||||||
typedef typename K::FT FT;
|
typedef typename K::FT FT;
|
||||||
|
|
||||||
|
/// The point type
|
||||||
|
typedef typename K::Point_3 Point_3;
|
||||||
|
|
||||||
|
/// The affine transformation type
|
||||||
|
typedef typename K::Aff_transformation_3 Aff_transformation_3;
|
||||||
|
|
||||||
|
/// The axis-aligned bounding box construction object
|
||||||
|
typedef typename K::Construct_bbox_3 Construct_bbox_3;
|
||||||
|
|
||||||
/// The matrix type
|
/// The matrix type
|
||||||
typedef CGAL::Eigen_matrix<FT, 3, 3> Matrix;
|
typedef CGAL::Eigen_matrix<FT, 3, 3> Matrix;
|
||||||
|
|
||||||
|
|
@ -52,15 +59,18 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Constructor from the base kernel
|
/// Constructor from the base kernel
|
||||||
explicit Optimal_bounding_box_traits(const K& k = K()) : K(k) { }
|
explicit Oriented_bounding_box_traits() { }
|
||||||
|
|
||||||
/// Get the transpose of a matrix
|
/// Offers `construct_bbox_3_object()(const Point_3&)`
|
||||||
|
Construct_bbox_3 construct_bbox_3_object() const { return Construct_bbox_3(); }
|
||||||
|
|
||||||
|
/// Returns the transpose of a matrix
|
||||||
Matrix transpose(const Matrix& mat) const
|
Matrix transpose(const Matrix& mat) const
|
||||||
{
|
{
|
||||||
return Matrix(mat.eigen_object().transpose());
|
return Matrix(mat.eigen_object().transpose());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the determinant of a matrix
|
/// Returns the determinant of a matrix
|
||||||
FT compute_determinant(const Matrix& matrix) const
|
FT compute_determinant(const Matrix& matrix) const
|
||||||
{
|
{
|
||||||
return matrix.eigen_object().determinant();
|
return matrix.eigen_object().determinant();
|
||||||
|
|
@ -78,7 +88,6 @@ public:
|
||||||
};
|
};
|
||||||
#endif // defined(CGAL_EIGEN3_ENABLED) || defined(DOXYGEN_RUNNING)
|
#endif // defined(CGAL_EIGEN3_ENABLED) || defined(DOXYGEN_RUNNING)
|
||||||
|
|
||||||
} // namespace Optimal_bounding_box
|
|
||||||
} // namespace CGAL
|
} // namespace CGAL
|
||||||
|
|
||||||
#endif // CGAL_OPTIMAL_BOUNDING_BOX_BOUNDING_BOX_TRAITS_H
|
#endif // CGAL_OPTIMAL_BOUNDING_BOX_BOUNDING_BOX_TRAITS_H
|
||||||
|
|
@ -49,7 +49,7 @@ public:
|
||||||
const Traits& traits)
|
const Traits& traits)
|
||||||
:
|
:
|
||||||
m_population(traits),
|
m_population(traits),
|
||||||
m_rng(rng), // @todo just a parameter of genetic_algorithm() ?
|
m_rng(rng),
|
||||||
m_points(points),
|
m_points(points),
|
||||||
m_traits(traits)
|
m_traits(traits)
|
||||||
{ }
|
{ }
|
||||||
|
|
@ -144,12 +144,12 @@ public:
|
||||||
const std::size_t population_size = 50;
|
const std::size_t population_size = 50;
|
||||||
|
|
||||||
// hardcoded nelder_mead_iterations
|
// hardcoded nelder_mead_iterations
|
||||||
const std::size_t nelder_mead_iterations = 20;
|
const std::size_t nelder_mead_iterations = 150;
|
||||||
|
|
||||||
// stopping criteria prameters
|
// stopping criteria prameters
|
||||||
double prev_fit_value = 0.;
|
double prev_fit_value = 0.;
|
||||||
double new_fit_value = 0.;
|
double new_fit_value = 0.;
|
||||||
const double tolerance = 1e-2;
|
const double tolerance = 1e-9;
|
||||||
int stale = 0;
|
int stale = 0;
|
||||||
|
|
||||||
for(std::size_t t=0; t<generations; ++t)
|
for(std::size_t t=0; t<generations; ++t)
|
||||||
|
|
@ -176,14 +176,19 @@ public:
|
||||||
//std::cout << "pop after nelder mead: " << std::endl;
|
//std::cout << "pop after nelder mead: " << std::endl;
|
||||||
//pop.show_population();
|
//pop.show_population();
|
||||||
//std::cout << std::endl;
|
//std::cout << std::endl;
|
||||||
const Matrix& R_now = fitness_map.get_best();
|
|
||||||
std::cout << "det = " << m_traits.compute_determinant(R_now) << std::endl;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
new_fit_value = fitness_map.get_best_fitness_value();
|
new_fit_value = fitness_map.get_best_fitness_value();
|
||||||
const double difference = new_fit_value - prev_fit_value;
|
const double difference = new_fit_value - prev_fit_value;
|
||||||
|
|
||||||
if(CGAL::abs(difference) < tolerance * new_fit_value)
|
#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG
|
||||||
|
const Matrix& R_now = fitness_map.get_best();
|
||||||
|
std::cout << "new best: " << R_now << std::endl;
|
||||||
|
std::cout << "det = " << m_traits.compute_determinant(R_now) << std::endl;
|
||||||
|
std::cout << "value difference with previous: " << difference << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(CGAL::abs(difference) < tolerance * new_fit_value) // @todo should depend on input bbox diag
|
||||||
++stale;
|
++stale;
|
||||||
|
|
||||||
if(stale == 5)
|
if(stale == 5)
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,8 @@ compute_fitness(const typename Traits::Matrix& R, // rotation matrix
|
||||||
CGAL_assertion(points.size() >= 3);
|
CGAL_assertion(points.size() >= 3);
|
||||||
|
|
||||||
FT xmin, ymin, zmin, xmax, ymax, zmax;
|
FT xmin, ymin, zmin, xmax, ymax, zmax;
|
||||||
xmin = ymin = zmin = std::numeric_limits<double>::max();
|
xmin = ymin = zmin = FT(std::numeric_limits<double>::max());
|
||||||
xmax = ymax = zmax = std::numeric_limits<double>::lowest();
|
xmax = ymax = zmax = FT(std::numeric_limits<double>::lowest());
|
||||||
|
|
||||||
for(const Point& pt : points)
|
for(const Point& pt : points)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,370 @@
|
||||||
|
// Copyright (c) 2018-2019 GeometryFactory (France).
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of CGAL (www.cgal.org).
|
||||||
|
//
|
||||||
|
// $URL$
|
||||||
|
// $Id$
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Author(s) : Mael Rouxel-Labbé
|
||||||
|
//
|
||||||
|
#ifndef CGAL_OPTIMAL_BOUNDING_BOX_ORIENTED_BOUNDING_BOX_H
|
||||||
|
#define CGAL_OPTIMAL_BOUNDING_BOX_ORIENTED_BOUNDING_BOX_H
|
||||||
|
|
||||||
|
#include <CGAL/license/Optimal_bounding_box.h>
|
||||||
|
|
||||||
|
#include <CGAL/Optimal_bounding_box/internal/population.h>
|
||||||
|
#include <CGAL/Optimal_bounding_box/internal/evolution.h>
|
||||||
|
#include <CGAL/Optimal_bounding_box/Oriented_bounding_box_traits.h>
|
||||||
|
|
||||||
|
#include <CGAL/boost/graph/Named_function_parameters.h>
|
||||||
|
#include <CGAL/boost/graph/named_params_helper.h>
|
||||||
|
|
||||||
|
#include <CGAL/assertions.h>
|
||||||
|
#include <CGAL/Bbox_3.h>
|
||||||
|
#include <CGAL/boost/graph/helpers.h>
|
||||||
|
#include <CGAL/convex_hull_3.h>
|
||||||
|
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||||
|
#include <CGAL/Iso_cuboid_3.h>
|
||||||
|
#include <CGAL/Kernel_traits.h>
|
||||||
|
#include <CGAL/Random.h>
|
||||||
|
#include <CGAL/Simple_cartesian.h>
|
||||||
|
|
||||||
|
#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS
|
||||||
|
#include <CGAL/Real_timer.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <iostream>
|
||||||
|
#include <iterator>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#ifdef DOXYGEN_RUNNING
|
||||||
|
#define CGAL_BGL_NP_TEMPLATE_PARAMETERS NamedParameters
|
||||||
|
#define CGAL_BGL_NP_CLASS NamedParameters
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace CGAL {
|
||||||
|
namespace Optimal_bounding_box {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
template <typename PointRange, typename Traits>
|
||||||
|
void construct_oriented_bounding_box(std::array<typename Traits::Point_3, 8>& obb_points,
|
||||||
|
const typename Traits::Aff_transformation_3& transformation,
|
||||||
|
const typename Traits::Aff_transformation_3& inverse_transformation,
|
||||||
|
const PointRange& points,
|
||||||
|
const Traits& traits)
|
||||||
|
{
|
||||||
|
typedef typename Traits::FT FT;
|
||||||
|
typedef typename Traits::Point_3 Point;
|
||||||
|
|
||||||
|
// Construct the bbox of the transformed point set
|
||||||
|
CGAL::Bbox_3 bbox;
|
||||||
|
for(const Point& pt : points)
|
||||||
|
{
|
||||||
|
const Point rotated_pt = transformation.transform(pt);
|
||||||
|
bbox += traits.construct_bbox_3_object()(rotated_pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
obb_points[0] = Point(bbox.xmin(), bbox.ymin(), bbox.zmin());
|
||||||
|
obb_points[1] = Point(bbox.xmax(), bbox.ymin(), bbox.zmin());
|
||||||
|
obb_points[2] = Point(bbox.xmax(), bbox.ymax(), bbox.zmin());
|
||||||
|
obb_points[3] = Point(bbox.xmin(), bbox.ymax(), bbox.zmin());
|
||||||
|
|
||||||
|
obb_points[4] = Point(bbox.xmin(), bbox.ymax(), bbox.zmax()); // see order in make_hexahedron()...
|
||||||
|
obb_points[5] = Point(bbox.xmin(), bbox.ymin(), bbox.zmax());
|
||||||
|
obb_points[6] = Point(bbox.xmax(), bbox.ymin(), bbox.zmax());
|
||||||
|
obb_points[7] = Point(bbox.xmax(), bbox.ymax(), bbox.zmax());
|
||||||
|
|
||||||
|
// Apply the inverse rotation to the rotated axis aligned bounding box
|
||||||
|
for(std::size_t i=0; i<8; ++i)
|
||||||
|
obb_points[i] = inverse_transformation.transform(obb_points[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename PointRange, typename Traits>
|
||||||
|
void compute_best_transformation(typename Traits::Aff_transformation_3& transformation,
|
||||||
|
typename Traits::Aff_transformation_3& inverse_transformation,
|
||||||
|
const PointRange& points,
|
||||||
|
CGAL::Random& rng,
|
||||||
|
const Traits& traits)
|
||||||
|
{
|
||||||
|
typedef typename Traits::Matrix Matrix;
|
||||||
|
typedef typename Traits::Aff_transformation_3 Aff_transformation_3;
|
||||||
|
|
||||||
|
const std::size_t max_generations = 50; // @todo hidden NP
|
||||||
|
|
||||||
|
#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS
|
||||||
|
CGAL::Real_timer timer;
|
||||||
|
timer.start();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Evolution<PointRange, Traits> search_solution(points, rng, traits);
|
||||||
|
search_solution.evolve(max_generations);
|
||||||
|
|
||||||
|
#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS
|
||||||
|
std::cout << "evolve: " << timer.time() << std::endl;
|
||||||
|
timer.reset();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const Matrix& rot = search_solution.get_best();
|
||||||
|
|
||||||
|
#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS
|
||||||
|
std::cout << "get best: " << timer.time() << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
transformation = Aff_transformation_3(rot(0, 0), rot(0, 1), rot(0, 2),
|
||||||
|
rot(1, 0), rot(1, 1), rot(1, 2),
|
||||||
|
rot(2, 0), rot(2, 1), rot(2, 2));
|
||||||
|
|
||||||
|
// inverse transformation is simply the transposed since the matrix is unary
|
||||||
|
inverse_transformation = Aff_transformation_3(rot(0, 0), rot(1, 0), rot(2, 0),
|
||||||
|
rot(0, 1), rot(1, 1), rot(2, 1),
|
||||||
|
rot(0, 2), rot(1, 2), rot(2, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Following two functions are overload to dispatch depending on return type
|
||||||
|
template <typename PointRange, typename Traits>
|
||||||
|
void construct_oriented_bounding_box(typename Traits::Aff_transformation_3& transformation,
|
||||||
|
const PointRange& points,
|
||||||
|
CGAL::Random& rng,
|
||||||
|
const Traits& traits)
|
||||||
|
{
|
||||||
|
typename Traits::Aff_transformation_3 inverse_transformation;
|
||||||
|
compute_best_transformation(transformation, inverse_transformation, points, rng, traits);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename PointRange, typename Traits>
|
||||||
|
void construct_oriented_bounding_box(std::array<typename Traits::Point_3, 8>& obb_points,
|
||||||
|
const PointRange& points,
|
||||||
|
CGAL::Random& rng,
|
||||||
|
const Traits& traits)
|
||||||
|
{
|
||||||
|
typename Traits::Aff_transformation_3 transformation, inverse_transformation;
|
||||||
|
compute_best_transformation(transformation, inverse_transformation, points, rng, traits);
|
||||||
|
|
||||||
|
construct_oriented_bounding_box(obb_points, transformation, inverse_transformation, points, traits);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Entry point, decide whether to compute the CH_3 or not
|
||||||
|
template <typename Output, typename PointRange, typename Traits>
|
||||||
|
void construct_oriented_bounding_box(Output& output,
|
||||||
|
const bool use_ch,
|
||||||
|
const PointRange& points,
|
||||||
|
CGAL::Random& rng,
|
||||||
|
const Traits& traits)
|
||||||
|
{
|
||||||
|
typedef typename Traits::Matrix Matrix;
|
||||||
|
typedef typename Traits::Point_3 Point;
|
||||||
|
|
||||||
|
CGAL_static_assertion((std::is_same<typename boost::range_value<PointRange>::type, Point>::value));
|
||||||
|
|
||||||
|
if(use_ch) // construct the convex hull to reduce the number of points
|
||||||
|
{
|
||||||
|
std::vector<Point> ch_points;
|
||||||
|
extreme_points_3(points, std::back_inserter(ch_points));
|
||||||
|
std::cout << "points on CH: " << ch_points.size() << std::endl;
|
||||||
|
return construct_oriented_bounding_box(output, ch_points, rng, traits);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return construct_oriented_bounding_box(output, points, rng, traits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Optimal_bounding_box
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
/// \addtogroup PkgOptimalBoundingBox_Oriented_bounding_box
|
||||||
|
///
|
||||||
|
/// The function `oriented_bounding_box` computes an approximation of the <i>optimal bounding box</i>,
|
||||||
|
/// which is defined as the rectangular box with smallest volume of all the rectangular boxes containing
|
||||||
|
/// the input points.
|
||||||
|
///
|
||||||
|
/// Internally, the algorithm uses an optimization process to find a transformation (rotation)
|
||||||
|
/// \f$ {\mathcal R}_b\f$ such that the axis-aligned box of the rotated input point set
|
||||||
|
/// has a volume that is as small as possible.
|
||||||
|
///
|
||||||
|
/// \cgalHeading{Input}
|
||||||
|
///
|
||||||
|
/// The input can be either a range of points, or a polygon mesh.
|
||||||
|
///
|
||||||
|
/// \cgalHeading{Output}
|
||||||
|
///
|
||||||
|
/// The result of the algorithm can be obtained as either:
|
||||||
|
/// - the best affine transformation (\f$ {\mathcal R}_b\f$) that the algorithm has found;
|
||||||
|
/// - an array of eight points, representing the best oriented bounding box (\f$ {\mathcal B}_b\f$)
|
||||||
|
/// that the algorithm has constructed, which is related to (\f$ {\mathcal R}_b\f$) as it is
|
||||||
|
/// the inverse transformation of the axis-aligned bounding box of the transformed point set.
|
||||||
|
/// The order of the points in the array is the same as in the function
|
||||||
|
/// \link PkgBGLHelperFct `CGAL::make_hexahedron()` \endlink,
|
||||||
|
/// which is a useful function to construct a mesh from these points.
|
||||||
|
///
|
||||||
|
/// Note that when returning an array of points, these points are constructed from the axis-aligned
|
||||||
|
/// bounding box and some precision loss should be expected if a kernel not providing exact constructions
|
||||||
|
/// is used.
|
||||||
|
|
||||||
|
/// \ingroup PkgOptimalBoundingBox_Oriented_bounding_box
|
||||||
|
///
|
||||||
|
/// See above.
|
||||||
|
///
|
||||||
|
/// \tparam PointRange a model of `Range`
|
||||||
|
/// \tparam Output `std::array<Point, 8>` with `Point` being equivalent to the traits' `Point_3` type,
|
||||||
|
/// or `CGAL::Affine_transformation_3<K>` with `K` being a kernel compatible with the point type.
|
||||||
|
/// \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters"
|
||||||
|
///
|
||||||
|
/// \param points the input points
|
||||||
|
/// \param out the resulting array of points or affine transformation
|
||||||
|
/// \param np an optional sequence of \ref obb_namedparameters "Named Parameters" among the ones listed below:
|
||||||
|
///
|
||||||
|
/// \cgalNamedParamsBegin
|
||||||
|
/// \cgalParamBegin{vertex_point_map}
|
||||||
|
/// the property map with the points associated to the vertices of `pmesh`.
|
||||||
|
/// If this parameter is omitted, an internal property map for
|
||||||
|
/// `CGAL::vertex_point_t` must be available in `PolygonMesh`
|
||||||
|
/// \cgalParamEnd
|
||||||
|
/// \cgalParamBegin{geom_traits}
|
||||||
|
/// a geometric traits class instance, model of the concept `OrientedBoundingBoxTraits`.
|
||||||
|
/// %Default is `CGAL::Oriented_bounding_box_traits<K>` where `K` is deduced from the point type.
|
||||||
|
/// \cgalParamEnd
|
||||||
|
/// \cgalParamBegin{use_convex_hull}
|
||||||
|
/// a Boolean value to indicate whether the algorithm should first extract the so-called extreme
|
||||||
|
/// points of the data range (i.e. construct the convex hull) to reduce the input data range
|
||||||
|
/// and accelerate the algorithm. %Default is `true`.
|
||||||
|
/// \cgalParamEnd
|
||||||
|
/// \cgalNamedParamsEnd
|
||||||
|
///
|
||||||
|
template <typename PointRange,
|
||||||
|
typename Output,
|
||||||
|
typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
|
||||||
|
void oriented_bounding_box(const PointRange& points,
|
||||||
|
Output& out,
|
||||||
|
const CGAL_BGL_NP_CLASS& np,
|
||||||
|
#ifndef DOXYGEN_RUNNING
|
||||||
|
typename boost::enable_if<
|
||||||
|
typename boost::has_range_iterator<PointRange>
|
||||||
|
>::type* = 0
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
using CGAL::parameters::choose_parameter;
|
||||||
|
using CGAL::parameters::get_parameter;
|
||||||
|
|
||||||
|
#if defined(CGAL_EIGEN3_ENABLED)
|
||||||
|
typedef typename boost::range_value<PointRange>::type Point;
|
||||||
|
typedef typename CGAL::Kernel_traits<Point>::type K;
|
||||||
|
typedef Oriented_bounding_box_traits<K> Default_traits;
|
||||||
|
#else
|
||||||
|
typedef void Default_traits;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef typename internal_np::Lookup_named_param_def<internal_np::geom_traits_t,
|
||||||
|
CGAL_BGL_NP_CLASS,
|
||||||
|
Default_traits>::type Geom_traits;
|
||||||
|
|
||||||
|
CGAL_static_assertion_msg(!(std::is_same<Geom_traits, void>::value),
|
||||||
|
"You must provide a traits class or have Eigen enabled!");
|
||||||
|
|
||||||
|
Geom_traits traits = choose_parameter(get_parameter(np, internal_np::geom_traits), Geom_traits());
|
||||||
|
|
||||||
|
const bool use_ch = choose_parameter(get_parameter(np, internal_np::use_convex_hull), true);
|
||||||
|
const unsigned int seed = choose_parameter(get_parameter(np, internal_np::random_seed), 0); // undocumented
|
||||||
|
|
||||||
|
CGAL::Random rng(seed);
|
||||||
|
|
||||||
|
// @todo handle those cases instead
|
||||||
|
CGAL_assertion(points.size() >= 3);
|
||||||
|
if(points.size() <= 3)
|
||||||
|
{
|
||||||
|
std::cerr << "The oriented bounding box cannot YET be computed for a mesh with fewer than 4 vertices!\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Optimal_bounding_box::internal::construct_oriented_bounding_box(out, use_ch, points, rng, traits);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \ingroup PkgOptimalBoundingBox_Oriented_bounding_box
|
||||||
|
///
|
||||||
|
/// Extracts the vertices of the mesh as a point range and calls the other overload.
|
||||||
|
///
|
||||||
|
/// \tparam PolygonMesh a model of `VertexListGraph`
|
||||||
|
/// \tparam Output `std::array<Point, 8>` with `Point` being equivalent to the traits' `Point_3` type,
|
||||||
|
/// or `CGAL::Affine_transformation_3<K>` with `K` being a kernel compatible with the point type.
|
||||||
|
/// \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters"
|
||||||
|
///
|
||||||
|
/// \param pmesh the input mesh
|
||||||
|
/// \param out the resulting array of points or affine transformation
|
||||||
|
/// \param np an optional sequence of \ref obb_namedparameters "Named Parameters" among the ones listed below:
|
||||||
|
///
|
||||||
|
/// \cgalNamedParamsBegin
|
||||||
|
/// \cgalParamBegin{vertex_point_map}
|
||||||
|
/// the property map with the points associated to the vertices of `pmesh`.
|
||||||
|
/// If this parameter is omitted, an internal property map for
|
||||||
|
/// `CGAL::vertex_point_t` must be available in `PolygonMesh`
|
||||||
|
/// \cgalParamEnd
|
||||||
|
/// \cgalParamBegin{geom_traits}
|
||||||
|
/// a geometric traits class instance, model of the concept `OrientedBoundingBoxTraits`.
|
||||||
|
/// %Default is `CGAL::Oriented_bounding_box_traits<K>` where `K` is deduced from the point type.
|
||||||
|
/// \cgalParamEnd
|
||||||
|
/// \cgalParamBegin{use_convex_hull}
|
||||||
|
/// a Boolean value to indicate whether the algorithm should first extract the so-called extreme
|
||||||
|
/// points of the data range (i.e. construct the convex hull) to reduce the input data range
|
||||||
|
/// and accelerate the algorithm. %Default is `true`.
|
||||||
|
/// \cgalParamEnd
|
||||||
|
/// \cgalNamedParamsEnd
|
||||||
|
///
|
||||||
|
template <typename PolygonMesh,
|
||||||
|
typename Output,
|
||||||
|
typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
|
||||||
|
void oriented_bounding_box(const PolygonMesh& pmesh,
|
||||||
|
Output& out,
|
||||||
|
const CGAL_BGL_NP_CLASS& np,
|
||||||
|
#ifndef DOXYGEN_RUNNING
|
||||||
|
typename boost::disable_if<
|
||||||
|
typename boost::has_range_iterator<PolygonMesh>
|
||||||
|
>::type* = 0
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||||
|
|
||||||
|
using CGAL::parameters::choose_parameter;
|
||||||
|
using CGAL::parameters::get_parameter;
|
||||||
|
|
||||||
|
typedef typename boost::graph_traits<PolygonMesh>::vertex_descriptor vertex_descriptor;
|
||||||
|
|
||||||
|
typedef typename PMP::GetVertexPointMap<PolygonMesh, CGAL_BGL_NP_CLASS>::const_type VPM;
|
||||||
|
typedef typename boost::property_traits<VPM>::value_type Point;
|
||||||
|
|
||||||
|
VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point),
|
||||||
|
get_const_property_map(vertex_point, pmesh));
|
||||||
|
|
||||||
|
std::vector<Point> points;
|
||||||
|
points.reserve(num_vertices(pmesh));
|
||||||
|
|
||||||
|
for(vertex_descriptor v : vertices(pmesh))
|
||||||
|
points.push_back(get(vpm, v));
|
||||||
|
|
||||||
|
oriented_bounding_box(points, out, np);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \cond SKIP_IN_MANUAL
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Convenience overloads
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <typename InputData /*range or mesh*/, typename OutputType /*array or transformation*/>
|
||||||
|
void oriented_bounding_box(const InputData& data,
|
||||||
|
OutputType& out)
|
||||||
|
{
|
||||||
|
return oriented_bounding_box(data, out, CGAL::parameters::all_default());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \endcond
|
||||||
|
|
||||||
|
} // end namespace CGAL
|
||||||
|
|
||||||
|
#endif // CGAL_OPTIMAL_BOUNDING_BOX_ORIENTED_BOUNDING_BOX_H
|
||||||
|
|
@ -14,321 +14,13 @@
|
||||||
#ifndef CGAL_OPTIMAL_BOUNDING_BOX_OBB_H
|
#ifndef CGAL_OPTIMAL_BOUNDING_BOX_OBB_H
|
||||||
#define CGAL_OPTIMAL_BOUNDING_BOX_OBB_H
|
#define CGAL_OPTIMAL_BOUNDING_BOX_OBB_H
|
||||||
|
|
||||||
#include <CGAL/license/Optimal_bounding_box.h>
|
/**
|
||||||
|
* \ingroup PkgOptimalBoundingBoxRef
|
||||||
|
* \file CGAL/optimal_bounding_box.h
|
||||||
|
* Convenience header file including the headers for all the free functions of this package.
|
||||||
|
*/
|
||||||
|
|
||||||
#include <CGAL/Optimal_bounding_box/internal/population.h>
|
#include <CGAL/Optimal_bounding_box/Oriented_bounding_box_traits.h>
|
||||||
#include <CGAL/Optimal_bounding_box/internal/evolution.h>
|
#include <CGAL/Optimal_bounding_box/oriented_bounding_box.h>
|
||||||
#include <CGAL/Optimal_bounding_box/Optimal_bounding_box_traits.h>
|
|
||||||
|
|
||||||
#include <CGAL/boost/graph/Named_function_parameters.h>
|
|
||||||
#include <CGAL/boost/graph/named_params_helper.h>
|
|
||||||
|
|
||||||
#include <CGAL/assertions.h>
|
|
||||||
#include <CGAL/Bbox_3.h>
|
|
||||||
#include <CGAL/boost/graph/helpers.h>
|
|
||||||
#include <CGAL/convex_hull_3.h>
|
|
||||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
|
||||||
#include <CGAL/Iso_cuboid_3.h>
|
|
||||||
#include <CGAL/Kernel_traits.h>
|
|
||||||
#include <CGAL/Random.h>
|
|
||||||
#include <CGAL/Simple_cartesian.h>
|
|
||||||
|
|
||||||
#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS
|
|
||||||
#include <CGAL/Real_timer.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <iostream>
|
|
||||||
#include <iterator>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#ifdef DOXYGEN_RUNNING
|
|
||||||
#define CGAL_BGL_NP_TEMPLATE_PARAMETERS NamedParameters
|
|
||||||
#define CGAL_BGL_NP_CLASS NamedParameters
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace CGAL {
|
|
||||||
namespace Optimal_bounding_box {
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
// works on matrices only
|
|
||||||
template <typename PointRange, typename Traits>
|
|
||||||
void post_processing(const typename Traits::Matrix& R,
|
|
||||||
std::array<typename Traits::Point_3, 8>& obb,
|
|
||||||
const PointRange& points,
|
|
||||||
const Traits& traits)
|
|
||||||
{
|
|
||||||
typedef typename Traits::FT FT;
|
|
||||||
typedef typename Traits::Point_3 Point;
|
|
||||||
typedef typename Traits::Matrix Matrix;
|
|
||||||
|
|
||||||
CGAL_assertion(R.number_of_rows() == 3 && R.number_of_columns() == 3);
|
|
||||||
|
|
||||||
const Matrix Rt = traits.transpose(R);
|
|
||||||
|
|
||||||
CGAL::Bbox_3 bbox;
|
|
||||||
for(const Point& pt : points)
|
|
||||||
{
|
|
||||||
// @fixme should it be R here Rt at the other one... ?
|
|
||||||
const FT x = pt.x(), y = pt.y(), z = pt.z();
|
|
||||||
Point rotated_pt(x*R(0, 0) + y*R(0, 1) + z*R(0, 2),
|
|
||||||
x*R(1, 0) + y*R(1, 1) + z*R(1, 2),
|
|
||||||
x*R(2, 0) + y*R(2, 1) + z*R(2, 2));
|
|
||||||
|
|
||||||
bbox += traits.construct_bbox_3_object()(rotated_pt);
|
|
||||||
}
|
|
||||||
|
|
||||||
// @todo could avoid building a cuboid
|
|
||||||
typename Traits::Iso_cuboid_3 ic(bbox);
|
|
||||||
|
|
||||||
// 3) apply inverse rotation to rotated AABB
|
|
||||||
for(std::size_t i = 0; i<8; ++i)
|
|
||||||
{
|
|
||||||
const FT x = ic[i].x(), y = ic[i].y(), z = ic[i].z();
|
|
||||||
obb[i] = Point(x*Rt(0, 0) + y*Rt(0, 1) + z*Rt(0, 2),
|
|
||||||
x*Rt(1, 0) + y*Rt(1, 1) + z*Rt(1, 2),
|
|
||||||
x*Rt(2, 0) + y*Rt(2, 1) + z*Rt(2, 2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename PointRange, typename Traits>
|
|
||||||
void construct_optimal_bounding_box(std::array<typename Traits::Point_3, 8>& obb_points,
|
|
||||||
const PointRange& points,
|
|
||||||
CGAL::Random& rng,
|
|
||||||
const Traits& traits)
|
|
||||||
{
|
|
||||||
typedef typename Traits::Matrix Matrix;
|
|
||||||
|
|
||||||
const std::size_t max_generations = 100;
|
|
||||||
|
|
||||||
#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS
|
|
||||||
CGAL::Real_timer timer;
|
|
||||||
timer.start();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Evolution<PointRange, Traits> search_solution(points, rng, traits);
|
|
||||||
search_solution.evolve(max_generations);
|
|
||||||
|
|
||||||
#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS
|
|
||||||
std::cout << "evolve: " << timer.time() << std::endl;
|
|
||||||
timer.reset();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const Matrix& rotation = search_solution.get_best();
|
|
||||||
|
|
||||||
#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS
|
|
||||||
std::cout << "get best: " << timer.time() << std::endl;
|
|
||||||
timer.reset();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
post_processing(rotation, obb_points, points, traits);
|
|
||||||
|
|
||||||
#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS
|
|
||||||
std::cout << "post-processing: " << timer.time() << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename PointRange, typename Traits>
|
|
||||||
void construct_optimal_bounding_box(std::array<typename Traits::Point_3, 8>& obb_points,
|
|
||||||
const bool use_ch,
|
|
||||||
const PointRange& points,
|
|
||||||
CGAL::Random& rng,
|
|
||||||
const Traits& traits)
|
|
||||||
{
|
|
||||||
typedef typename Traits::Matrix Matrix;
|
|
||||||
typedef typename Traits::Point_3 Point;
|
|
||||||
|
|
||||||
CGAL_static_assertion((std::is_same<typename boost::range_value<PointRange>::type, Point>::value));
|
|
||||||
|
|
||||||
if(use_ch) // construct the convex hull to reduce the number of points
|
|
||||||
{
|
|
||||||
std::vector<Point> ch_points;
|
|
||||||
extreme_points_3(points, std::back_inserter(ch_points));
|
|
||||||
return construct_optimal_bounding_box(obb_points, ch_points, rng, traits);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return construct_optimal_bounding_box(obb_points, points, rng, traits);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Optimal_bounding_box
|
|
||||||
} // namespace internal
|
|
||||||
|
|
||||||
/// \ingroup PkgOptimalBoundingBoxFunctions
|
|
||||||
///
|
|
||||||
/// constructs a rectangular box that contains all the input points. This bounding box
|
|
||||||
/// is obtained via an optimization process aiming to get a close approximation of the
|
|
||||||
/// optimal bounding box, which is defined as the smallest (in terms of volume)
|
|
||||||
/// of all the rectangular boxes containing the input points.
|
|
||||||
///
|
|
||||||
/// \tparam PointRange a model of `Range` with value type `Point`
|
|
||||||
/// \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters"
|
|
||||||
///
|
|
||||||
/// \param points the input points
|
|
||||||
/// \param obb_points the eight points of the resulting englobing box.
|
|
||||||
/// The order of points is the same as in the function `CGAL::make_hexahedron()`
|
|
||||||
/// \param np an optional sequence of \ref obb_namedparameters "Named Parameters" among the ones listed below:
|
|
||||||
///
|
|
||||||
/// \cgalNamedParamsBegin
|
|
||||||
/// \cgalParamBegin{vertex_point_map}
|
|
||||||
/// the property map with the points associated to the vertices of `pmesh`.
|
|
||||||
/// If this parameter is omitted, an internal property map for
|
|
||||||
/// `CGAL::vertex_point_t` must be available in `PolygonMesh`
|
|
||||||
/// \cgalParamEnd
|
|
||||||
/// \cgalParamBegin{geom_traits}
|
|
||||||
/// a geometric traits class instance, model of the concept `OptimalBoundingBoxTraits`. %Default is
|
|
||||||
/// `CGAL::Optimal_bounding_box::Optimal_bounding_box_traits<K>` where `K` is deduced
|
|
||||||
/// from the point type, which must then be compatible with `CGAL::Kernel_traits`.
|
|
||||||
/// \cgalParamEnd
|
|
||||||
/// \cgalParamBegin{use_convex_hull}
|
|
||||||
/// a Boolean value to indicate whether the algorithm should first extract the so-called extreme
|
|
||||||
/// points of the data range (i.e. construct the convex hull) to reduce the input data range
|
|
||||||
/// and accelerate the algorithm. The optimal value of this parameter will depend on the data
|
|
||||||
/// as it is a balance between two costs. %Default is `true`.
|
|
||||||
/// \cgalParamEnd
|
|
||||||
/// \cgalNamedParamsEnd
|
|
||||||
///
|
|
||||||
/// \pre the value type of `PointRange` is `Point`
|
|
||||||
///
|
|
||||||
template <typename PointRange,
|
|
||||||
typename Point,
|
|
||||||
typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
|
|
||||||
void optimal_bounding_box(const PointRange& points,
|
|
||||||
std::array<Point, 8>& obb_points,
|
|
||||||
const CGAL_BGL_NP_CLASS& np)
|
|
||||||
{
|
|
||||||
using CGAL::parameters::choose_parameter;
|
|
||||||
using CGAL::parameters::get_parameter;
|
|
||||||
|
|
||||||
#if defined(CGAL_EIGEN3_ENABLED)
|
|
||||||
typedef typename CGAL::Kernel_traits<Point>::type K;
|
|
||||||
typedef Optimal_bounding_box::Optimal_bounding_box_traits<K> Default_traits;
|
|
||||||
#else
|
|
||||||
typedef void Default_traits;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef typename internal_np::Lookup_named_param_def<internal_np::face_size_map_t,
|
|
||||||
CGAL_BGL_NP_CLASS,
|
|
||||||
Default_traits>::type Geom_traits;
|
|
||||||
|
|
||||||
CGAL_static_assertion_msg(!(std::is_same<Geom_traits, void>::value),
|
|
||||||
"You must provide a traits class or have Eigen enabled!");
|
|
||||||
|
|
||||||
Geom_traits traits = choose_parameter(get_parameter(np, internal_np::geom_traits), Geom_traits());
|
|
||||||
|
|
||||||
const bool use_ch = choose_parameter(get_parameter(np, internal_np::use_convex_hull), false);
|
|
||||||
const unsigned int seed = choose_parameter(get_parameter(np, internal_np::random_seed), 0); // undocumented
|
|
||||||
|
|
||||||
CGAL::Random rng(seed);
|
|
||||||
|
|
||||||
// @todo handle those cases instead
|
|
||||||
CGAL_assertion(points.size() >= 3);
|
|
||||||
if(points.size() <= 3)
|
|
||||||
{
|
|
||||||
std::cerr << "The optimal bounding box cannot YET be computed for a mesh with fewer than 4 vertices!\n";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Optimal_bounding_box::internal::construct_optimal_bounding_box(obb_points, use_ch, points, rng, traits);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \cond SKIP_IN_MANUAL
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// Convenience overloads for point ranges
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
template <typename PointRange, typename Point>
|
|
||||||
void optimal_bounding_box(const PointRange& points,
|
|
||||||
std::array<Point, 8>& obb_points)
|
|
||||||
{
|
|
||||||
return optimal_bounding_box(points, obb_points, CGAL::parameters::all_default());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \endcond
|
|
||||||
|
|
||||||
/// \ingroup PkgOptimalBoundingBoxFunctions
|
|
||||||
///
|
|
||||||
/// constructs a rectangular box that contains the input mesh. This bounding box
|
|
||||||
/// is obtained via an optimization process aiming to get a close approximation of the
|
|
||||||
/// optimal bounding box, which is defined as the smallest (in terms of volume)
|
|
||||||
/// of all the rectangular boxes containing the input mesh.
|
|
||||||
///
|
|
||||||
/// \tparam PolygonMesh a model of `FaceListGraph`
|
|
||||||
/// \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters"
|
|
||||||
///
|
|
||||||
/// \param pmesh the input mesh
|
|
||||||
/// \param obb_mesh the resulting enclosing bounding box (an hexahedron)
|
|
||||||
/// \param np an optional sequence of \ref obb_namedparameters "Named Parameters" among the ones listed below:
|
|
||||||
///
|
|
||||||
/// \cgalNamedParamsBegin
|
|
||||||
/// \cgalParamBegin{vertex_point_map}
|
|
||||||
/// the property map with the points associated to the vertices of `pmesh`.
|
|
||||||
/// If this parameter is omitted, an internal property map for
|
|
||||||
/// `CGAL::vertex_point_t` must be available in `PolygonMesh`
|
|
||||||
/// \cgalParamEnd
|
|
||||||
/// \cgalParamBegin{geom_traits}
|
|
||||||
/// a geometric traits class instance, model of the concept `OptimalBoundingBoxTraits`. %Default is
|
|
||||||
/// `CGAL::Optimal_bounding_box::Optimal_bounding_box_traits<K>` where `K` is deduced
|
|
||||||
/// from the point type, which must be compatible with `CGAL::Kernel_traits`.
|
|
||||||
/// \cgalParamEnd
|
|
||||||
/// \cgalParamBegin{use_convex_hull}
|
|
||||||
/// a Boolean value to indicate whether the algorithm should first extract the so-called extreme
|
|
||||||
/// points of the data range (i.e. construct the convex hull) to reduce the input data range
|
|
||||||
/// and accelerate the algorithm. The optimal value of this parameter will depend on the data
|
|
||||||
/// as it is a balance between two costs. %Default is `true`.
|
|
||||||
/// \cgalParamEnd
|
|
||||||
/// \cgalNamedParamsEnd
|
|
||||||
///
|
|
||||||
template <typename PolygonMesh,
|
|
||||||
typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
|
|
||||||
void optimal_bounding_box(const PolygonMesh& pmesh,
|
|
||||||
PolygonMesh& obb_mesh,
|
|
||||||
const CGAL_BGL_NP_CLASS& np)
|
|
||||||
{
|
|
||||||
namespace PMP = CGAL::Polygon_mesh_processing;
|
|
||||||
|
|
||||||
using CGAL::parameters::choose_parameter;
|
|
||||||
using CGAL::parameters::get_parameter;
|
|
||||||
|
|
||||||
typedef typename boost::graph_traits<PolygonMesh>::vertex_descriptor vertex_descriptor;
|
|
||||||
|
|
||||||
typedef typename PMP::GetVertexPointMap<PolygonMesh, CGAL_BGL_NP_CLASS>::const_type VPM;
|
|
||||||
typedef typename boost::property_traits<VPM>::value_type Point;
|
|
||||||
|
|
||||||
VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point),
|
|
||||||
get_const_property_map(vertex_point, pmesh));
|
|
||||||
|
|
||||||
std::vector<Point> points;
|
|
||||||
points.reserve(num_vertices(pmesh));
|
|
||||||
|
|
||||||
for(vertex_descriptor v : vertices(pmesh))
|
|
||||||
points.push_back(get(vpm, v));
|
|
||||||
|
|
||||||
std::array<Point, 8> obb_points;
|
|
||||||
optimal_bounding_box(points, obb_points, np);
|
|
||||||
|
|
||||||
CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3],
|
|
||||||
obb_points[4], obb_points[5], obb_points[6], obb_points[7], obb_mesh);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \cond SKIP_IN_MANUAL
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// Convenience overloads for polygon meshes
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
template <typename PolygonMesh>
|
|
||||||
void optimal_bounding_box(const PolygonMesh& pmesh,
|
|
||||||
PolygonMesh& obb_mesh)
|
|
||||||
{
|
|
||||||
return optimal_bounding_box(pmesh, obb_mesh, CGAL::parameters::all_default());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \endcond
|
|
||||||
|
|
||||||
} // end namespace CGAL
|
|
||||||
|
|
||||||
#endif // CGAL_OPTIMAL_BOUNDING_BOX_OBB_H
|
#endif // CGAL_OPTIMAL_BOUNDING_BOX_OBB_H
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue