• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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