Program Listing for File graph.hpp

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

#pragma once

/*******************************************************************************
 * Includes
 ******************************************************************************/
#include <boost/graph/adjacency_list.hpp>
#include <boost/optional.hpp>
#include <boost/range/adaptor/transformed.hpp>

#include "rcppsw/rcppsw.hpp"
#include "rcppsw/math/vector3.hpp"

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

template <typename TBGLGraphType>
using find_result_type = typename std::add_pointer<
  decltype(std::declval<TBGLGraphType>().operator[](std::declval<typename TBGLGraphType::vertex_descriptor>()))
  >::type;

} /* namespace detail */

/*******************************************************************************
 * Templates
 ******************************************************************************/

template <typename TBGLGraphType>
static inline auto vertices(const TBGLGraphType& g) -> decltype(boost::vertices(std::declval<const TBGLGraphType>())) {
  return boost::vertices(g);
}

template <typename TBGLGraphType>
static inline auto vertex_properties(const TBGLGraphType& g) {
  auto bundle_map = boost::get(boost::vertex_bundle, g);
  auto accessor = [&bundle_map](typename TBGLGraphType::vertex_descriptor vd) -> auto&{
                    return bundle_map[vd];
                  };
  return boost::vertices(g) | boost::adaptors::transformed(accessor);
}

template <typename TBGLGraphType>
static inline auto out_edges(const TBGLGraphType& g,
                             const typename TBGLGraphType::vertex_descriptor& v) {
  return boost::out_edges(v, g);
}

template <typename TBGLGraphType>
static inline auto out_degree(const TBGLGraphType& g,
                              const typename TBGLGraphType::vertex_descriptor& v) {
  return boost::out_degree(v, g);
}

template <typename TBGLGraphType>
static inline auto target(const TBGLGraphType& g,
                          const typename TBGLGraphType::edge_descriptor& e) {
  return boost::target(e, g);
}

template <typename TBGLGraphType>
static inline auto adjacent_vertices(const TBGLGraphType& g,
                                     typename TBGLGraphType::vertex_descriptor v) {
  return boost::adjacent_vertices(v, g);
}

template <typename TBGLGraphType>
static inline auto add_vertex(TBGLGraphType& g) {
  return boost::add_vertex(g);
}
template <typename TBGLGraphType>
static inline auto remove_vertex(TBGLGraphType& g,
                                 typename TBGLGraphType::vertex_descriptor v) {
  return boost::remove_vertex(v, g);
}

template <typename TBGLGraphType>
static inline auto add_edge(TBGLGraphType& g,
                            typename TBGLGraphType::vertex_descriptor u,
                            typename TBGLGraphType::vertex_descriptor v) {
  return boost::add_edge(u, v, g);
}

template <typename TBGLGraphType, typename TCoordType>
static inline boost::optional<typename TBGLGraphType::vertex_descriptor> find(
    const TBGLGraphType& g, const TCoordType& c) {

  auto [v_i, v_end] = boost::vertices(g);

  /* std::find_if does not seem to work with filtered_graph objects... */
  for (auto it = v_i; it != v_end; ++it) {
    if (g[*it].coord == c) {
      return boost::make_optional(*it);
    }
  } /* (it...) */
  return boost::none;
}

template <typename TBGLGraphType>
static inline bool contains(const TBGLGraphType& g, const rmath::vector3z& c) {
  return boost::none != rdgraph::find(g, c);
}

template <typename TBGLGraphType>
static inline size_t n_vertices(const TBGLGraphType& g) {
  return boost::num_vertices(g);
}

} /* namespace rcppsw::ds::graph */