hbf / miniball

Fast computation of the smallest enclosing ball of a point set, in low or moderately high dimensions.
133 stars 41 forks source link

Add array support (in addition to std::vector) #23

Closed IntellectualKitty closed 7 years ago

IntellectualKitty commented 7 years ago

This PR provides code to support standard arrays as well as std::vector. This was necessary to be able to integrate Miniball into a project that requires bounding sphere computation from points stored in either arrays or vectors.

In internal storage and usage in the Seb and Subspan classes, const PointAccessor &S has been replaced with const Pt* point and const size_t num_points. Also, the Seb class has two constructors, the original constructor that accepts a vector -- which initializes points and num_points using the std::vector data() and size() member functions, respectively -- and a new constructor to accept a Pt array and its size directly.

I have made changes to the comments in an attempt to both make the new code clear but also to try to maintain consistent references to your paper, namely by making sure that it's clear that points and num_points refer to the point set S, for example with these comments for Seb's (and Subspan's) private members:

    const Pt* points;                 // points and num_points are the set of inserted
    const size_t num_points;          // points, formally referred to as S

Since PointAccessor is no longer viable, it has been removed from all template arguments. Since points were accessed using operator[] in std::vector rather than with an iterator, I don't believe that this reduces STL support since, from my review of applicable STL containers (such as std::list or std::multiset) at cppreference.com, only std::vector supports access with operator[].

paulharris commented 7 years ago

Hi there,

You do not need to do this, vector<> is only a default template parameter.

Just implement your own PointAccessor that works with an array.

I've done this in my branch, in example.C

Note at the bottom, how I declare the "Miniball" type. typedef Seb::Smallest_enclosing_ball< double, double const*, PointAcc_Array > Miniball;

In short:


class PointAcc_Array
{
   double const* ptr;
   size_t num_points;
   size_t dims;

public:
   PointAcc_Array( double const* ptr, size_t num_points, size_t dims ) :
      ptr(ptr), num_points(num_points), dims(dims)
   {
   }

   double const* operator[]( size_t ptr_idx ) const
   {
      return ptr + (ptr_idx * dims);
   }

   size_t size() const { return num_points; }
};

  // Compute the miniball by inserting each value
  typedef Seb::Smallest_enclosing_ball< double, double const*, PointAcc_Array > Miniball;
  PointAcc_Array acc(&all_coords[0], n, d);
  Miniball mb(d, acc);

  // Output
  FT rad = mb.radius();
  FT rad_squared = mb.squared_radius();
IntellectualKitty commented 7 years ago

@paulharris, thanks for this. I appreciate it.