annotate DEPENDENCIES/generic/include/boost/geometry/policies/relate/intersection_points.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 c530137014c0
children
rev   line source
Chris@16 1 // Boost.Geometry (aka GGL, Generic Geometry Library)
Chris@16 2
Chris@16 3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
Chris@16 4
Chris@16 5 // Use, modification and distribution is subject to the Boost Software License,
Chris@16 6 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 7 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 8
Chris@16 9 #ifndef BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP
Chris@16 10 #define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP
Chris@16 11
Chris@16 12
Chris@16 13 #include <algorithm>
Chris@16 14 #include <string>
Chris@16 15
Chris@16 16 #include <boost/concept_check.hpp>
Chris@16 17 #include <boost/numeric/conversion/cast.hpp>
Chris@16 18
Chris@101 19 #include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
Chris@16 20 #include <boost/geometry/core/access.hpp>
Chris@16 21 #include <boost/geometry/strategies/side_info.hpp>
Chris@101 22 #include <boost/geometry/util/promote_integral.hpp>
Chris@16 23 #include <boost/geometry/util/select_calculation_type.hpp>
Chris@16 24 #include <boost/geometry/util/select_most_precise.hpp>
Chris@101 25 #include <boost/geometry/util/math.hpp>
Chris@16 26
Chris@16 27 namespace boost { namespace geometry
Chris@16 28 {
Chris@16 29
Chris@16 30 namespace policies { namespace relate
Chris@16 31 {
Chris@16 32
Chris@16 33
Chris@101 34 /*!
Chris@101 35 \brief Policy calculating the intersection points themselves
Chris@101 36 */
Chris@101 37 template
Chris@101 38 <
Chris@101 39 typename ReturnType
Chris@101 40 >
Chris@16 41 struct segments_intersection_points
Chris@16 42 {
Chris@16 43 typedef ReturnType return_type;
Chris@16 44
Chris@101 45 template
Chris@101 46 <
Chris@101 47 typename Point,
Chris@101 48 typename Segment,
Chris@101 49 typename SegmentRatio,
Chris@101 50 typename T
Chris@101 51 >
Chris@101 52 static inline void assign(Point& point,
Chris@101 53 Segment const& segment,
Chris@101 54 SegmentRatio const& ratio,
Chris@101 55 T const& dx, T const& dy)
Chris@101 56 {
Chris@101 57 typedef typename geometry::coordinate_type<Point>::type coordinate_type;
Chris@16 58
Chris@101 59 // Calculate the intersection point based on segment_ratio
Chris@101 60 // Up to now, division was postponed. Here we divide using numerator/
Chris@101 61 // denominator. In case of integer this results in an integer
Chris@101 62 // division.
Chris@101 63 BOOST_ASSERT(ratio.denominator() != 0);
Chris@101 64
Chris@101 65 typedef typename promote_integral<coordinate_type>::type promoted_type;
Chris@101 66
Chris@101 67 promoted_type const numerator
Chris@101 68 = boost::numeric_cast<promoted_type>(ratio.numerator());
Chris@101 69 promoted_type const denominator
Chris@101 70 = boost::numeric_cast<promoted_type>(ratio.denominator());
Chris@101 71 promoted_type const dx_promoted = boost::numeric_cast<promoted_type>(dx);
Chris@101 72 promoted_type const dy_promoted = boost::numeric_cast<promoted_type>(dy);
Chris@101 73
Chris@101 74 set<0>(point, get<0, 0>(segment) + boost::numeric_cast
Chris@101 75 <
Chris@101 76 coordinate_type
Chris@101 77 >(numerator * dx_promoted / denominator));
Chris@101 78 set<1>(point, get<0, 1>(segment) + boost::numeric_cast
Chris@101 79 <
Chris@101 80 coordinate_type
Chris@101 81 >(numerator * dy_promoted / denominator));
Chris@101 82 }
Chris@101 83
Chris@101 84
Chris@101 85 template
Chris@101 86 <
Chris@101 87 typename Segment1,
Chris@101 88 typename Segment2,
Chris@101 89 typename SegmentIntersectionInfo
Chris@101 90 >
Chris@101 91 static inline return_type segments_crosses(side_info const&,
Chris@101 92 SegmentIntersectionInfo const& sinfo,
Chris@101 93 Segment1 const& s1, Segment2 const& s2)
Chris@16 94 {
Chris@16 95 return_type result;
Chris@16 96 result.count = 1;
Chris@101 97
Chris@101 98 if (sinfo.robust_ra < sinfo.robust_rb)
Chris@101 99 {
Chris@101 100 assign(result.intersections[0], s1, sinfo.robust_ra,
Chris@101 101 sinfo.dx_a, sinfo.dy_a);
Chris@101 102 }
Chris@101 103 else
Chris@101 104 {
Chris@101 105 assign(result.intersections[0], s2, sinfo.robust_rb,
Chris@101 106 sinfo.dx_b, sinfo.dy_b);
Chris@101 107 }
Chris@101 108
Chris@101 109 result.fractions[0].assign(sinfo);
Chris@16 110
Chris@16 111 return result;
Chris@16 112 }
Chris@16 113
Chris@101 114 template <typename Segment1, typename Segment2, typename Ratio>
Chris@101 115 static inline return_type segments_collinear(
Chris@101 116 Segment1 const& a, Segment2 const& b, bool /*opposite*/,
Chris@101 117 int a1_wrt_b, int a2_wrt_b, int b1_wrt_a, int b2_wrt_a,
Chris@101 118 Ratio const& ra_from_wrt_b, Ratio const& ra_to_wrt_b,
Chris@101 119 Ratio const& rb_from_wrt_a, Ratio const& rb_to_wrt_a)
Chris@16 120 {
Chris@16 121 return_type result;
Chris@101 122 unsigned int index = 0, count_a = 0, count_b = 0;
Chris@101 123 Ratio on_a[2];
Chris@16 124
Chris@101 125 // The conditions "index < 2" are necessary for non-robust handling,
Chris@101 126 // if index would be 2 this indicate an (currently uncatched) error
Chris@16 127
Chris@101 128 // IMPORTANT: the order of conditions is different as in direction.hpp
Chris@101 129 if (a1_wrt_b >= 1 && a1_wrt_b <= 3 // ra_from_wrt_b.on_segment()
Chris@101 130 && index < 2)
Chris@101 131 {
Chris@101 132 // a1--------->a2
Chris@101 133 // b1----->b2
Chris@101 134 //
Chris@101 135 // ra1 (relative to b) is between 0/1:
Chris@101 136 // -> First point of A is intersection point
Chris@101 137 detail::assign_point_from_index<0>(a, result.intersections[index]);
Chris@101 138 result.fractions[index].assign(Ratio::zero(), ra_from_wrt_b);
Chris@101 139 on_a[index] = Ratio::zero();
Chris@101 140 index++;
Chris@101 141 count_a++;
Chris@101 142 }
Chris@101 143 if (b1_wrt_a == 2 //rb_from_wrt_a.in_segment()
Chris@101 144 && index < 2)
Chris@101 145 {
Chris@101 146 // We take the first intersection point of B
Chris@101 147 // a1--------->a2
Chris@101 148 // b1----->b2
Chris@101 149 // But only if it is not located on A
Chris@101 150 // a1--------->a2
Chris@101 151 // b1----->b2 rb_from_wrt_a == 0/1 -> a already taken
Chris@16 152
Chris@101 153 detail::assign_point_from_index<0>(b, result.intersections[index]);
Chris@101 154 result.fractions[index].assign(rb_from_wrt_a, Ratio::zero());
Chris@101 155 on_a[index] = rb_from_wrt_a;
Chris@101 156 index++;
Chris@101 157 count_b++;
Chris@101 158 }
Chris@16 159
Chris@101 160 if (a2_wrt_b >= 1 && a2_wrt_b <= 3 //ra_to_wrt_b.on_segment()
Chris@101 161 && index < 2)
Chris@101 162 {
Chris@101 163 // Similarly, second IP (here a2)
Chris@101 164 // a1--------->a2
Chris@101 165 // b1----->b2
Chris@101 166 detail::assign_point_from_index<1>(a, result.intersections[index]);
Chris@101 167 result.fractions[index].assign(Ratio::one(), ra_to_wrt_b);
Chris@101 168 on_a[index] = Ratio::one();
Chris@101 169 index++;
Chris@101 170 count_a++;
Chris@101 171 }
Chris@101 172 if (b2_wrt_a == 2 // rb_to_wrt_a.in_segment()
Chris@101 173 && index < 2)
Chris@101 174 {
Chris@101 175 detail::assign_point_from_index<1>(b, result.intersections[index]);
Chris@101 176 result.fractions[index].assign(rb_to_wrt_a, Ratio::one());
Chris@101 177 on_a[index] = rb_to_wrt_a;
Chris@101 178 index++;
Chris@101 179 count_b++;
Chris@101 180 }
Chris@16 181
Chris@101 182 // TEMPORARY
Chris@101 183 // If both are from b, and b is reversed w.r.t. a, we swap IP's
Chris@101 184 // to align them w.r.t. a
Chris@101 185 // get_turn_info still relies on some order (in some collinear cases)
Chris@101 186 if (index == 2 && on_a[1] < on_a[0])
Chris@101 187 {
Chris@101 188 std::swap(result.fractions[0], result.fractions[1]);
Chris@101 189 std::swap(result.intersections[0], result.intersections[1]);
Chris@101 190 }
Chris@101 191
Chris@101 192 result.count = index;
Chris@101 193
Chris@16 194 return result;
Chris@16 195 }
Chris@16 196
Chris@16 197 static inline return_type disjoint()
Chris@16 198 {
Chris@16 199 return return_type();
Chris@16 200 }
Chris@16 201 static inline return_type error(std::string const&)
Chris@16 202 {
Chris@16 203 return return_type();
Chris@16 204 }
Chris@16 205
Chris@101 206 // Both degenerate
Chris@101 207 template <typename Segment>
Chris@101 208 static inline return_type degenerate(Segment const& segment, bool)
Chris@16 209 {
Chris@16 210 return_type result;
Chris@16 211 result.count = 1;
Chris@101 212 set<0>(result.intersections[0], get<0, 0>(segment));
Chris@101 213 set<1>(result.intersections[0], get<0, 1>(segment));
Chris@101 214 return result;
Chris@101 215 }
Chris@101 216
Chris@101 217 // One degenerate
Chris@101 218 template <typename Segment, typename Ratio>
Chris@101 219 static inline return_type one_degenerate(Segment const& degenerate_segment,
Chris@101 220 Ratio const& ratio, bool a_degenerate)
Chris@101 221 {
Chris@101 222 return_type result;
Chris@101 223 result.count = 1;
Chris@101 224 set<0>(result.intersections[0], get<0, 0>(degenerate_segment));
Chris@101 225 set<1>(result.intersections[0], get<0, 1>(degenerate_segment));
Chris@101 226 if (a_degenerate)
Chris@101 227 {
Chris@101 228 // IP lies on ratio w.r.t. segment b
Chris@101 229 result.fractions[0].assign(Ratio::zero(), ratio);
Chris@101 230 }
Chris@101 231 else
Chris@101 232 {
Chris@101 233 result.fractions[0].assign(ratio, Ratio::zero());
Chris@101 234 }
Chris@16 235 return result;
Chris@16 236 }
Chris@16 237 };
Chris@16 238
Chris@16 239
Chris@16 240 }} // namespace policies::relate
Chris@16 241
Chris@16 242 }} // namespace boost::geometry
Chris@16 243
Chris@16 244 #endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP