Skip to content
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

Draft
wants to merge 25 commits into
base: master
Choose a base branch
from

Conversation

afabri
Copy link
Member

@afabri afabri commented Jun 5, 2024

Summary of Changes

For the upcoming Frechet Distance package we need a dD bounding box. We do not have that in Kernel_d, and there is such a class in ign's Distributed Delaunay Triangulation package to come (link). This PR copies it to the Kernel package (with the ok of @mbredif), but in the CGAL namespace.

This draft pull request is to get a discussion started.

  • In the initial version even the number type is a template parameter. Do we want to keep that?
  • Do we want to make Bbox_2/3 a typedef of this new class?
  • We have to go through the API and probably enrich it with what Bbox_2 offers additionally.
  • Do we have to add functions in Kernel_d?

TODO

Release Management

  • Affected package(s): Kernel_23
  • Feature/Small Feature (if any): tbd
  • Link to compiled documentation (obligatory for small feature) wrong link name to be changed
  • License and copyright ownership: LGPL , owned by IGN

@lrineau lrineau changed the title Kernel: Add a Bbox class with dimension as parameter Kernel_23d: Add a Bbox class with dimension as parameter Jun 10, 2024
@afabri
Copy link
Member Author

afabri commented Jun 12, 2024

@mglisse I am also wondering why there is no bounding box class in Epick_d etc. Apparently there is no need for it so far, but would you like to see it integrated? With functors etc.

Comment on lines 35 to 39
CGAL_assertion(min_values.size() == 0 || min_values.size() == bbox.min_values.size());
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];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assertion allows min_values.size() == 0 and dim != 0, but then min_values[i] is read 😕

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's wrong indeed.
min_values.size()==0 happens for a default constructed Bbox with a dynamic dimension, which models an empty bbox. In this case, values should just be copied from bbox to this.

@afabri
Copy link
Member Author

afabri commented Jun 12, 2024

@mbredif do I have to make you collaborator, or is this already the case?

@mglisse
Copy link
Member

mglisse commented Jun 12, 2024

@mglisse I am also wondering why there is no bounding box class in Epick_d etc.

I remember thinking about it, maybe discussing it, but I don't remember the content...

Apparently there is no need for it so far,

That may have played a big role 😉 (it doesn't seem to be part of the Kernel_d concept)

but would you like to see it integrated? With functors etc.

If you have a use for it, we probably should.
To be sure I understand: the current bbox_23 always use double, whatever the kernel, making them not really kernel objects. Is the plan the same for the new bbox, i.e. ignore the generality offered by the template parameter and only use it with double (otherwise it becomes Iso_rectangle_2/Iso_cuboid_3)?
It looks like the kernel integration can be done later in a separate PR (this one adds the class), which gives me a bit of time to think about how that fits with the design of NewKernel_d.

Comment on lines +132 to +133
this->min_values.resize(d);
this->max_values.resize(d);
Copy link
Member

Choose a reason for hiding this comment

The 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.

{
int d = bbox.dimension();
for(int i=0; i<d; ++i)
out << (bbox.min)(i) << " " << (bbox.max)(i) << " ";
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bbox_2/3 first print lower left and then upper right.

Kernel_23/include/CGAL/Bbox.h Outdated Show resolved Hide resolved
enum { D = N };
public:
inline constexpr int dimension() const { return D; }
Bbox(int d = 0 ) { assert(d==N || d==0); this->init(d ); }
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find it surprising that for a Bbox with non-dynamic dimension I have to pass parameter d.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that was to offer a common API whatever the dimension dynamics

@afabri
Copy link
Member Author

afabri commented Jun 20, 2024

We also need a constructor taking an iterator range of coordinates. And maybe also for a range of pairs of coordinates.
The former is needed when constructing a bbox from a point with floating point coordinates. The latter when constructing
it from exact coordinates transformed to a std::pair<double,double> using CGAL::to_double().

I just realize that this would correspond more to what you do for the I/O operators. But do we want a constructor for a range of low and a second range for high? Seems not intuitive.

@afabri
Copy link
Member Author

afabri commented Jun 20, 2024

As Epick_d may have a dynamic and a static dimension, depending on a template parameter, the functor Epick_d::Construct_bbox_d() must return either a bbox type with dynamic and static dimension, respectively.

@sloriot
Copy link
Member

sloriot commented Jul 9, 2024

Kernel_23 failing in CGAL-6.0-Ic-284

@sloriot
Copy link
Member

sloriot commented Jul 25, 2024

Kernel_23 tests are failing in CGAL-6.0-Ic-295.
See for example here and there.

@MaelRL MaelRL changed the title Kernel_23d: Add a Bbox class with dimension as parameter Add a Bbox class with dimension as parameter Aug 12, 2024
};
}

CGAL_KD_DEFAULT_FUNCTOR(Construct_bbox_tag,(CartesianDKernelFunctors::Construct_bbox<K>),(Point_tag),(Construct_ttag<Point_cartesian_const_iterator_tag>));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mglisse do you have any doc for the macro CGAL_KD_DEFAULT_FUNCTOR. I'm pretty sure this line is incorrect but I don't know how to fix it.

Copy link
Member

Choose a reason for hiding this comment

The 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).

