-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a Bbox class with dimension as parameter #8258
base: master
Are you sure you want to change the base?
Changes from 20 commits
ec56c66
6638dec
cf6996b
48d734c
4bc2770
8ef1f72
570433d
0c9cb3d
b83bcc4
a432d96
0cc387e
68ecd6d
9ade3d2
61ae325
08389c7
fe7c37b
63dd907
d2b1ea7
6650de8
6d11389
7133b28
7ab31a8
316ab90
ab06574
769906a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
// Copyright (c) 2022 Institut Géographique National - IGN (France) | ||
// All rights reserved. | ||
// | ||
// This file is part of CGAL (www.cgal.org). | ||
// | ||
// $URL$ | ||
// $Id$ | ||
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial | ||
// | ||
// Author(s) : Mathieu Brédif | ||
|
||
#ifndef CGAL_BBOX_H | ||
#define CGAL_BBOX_H | ||
|
||
#include <boost/config.hpp> // defines BOOST_PREVENT_MACRO_SUBSTITUTION | ||
#include <stddef.h> | ||
#include <limits> | ||
#include <array> | ||
#include <iostream> | ||
#include <iterator> | ||
#include <CGAL/assertions.h> | ||
#include <CGAL/Dimension.h> | ||
|
||
namespace CGAL { | ||
namespace Impl { | ||
|
||
template<typename Container, typename Derived> | ||
class Bbox | ||
{ | ||
protected: | ||
typedef typename Container::value_type T; | ||
Container min_values; | ||
Container max_values; | ||
|
||
public: | ||
Bbox& operator+=(const Bbox& bbox) | ||
{ | ||
CGAL_assertion(min_values.size() == 0 || min_values.size() == bbox.min_values.size()); | ||
if(min_values.size() == 0){ | ||
*this = bbox; | ||
} | ||
int dim = bbox.min_values.size(); | ||
for(int i=0; i<dim; ++i) | ||
{ | ||
if(min_values[i] > bbox.min_values[i]) min_values[i] = bbox.min_values[i]; | ||
if(max_values[i] < bbox.max_values[i]) max_values[i] = bbox.max_values[i]; | ||
} | ||
return *this; | ||
} | ||
|
||
inline int dimension() const | ||
{ | ||
return static_cast<const Derived*>(this)->dimension(); | ||
} | ||
|
||
inline T min BOOST_PREVENT_MACRO_SUBSTITUTION (int i) const | ||
{ | ||
return min_values[i]; | ||
} | ||
|
||
inline T max BOOST_PREVENT_MACRO_SUBSTITUTION (int i) const | ||
{ | ||
return max_values[i]; | ||
} | ||
|
||
inline T& min BOOST_PREVENT_MACRO_SUBSTITUTION (int i) | ||
{ | ||
return min_values[i]; | ||
} | ||
|
||
inline T& max BOOST_PREVENT_MACRO_SUBSTITUTION (int i) | ||
{ | ||
return max_values[i]; | ||
} | ||
|
||
inline T measure() const { | ||
T result = max_values[0] - min_values[0]; | ||
if (result <= 0) return 0; | ||
for(int i=1; i<dimension(); ++i) | ||
result *= max_values[i] - min_values[i]; | ||
return result; | ||
} | ||
|
||
inline T intersection_measure(const Bbox& bbox) const { | ||
CGAL_assertion(dimension() == bbox.dimension()); | ||
T result = 1; | ||
for(int i=0; i<dimension(); ++i) { | ||
result *= (std::min)((max)(i), (bbox.max)(i)) - | ||
(std::max)((min)(i), (bbox.min)(i)); | ||
if (result <= 0) return 0; | ||
} | ||
return result; | ||
} | ||
|
||
bool operator==(const Bbox& bbox) const { | ||
for(int i=0; i<dimension(); ++i) | ||
if (min_values[i] != bbox.min_values[i] || max_values[i] != bbox.max_values[i]) | ||
return false; | ||
return true; | ||
} | ||
|
||
bool operator!=(const Bbox& bbox) const { return !operator==(bbox); } | ||
|
||
protected: | ||
void init(int d, T range = -std::numeric_limits<T>::infinity()) { | ||
for(int i=0; i<d; ++i) | ||
{ | ||
min_values[i] = -range; | ||
max_values[i] = range; | ||
} | ||
} | ||
|
||
template <typename I> | ||
void init(int d, I b, I e) { | ||
afabri marked this conversation as resolved.
Show resolved
Hide resolved
|
||
CGAL_assertion(d == std::distance(b,e)); | ||
for(int i=0; i<d; ++i,++b) | ||
{ | ||
min_values[i] = (*b).first; | ||
max_values[i] = (*b).second; | ||
} | ||
} | ||
}; | ||
|
||
} | ||
|
||
template <typename Di, typename T> | ||
class Bbox; | ||
|
||
// A fixed D-dimensional axis aligned box | ||
template<int N, typename T> | ||
class Bbox<Dimension_tag<N>, T> : public Impl::Bbox<std::array<T, N>, Bbox<Dimension_tag<N>,T>> | ||
{ | ||
enum { D = N }; | ||
public: | ||
inline constexpr int dimension() const { return D; } | ||
Bbox(int d = 0 ) { CGAL_assertion(d==N || d==0); this->init(d ); } | ||
Bbox(int d, const T& range) { CGAL_assertion(d==N || d==0); this->init(d, range); } | ||
template <typename I> | ||
Bbox(int d, I b, I e) { CGAL_assertion(d==N || d==0); this->init(d, b, e); } | ||
}; | ||
|
||
// A dynamic D-dimensional axis aligned box | ||
template<typename T> | ||
class Bbox<Dynamic_dimension_tag,T> : public Impl::Bbox<std::vector<T>, Bbox<Dynamic_dimension_tag,T>> | ||
{ | ||
public: | ||
inline int dimension() const { return this->min_values.size(); } | ||
Bbox(int d = 0 ) { init_values(d); this->init(d ); } | ||
Bbox(int d, const T& range) { init_values(d); this->init(d, range); } | ||
template <typename I> | ||
Bbox(int d, I b, I e) { init_values(d); this->init(d, b, e); } | ||
|
||
protected: | ||
void init_values(int d) { | ||
this->min_values.resize(d); | ||
this->max_values.resize(d); | ||
Comment on lines
+157
to
+158
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems a bit wasteful to use 2 containers of size d instead of one of size 2*d, but that's an implementation detail so it doesn't matter now. |
||
} | ||
}; | ||
|
||
template<typename Container, typename Derived> | ||
std::ostream& operator<<(std::ostream& out, const Impl::Bbox<Container, Derived>& bbox) | ||
{ | ||
int d = bbox.dimension(); | ||
for(int i=0; i<d; ++i) | ||
out << (bbox.min)(i) << " " << (bbox.max)(i) << " "; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
return out; | ||
} | ||
|
||
template<typename Container, typename Derived> | ||
std::istream& operator>>(std::istream& in, Impl::Bbox<Container, Derived>& bbox) | ||
{ | ||
int d = bbox.dimension(); | ||
for(int i=0; i<d; ++i) | ||
in >> (bbox.min)(i) >> (bbox.max)(i); | ||
return in; | ||
} | ||
|
||
|
||
} // namespace CGAL | ||
|
||
#endif // CGAL_DDT_BBOX_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,7 @@ | |
|
||
#include <CGAL/NewKernel_d/utils.h> | ||
#include <CGAL/Dimension.h> | ||
#include <CGAL/Bbox.h> | ||
#include <CGAL/Uncertain.h> | ||
#include <CGAL/NewKernel_d/store_kernel.h> | ||
#include <CGAL/type_traits/is_iterator.h> | ||
|
@@ -1006,6 +1007,29 @@ template<class R_> struct Squared_length : private Store_kernel<R_> { | |
|
||
CGAL_KD_DEFAULT_FUNCTOR(Squared_length_tag,(CartesianDKernelFunctors::Squared_length<K>),(Vector_tag),(Construct_ttag<Vector_cartesian_const_iterator_tag>)); | ||
|
||
namespace CartesianDKernelFunctors { | ||
template<class R_> struct Construct_bbox : private Store_kernel<R_> { | ||
CGAL_FUNCTOR_INIT_STORE(Construct_bbox) | ||
typedef R_ R; | ||
typedef typename R::Dimension Dimension; | ||
typedef typename Get_type<R, RT_tag>::type RT; | ||
typedef typename Get_type<R, Point_tag>::type Point; | ||
typedef typename Get_functor<R, Construct_ttag<Point_cartesian_const_iterator_tag> >::type CI; | ||
|
||
typedef Bbox<Dimension,double> result_type; | ||
typedef Point argument_type; | ||
result_type operator()(Point const&a)const{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Out of curiosity, is it likely to stick to just this function, or do you expect to add overloads for Segment, Sphere, Iso_box, etc? I am asking because ideally (I stopped before making things consistent), overload resolution should happen in Kernel_d_interface, and dispatch to different non-overloaded functors like Bbox_from_point, Bbox_from_segment. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be natural to generalize. We started this only for the Frechet Distance submission, where we only deal with points. |
||
CI ci(this->kernel()); | ||
typename Real_embeddable_traits<RT>::To_interval f; | ||
typename Get_functor<R, Point_dimension_tag>::type pd(this->kernel()); | ||
return result_type(pd(a), make_transforming_iterator(ci(a, Begin_tag()), f), make_transforming_iterator(ci(a, End_tag()), f)); | ||
} | ||
}; | ||
} | ||
|
||
CGAL_KD_DEFAULT_FUNCTOR(Construct_bbox_tag,(CartesianDKernelFunctors::Construct_bbox<K>),(Point_tag),(Construct_ttag<Point_cartesian_const_iterator_tag>)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mglisse do you have any doc for the macro There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The line looks ok to me. You have the tag, the class, the required objects, the required other functors, that's it. Ah, maybe you are missing Point_dimension_tag in the last list (I am not sure this list is really used currently). |
||
|
||
|
||
namespace CartesianDKernelFunctors { | ||
template<class R_> struct Squared_distance_to_origin : private Store_kernel<R_> { | ||
CGAL_FUNCTOR_INIT_STORE(Squared_distance_to_origin) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -201,6 +201,7 @@ namespace CGAL { | |
CGAL_DECL_COMPUTE(Squared_distance); | ||
CGAL_DECL_COMPUTE(Squared_distance_to_origin); | ||
CGAL_DECL_COMPUTE(Squared_length); | ||
CGAL_DECL_COMPUTE(Construct_bbox); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it makes more sense as CGAL_DECL_MISC. "Compute" is for things that return a Lazy_exact_nt in Epeck_d. |
||
CGAL_DECL_COMPUTE(Squared_radius); | ||
CGAL_DECL_COMPUTE(Squared_circumradius); | ||
CGAL_DECL_COMPUTE(Scalar_product); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mbredif don't we have to check that the dimensions are equal?