Program Listing for File stacked_grid2D.hpp

Return to documentation for file (rcppsw/ds/stacked_grid2D.hpp)

#pragma once

/*******************************************************************************
 * Includes
 ******************************************************************************/
#include <tuple>
#include <utility>
#include <vector>

#include "rcppsw/ds/grid2D_overlay.hpp"
#include "rcppsw/math/vector2.hpp"
#include "rcppsw/types/discretize_ratio.hpp"

/*******************************************************************************
 * Namespaces/Decls
 ******************************************************************************/
namespace rcppsw::ds {

/*******************************************************************************
 * Class Definitions
 ******************************************************************************/
template <typename TupleTypes>
class stacked_grid2D {
 public:
  stacked_grid2D(const math::vector2d& origin,
                 const math::vector2d& dims,
                 const types::discretize_ratio& grid_res,
                 const types::discretize_ratio& field_res)
      : m_layers(kStackSize) {
    add_layers<kStackSize - 1>(origin, dims, grid_res, field_res);
  }

  virtual ~stacked_grid2D(void) { rm_layers<kStackSize - 1>(); }

  template <size_t Index>
  using value_type = typename std::tuple_element<Index, TupleTypes>::type;

  template <size_t Index>
  using layer_value_type = rcppsw::ds::grid2D_overlay<value_type<Index>>;

  template <size_t Index>
  typename layer_value_type<Index>::value_type& access(size_t i, size_t j) {
    return reinterpret_cast<layer_value_type<Index>*>(m_layers[Index])
        ->access(i, j);
  }

  template <size_t Index>
  const typename layer_value_type<Index>::value_type& access(size_t i,
                                                             size_t j) const {
    return reinterpret_cast<const layer_value_type<Index>*>(m_layers[Index])
        ->access(i, j);
  }

  template <size_t Index>
  typename layer_value_type<Index>::value_type& access(const math::vector2z& d) {
    return access<Index>(d.x(), d.y());
  }
  template <size_t Index>
  const typename layer_value_type<Index>::value_type&
  access(const math::vector2z& d) const {
    return access<Index>(d.x(), d.y());
  }

  template <size_t Index>
  layer_value_type<Index>* layer(void) {
    return reinterpret_cast<layer_value_type<Index>*>(m_layers[Index]);
  }
  template <size_t Index>
  const layer_value_type<Index>* layer(void) const {
    return reinterpret_cast<const layer_value_type<Index>*>(m_layers[Index]);
  }

  size_t xdsize(void) const {
    return (reinterpret_cast<const layer_value_type<0>*>(m_layers[0]))->xdsize();
  }

  rmath::vector2d rdims2D(void) const {
    return (reinterpret_cast<const layer_value_type<0>*>(m_layers[0]))->rdims2D();
  }

  rmath::vector2z ddims2D(void) const {
    return (reinterpret_cast<const layer_value_type<0>*>(m_layers[0]))->ddims2D();
  }

  double xrsize(void) const {
    return (reinterpret_cast<const layer_value_type<0>*>(m_layers[0]))->xrsize();
  }

  size_t ydsize(void) const {
    return (reinterpret_cast<const layer_value_type<0>*>(m_layers[0]))->ydsize();
  }

  double yrsize(void) const {
    return (reinterpret_cast<const layer_value_type<0>*>(m_layers[0]))->yrsize();
  }

  const types::discretize_ratio& resolution(void) const {
    return (reinterpret_cast<const layer_value_type<0>*>(m_layers[0]))
        ->resolution();
  }

 private:
  static size_t constexpr kStackSize = std::tuple_size<TupleTypes>::value;

  template <size_t Index, RCPPSW_SFINAE_DECLDEF((Index > 0)), typename... Args>
  void add_layers(Args&&... args) {
    add_layer<Index, Args...>(std::forward<Args>(args)...);
    add_layer<Index - 1, Args...>(std::forward<Args>(args)...);
  }

  template <size_t Index, RCPPSW_SFINAE_DECLDEF((Index == 0)), typename... Args>
  void add_layers(Args&&... args) {
    add_layer<Index, Args...>(std::forward<Args>(args)...);
  }

  template <size_t Index, typename... Args>
  void add_layer(Args&&... args) {
    m_layers[kStackSize - Index - 1] =
        new layer_value_type<kStackSize - Index - 1>(std::forward<Args>(args)...);
  }

  template <size_t Index>
  void rm_layers(void) {
    rm_layer<Index>();
  }

  template <size_t Index, RCPPSW_SFINAE_DECLDEF((Index > 0))>
  void rm_layer(void) {
    delete reinterpret_cast<const layer_value_type<Index>*>(
        m_layers[kStackSize - Index - 1]);
  }

  template <size_t Index, RCPPSW_SFINAE_DECLDEF((Index == 0))>
  void rm_layer(void) {
    delete reinterpret_cast<const layer_value_type<0>*>(m_layers[0]);
  }

  /* clang-format off */
  std::vector<void*> m_layers;
  /* clang-format on */
};

} /* namespace rcppsw::ds */