1 // Boost.Geometry (aka GGL, Generic Geometry Library) 2 3 // Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands. 4 // Copyright (c) 2011-2012 Bruno Lalande, Paris, France. 5 // Copyright (c) 2011-2012 Mateusz Loskot, London, UK. 6 7 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library 8 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. 9 10 // Use, modification and distribution is subject to the Boost Software License, 11 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 12 // http://www.boost.org/LICENSE_1_0.txt) 13 14 #ifndef BOOST_GEOMETRY_UTIL_RATIONAL_HPP 15 #define BOOST_GEOMETRY_UTIL_RATIONAL_HPP 16 17 #include <boost/rational.hpp> 18 #include <boost/numeric/conversion/bounds.hpp> 19 20 #include <boost/geometry/util/coordinate_cast.hpp> 21 #include <boost/geometry/util/select_most_precise.hpp> 22 23 24 namespace boost{ namespace geometry 25 { 26 27 28 // Specialize for Boost.Geometry's coordinate cast 29 // (from string to coordinate type) 30 namespace detail 31 { 32 33 template <typename T> 34 struct coordinate_cast<rational<T> > 35 { split_partsboost::geometry::detail::coordinate_cast36 static inline void split_parts(std::string const& source, std::string::size_type p, 37 T& before, T& after, bool& negate, std::string::size_type& len) 38 { 39 std::string before_part = source.substr(0, p); 40 std::string const after_part = source.substr(p + 1); 41 42 negate = false; 43 44 if (before_part.size() > 0 && before_part[0] == '-') 45 { 46 negate = true; 47 before_part.erase(0, 1); 48 } 49 before = atol(before_part.c_str()); 50 after = atol(after_part.c_str()); 51 len = after_part.length(); 52 } 53 54 applyboost::geometry::detail::coordinate_cast55 static inline rational<T> apply(std::string const& source) 56 { 57 T before, after; 58 bool negate; 59 std::string::size_type len; 60 61 // Note: decimal comma is not (yet) supported, it does (and should) not 62 // occur in a WKT, where points are comma separated. 63 std::string::size_type p = source.find("."); 64 if (p == std::string::npos) 65 { 66 p = source.find("/"); 67 if (p == std::string::npos) 68 { 69 return rational<T>(atol(source.c_str())); 70 } 71 split_parts(source, p, before, after, negate, len); 72 73 return negate 74 ? -rational<T>(before, after) 75 : rational<T>(before, after) 76 ; 77 78 } 79 80 split_parts(source, p, before, after, negate, len); 81 82 T den = 1; 83 for (std::string::size_type i = 0; i < len; i++) 84 { 85 den *= 10; 86 } 87 88 return negate 89 ? -rational<T>(before) - rational<T>(after, den) 90 : rational<T>(before) + rational<T>(after, den) 91 ; 92 } 93 }; 94 95 } // namespace detail 96 97 // Specialize for Boost.Geometry's select_most_precise 98 template <typename T1, typename T2> 99 struct select_most_precise<boost::rational<T1>, boost::rational<T2> > 100 { 101 typedef typename boost::rational 102 < 103 typename select_most_precise<T1, T2>::type 104 > type; 105 }; 106 107 template <typename T> 108 struct select_most_precise<boost::rational<T>, double> 109 { 110 typedef typename boost::rational<T> type; 111 }; 112 113 114 }} // namespace boost::geometry 115 116 117 // Specializes boost::rational to boost::numeric::bounds 118 namespace boost { namespace numeric 119 { 120 121 template<class T> 122 struct bounds<rational<T> > 123 { lowestboost::numeric::bounds124 static inline rational<T> lowest() 125 { 126 return rational<T>(bounds<T>::lowest(), 1); 127 } highestboost::numeric::bounds128 static inline rational<T> highest() 129 { 130 return rational<T>(bounds<T>::highest(), 1); 131 } 132 }; 133 134 }} // namespace boost::numeric 135 136 137 // Support for boost::numeric_cast to int and to double (necessary for SVG-mapper) 138 namespace boost { namespace numeric 139 { 140 141 template 142 < 143 typename T, 144 typename Traits, 145 typename OverflowHandler, 146 typename Float2IntRounder, 147 typename RawConverter, 148 typename UserRangeChecker 149 > 150 struct converter<int, rational<T>, Traits, OverflowHandler, Float2IntRounder, RawConverter, UserRangeChecker> 151 { convertboost::numeric::converter152 static inline int convert(rational<T> const& arg) 153 { 154 return int(rational_cast<double>(arg)); 155 } 156 }; 157 158 template 159 < 160 typename T, 161 typename Traits, 162 typename OverflowHandler, 163 typename Float2IntRounder, 164 typename RawConverter, 165 typename UserRangeChecker 166 > 167 struct converter<double, rational<T>, Traits, OverflowHandler, Float2IntRounder, RawConverter, UserRangeChecker> 168 { convertboost::numeric::converter169 static inline double convert(rational<T> const& arg) 170 { 171 return rational_cast<double>(arg); 172 } 173 }; 174 175 176 }} 177 178 179 #endif // BOOST_GEOMETRY_UTIL_RATIONAL_HPP 180