annotate DEPENDENCIES/generic/include/boost/geometry/policies/robustness/segment_ratio.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents f46d142149f5
children
rev   line source
Chris@102 1 // Boost.Geometry (aka GGL, Generic Geometry Library)
Chris@102 2
Chris@102 3 // Copyright (c) 2013 Barend Gehrels, Amsterdam, the Netherlands.
Chris@102 4
Chris@102 5 // Use, modification and distribution is subject to the Boost Software License,
Chris@102 6 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@102 7 // http://www.boost.org/LICENSE_1_0.txt)
Chris@102 8
Chris@102 9 #ifndef BOOST_GEOMETRY_POLICIES_ROBUSTNESS_SEGMENT_RATIO_HPP
Chris@102 10 #define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_SEGMENT_RATIO_HPP
Chris@102 11
Chris@102 12 #include <boost/assert.hpp>
Chris@102 13 #include <boost/config.hpp>
Chris@102 14 #include <boost/rational.hpp>
Chris@102 15
Chris@102 16 #include <boost/geometry/util/math.hpp>
Chris@102 17 #include <boost/geometry/util/promote_floating_point.hpp>
Chris@102 18
Chris@102 19 namespace boost { namespace geometry
Chris@102 20 {
Chris@102 21
Chris@102 22
Chris@102 23 namespace detail { namespace segment_ratio
Chris@102 24 {
Chris@102 25
Chris@102 26 template
Chris@102 27 <
Chris@102 28 typename Type,
Chris@102 29 bool IsIntegral = boost::is_integral<Type>::type::value
Chris@102 30 >
Chris@102 31 struct less {};
Chris@102 32
Chris@102 33 template <typename Type>
Chris@102 34 struct less<Type, true>
Chris@102 35 {
Chris@102 36 template <typename Ratio>
Chris@102 37 static inline bool apply(Ratio const& lhs, Ratio const& rhs)
Chris@102 38 {
Chris@102 39 return boost::rational<Type>(lhs.numerator(), lhs.denominator())
Chris@102 40 < boost::rational<Type>(rhs.numerator(), rhs.denominator());
Chris@102 41 }
Chris@102 42 };
Chris@102 43
Chris@102 44 template <typename Type>
Chris@102 45 struct less<Type, false>
Chris@102 46 {
Chris@102 47 template <typename Ratio>
Chris@102 48 static inline bool apply(Ratio const& lhs, Ratio const& rhs)
Chris@102 49 {
Chris@102 50 BOOST_ASSERT(lhs.denominator() != 0);
Chris@102 51 BOOST_ASSERT(rhs.denominator() != 0);
Chris@102 52 return lhs.numerator() * rhs.denominator()
Chris@102 53 < rhs.numerator() * lhs.denominator();
Chris@102 54 }
Chris@102 55 };
Chris@102 56
Chris@102 57 template
Chris@102 58 <
Chris@102 59 typename Type,
Chris@102 60 bool IsIntegral = boost::is_integral<Type>::type::value
Chris@102 61 >
Chris@102 62 struct equal {};
Chris@102 63
Chris@102 64 template <typename Type>
Chris@102 65 struct equal<Type, true>
Chris@102 66 {
Chris@102 67 template <typename Ratio>
Chris@102 68 static inline bool apply(Ratio const& lhs, Ratio const& rhs)
Chris@102 69 {
Chris@102 70 return boost::rational<Type>(lhs.numerator(), lhs.denominator())
Chris@102 71 == boost::rational<Type>(rhs.numerator(), rhs.denominator());
Chris@102 72 }
Chris@102 73 };
Chris@102 74
Chris@102 75 template <typename Type>
Chris@102 76 struct equal<Type, false>
Chris@102 77 {
Chris@102 78 template <typename Ratio>
Chris@102 79 static inline bool apply(Ratio const& lhs, Ratio const& rhs)
Chris@102 80 {
Chris@102 81 BOOST_ASSERT(lhs.denominator() != 0);
Chris@102 82 BOOST_ASSERT(rhs.denominator() != 0);
Chris@102 83 return geometry::math::equals
Chris@102 84 (
Chris@102 85 lhs.numerator() * rhs.denominator(),
Chris@102 86 rhs.numerator() * lhs.denominator()
Chris@102 87 );
Chris@102 88 }
Chris@102 89 };
Chris@102 90
Chris@102 91 }}
Chris@102 92
Chris@102 93 //! Small class to keep a ratio (e.g. 1/4)
Chris@102 94 //! Main purpose is intersections and checking on 0, 1, and smaller/larger
Chris@102 95 //! The prototype used Boost.Rational. However, we also want to store FP ratios,
Chris@102 96 //! (so numerator/denominator both in float)
Chris@102 97 //! and Boost.Rational starts with GCD which we prefer to avoid if not necessary
Chris@102 98 //! On a segment means: this ratio is between 0 and 1 (both inclusive)
Chris@102 99 //!
Chris@102 100 template <typename Type>
Chris@102 101 class segment_ratio
Chris@102 102 {
Chris@102 103 public :
Chris@102 104 typedef Type numeric_type;
Chris@102 105
Chris@102 106 // Type-alias for the type itself
Chris@102 107 typedef segment_ratio<Type> thistype;
Chris@102 108
Chris@102 109 inline segment_ratio()
Chris@102 110 : m_numerator(0)
Chris@102 111 , m_denominator(1)
Chris@102 112 , m_approximation(0)
Chris@102 113 {}
Chris@102 114
Chris@102 115 inline segment_ratio(const Type& nominator, const Type& denominator)
Chris@102 116 : m_numerator(nominator)
Chris@102 117 , m_denominator(denominator)
Chris@102 118 {
Chris@102 119 initialize();
Chris@102 120 }
Chris@102 121
Chris@102 122 inline Type const& numerator() const { return m_numerator; }
Chris@102 123 inline Type const& denominator() const { return m_denominator; }
Chris@102 124
Chris@102 125 inline void assign(const Type& nominator, const Type& denominator)
Chris@102 126 {
Chris@102 127 m_numerator = nominator;
Chris@102 128 m_denominator = denominator;
Chris@102 129 initialize();
Chris@102 130 }
Chris@102 131
Chris@102 132 inline void initialize()
Chris@102 133 {
Chris@102 134 // Minimal normalization
Chris@102 135 // 1/-4 => -1/4, -1/-4 => 1/4
Chris@102 136 if (m_denominator < 0)
Chris@102 137 {
Chris@102 138 m_numerator = -m_numerator;
Chris@102 139 m_denominator = -m_denominator;
Chris@102 140 }
Chris@102 141
Chris@102 142 typedef typename promote_floating_point<Type>::type num_type;
Chris@102 143 static const num_type scale = 1000000.0;
Chris@102 144 m_approximation =
Chris@102 145 m_denominator == 0 ? 0
Chris@102 146 : boost::numeric_cast<double>
Chris@102 147 (
Chris@102 148 boost::numeric_cast<num_type>(m_numerator) * scale
Chris@102 149 / boost::numeric_cast<num_type>(m_denominator)
Chris@102 150 );
Chris@102 151 }
Chris@102 152
Chris@102 153 inline bool is_zero() const { return math::equals(m_numerator, 0); }
Chris@102 154 inline bool is_one() const { return math::equals(m_numerator, m_denominator); }
Chris@102 155 inline bool on_segment() const
Chris@102 156 {
Chris@102 157 // e.g. 0/4 or 4/4 or 2/4
Chris@102 158 return m_numerator >= 0 && m_numerator <= m_denominator;
Chris@102 159 }
Chris@102 160 inline bool in_segment() const
Chris@102 161 {
Chris@102 162 // e.g. 1/4
Chris@102 163 return m_numerator > 0 && m_numerator < m_denominator;
Chris@102 164 }
Chris@102 165 inline bool on_end() const
Chris@102 166 {
Chris@102 167 // e.g. 0/4 or 4/4
Chris@102 168 return is_zero() || is_one();
Chris@102 169 }
Chris@102 170 inline bool left() const
Chris@102 171 {
Chris@102 172 // e.g. -1/4
Chris@102 173 return m_numerator < 0;
Chris@102 174 }
Chris@102 175 inline bool right() const
Chris@102 176 {
Chris@102 177 // e.g. 5/4
Chris@102 178 return m_numerator > m_denominator;
Chris@102 179 }
Chris@102 180
Chris@102 181 inline bool close_to(thistype const& other) const
Chris@102 182 {
Chris@102 183 return geometry::math::abs(m_approximation - other.m_approximation) < 2;
Chris@102 184 }
Chris@102 185
Chris@102 186 inline bool operator< (thistype const& other) const
Chris@102 187 {
Chris@102 188 return close_to(other)
Chris@102 189 ? detail::segment_ratio::less<Type>::apply(*this, other)
Chris@102 190 : m_approximation < other.m_approximation;
Chris@102 191 }
Chris@102 192
Chris@102 193 inline bool operator== (thistype const& other) const
Chris@102 194 {
Chris@102 195 return close_to(other)
Chris@102 196 && detail::segment_ratio::equal<Type>::apply(*this, other);
Chris@102 197 }
Chris@102 198
Chris@102 199 static inline thistype zero()
Chris@102 200 {
Chris@102 201 static thistype result(0, 1);
Chris@102 202 return result;
Chris@102 203 }
Chris@102 204
Chris@102 205 static inline thistype one()
Chris@102 206 {
Chris@102 207 static thistype result(1, 1);
Chris@102 208 return result;
Chris@102 209 }
Chris@102 210
Chris@102 211 #if defined(BOOST_GEOMETRY_DEFINE_STREAM_OPERATOR_SEGMENT_RATIO)
Chris@102 212 friend std::ostream& operator<<(std::ostream &os, segment_ratio const& ratio)
Chris@102 213 {
Chris@102 214 os << ratio.m_numerator << "/" << ratio.m_denominator
Chris@102 215 << " (" << (static_cast<double>(ratio.m_numerator)
Chris@102 216 / static_cast<double>(ratio.m_denominator))
Chris@102 217 << ")";
Chris@102 218 return os;
Chris@102 219 }
Chris@102 220 #endif
Chris@102 221
Chris@102 222
Chris@102 223
Chris@102 224 private :
Chris@102 225 Type m_numerator;
Chris@102 226 Type m_denominator;
Chris@102 227
Chris@102 228 // Contains ratio on scale 0..1000000 (for 0..1)
Chris@102 229 // This is an approximation for fast and rough comparisons
Chris@102 230 // Boost.Rational is used if the approximations are close.
Chris@102 231 // Reason: performance, Boost.Rational does a GCD by default and also the
Chris@102 232 // comparisons contain while-loops.
Chris@102 233 double m_approximation;
Chris@102 234 };
Chris@102 235
Chris@102 236
Chris@102 237 }} // namespace boost::geometry
Chris@102 238
Chris@102 239 #endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_SEGMENT_RATIO_HPP