annotate DEPENDENCIES/generic/include/boost/geometry/policies/relate/direction.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_DIRECTION_HPP
Chris@16 10 #define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_DIRECTION_HPP
Chris@16 11
Chris@16 12
Chris@16 13 #include <cstddef>
Chris@16 14 #include <string>
Chris@16 15
Chris@16 16 #include <boost/concept_check.hpp>
Chris@16 17
Chris@16 18 #include <boost/geometry/arithmetic/determinant.hpp>
Chris@16 19 #include <boost/geometry/strategies/side_info.hpp>
Chris@16 20
Chris@16 21 #include <boost/geometry/util/math.hpp>
Chris@16 22 #include <boost/geometry/util/select_calculation_type.hpp>
Chris@16 23 #include <boost/geometry/util/select_most_precise.hpp>
Chris@16 24
Chris@16 25
Chris@16 26 namespace boost { namespace geometry
Chris@16 27 {
Chris@16 28
Chris@16 29
Chris@16 30 namespace policies { namespace relate
Chris@16 31 {
Chris@16 32
Chris@16 33 struct direction_type
Chris@16 34 {
Chris@16 35 // NOTE: "char" will be replaced by enum in future version
Chris@16 36
Chris@16 37 inline direction_type(side_info const& s, char h,
Chris@16 38 int ha, int hb,
Chris@16 39 int da = 0, int db = 0,
Chris@16 40 bool op = false)
Chris@16 41 : how(h)
Chris@16 42 , opposite(op)
Chris@16 43 , how_a(ha)
Chris@16 44 , how_b(hb)
Chris@16 45 , dir_a(da)
Chris@16 46 , dir_b(db)
Chris@16 47 , sides(s)
Chris@16 48 {
Chris@16 49 arrival[0] = ha;
Chris@16 50 arrival[1] = hb;
Chris@16 51 }
Chris@16 52
Chris@16 53 inline direction_type(char h, bool op, int ha = 0, int hb = 0)
Chris@16 54 : how(h)
Chris@16 55 , opposite(op)
Chris@16 56 , how_a(ha)
Chris@16 57 , how_b(hb)
Chris@16 58 , dir_a(0)
Chris@16 59 , dir_b(0)
Chris@16 60 {
Chris@16 61 arrival[0] = ha;
Chris@16 62 arrival[1] = hb;
Chris@16 63 }
Chris@16 64
Chris@16 65
Chris@16 66 // TODO: replace this
Chris@16 67 // NOTE: "char" will be replaced by enum in future version
Chris@16 68 // "How" is the intersection formed?
Chris@16 69 char how;
Chris@16 70
Chris@16 71 // Is it opposite (for collinear/equal cases)
Chris@16 72 bool opposite;
Chris@16 73
Chris@16 74 // Information on how A arrives at intersection, how B arrives at intersection
Chris@16 75 // 1: arrives at intersection
Chris@16 76 // -1: starts from intersection
Chris@16 77 int how_a;
Chris@16 78 int how_b;
Chris@16 79
Chris@16 80 // Direction: how is A positioned from B
Chris@16 81 // 1: points left, seen from IP
Chris@16 82 // -1: points right, seen from IP
Chris@16 83 // In case of intersection: B's TO direction
Chris@16 84 // In case that B's TO direction is at A: B's from direction
Chris@16 85 // In collinear cases: it is 0
Chris@16 86 int dir_a; // Direction of A-s TO from IP
Chris@16 87 int dir_b; // Direction of B-s TO from IP
Chris@16 88
Chris@16 89 // New information
Chris@16 90 side_info sides;
Chris@101 91 // THIS IS EQUAL TO arrival_a, arrival_b - they probably can go now we have robust fractions
Chris@101 92 int arrival[2]; // 1=arrival, -1=departure, 0=neutral; == how_a//how_b
Chris@16 93
Chris@16 94
Chris@16 95 // About arrival[0] (== arrival of a2 w.r.t. b) for COLLINEAR cases
Chris@16 96 // Arrival 1: a1--------->a2 (a arrives within b)
Chris@16 97 // b1----->b2
Chris@16 98
Chris@16 99 // Arrival 1: (a in b)
Chris@16 100 //
Chris@16 101
Chris@16 102
Chris@16 103 // Arrival -1: a1--------->a2 (a does not arrive within b)
Chris@16 104 // b1----->b2
Chris@16 105
Chris@16 106 // Arrival -1: (b in a) a_1-------------a_2
Chris@16 107 // b_1---b_2
Chris@16 108
Chris@16 109 // Arrival 0: a1------->a2 (a arrives at TO-border of b)
Chris@16 110 // b1--->b2
Chris@16 111
Chris@16 112 };
Chris@16 113
Chris@16 114 struct segments_direction
Chris@16 115 {
Chris@16 116 typedef direction_type return_type;
Chris@16 117
Chris@101 118 template
Chris@101 119 <
Chris@101 120 typename Segment1,
Chris@101 121 typename Segment2,
Chris@101 122 typename SegmentIntersectionInfo
Chris@101 123 >
Chris@101 124 static inline return_type segments_crosses(side_info const& sides,
Chris@101 125 SegmentIntersectionInfo const& ,
Chris@101 126 Segment1 const& , Segment2 const& )
Chris@16 127 {
Chris@16 128 bool const ra0 = sides.get<0,0>() == 0;
Chris@16 129 bool const ra1 = sides.get<0,1>() == 0;
Chris@16 130 bool const rb0 = sides.get<1,0>() == 0;
Chris@16 131 bool const rb1 = sides.get<1,1>() == 0;
Chris@16 132
Chris@16 133 return
Chris@16 134 // opposite and same starting point (FROM)
Chris@101 135 ra0 && rb0 ? calculate_side<1>(sides, 'f', -1, -1)
Chris@16 136
Chris@16 137 // opposite and point to each other (TO)
Chris@101 138 : ra1 && rb1 ? calculate_side<0>(sides, 't', 1, 1)
Chris@16 139
Chris@16 140 // not opposite, forming an angle, first a then b,
Chris@16 141 // directed either both left, or both right
Chris@16 142 // Check side of B2 from A. This is not calculated before
Chris@101 143 : ra1 && rb0 ? angle<1>(sides, 'a', 1, -1)
Chris@16 144
Chris@16 145 // not opposite, forming a angle, first b then a,
Chris@16 146 // directed either both left, or both right
Chris@101 147 : ra0 && rb1 ? angle<0>(sides, 'a', -1, 1)
Chris@16 148
Chris@16 149 // b starts from interior of a
Chris@101 150 : rb0 ? starts_from_middle(sides, 'B', 0, -1)
Chris@16 151
Chris@16 152 // a starts from interior of b (#39)
Chris@101 153 : ra0 ? starts_from_middle(sides, 'A', -1, 0)
Chris@16 154
Chris@16 155 // b ends at interior of a, calculate direction of A from IP
Chris@101 156 : rb1 ? b_ends_at_middle(sides)
Chris@16 157
Chris@16 158 // a ends at interior of b
Chris@101 159 : ra1 ? a_ends_at_middle(sides)
Chris@16 160
Chris@16 161 // normal intersection
Chris@101 162 : calculate_side<1>(sides, 'i', -1, -1)
Chris@16 163 ;
Chris@16 164 }
Chris@16 165
Chris@101 166 template <typename Ratio>
Chris@101 167 static inline int arrival_value(Ratio const& r_from, Ratio const& r_to)
Chris@16 168 {
Chris@101 169 // a1--------->a2
Chris@101 170 // b1----->b2
Chris@101 171 // a departs: -1
Chris@101 172
Chris@101 173 // a1--------->a2
Chris@101 174 // b1----->b2
Chris@101 175 // a arrives: 1
Chris@101 176
Chris@101 177 // a1--------->a2
Chris@101 178 // b1----->b2
Chris@101 179 // both arrive there -> r-to = 1/1, or 0/1 (on_segment)
Chris@101 180
Chris@101 181 // First check the TO (for arrival), then FROM (for departure)
Chris@101 182 return r_to.in_segment() ? 1
Chris@101 183 : r_to.on_segment() ? 0
Chris@101 184 : r_from.on_segment() ? -1
Chris@101 185 : -1
Chris@101 186 ;
Chris@16 187 }
Chris@16 188
Chris@101 189 template <typename Ratio>
Chris@101 190 static inline void analyze(Ratio const& r,
Chris@101 191 int& in_segment_count,
Chris@101 192 int& on_end_count,
Chris@101 193 int& outside_segment_count)
Chris@101 194 {
Chris@101 195 if (r.on_end())
Chris@101 196 {
Chris@101 197 on_end_count++;
Chris@101 198 }
Chris@101 199 else if (r.in_segment())
Chris@101 200 {
Chris@101 201 in_segment_count++;
Chris@101 202 }
Chris@101 203 else
Chris@101 204 {
Chris@101 205 outside_segment_count++;
Chris@101 206 }
Chris@101 207 }
Chris@101 208
Chris@101 209 static inline int arrival_from_position_value(int /*v_from*/, int v_to)
Chris@101 210 {
Chris@101 211 return v_to == 2 ? 1
Chris@101 212 : v_to == 1 || v_to == 3 ? 0
Chris@101 213 //: v_from >= 1 && v_from <= 3 ? -1
Chris@101 214 : -1;
Chris@101 215
Chris@101 216 // NOTE: this should be an equivalent of the above for the other order
Chris@101 217 /* (v_from < 3 && v_to > 3) || (v_from > 3 && v_to < 3) ? 1
Chris@101 218 : v_from == 3 || v_to == 3 ? 0
Chris@101 219 : -1;*/
Chris@101 220 }
Chris@101 221
Chris@101 222 static inline void analyse_position_value(int pos_val,
Chris@101 223 int & in_segment_count,
Chris@101 224 int & on_end_count,
Chris@101 225 int & outside_segment_count)
Chris@101 226 {
Chris@101 227 if ( pos_val == 1 || pos_val == 3 )
Chris@101 228 {
Chris@101 229 on_end_count++;
Chris@101 230 }
Chris@101 231 else if ( pos_val == 2 )
Chris@101 232 {
Chris@101 233 in_segment_count++;
Chris@101 234 }
Chris@101 235 else
Chris@101 236 {
Chris@101 237 outside_segment_count++;
Chris@101 238 }
Chris@101 239 }
Chris@101 240
Chris@101 241 template <typename Segment1, typename Segment2, typename Ratio>
Chris@101 242 static inline return_type segments_collinear(
Chris@101 243 Segment1 const& , Segment2 const& , bool opposite,
Chris@101 244 int a1_wrt_b, int a2_wrt_b, int b1_wrt_a, int b2_wrt_a,
Chris@101 245 Ratio const& /*ra_from_wrt_b*/, Ratio const& /*ra_to_wrt_b*/,
Chris@101 246 Ratio const& /*rb_from_wrt_a*/, Ratio const& /*rb_to_wrt_a*/)
Chris@16 247 {
Chris@16 248 return_type r('c', opposite);
Chris@101 249
Chris@101 250 // IMPORTANT: the order of conditions is different as in intersection_points.hpp
Chris@101 251 // We assign A in 0 and B in 1
Chris@101 252 r.arrival[0] = arrival_from_position_value(a1_wrt_b, a2_wrt_b);
Chris@101 253 r.arrival[1] = arrival_from_position_value(b1_wrt_a, b2_wrt_a);
Chris@101 254
Chris@101 255 // Analyse them
Chris@101 256 int a_in_segment_count = 0;
Chris@101 257 int a_on_end_count = 0;
Chris@101 258 int a_outside_segment_count = 0;
Chris@101 259 int b_in_segment_count = 0;
Chris@101 260 int b_on_end_count = 0;
Chris@101 261 int b_outside_segment_count = 0;
Chris@101 262 analyse_position_value(a1_wrt_b,
Chris@101 263 a_in_segment_count, a_on_end_count, a_outside_segment_count);
Chris@101 264 analyse_position_value(a2_wrt_b,
Chris@101 265 a_in_segment_count, a_on_end_count, a_outside_segment_count);
Chris@101 266 analyse_position_value(b1_wrt_a,
Chris@101 267 b_in_segment_count, b_on_end_count, b_outside_segment_count);
Chris@101 268 analyse_position_value(b2_wrt_a,
Chris@101 269 b_in_segment_count, b_on_end_count, b_outside_segment_count);
Chris@101 270
Chris@101 271 if (a_on_end_count == 1
Chris@101 272 && b_on_end_count == 1
Chris@101 273 && a_outside_segment_count == 1
Chris@101 274 && b_outside_segment_count == 1)
Chris@101 275 {
Chris@101 276 // This is a collinear touch
Chris@101 277 // --------> A (or B)
Chris@101 278 // <---------- B (or A)
Chris@101 279 // We adapt the "how"
Chris@101 280 // TODO: how was to be refactored anyway,
Chris@101 281 if (! opposite)
Chris@101 282 {
Chris@101 283 r.how = 'a';
Chris@101 284 }
Chris@101 285 else
Chris@101 286 {
Chris@101 287 r.how = r.arrival[0] == 0 ? 't' : 'f';
Chris@101 288 }
Chris@101 289 }
Chris@101 290 else if (a_on_end_count == 2
Chris@101 291 && b_on_end_count == 2)
Chris@101 292 {
Chris@101 293 r.how = 'e';
Chris@101 294 }
Chris@101 295
Chris@16 296 return r;
Chris@16 297 }
Chris@16 298
Chris@101 299 template <typename Segment>
Chris@101 300 static inline return_type degenerate(Segment const& , bool)
Chris@16 301 {
Chris@16 302 return return_type('0', false);
Chris@16 303 }
Chris@16 304
Chris@101 305 template <typename Segment, typename Ratio>
Chris@101 306 static inline return_type one_degenerate(Segment const& ,
Chris@101 307 Ratio const& ,
Chris@101 308 bool)
Chris@16 309 {
Chris@101 310 // To be decided
Chris@101 311 return return_type('0', false);
Chris@16 312 }
Chris@16 313
Chris@101 314 static inline return_type disjoint()
Chris@16 315 {
Chris@16 316 return return_type('d', false);
Chris@16 317 }
Chris@16 318
Chris@16 319 static inline return_type error(std::string const&)
Chris@16 320 {
Chris@16 321 // Return "E" to denote error
Chris@16 322 // This will throw an error in get_turn_info
Chris@16 323 // TODO: change to enum or similar
Chris@16 324 return return_type('E', false);
Chris@16 325 }
Chris@16 326
Chris@16 327 private :
Chris@16 328
Chris@16 329 template <std::size_t I>
Chris@16 330 static inline return_type calculate_side(side_info const& sides,
Chris@16 331 char how, int how_a, int how_b)
Chris@16 332 {
Chris@101 333 int const dir = sides.get<1, I>() == 1 ? 1 : -1;
Chris@101 334 return return_type(sides, how, how_a, how_b, -dir, dir);
Chris@16 335 }
Chris@16 336
Chris@16 337 template <std::size_t I>
Chris@16 338 static inline return_type angle(side_info const& sides,
Chris@16 339 char how, int how_a, int how_b)
Chris@16 340 {
Chris@101 341 int const dir = sides.get<1, I>() == 1 ? 1 : -1;
Chris@101 342 return return_type(sides, how, how_a, how_b, dir, dir);
Chris@16 343 }
Chris@16 344
Chris@16 345
Chris@16 346 static inline return_type starts_from_middle(side_info const& sides,
Chris@16 347 char which,
Chris@16 348 int how_a, int how_b)
Chris@16 349 {
Chris@16 350 // Calculate ARROW of b segment w.r.t. s1
Chris@101 351 int dir = sides.get<1, 1>() == 1 ? 1 : -1;
Chris@16 352
Chris@16 353 // From other perspective, then reverse
Chris@16 354 bool const is_a = which == 'A';
Chris@16 355 if (is_a)
Chris@16 356 {
Chris@16 357 dir = -dir;
Chris@16 358 }
Chris@16 359
Chris@16 360 return return_type(sides, 's',
Chris@16 361 how_a,
Chris@16 362 how_b,
Chris@16 363 is_a ? dir : -dir,
Chris@16 364 ! is_a ? dir : -dir);
Chris@16 365 }
Chris@16 366
Chris@16 367
Chris@16 368
Chris@16 369 // To be harmonized
Chris@101 370 static inline return_type a_ends_at_middle(side_info const& sides)
Chris@16 371 {
Chris@16 372 // Ending at the middle, one ARRIVES, the other one is NEUTRAL
Chris@101 373 // (because it both "arrives" and "departs" there)
Chris@101 374 int const dir = sides.get<1, 1>() == 1 ? 1 : -1;
Chris@101 375 return return_type(sides, 'm', 1, 0, dir, dir);
Chris@16 376 }
Chris@16 377
Chris@16 378
Chris@101 379 static inline return_type b_ends_at_middle(side_info const& sides)
Chris@16 380 {
Chris@101 381 int const dir = sides.get<0, 1>() == 1 ? 1 : -1;
Chris@101 382 return return_type(sides, 'm', 0, 1, dir, dir);
Chris@16 383 }
Chris@16 384
Chris@16 385 };
Chris@16 386
Chris@16 387 }} // namespace policies::relate
Chris@16 388
Chris@16 389 }} // namespace boost::geometry
Chris@16 390
Chris@16 391 #endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_DIRECTION_HPP