@afabri
Copy link
Member Author

afabri commented Aug 19, 2024

I am wondering if it is not just something missing in Lazy_cartesian.h as I now got it working for Epick_d.

@@ -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);
Copy link
Member

Choose a reason for hiding this comment

The 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.
And then Lazy_cartesian needs something similar to Point_dimension_tag, assuming that the Bbox is supposed to be built from the approximate object (maybe merge the cases Point_dimension_tag, Vector_dimension_tag, and this new one in a partial specialization struct Functor<T,D,Misc_tag>?)

};
}

CGAL_KD_DEFAULT_FUNCTOR(Construct_bbox_tag,(CartesianDKernelFunctors::Construct_bbox<K>),(Point_tag),(Construct_ttag<Point_cartesian_const_iterator_tag>));
Copy link
Member

Choose a reason for hiding this comment

The 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).


typedef Bbox<Dimension,double> result_type;
typedef Point argument_type;
result_type operator()(Point const&a)const{
Copy link
Member

Choose a reason for hiding this comment

The 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.

Copy link
Member Author

Choose a reason for hiding this comment

The 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.

@mglisse
Copy link
Member

mglisse commented Aug 21, 2024

In fact there is the nested type Dimension

Yes, that's also what we use in Gudhi to access the compile-time dimension of a CGAL Kernel. It is even documented in the Kernel_d concept 🍀 .

@afabri
Copy link
Member Author

afabri commented Aug 22, 2024

@sloriot and I, we are blocked with getting Epick_d.cpp compiled. There is probably a specialization we have to add, but we have no idea what exactly,

@@ -260,6 +260,7 @@ namespace CGAL {
CGAL_DECL_CONSTRUCT(Construct_circumcenter,Point);
CGAL_DECL_CONSTRUCT(Point_drop_weight,Point);
CGAL_DECL_CONSTRUCT(Power_center,Weighted_point);
CGAL_DECL_CONSTRUCT(Construct_bbox,Bbox);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggested MISC though, since this doesn't return a Lazy object in Epeck_d.

@mglisse
Copy link
Member

mglisse commented Aug 22, 2024

@sloriot and I, we are blocked with getting Epick_d.cpp compiled. There is probably a specialization we have to add, but we have no idea what exactly,

I mentioned looking at Point_dimension_tag in Lazy_cartesian.h. Something like

--- a/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h
+++ b/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h
@@ -309,24 +309,15 @@ struct Lazy_cartesian :
     template<class T,class D> struct Functor<T,D,Construct_tag> {
             typedef Lazy_construction2<T,Kernel> type;
     };
-    template<class D> struct Functor<Point_dimension_tag,D,Misc_tag> {
-            typedef typename Get_functor<Approximate_kernel, Point_dimension_tag>::type FA;
-            struct type {
-              FA fa;
-              type(){}
-              type(Kernel const&k):fa(k.approximate_kernel()){}
-              template<class P>
-              int operator()(P const&p)const{return fa(CGAL::approx(p));}
-            };
-    };
-    template<class D> struct Functor<Vector_dimension_tag,D,Misc_tag> {
-            typedef typename Get_functor<Approximate_kernel, Vector_dimension_tag>::type FA;
+    template<class T,class D> struct Functor<T,D,Misc_tag> {
+            // By default (Point_dimension, Construct_bbox), apply to the approximate object
+            typedef typename Get_functor<Approximate_kernel, T>::type FA;
             struct type {
               FA fa;
               type(){}
               type(Kernel const&k):fa(k.approximate_kernel()){}
-              template<class V>
-              int operator()(V const&v)const{return fa(CGAL::approx(v));}
+              template<class P...>
+              decltype(auto) operator()(P&&...p)const{return fa(CGAL::approx(std::forward<P>(p))...);}
             };
     };
     template<class D> struct Functor<Linear_base_tag,D,Misc_tag> {

(completely untested)
If that still doesn't work, I'll checkout the branch to experiment, but not right now.

@sloriot
Copy link
Member

sloriot commented Aug 22, 2024

@mglisse in the meantime I achieved to make it compile and run. Not sure if that's the right way to do it.

@mglisse
Copy link
Member

mglisse commented Aug 22, 2024

@mglisse in the meantime I achieved to make it compile and run. Not sure if that's the right way to do it.

See https://github.com/mglisse/cgal/tree/Kernel_23-Bbox_d-ign, where I added commit mglisse@316ab90 .

@sloriot
Copy link
Member

sloriot commented Aug 22, 2024

@mglisse in the meantime I achieved to make it compile and run. Not sure if that's the right way to do it.

See https://github.com/mglisse/cgal/tree/Kernel_23-Bbox_d-ign, where I added commit mglisse@316ab90 .

That's indeed much simpler. I did not see that MISC macro. Thanks!

@sloriot sloriot added this to the 6.1-beta milestone Oct 10, 2024
@sloriot
Copy link
Member

sloriot commented Oct 14, 2024

Successfully tested in CGAL-6.0.1-Ic-345

@sloriot
Copy link
Member

sloriot commented Oct 14, 2024

Still a draft and small feature missing.

@lrineau lrineau added Not yet approved The feature or pull-request has not yet been approved. TODO labels Oct 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants