1
\$\begingroup\$

I need to write a function that takes a box in space, represented as an std::vector of boost::intervals, and split it into several smaller boxes. First, for convenience, I made some definitions

#include <iostream>
#include <boost/numeric/interval.hpp>
#include <vector>

namespace bn = boost::numeric;
namespace bi = bn::interval_lib;

// Interval typedefs
using Interval = bn::interval<
      double,
      bi::policies<
          bi::save_state<bi::rounded_transc_std<double> >,
          bi::checking_base<double>
      >
  >;

template<typename T> using array = std::vector<T>;

Then, I shamelessly used code from this stackoverflow question that describes how to achieve a Cartesian product of a set (vector) of sets (vectors). I turned it into a Template (for generality purpose) like so:

template <class T>
class Combinator
{
public:
    Combinator(array<array<T>>& tsttors)
        : m_tsttors(tsttors)
    {
        m_combination.reserve(m_tsttors.size());
        for(auto& v : m_tsttors)
            m_combination.push_back(v.begin());
    }

    bool next() {
        // iterate through tsttors in reverse order
        for(int i = m_tsttors.size() - 1; i >= 0; --i) {
            array<T>& v = m_tsttors[i];
            typename array<T>::iterator& it = m_combination[i];

            if(++it != v.end())
                return true;
            it = v.begin();
        }
        return false;
    }

    array<typename array<T>::iterator> combination() const {
        return m_combination;
    }

private:
    array<array<T>>& m_tsttors; // reference to data
    array<typename array<T>::iterator> m_combination;
};

After that, I decided I would split each dimension of the box (which is not of fixed dimension) into some number n of subintervals and then take their cartesian product to get what I called a grid of boxes. I implemented this like:

array<array<Interval>> box_grid(const array<Interval> &box, const int &parts){
    array<array<Interval>> splits;
    for(const auto& components : box) { // iterating through all box-dimensions
        const double &length = width(components);
        const double &start = components.lower();
        array<Interval> split_oned; // split each dimension

        for(int i = 0; i< parts; i++){ // evenly into "parts" parts
            Interval ival {start+ i*length/parts, start + (i+1)*length/parts};
            split_oned.push_back(ival);
        }
        splits.push_back(split_oned); // collect each split dimension
    }

    // and take their cartesian product for the boxes
    Combinator<Interval> combinator(splits);
    array<array<Interval>> box_array;
    do
    {
        const array<array<Interval>::iterator> combination = combinator.combination();
        array<Interval> single_box;
        for(const auto& it : combination){
            single_box.push_back(*it);
        }
        box_array.push_back(single_box);
    } while(combinator.next());

    return box_array;
}

As I am new to C++ and not very adept at programming in general, I would love to have some feedback and suggestions on improvement. I will use this code for scientific purposes, so performance is crucial. Thanks in advance.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.