// Boost.Geometry (aka GGL, Generic Geometry Library) // Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2008-2011 Bruno Lalande, Paris, France. // Copyright (c) 2009-2011 Mateusz Loskot, London, UK. // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // Example combining Boost.Geometry with Boost.Units #include #include #include #include #include #include // TEMPORARY this will go to somewhere within Boost.Geometry namespace boost { namespace geometry { namespace cs { template struct units_cartesian {}; } namespace traits { template struct cs_tag > { typedef cartesian_tag type; }; } namespace model { // Define a point type to interoperate with Boost.Units, having // 1. a constructor taking quantities // 2. defining a quantified coordinate system // Note that all values are still stored in "normal" types as double template > class quantity_point : public model::point { typedef boost::units::quantity qtype; public : // Templated constructor to allow constructing with other units then qtype, // e.g. to convert from centimeters to meters template inline quantity_point(Q const& x, Q const& y) : model::point( qtype(x).value(), qtype(y).value()) {} }; } // Adapt quantity_point to the Point Concept #ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS namespace traits { template struct tag > { typedef point_tag type; }; template struct coordinate_type > { typedef CoordinateType type; }; template struct coordinate_system > { typedef CoordinateSystem type; }; template struct dimension > : boost::mpl::int_ {}; template struct access, Dimension > { static inline CoordinateType get( model::quantity_point const& p) { return p.template get(); } static inline void set(model::quantity_point& p, CoordinateType const& value) { p.template set(value); } }; } // namespace traits #endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS // For extra support for functions as distance,area,get,set namespace units { namespace detail { // Define an extra meta-function to get the units of a coordinate system template struct unit_dimension { // define it as dimensionless // or MPL ASSERT }; template struct unit_dimension > { typedef U type; }; } // Define an extra metafunction to define the quantity of a Geometry type template ::type> struct quantity { typedef boost::units::quantity < typename detail::unit_dimension < typename coordinate_system::type >::type, CT > type; }; template inline typename quantity::type>::type distance(Geometry1 const& g1, Geometry2 const& g2) { typedef typename quantity::type>::type q; return q::from_value(geometry::distance(g1, g2)); } template inline typename quantity::type get(Point const& p) { typedef typename quantity::type q; return q::from_value(geometry::get(p)); } } }} // END TEMPORARY int main(void) { using namespace boost::geometry; using namespace boost::units; // 1: using it directly { typedef model::quantity_point point; point p1(1 * si::meter, 2 * si::meter); point p2(3 * si::meter, 4 * si::meter); std::cout << get<0>(p2) << std::endl; // This is a little inconvenient: quantity d = distance(p1, p2) * si::meter; std::cout << d << std::endl; } // 2: same but now using centimeters, and using boost::geometry::units:: { typedef model::quantity_point point; point p1(1 * si::meter, 2 * si::meter); point p2(3 * si::meter, 4 * si::meter); std::cout << boost::geometry::units::get<0>(p2) << std::endl; quantity d = boost::geometry::units::distance(p1, p2); std::cout << d << std::endl; } return 0; }