Skip to content

Instantly share code, notes, and snippets.

@kikitte
Created May 2, 2025 09:45
Show Gist options
  • Select an option

  • Save kikitte/b07286141a92f87e4ed0c9a502ecfda5 to your computer and use it in GitHub Desktop.

Select an option

Save kikitte/b07286141a92f87e4ed0c9a502ecfda5 to your computer and use it in GitHub Desktop.
defining multiple geometry types based on glm vector
#pragma once
#include <type_traits>
#define GLM_FORCE_XYZW_ONLY
#include <glm/vec2.hpp>
#include <glm/vec3.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/multi_point.hpp>
#include <boost/geometry/geometries/linestring.hpp>
#include <boost/geometry/geometries/multi_linestring.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/geometries/multi_polygon.hpp>
#include <boost/geometry/geometries/box.hpp>
// Traits to check if a type is a glm vector
template<typename T>
struct is_glm_vector : std::false_type
{};
template<glm::length_t L, typename T, glm::qualifier Q>
struct is_glm_vector<glm::vec<L, T, Q>> : std::true_type
{};
template<typename T>
struct is_glm_vector2 : std::false_type
{};
template<typename T, glm::qualifier Q>
struct is_glm_vector2<glm::vec<2, T, Q>> : std::true_type
{};
template<typename T>
struct is_glm_vector3 : std::false_type
{};
template<typename T, glm::qualifier Q>
struct is_glm_vector3<glm::vec<3, T, Q>> : std::true_type
{};
// Make a glm vector as a valid point geometry
namespace boost
{
namespace geometry
{
namespace traits
{
template<typename T>
struct tag<T, typename std::enable_if<is_glm_vector<T>::value>::type>
{
using type = point_tag;
};
template<typename T>
struct dimension<T, typename std::enable_if<is_glm_vector<T>::value>::type>
{
static constexpr std::size_t value = static_cast<std::size_t>( T::length() );
};
template<typename T>
struct coordinate_type<T, typename std::enable_if<is_glm_vector<T>::value>::type>
{
using type = typename T::value_type;
};
template<typename T>
struct coordinate_system<T, typename std::enable_if<is_glm_vector<T>::value>::type>
{
using type = boost::geometry::cs::cartesian;
};
template<typename T>
struct access<T, 0, typename std::enable_if<is_glm_vector<T>::value>::type>
{
using CoordinateType = typename coordinate_type<T>::type;
static inline CoordinateType get( const T &p ) { return p.x; }
static inline void set( T &p, const CoordinateType &value ) { p.x = value; }
};
template<typename T>
struct access<T, 1, typename std::enable_if<is_glm_vector<T>::value>::type>
{
using CoordinateType = typename coordinate_type<T>::type;
static inline CoordinateType get( const T &p ) { return p.y; }
static inline void set( T &p, const CoordinateType &value ) { p.y = value; }
};
template<typename T>
struct access<T, 2, typename std::enable_if<is_glm_vector3<T>::value>::type>
{
using CoordinateType = typename coordinate_type<T>::type;
static inline CoordinateType get( const T &p ) { return p.z; }
static inline void set( T &p, const CoordinateType &value ) { p.z = value; }
};
} //namespace traits
} //namespace geometry
} //namespace boost
namespace glm_bg
{
// 3 is the dimension number.
using point3 = glm::dvec3;
using multipoint3 = boost::geometry::model::multi_point<point3>;
using line3 = boost::geometry::model::linestring<point3>;
using multiline3 = boost::geometry::model::multi_linestring<line3>;
using polygon3 = boost::geometry::model::polygon<point3>;
using multipolygon3 = boost::geometry::model::multi_polygon<polygon3>;
using box3 = boost::geometry::model::box<point3>;
using point2 = glm::dvec2;
using multipoint2 = boost::geometry::model::multi_point<point2>;
using line2 = boost::geometry::model::linestring<point2>;
using multiline2 = boost::geometry::model::multi_linestring<line2>;
using polygon2 = boost::geometry::model::polygon<point2>;
using multipolygon2 = boost::geometry::model::multi_polygon<polygon2>;
using box2 = boost::geometry::model::box<point2>;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment