get_turn_info.hpp 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
  4. // This file was modified by Oracle on 2015, 2017, 2018, 2019.
  5. // Modifications copyright (c) 2015-2019 Oracle and/or its affiliates.
  6. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  7. // Use, modification and distribution is subject to the Boost Software License,
  8. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP
  11. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP
  12. #include <boost/core/ignore_unused.hpp>
  13. #include <boost/throw_exception.hpp>
  14. #include <boost/geometry/core/access.hpp>
  15. #include <boost/geometry/core/assert.hpp>
  16. #include <boost/geometry/core/config.hpp>
  17. #include <boost/geometry/core/exception.hpp>
  18. #include <boost/geometry/algorithms/convert.hpp>
  19. #include <boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp>
  20. #include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
  21. #include <boost/geometry/geometries/segment.hpp>
  22. #include <boost/geometry/policies/robustness/robust_point_type.hpp>
  23. #include <boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp>
  24. // Silence warning C4127: conditional expression is constant
  25. #if defined(_MSC_VER)
  26. #pragma warning(push)
  27. #pragma warning(disable : 4127)
  28. #endif
  29. namespace boost { namespace geometry
  30. {
  31. #if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)
  32. class turn_info_exception : public geometry::exception
  33. {
  34. std::string message;
  35. public:
  36. // NOTE: "char" will be replaced by enum in future version
  37. inline turn_info_exception(char const method)
  38. {
  39. message = "Boost.Geometry Turn exception: ";
  40. message += method;
  41. }
  42. virtual ~turn_info_exception() throw()
  43. {}
  44. virtual char const* what() const throw()
  45. {
  46. return message.c_str();
  47. }
  48. };
  49. #endif
  50. #ifndef DOXYGEN_NO_DETAIL
  51. namespace detail { namespace overlay
  52. {
  53. struct base_turn_handler
  54. {
  55. // Returns true if both sides are opposite
  56. static inline bool opposite(int side1, int side2)
  57. {
  58. // We cannot state side1 == -side2, because 0 == -0
  59. // So either side1*side2==-1 or side1==-side2 && side1 != 0
  60. return side1 * side2 == -1;
  61. }
  62. // Same side of a segment (not being 0)
  63. static inline bool same(int side1, int side2)
  64. {
  65. return side1 * side2 == 1;
  66. }
  67. // Both get the same operation
  68. template <typename TurnInfo>
  69. static inline void both(TurnInfo& ti, operation_type const op)
  70. {
  71. ti.operations[0].operation = op;
  72. ti.operations[1].operation = op;
  73. }
  74. // If condition, first union/second intersection, else vice versa
  75. template <typename TurnInfo>
  76. static inline void ui_else_iu(bool condition, TurnInfo& ti)
  77. {
  78. ti.operations[0].operation = condition
  79. ? operation_union : operation_intersection;
  80. ti.operations[1].operation = condition
  81. ? operation_intersection : operation_union;
  82. }
  83. // If condition, both union, else both intersection
  84. template <typename TurnInfo>
  85. static inline void uu_else_ii(bool condition, TurnInfo& ti)
  86. {
  87. both(ti, condition ? operation_union : operation_intersection);
  88. }
  89. template <typename TurnInfo, typename IntersectionInfo>
  90. static inline void assign_point(TurnInfo& ti,
  91. method_type method,
  92. IntersectionInfo const& info, unsigned int index)
  93. {
  94. ti.method = method;
  95. BOOST_GEOMETRY_ASSERT(index < info.count);
  96. geometry::convert(info.intersections[index], ti.point);
  97. ti.operations[0].fraction = info.fractions[index].robust_ra;
  98. ti.operations[1].fraction = info.fractions[index].robust_rb;
  99. }
  100. template <typename IntersectionInfo>
  101. static inline unsigned int non_opposite_to_index(IntersectionInfo const& info)
  102. {
  103. return info.fractions[0].robust_rb < info.fractions[1].robust_rb
  104. ? 1 : 0;
  105. }
  106. template <typename Point1, typename Point2>
  107. static inline typename geometry::coordinate_type<Point1>::type
  108. distance_measure(Point1 const& a, Point2 const& b)
  109. {
  110. // TODO: use comparable distance for point-point instead - but that
  111. // causes currently cycling include problems
  112. typedef typename geometry::coordinate_type<Point1>::type ctype;
  113. ctype const dx = get<0>(a) - get<0>(b);
  114. ctype const dy = get<1>(a) - get<1>(b);
  115. return dx * dx + dy * dy;
  116. }
  117. template
  118. <
  119. std::size_t IndexP,
  120. std::size_t IndexQ,
  121. typename UniqueSubRange1,
  122. typename UniqueSubRange2,
  123. typename UmbrellaStrategy,
  124. typename TurnInfo
  125. >
  126. static inline void both_collinear(
  127. UniqueSubRange1 const& range_p,
  128. UniqueSubRange2 const& range_q,
  129. UmbrellaStrategy const&,
  130. std::size_t index_p, std::size_t index_q,
  131. TurnInfo& ti)
  132. {
  133. boost::ignore_unused(range_p, range_q);
  134. BOOST_GEOMETRY_ASSERT(IndexP + IndexQ == 1);
  135. BOOST_GEOMETRY_ASSERT(index_p > 0 && index_p <= 2);
  136. BOOST_GEOMETRY_ASSERT(index_q > 0 && index_q <= 2);
  137. #if ! defined(BOOST_GEOMETRY_USE_RESCALING)
  138. ti.operations[IndexP].remaining_distance = distance_measure(ti.point, range_p.at(index_p));
  139. ti.operations[IndexQ].remaining_distance = distance_measure(ti.point, range_q.at(index_q));
  140. // pk/q2 is considered as collinear, but there might be
  141. // a tiny measurable difference. If so, use that.
  142. // Calculate pk // qj-qk
  143. typedef detail::distance_measure
  144. <
  145. typename select_coordinate_type
  146. <
  147. typename UniqueSubRange1::point_type,
  148. typename UniqueSubRange2::point_type
  149. >::type
  150. > dm_type;
  151. const bool p_closer =
  152. ti.operations[IndexP].remaining_distance
  153. < ti.operations[IndexQ].remaining_distance;
  154. dm_type const dm
  155. = p_closer
  156. ? get_distance_measure<typename UmbrellaStrategy::cs_tag>(range_q.at(index_q - 1),
  157. range_q.at(index_q), range_p.at(index_p))
  158. : get_distance_measure<typename UmbrellaStrategy::cs_tag>(range_p.at(index_p - 1),
  159. range_p.at(index_p), range_q.at(index_q));
  160. if (! dm.is_zero())
  161. {
  162. // Not truely collinear, distinguish for union/intersection
  163. // If p goes left (positive), take that for a union
  164. bool p_left = p_closer ? dm.is_positive() : dm.is_negative();
  165. ti.operations[IndexP].operation = p_left
  166. ? operation_union : operation_intersection;
  167. ti.operations[IndexQ].operation = p_left
  168. ? operation_intersection : operation_union;
  169. return;
  170. }
  171. #endif
  172. both(ti, operation_continue);
  173. }
  174. };
  175. template
  176. <
  177. typename TurnInfo
  178. >
  179. struct touch_interior : public base_turn_handler
  180. {
  181. // Index: 0, P is the interior, Q is touching and vice versa
  182. template
  183. <
  184. unsigned int Index,
  185. typename UniqueSubRange1,
  186. typename UniqueSubRange2,
  187. typename IntersectionInfo,
  188. typename DirInfo,
  189. typename SidePolicy,
  190. typename UmbrellaStrategy
  191. >
  192. static inline void apply(UniqueSubRange1 const& range_p,
  193. UniqueSubRange2 const& range_q,
  194. TurnInfo& ti,
  195. IntersectionInfo const& intersection_info,
  196. DirInfo const& dir_info,
  197. SidePolicy const& side,
  198. UmbrellaStrategy const& umbrella_strategy)
  199. {
  200. assign_point(ti, method_touch_interior, intersection_info, 0);
  201. // Both segments of q touch segment p somewhere in its interior
  202. // 1) We know: if q comes from LEFT or RIGHT
  203. // (i.e. dir_info.sides.get<Index,0>() == 1 or -1)
  204. // 2) Important is: if q_k goes to LEFT, RIGHT, COLLINEAR
  205. // and, if LEFT/COLL, if it is lying LEFT or RIGHT w.r.t. q_i
  206. BOOST_STATIC_ASSERT(Index <= 1);
  207. static unsigned int const index_p = Index;
  208. static unsigned int const index_q = 1 - Index;
  209. bool const has_pk = ! range_p.is_last_segment();
  210. bool const has_qk = ! range_q.is_last_segment();
  211. int const side_qi_p = dir_info.sides.template get<index_q, 0>();
  212. int const side_qk_p = has_qk ? side.qk_wrt_p1() : 0;
  213. if (side_qi_p == -side_qk_p)
  214. {
  215. // Q crosses P from left->right or from right->left (test "ML1")
  216. // Union: folow P (left->right) or Q (right->left)
  217. // Intersection: other turn
  218. unsigned int index = side_qk_p == -1 ? index_p : index_q;
  219. ti.operations[index].operation = operation_union;
  220. ti.operations[1 - index].operation = operation_intersection;
  221. return;
  222. }
  223. int const side_qk_q = has_qk ? side.qk_wrt_q1() : 0;
  224. // Only necessary if rescaling is turned off:
  225. int const side_pj_q2 = has_qk ? side.pj_wrt_q2() : 0;
  226. if (side_qi_p == -1 && side_qk_p == -1 && side_qk_q == 1)
  227. {
  228. // Q turns left on the right side of P (test "MR3")
  229. // Both directions for "intersection"
  230. both(ti, operation_intersection);
  231. ti.touch_only = true;
  232. }
  233. else if (side_qi_p == 1 && side_qk_p == 1 && side_qk_q == -1)
  234. {
  235. if (has_qk && side_pj_q2 == -1)
  236. {
  237. // Q turns right on the left side of P (test "ML3")
  238. // Union: take both operations
  239. // Intersection: skip
  240. both(ti, operation_union);
  241. }
  242. else
  243. {
  244. // q2 is collinear with p1, so it does not turn back. This
  245. // can happen in floating point precision. In this case,
  246. // block one of the operations to avoid taking that path.
  247. ti.operations[index_p].operation = operation_union;
  248. ti.operations[index_q].operation = operation_blocked;
  249. }
  250. ti.touch_only = true;
  251. }
  252. else if (side_qi_p == side_qk_p && side_qi_p == side_qk_q)
  253. {
  254. // Q turns left on the left side of P (test "ML2")
  255. // or Q turns right on the right side of P (test "MR2")
  256. // Union: take left turn (Q if Q turns left, P if Q turns right)
  257. // Intersection: other turn
  258. unsigned int index = side_qk_q == 1 ? index_q : index_p;
  259. if (has_qk && side_pj_q2 == 0)
  260. {
  261. // Even though sides xk w.r.t. 1 are distinct, pj is collinear
  262. // with q. Therefore swap the path
  263. index = 1 - index;
  264. }
  265. if (has_pk && has_qk && opposite(side_pj_q2, side_qi_p))
  266. {
  267. // Without rescaling, floating point requires extra measures
  268. int const side_qj_p1 = side.qj_wrt_p1();
  269. int const side_qj_p2 = side.qj_wrt_p2();
  270. if (same(side_qj_p1, side_qj_p2))
  271. {
  272. int const side_pj_q1 = side.pj_wrt_q1();
  273. if (opposite(side_pj_q1, side_pj_q2))
  274. {
  275. index = 1 - index;
  276. }
  277. }
  278. }
  279. ti.operations[index].operation = operation_union;
  280. ti.operations[1 - index].operation = operation_intersection;
  281. ti.touch_only = true;
  282. }
  283. else if (side_qk_p == 0)
  284. {
  285. // Q intersects on interior of P and continues collinearly
  286. if (side_qk_q == side_qi_p)
  287. {
  288. both_collinear<index_p, index_q>(range_p, range_q, umbrella_strategy, 1, 2, ti);
  289. return;
  290. }
  291. else
  292. {
  293. // Opposite direction, which is never travelled.
  294. // If Q turns left, P continues for intersection
  295. // If Q turns right, P continues for union
  296. ti.operations[index_p].operation = side_qk_q == 1
  297. ? operation_intersection
  298. : operation_union;
  299. ti.operations[index_q].operation = operation_blocked;
  300. }
  301. }
  302. else
  303. {
  304. // Should not occur!
  305. ti.method = method_error;
  306. }
  307. }
  308. };
  309. template
  310. <
  311. typename TurnInfo
  312. >
  313. struct touch : public base_turn_handler
  314. {
  315. static inline bool between(int side1, int side2, int turn)
  316. {
  317. return side1 == side2 && ! opposite(side1, turn);
  318. }
  319. /*static inline void block_second(bool block, TurnInfo& ti)
  320. {
  321. if (block)
  322. {
  323. ti.operations[1].operation = operation_blocked;
  324. }
  325. }*/
  326. template
  327. <
  328. typename UniqueSubRange1,
  329. typename UniqueSubRange2,
  330. typename IntersectionInfo,
  331. typename DirInfo,
  332. typename SideCalculator,
  333. typename UmbrellaStrategy
  334. >
  335. static inline void apply(UniqueSubRange1 const& range_p,
  336. UniqueSubRange2 const& range_q,
  337. TurnInfo& ti,
  338. IntersectionInfo const& intersection_info,
  339. DirInfo const& dir_info,
  340. SideCalculator const& side,
  341. UmbrellaStrategy const& umbrella_strategy)
  342. {
  343. assign_point(ti, method_touch, intersection_info, 0);
  344. bool const has_pk = ! range_p.is_last_segment();
  345. bool const has_qk = ! range_q.is_last_segment();
  346. int const side_qi_p1 = dir_info.sides.template get<1, 0>();
  347. int const side_qk_p1 = has_qk ? side.qk_wrt_p1() : 0;
  348. // If Qi and Qk are both at same side of Pi-Pj,
  349. // or collinear (so: not opposite sides)
  350. if (! opposite(side_qi_p1, side_qk_p1))
  351. {
  352. int const side_pk_q2 = has_pk && has_qk ? side.pk_wrt_q2() : 0;
  353. int const side_pk_p = has_pk ? side.pk_wrt_p1() : 0;
  354. int const side_qk_q = has_qk ? side.qk_wrt_q1() : 0;
  355. bool const q_turns_left = side_qk_q == 1;
  356. bool const block_q = side_qk_p1 == 0
  357. && ! same(side_qi_p1, side_qk_q)
  358. ;
  359. // If Pk at same side as Qi/Qk
  360. // (the "or" is for collinear case)
  361. // or Q is fully collinear && P turns not to left
  362. if (side_pk_p == side_qi_p1
  363. || side_pk_p == side_qk_p1
  364. || (side_qi_p1 == 0 && side_qk_p1 == 0 && side_pk_p != -1)
  365. )
  366. {
  367. // Collinear -> lines join, continue
  368. // (#BRL2)
  369. if (side_pk_q2 == 0 && ! block_q)
  370. {
  371. both_collinear<0, 1>(range_p, range_q, umbrella_strategy, 2, 2, ti);
  372. return;
  373. }
  374. int const side_pk_q1 = has_pk && has_qk ? side.pk_wrt_q1() : 0;
  375. // Collinear opposite case -> block P
  376. // (#BRL4, #BLR8)
  377. if (side_pk_q1 == 0)
  378. {
  379. ti.operations[0].operation = operation_blocked;
  380. // Q turns right -> union (both independent),
  381. // Q turns left -> intersection
  382. ti.operations[1].operation = block_q ? operation_blocked
  383. : q_turns_left ? operation_intersection
  384. : operation_union;
  385. return;
  386. }
  387. // Pk between Qi and Qk
  388. // (#BRL3, #BRL7)
  389. if (between(side_pk_q1, side_pk_q2, side_qk_q))
  390. {
  391. ui_else_iu(q_turns_left, ti);
  392. if (block_q)
  393. {
  394. ti.operations[1].operation = operation_blocked;
  395. }
  396. //block_second(block_q, ti);
  397. return;
  398. }
  399. // Pk between Qk and P, so left of Qk (if Q turns right) and vv
  400. // (#BRL1)
  401. if (side_pk_q2 == -side_qk_q)
  402. {
  403. ui_else_iu(! q_turns_left, ti);
  404. ti.touch_only = true;
  405. return;
  406. }
  407. //
  408. // (#BRL5, #BRL9)
  409. if (side_pk_q1 == -side_qk_q)
  410. {
  411. uu_else_ii(! q_turns_left, ti);
  412. if (block_q)
  413. {
  414. ti.operations[1].operation = operation_blocked;
  415. }
  416. else
  417. {
  418. ti.touch_only = true;
  419. }
  420. //block_second(block_q, ti);
  421. return;
  422. }
  423. }
  424. else
  425. {
  426. // Pk at other side than Qi/Pk
  427. ti.operations[0].operation = q_turns_left
  428. ? operation_intersection
  429. : operation_union;
  430. ti.operations[1].operation = block_q
  431. ? operation_blocked
  432. : side_qi_p1 == 1 || side_qk_p1 == 1
  433. ? operation_union
  434. : operation_intersection;
  435. if (! block_q)
  436. {
  437. ti.touch_only = true;
  438. }
  439. return;
  440. }
  441. }
  442. else
  443. {
  444. // From left to right or from right to left
  445. int const side_pk_p = has_pk ? side.pk_wrt_p1() : 0;
  446. bool const right_to_left = side_qk_p1 == 1;
  447. // If p turns into direction of qi (1,2)
  448. if (side_pk_p == side_qi_p1)
  449. {
  450. int const side_pk_q1 = has_pk ? side.pk_wrt_q1() : 0;
  451. // Collinear opposite case -> block P
  452. if (side_pk_q1 == 0)
  453. {
  454. ti.operations[0].operation = operation_blocked;
  455. ti.operations[1].operation = right_to_left
  456. ? operation_union : operation_intersection;
  457. return;
  458. }
  459. if (side_pk_q1 == side_qk_p1)
  460. {
  461. uu_else_ii(right_to_left, ti);
  462. ti.touch_only = true;
  463. return;
  464. }
  465. }
  466. // If p turns into direction of qk (4,5)
  467. if (side_pk_p == side_qk_p1)
  468. {
  469. int const side_pk_q2 = has_pk ? side.pk_wrt_q2() : 0;
  470. // Collinear case -> lines join, continue
  471. if (side_pk_q2 == 0)
  472. {
  473. both(ti, operation_continue);
  474. return;
  475. }
  476. if (side_pk_q2 == side_qk_p1)
  477. {
  478. ui_else_iu(right_to_left, ti);
  479. ti.touch_only = true;
  480. return;
  481. }
  482. }
  483. // otherwise (3)
  484. ui_else_iu(! right_to_left, ti);
  485. return;
  486. }
  487. }
  488. };
  489. template
  490. <
  491. typename TurnInfo
  492. >
  493. struct equal : public base_turn_handler
  494. {
  495. template
  496. <
  497. typename UniqueSubRange1,
  498. typename UniqueSubRange2,
  499. typename IntersectionInfo,
  500. typename DirInfo,
  501. typename SideCalculator,
  502. typename UmbrellaStrategy
  503. >
  504. static inline void apply(UniqueSubRange1 const& range_p,
  505. UniqueSubRange2 const& range_q,
  506. TurnInfo& ti,
  507. IntersectionInfo const& info,
  508. DirInfo const& ,
  509. SideCalculator const& side,
  510. UmbrellaStrategy const& umbrella_strategy)
  511. {
  512. // Copy the intersection point in TO direction
  513. assign_point(ti, method_equal, info, non_opposite_to_index(info));
  514. bool const has_pk = ! range_p.is_last_segment();
  515. bool const has_qk = ! range_q.is_last_segment();
  516. int const side_pk_q2 = has_pk && has_qk ? side.pk_wrt_q2() : 0;
  517. int const side_pk_p = has_pk ? side.pk_wrt_p1() : 0;
  518. int const side_qk_p = has_qk ? side.qk_wrt_p1() : 0;
  519. #if ! defined(BOOST_GEOMETRY_USE_RESCALING)
  520. if (has_pk && has_qk && side_pk_p == side_qk_p)
  521. {
  522. // They turn to the same side, or continue both collinearly
  523. // Without rescaling, to check for union/intersection,
  524. // try to check side values (without any thresholds)
  525. typedef typename select_coordinate_type
  526. <
  527. typename UniqueSubRange1::point_type,
  528. typename UniqueSubRange2::point_type
  529. >::type coordinate_type;
  530. typedef detail::distance_measure<coordinate_type> dm_type;
  531. dm_type const dm_qk_p
  532. = get_distance_measure<typename UmbrellaStrategy::cs_tag>(range_q.at(1), range_q.at(2), range_p.at(2));
  533. dm_type const dm_pk_q
  534. = get_distance_measure<typename UmbrellaStrategy::cs_tag>(range_p.at(1), range_p.at(2), range_q.at(2));
  535. if (dm_pk_q.measure != dm_qk_p.measure)
  536. {
  537. // A (possibly very small) difference is detected, which
  538. // can be used to distinguish between union/intersection
  539. ui_else_iu(dm_pk_q.measure < dm_qk_p.measure, ti);
  540. return;
  541. }
  542. }
  543. #endif
  544. // If pk is collinear with qj-qk, they continue collinearly.
  545. // This can be on either side of p1 (== q1), or collinear
  546. // The second condition checks if they do not continue
  547. // oppositely
  548. if (side_pk_q2 == 0 && side_pk_p == side_qk_p)
  549. {
  550. both_collinear<0, 1>(range_p, range_q, umbrella_strategy, 2, 2, ti);
  551. return;
  552. }
  553. // If they turn to same side (not opposite sides)
  554. if (! opposite(side_pk_p, side_qk_p))
  555. {
  556. // If pk is left of q2 or collinear: p: union, q: intersection
  557. ui_else_iu(side_pk_q2 != -1, ti);
  558. }
  559. else
  560. {
  561. // They turn opposite sides. If p turns left (or collinear),
  562. // p: union, q: intersection
  563. ui_else_iu(side_pk_p != -1, ti);
  564. }
  565. }
  566. };
  567. template
  568. <
  569. typename TurnInfo,
  570. typename AssignPolicy
  571. >
  572. struct equal_opposite : public base_turn_handler
  573. {
  574. template
  575. <
  576. typename UniqueSubRange1,
  577. typename UniqueSubRange2,
  578. typename OutputIterator,
  579. typename IntersectionInfo
  580. >
  581. static inline void apply(
  582. UniqueSubRange1 const& /*range_p*/,
  583. UniqueSubRange2 const& /*range_q*/,
  584. /* by value: */ TurnInfo tp,
  585. OutputIterator& out,
  586. IntersectionInfo const& intersection_info)
  587. {
  588. // For equal-opposite segments, normally don't do anything.
  589. if (AssignPolicy::include_opposite)
  590. {
  591. tp.method = method_equal;
  592. for (unsigned int i = 0; i < 2; i++)
  593. {
  594. tp.operations[i].operation = operation_opposite;
  595. }
  596. for (unsigned int i = 0; i < intersection_info.i_info().count; i++)
  597. {
  598. assign_point(tp, method_none, intersection_info.i_info(), i);
  599. *out++ = tp;
  600. }
  601. }
  602. }
  603. };
  604. template
  605. <
  606. typename TurnInfo
  607. >
  608. struct collinear : public base_turn_handler
  609. {
  610. /*
  611. arrival P pk//p1 qk//q1 product* case result
  612. 1 1 1 CLL1 ui
  613. -1 1 -1 CLL2 iu
  614. 1 1 1 CLR1 ui
  615. -1 -1 1 CLR2 ui
  616. 1 -1 -1 CRL1 iu
  617. -1 1 -1 CRL2 iu
  618. 1 -1 -1 CRR1 iu
  619. -1 -1 1 CRR2 ui
  620. 1 0 0 CC1 cc
  621. -1 0 0 CC2 cc
  622. *product = arrival * (pk//p1 or qk//q1)
  623. Stated otherwise:
  624. - if P arrives: look at turn P
  625. - if Q arrives: look at turn Q
  626. - if P arrives and P turns left: union for P
  627. - if P arrives and P turns right: intersection for P
  628. - if Q arrives and Q turns left: union for Q (=intersection for P)
  629. - if Q arrives and Q turns right: intersection for Q (=union for P)
  630. ROBUSTNESS: p and q are collinear, so you would expect
  631. that side qk//p1 == pk//q1. But that is not always the case
  632. in near-epsilon ranges. Then decision logic is different.
  633. If p arrives, q is further, so the angle qk//p1 is (normally)
  634. more precise than pk//p1
  635. */
  636. template
  637. <
  638. typename UniqueSubRange1,
  639. typename UniqueSubRange2,
  640. typename IntersectionInfo,
  641. typename DirInfo,
  642. typename SidePolicy
  643. >
  644. static inline void apply(
  645. UniqueSubRange1 const& range_p,
  646. UniqueSubRange2 const& range_q,
  647. TurnInfo& ti,
  648. IntersectionInfo const& info,
  649. DirInfo const& dir_info,
  650. SidePolicy const& side)
  651. {
  652. // Copy the intersection point in TO direction
  653. assign_point(ti, method_collinear, info, non_opposite_to_index(info));
  654. int const arrival = dir_info.arrival[0];
  655. // Should not be 0, this is checked before
  656. BOOST_GEOMETRY_ASSERT(arrival != 0);
  657. bool const has_pk = ! range_p.is_last_segment();
  658. bool const has_qk = ! range_q.is_last_segment();
  659. int const side_p = has_pk ? side.pk_wrt_p1() : 0;
  660. int const side_q = has_qk ? side.qk_wrt_q1() : 0;
  661. // If p arrives, use p, else use q
  662. int const side_p_or_q = arrival == 1
  663. ? side_p
  664. : side_q
  665. ;
  666. // See comments above,
  667. // resulting in a strange sort of mathematic rule here:
  668. // The arrival-info multiplied by the relevant side
  669. // delivers a consistent result.
  670. int const product = arrival * side_p_or_q;
  671. if(product == 0)
  672. {
  673. both(ti, operation_continue);
  674. }
  675. else
  676. {
  677. ui_else_iu(product == 1, ti);
  678. }
  679. // Calculate remaining distance. If it continues collinearly it is
  680. // measured until the end of the next segment
  681. ti.operations[0].remaining_distance
  682. = side_p == 0 && has_pk
  683. ? distance_measure(ti.point, range_p.at(2))
  684. : distance_measure(ti.point, range_p.at(1));
  685. ti.operations[1].remaining_distance
  686. = side_q == 0 && has_qk
  687. ? distance_measure(ti.point, range_q.at(2))
  688. : distance_measure(ti.point, range_q.at(1));
  689. }
  690. };
  691. template
  692. <
  693. typename TurnInfo,
  694. typename AssignPolicy
  695. >
  696. struct collinear_opposite : public base_turn_handler
  697. {
  698. private :
  699. /*
  700. arrival P arrival Q pk//p1 qk//q1 case result2 result
  701. --------------------------------------------------------------
  702. 1 1 1 -1 CLO1 ix xu
  703. 1 1 1 0 CLO2 ix (xx)
  704. 1 1 1 1 CLO3 ix xi
  705. 1 1 0 -1 CCO1 (xx) xu
  706. 1 1 0 0 CCO2 (xx) (xx)
  707. 1 1 0 1 CCO3 (xx) xi
  708. 1 1 -1 -1 CRO1 ux xu
  709. 1 1 -1 0 CRO2 ux (xx)
  710. 1 1 -1 1 CRO3 ux xi
  711. -1 1 -1 CXO1 xu
  712. -1 1 0 CXO2 (xx)
  713. -1 1 1 CXO3 xi
  714. 1 -1 1 CXO1 ix
  715. 1 -1 0 CXO2 (xx)
  716. 1 -1 -1 CXO3 ux
  717. */
  718. template
  719. <
  720. unsigned int Index,
  721. typename IntersectionInfo
  722. >
  723. static inline bool set_tp(int side_rk_r, bool handle_robustness,
  724. int side_rk_s,
  725. TurnInfo& tp, IntersectionInfo const& intersection_info)
  726. {
  727. BOOST_STATIC_ASSERT(Index <= 1);
  728. boost::ignore_unused(handle_robustness, side_rk_s);
  729. operation_type blocked = operation_blocked;
  730. switch(side_rk_r)
  731. {
  732. case 1 :
  733. // Turning left on opposite collinear: intersection
  734. tp.operations[Index].operation = operation_intersection;
  735. break;
  736. case -1 :
  737. // Turning right on opposite collinear: union
  738. tp.operations[Index].operation = operation_union;
  739. break;
  740. case 0 :
  741. // No turn on opposite collinear: block, do not traverse
  742. // But this "xx" is usually ignored, it is useless to include
  743. // two operations blocked, so the whole point does not need
  744. // to be generated.
  745. // So return false to indicate nothing is to be done.
  746. if (AssignPolicy::include_opposite)
  747. {
  748. tp.operations[Index].operation = operation_opposite;
  749. blocked = operation_opposite;
  750. }
  751. else
  752. {
  753. return false;
  754. }
  755. break;
  756. }
  757. // The other direction is always blocked when collinear opposite
  758. tp.operations[1 - Index].operation = blocked;
  759. // If P arrives within Q, set info on P (which is done above, index=0),
  760. // this turn-info belongs to the second intersection point, index=1
  761. // (see e.g. figure CLO1)
  762. assign_point(tp, method_collinear, intersection_info, 1 - Index);
  763. return true;
  764. }
  765. public:
  766. static inline void empty_transformer(TurnInfo &) {}
  767. template
  768. <
  769. typename UniqueSubRange1,
  770. typename UniqueSubRange2,
  771. typename OutputIterator,
  772. typename IntersectionInfo,
  773. typename SidePolicy
  774. >
  775. static inline void apply(
  776. UniqueSubRange1 const& range_p,
  777. UniqueSubRange2 const& range_q,
  778. // Opposite collinear can deliver 2 intersection points,
  779. TurnInfo const& tp_model,
  780. OutputIterator& out,
  781. IntersectionInfo const& intersection_info,
  782. SidePolicy const& side)
  783. {
  784. apply(range_p, range_q,
  785. tp_model, out, intersection_info, side, empty_transformer);
  786. }
  787. public:
  788. template
  789. <
  790. typename UniqueSubRange1,
  791. typename UniqueSubRange2,
  792. typename OutputIterator,
  793. typename IntersectionInfo,
  794. typename SidePolicy,
  795. typename TurnTransformer
  796. >
  797. static inline void apply(
  798. UniqueSubRange1 const& range_p,
  799. UniqueSubRange2 const& range_q,
  800. // Opposite collinear can deliver 2 intersection points,
  801. TurnInfo const& tp_model,
  802. OutputIterator& out,
  803. IntersectionInfo const& info,
  804. SidePolicy const& side,
  805. TurnTransformer turn_transformer)
  806. {
  807. TurnInfo tp = tp_model;
  808. int const p_arrival = info.d_info().arrival[0];
  809. int const q_arrival = info.d_info().arrival[1];
  810. // If P arrives within Q, there is a turn dependent on P
  811. if ( p_arrival == 1
  812. && ! range_p.is_last_segment()
  813. && set_tp<0>(side.pk_wrt_p1(), true, side.pk_wrt_q1(), tp, info.i_info()) )
  814. {
  815. turn_transformer(tp);
  816. *out++ = tp;
  817. }
  818. // If Q arrives within P, there is a turn dependent on Q
  819. if ( q_arrival == 1
  820. && ! range_q.is_last_segment()
  821. && set_tp<1>(side.qk_wrt_q1(), false, side.qk_wrt_p1(), tp, info.i_info()) )
  822. {
  823. turn_transformer(tp);
  824. *out++ = tp;
  825. }
  826. if (AssignPolicy::include_opposite)
  827. {
  828. // Handle cases not yet handled above
  829. if ((q_arrival == -1 && p_arrival == 0)
  830. || (p_arrival == -1 && q_arrival == 0))
  831. {
  832. for (unsigned int i = 0; i < 2; i++)
  833. {
  834. tp.operations[i].operation = operation_opposite;
  835. }
  836. for (unsigned int i = 0; i < info.i_info().count; i++)
  837. {
  838. assign_point(tp, method_collinear, info.i_info(), i);
  839. *out++ = tp;
  840. }
  841. }
  842. }
  843. }
  844. };
  845. template
  846. <
  847. typename TurnInfo
  848. >
  849. struct crosses : public base_turn_handler
  850. {
  851. template <typename IntersectionInfo, typename DirInfo>
  852. static inline void apply(TurnInfo& ti,
  853. IntersectionInfo const& intersection_info,
  854. DirInfo const& dir_info)
  855. {
  856. assign_point(ti, method_crosses, intersection_info, 0);
  857. // In all cases:
  858. // If Q crosses P from left to right
  859. // Union: take P
  860. // Intersection: take Q
  861. // Otherwise: vice versa
  862. int const side_qi_p1 = dir_info.sides.template get<1, 0>();
  863. unsigned int const index = side_qi_p1 == 1 ? 0 : 1;
  864. ti.operations[index].operation = operation_union;
  865. ti.operations[1 - index].operation = operation_intersection;
  866. }
  867. };
  868. struct only_convert : public base_turn_handler
  869. {
  870. template<typename TurnInfo, typename IntersectionInfo>
  871. static inline void apply(TurnInfo& ti, IntersectionInfo const& intersection_info)
  872. {
  873. assign_point(ti, method_none, intersection_info, 0); // was collinear
  874. ti.operations[0].operation = operation_continue;
  875. ti.operations[1].operation = operation_continue;
  876. }
  877. };
  878. /*!
  879. \brief Policy doing nothing
  880. \details get_turn_info can have an optional policy include extra
  881. truns. By default it does not, and this class is that default.
  882. */
  883. struct assign_null_policy
  884. {
  885. static bool const include_no_turn = false;
  886. static bool const include_degenerate = false;
  887. static bool const include_opposite = false;
  888. };
  889. /*!
  890. \brief Turn information: intersection point, method, and turn information
  891. \details Information necessary for traversal phase (a phase
  892. of the overlay process). The information is gathered during the
  893. get_turns (segment intersection) phase.
  894. \tparam AssignPolicy policy to assign extra info,
  895. e.g. to calculate distance from segment's first points
  896. to intersection points.
  897. It also defines if a certain class of points
  898. (degenerate, non-turns) should be included.
  899. */
  900. template<typename AssignPolicy>
  901. struct get_turn_info
  902. {
  903. // Intersect a segment p with a segment q
  904. // Both p and q are modelled as sub_ranges to provide more points
  905. // to be able to give more information about the turn (left/right)
  906. template
  907. <
  908. typename UniqueSubRange1,
  909. typename UniqueSubRange2,
  910. typename TurnInfo,
  911. typename UmbrellaStrategy,
  912. typename RobustPolicy,
  913. typename OutputIterator
  914. >
  915. static inline OutputIterator apply(
  916. UniqueSubRange1 const& range_p,
  917. UniqueSubRange2 const& range_q,
  918. TurnInfo const& tp_model,
  919. UmbrellaStrategy const& umbrella_strategy,
  920. RobustPolicy const& robust_policy,
  921. OutputIterator out)
  922. {
  923. typedef intersection_info
  924. <
  925. UniqueSubRange1, UniqueSubRange2,
  926. typename TurnInfo::point_type,
  927. UmbrellaStrategy,
  928. RobustPolicy
  929. > inters_info;
  930. inters_info inters(range_p, range_q, umbrella_strategy, robust_policy);
  931. char const method = inters.d_info().how;
  932. // Copy, to copy possibly extended fields
  933. TurnInfo tp = tp_model;
  934. bool do_only_convert = false;
  935. // Select method and apply
  936. switch(method)
  937. {
  938. case 'a' : // "angle"
  939. case 'f' : // "from"
  940. case 's' : // "start"
  941. do_only_convert = true;
  942. break;
  943. case 'd' : // disjoint: never do anything
  944. break;
  945. case 'm' :
  946. {
  947. typedef touch_interior
  948. <
  949. TurnInfo
  950. > handler;
  951. // If Q (1) arrives (1)
  952. if ( inters.d_info().arrival[1] == 1 )
  953. {
  954. handler::template apply<0>(range_p, range_q, tp, inters.i_info(), inters.d_info(),
  955. inters.sides(), umbrella_strategy);
  956. }
  957. else
  958. {
  959. // Swap p/q
  960. handler::template apply<1>(range_q, range_p, tp, inters.i_info(), inters.d_info(),
  961. inters.get_swapped_sides(), umbrella_strategy);
  962. }
  963. *out++ = tp;
  964. }
  965. break;
  966. case 'i' :
  967. {
  968. crosses<TurnInfo>::apply(tp, inters.i_info(), inters.d_info());
  969. *out++ = tp;
  970. }
  971. break;
  972. case 't' :
  973. {
  974. // Both touch (both arrive there)
  975. touch<TurnInfo>::apply(range_p, range_q, tp, inters.i_info(), inters.d_info(), inters.sides(), umbrella_strategy);
  976. *out++ = tp;
  977. }
  978. break;
  979. case 'e':
  980. {
  981. if ( ! inters.d_info().opposite )
  982. {
  983. // Both equal
  984. // or collinear-and-ending at intersection point
  985. equal<TurnInfo>::apply(range_p, range_q, tp, inters.i_info(), inters.d_info(), inters.sides(), umbrella_strategy);
  986. *out++ = tp;
  987. }
  988. else
  989. {
  990. equal_opposite
  991. <
  992. TurnInfo,
  993. AssignPolicy
  994. >::apply(range_p, range_q, tp, out, inters);
  995. }
  996. }
  997. break;
  998. case 'c' :
  999. {
  1000. // Collinear
  1001. if ( ! inters.d_info().opposite )
  1002. {
  1003. if ( inters.d_info().arrival[0] == 0 )
  1004. {
  1005. // Collinear, but similar thus handled as equal
  1006. equal<TurnInfo>::apply(range_p, range_q, tp,
  1007. inters.i_info(), inters.d_info(), inters.sides(), umbrella_strategy);
  1008. // override assigned method
  1009. tp.method = method_collinear;
  1010. }
  1011. else
  1012. {
  1013. collinear<TurnInfo>::apply(range_p, range_q, tp,
  1014. inters.i_info(), inters.d_info(), inters.sides());
  1015. }
  1016. *out++ = tp;
  1017. }
  1018. else
  1019. {
  1020. collinear_opposite
  1021. <
  1022. TurnInfo,
  1023. AssignPolicy
  1024. >::apply(range_p, range_q,
  1025. tp, out, inters, inters.sides());
  1026. }
  1027. }
  1028. break;
  1029. case '0' :
  1030. {
  1031. // degenerate points
  1032. if (AssignPolicy::include_degenerate)
  1033. {
  1034. only_convert::apply(tp, inters.i_info());
  1035. *out++ = tp;
  1036. }
  1037. }
  1038. break;
  1039. default :
  1040. {
  1041. #if defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS)
  1042. std::cout << "TURN: Unknown method: " << method << std::endl;
  1043. #endif
  1044. #if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)
  1045. BOOST_THROW_EXCEPTION(turn_info_exception(method));
  1046. #endif
  1047. }
  1048. break;
  1049. }
  1050. if (do_only_convert
  1051. && AssignPolicy::include_no_turn
  1052. && inters.i_info().count > 0)
  1053. {
  1054. only_convert::apply(tp, inters.i_info());
  1055. *out++ = tp;
  1056. }
  1057. return out;
  1058. }
  1059. };
  1060. }} // namespace detail::overlay
  1061. #endif //DOXYGEN_NO_DETAIL
  1062. }} // namespace boost::geometry
  1063. #if defined(_MSC_VER)
  1064. #pragma warning(pop)
  1065. #endif
  1066. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP