intersection_insert.hpp 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
  3. // This file was modified by Oracle on 2014, 2015, 2017, 2019.
  4. // Modifications copyright (c) 2014-2019 Oracle and/or its affiliates.
  5. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
  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_INTERSECTION_INSERT_HPP
  11. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INTERSECTION_INSERT_HPP
  12. #include <cstddef>
  13. #include <boost/mpl/if.hpp>
  14. #include <boost/mpl/assert.hpp>
  15. #include <boost/range/metafunctions.hpp>
  16. #include <boost/geometry/core/is_areal.hpp>
  17. #include <boost/geometry/core/point_order.hpp>
  18. #include <boost/geometry/core/reverse_dispatch.hpp>
  19. #include <boost/geometry/geometries/concepts/check.hpp>
  20. #include <boost/geometry/algorithms/convert.hpp>
  21. #include <boost/geometry/algorithms/detail/point_on_border.hpp>
  22. #include <boost/geometry/algorithms/detail/overlay/clip_linestring.hpp>
  23. #include <boost/geometry/algorithms/detail/overlay/follow.hpp>
  24. #include <boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp>
  25. #include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
  26. #include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
  27. #include <boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp>
  28. #include <boost/geometry/algorithms/detail/overlay/segment_as_subrange.hpp>
  29. #include <boost/geometry/policies/robustness/rescale_policy_tags.hpp>
  30. #include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
  31. #include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
  32. #include <boost/geometry/views/segment_view.hpp>
  33. #include <boost/geometry/views/detail/boundary_view.hpp>
  34. #include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
  35. #include <boost/geometry/algorithms/detail/overlay/linear_linear.hpp>
  36. #include <boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp>
  37. #include <boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp>
  38. #if defined(BOOST_GEOMETRY_DEBUG_FOLLOW)
  39. #include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
  40. #include <boost/geometry/io/wkt/wkt.hpp>
  41. #endif
  42. namespace boost { namespace geometry
  43. {
  44. #ifndef DOXYGEN_NO_DETAIL
  45. namespace detail { namespace intersection
  46. {
  47. template <typename PointOut>
  48. struct intersection_segment_segment_point
  49. {
  50. template
  51. <
  52. typename Segment1, typename Segment2,
  53. typename RobustPolicy,
  54. typename OutputIterator, typename Strategy
  55. >
  56. static inline OutputIterator apply(Segment1 const& segment1,
  57. Segment2 const& segment2,
  58. RobustPolicy const& ,
  59. OutputIterator out,
  60. Strategy const& strategy)
  61. {
  62. // Make sure this is only called with no rescaling
  63. BOOST_STATIC_ASSERT((boost::is_same
  64. <
  65. no_rescale_policy_tag,
  66. typename rescale_policy_type<RobustPolicy>::type
  67. >::value));
  68. typedef typename point_type<PointOut>::type point_type;
  69. // Get the intersection point (or two points)
  70. typedef segment_intersection_points<point_type> intersection_return_type;
  71. typedef policies::relate::segments_intersection_points
  72. <
  73. intersection_return_type
  74. > policy_type;
  75. detail::segment_as_subrange<Segment1> sub_range1(segment1);
  76. detail::segment_as_subrange<Segment2> sub_range2(segment2);
  77. intersection_return_type
  78. is = strategy.apply(sub_range1, sub_range2, policy_type());
  79. for (std::size_t i = 0; i < is.count; i++)
  80. {
  81. PointOut p;
  82. geometry::convert(is.intersections[i], p);
  83. *out++ = p;
  84. }
  85. return out;
  86. }
  87. };
  88. template <typename PointOut>
  89. struct intersection_linestring_linestring_point
  90. {
  91. template
  92. <
  93. typename Linestring1, typename Linestring2,
  94. typename RobustPolicy,
  95. typename OutputIterator,
  96. typename Strategy
  97. >
  98. static inline OutputIterator apply(Linestring1 const& linestring1,
  99. Linestring2 const& linestring2,
  100. RobustPolicy const& robust_policy,
  101. OutputIterator out,
  102. Strategy const& strategy)
  103. {
  104. // Make sure this is only called with no rescaling
  105. BOOST_STATIC_ASSERT((boost::is_same
  106. <
  107. no_rescale_policy_tag,
  108. typename rescale_policy_type<RobustPolicy>::type
  109. >::value));
  110. typedef detail::overlay::turn_info<PointOut> turn_info;
  111. std::deque<turn_info> turns;
  112. geometry::get_intersection_points(linestring1, linestring2,
  113. robust_policy, turns, strategy);
  114. for (typename boost::range_iterator<std::deque<turn_info> const>::type
  115. it = boost::begin(turns); it != boost::end(turns); ++it)
  116. {
  117. PointOut p;
  118. geometry::convert(it->point, p);
  119. *out++ = p;
  120. }
  121. return out;
  122. }
  123. };
  124. /*!
  125. \brief Version of linestring with an areal feature (polygon or multipolygon)
  126. */
  127. template
  128. <
  129. bool ReverseAreal,
  130. typename LineStringOut,
  131. overlay_type OverlayType
  132. >
  133. struct intersection_of_linestring_with_areal
  134. {
  135. #if defined(BOOST_GEOMETRY_DEBUG_FOLLOW)
  136. template <typename Turn, typename Operation>
  137. static inline void debug_follow(Turn const& turn, Operation op,
  138. int index)
  139. {
  140. std::cout << index
  141. << " at " << op.seg_id
  142. << " meth: " << method_char(turn.method)
  143. << " op: " << operation_char(op.operation)
  144. << " vis: " << visited_char(op.visited)
  145. << " of: " << operation_char(turn.operations[0].operation)
  146. << operation_char(turn.operations[1].operation)
  147. << " " << geometry::wkt(turn.point)
  148. << std::endl;
  149. }
  150. template <typename Turn>
  151. static inline void debug_turn(Turn const& t, bool non_crossing)
  152. {
  153. std::cout << "checking turn @"
  154. << geometry::wkt(t.point)
  155. << "; " << method_char(t.method)
  156. << ":" << operation_char(t.operations[0].operation)
  157. << "/" << operation_char(t.operations[1].operation)
  158. << "; non-crossing? "
  159. << std::boolalpha << non_crossing << std::noboolalpha
  160. << std::endl;
  161. }
  162. #endif
  163. #ifdef BOOST_GEOMETRY_SETOPS_LA_OLD_BEHAVIOR
  164. class is_crossing_turn
  165. {
  166. // return true is the operation is intersection or blocked
  167. template <std::size_t Index, typename Turn>
  168. static inline bool has_op_i_or_b(Turn const& t)
  169. {
  170. return
  171. t.operations[Index].operation == overlay::operation_intersection
  172. ||
  173. t.operations[Index].operation == overlay::operation_blocked;
  174. }
  175. template <typename Turn>
  176. static inline bool has_method_crosses(Turn const& t)
  177. {
  178. return t.method == overlay::method_crosses;
  179. }
  180. template <typename Turn>
  181. static inline bool is_cc(Turn const& t)
  182. {
  183. return
  184. (t.method == overlay::method_touch_interior
  185. ||
  186. t.method == overlay::method_equal
  187. ||
  188. t.method == overlay::method_collinear)
  189. &&
  190. t.operations[0].operation == t.operations[1].operation
  191. &&
  192. t.operations[0].operation == overlay::operation_continue
  193. ;
  194. }
  195. template <typename Turn>
  196. static inline bool has_i_or_b_ops(Turn const& t)
  197. {
  198. return
  199. (t.method == overlay::method_touch
  200. ||
  201. t.method == overlay::method_touch_interior
  202. ||
  203. t.method == overlay::method_collinear)
  204. &&
  205. t.operations[1].operation != t.operations[0].operation
  206. &&
  207. (has_op_i_or_b<0>(t) || has_op_i_or_b<1>(t));
  208. }
  209. public:
  210. template <typename Turn>
  211. static inline bool apply(Turn const& t)
  212. {
  213. bool const is_crossing
  214. = has_method_crosses(t) || is_cc(t) || has_i_or_b_ops(t);
  215. #if defined(BOOST_GEOMETRY_DEBUG_FOLLOW)
  216. debug_turn(t, ! is_crossing);
  217. #endif
  218. return is_crossing;
  219. }
  220. };
  221. struct is_non_crossing_turn
  222. {
  223. template <typename Turn>
  224. static inline bool apply(Turn const& t)
  225. {
  226. return ! is_crossing_turn::apply(t);
  227. }
  228. };
  229. template <typename Turns>
  230. static inline bool no_crossing_turns_or_empty(Turns const& turns)
  231. {
  232. return detail::check_iterator_range
  233. <
  234. is_non_crossing_turn,
  235. true // allow an empty turns range
  236. >::apply(boost::begin(turns), boost::end(turns));
  237. }
  238. template <typename Turns>
  239. static inline int inside_or_outside_turn(Turns const& turns)
  240. {
  241. using namespace overlay;
  242. for (typename Turns::const_iterator it = turns.begin();
  243. it != turns.end(); ++it)
  244. {
  245. operation_type op0 = it->operations[0].operation;
  246. operation_type op1 = it->operations[1].operation;
  247. if (op0 == operation_intersection && op1 == operation_intersection)
  248. {
  249. return 1; // inside
  250. }
  251. else if (op0 == operation_union && op1 == operation_union)
  252. {
  253. return -1; // outside
  254. }
  255. }
  256. return 0;
  257. }
  258. #else // BOOST_GEOMETRY_SETOPS_LA_OLD_BEHAVIOR
  259. template <typename Linestring, typename Areal, typename Strategy, typename Turns>
  260. static inline bool simple_turns_analysis(Linestring const& linestring,
  261. Areal const& areal,
  262. Strategy const& strategy,
  263. Turns const& turns,
  264. int & inside_value)
  265. {
  266. using namespace overlay;
  267. bool found_continue = false;
  268. bool found_intersection = false;
  269. bool found_union = false;
  270. bool found_front = false;
  271. for (typename Turns::const_iterator it = turns.begin();
  272. it != turns.end(); ++it)
  273. {
  274. method_type const method = it->method;
  275. operation_type const op = it->operations[0].operation;
  276. if (method == method_crosses)
  277. {
  278. return false;
  279. }
  280. else if (op == operation_intersection)
  281. {
  282. found_intersection = true;
  283. }
  284. else if (op == operation_union)
  285. {
  286. found_union = true;
  287. }
  288. else if (op == operation_continue)
  289. {
  290. found_continue = true;
  291. }
  292. if ((found_intersection || found_continue) && found_union)
  293. {
  294. return false;
  295. }
  296. if (it->operations[0].position == position_front)
  297. {
  298. found_front = true;
  299. }
  300. }
  301. if (found_front)
  302. {
  303. if (found_intersection)
  304. {
  305. inside_value = 1; // inside
  306. }
  307. else if (found_union)
  308. {
  309. inside_value = -1; // outside
  310. }
  311. else // continue and blocked
  312. {
  313. inside_value = 0;
  314. }
  315. return true;
  316. }
  317. // if needed analyse points of a linestring
  318. // NOTE: range_in_geometry checks points of a linestring
  319. // until a point inside/outside areal is found
  320. // TODO: Could be replaced with point_in_geometry() because found_front is false
  321. inside_value = range_in_geometry(linestring, areal, strategy);
  322. if ( (found_intersection && inside_value == -1) // going in from outside
  323. || (found_continue && inside_value == -1) // going on boundary from outside
  324. || (found_union && inside_value == 1) ) // going out from inside
  325. {
  326. return false;
  327. }
  328. return true;
  329. }
  330. #endif // BOOST_GEOMETRY_SETOPS_LA_OLD_BEHAVIOR
  331. template
  332. <
  333. typename LineString, typename Areal,
  334. typename RobustPolicy,
  335. typename OutputIterator, typename Strategy
  336. >
  337. static inline OutputIterator apply(LineString const& linestring, Areal const& areal,
  338. RobustPolicy const& robust_policy,
  339. OutputIterator out,
  340. Strategy const& strategy)
  341. {
  342. // Make sure this is only called with no rescaling
  343. BOOST_STATIC_ASSERT((boost::is_same
  344. <
  345. no_rescale_policy_tag,
  346. typename rescale_policy_type<RobustPolicy>::type
  347. >::value));
  348. if (boost::size(linestring) == 0)
  349. {
  350. return out;
  351. }
  352. typedef detail::overlay::follow
  353. <
  354. LineStringOut,
  355. LineString,
  356. Areal,
  357. OverlayType,
  358. false // do not remove spikes for linear geometries
  359. > follower;
  360. typedef typename point_type<LineStringOut>::type point_type;
  361. typedef geometry::segment_ratio
  362. <
  363. typename coordinate_type<point_type>::type
  364. > ratio_type;
  365. #ifdef BOOST_GEOMETRY_SETOPS_LA_OLD_BEHAVIOR
  366. typedef detail::overlay::traversal_turn_info
  367. <
  368. point_type, ratio_type
  369. > turn_info;
  370. #else
  371. typedef detail::overlay::turn_info
  372. <
  373. point_type,
  374. ratio_type,
  375. detail::overlay::turn_operation_linear
  376. <
  377. point_type,
  378. ratio_type
  379. >
  380. > turn_info;
  381. #endif
  382. std::deque<turn_info> turns;
  383. detail::get_turns::no_interrupt_policy policy;
  384. #ifdef BOOST_GEOMETRY_SETOPS_LA_OLD_BEHAVIOR
  385. geometry::get_turns
  386. <
  387. false,
  388. (OverlayType == overlay_intersection ? ReverseAreal : !ReverseAreal),
  389. detail::overlay::assign_null_policy
  390. >(linestring, areal, strategy, robust_policy, turns, policy);
  391. if (no_crossing_turns_or_empty(turns))
  392. {
  393. // No intersection points, it is either
  394. // inside (interior + borders)
  395. // or outside (exterior + borders)
  396. // analyse the turns
  397. int inside_value = inside_or_outside_turn(turns);
  398. if (inside_value == 0)
  399. {
  400. // if needed analyse points of a linestring
  401. // NOTE: range_in_geometry checks points of a linestring
  402. // until a point inside/outside areal is found
  403. inside_value = overlay::range_in_geometry(linestring, areal, strategy);
  404. }
  405. // add linestring to the output if conditions are met
  406. if (inside_value != 0 && follower::included(inside_value))
  407. {
  408. LineStringOut copy;
  409. geometry::convert(linestring, copy);
  410. *out++ = copy;
  411. }
  412. return out;
  413. }
  414. #else // BOOST_GEOMETRY_SETOPS_LA_OLD_BEHAVIOR
  415. typedef detail::overlay::get_turn_info_linear_areal
  416. <
  417. detail::overlay::assign_null_policy
  418. > turn_policy;
  419. dispatch::get_turns
  420. <
  421. typename geometry::tag<LineString>::type,
  422. typename geometry::tag<Areal>::type,
  423. LineString,
  424. Areal,
  425. false,
  426. (OverlayType == overlay_intersection ? ReverseAreal : !ReverseAreal),
  427. turn_policy
  428. >::apply(0, linestring, 1, areal,
  429. strategy, robust_policy,
  430. turns, policy);
  431. int inside_value = 0;
  432. if (simple_turns_analysis(linestring, areal, strategy, turns, inside_value))
  433. {
  434. // No crossing the boundary, it is either
  435. // inside (interior + borders)
  436. // or outside (exterior + borders)
  437. // or on boundary
  438. // add linestring to the output if conditions are met
  439. if (follower::included(inside_value))
  440. {
  441. LineStringOut copy;
  442. geometry::convert(linestring, copy);
  443. *out++ = copy;
  444. }
  445. return out;
  446. }
  447. #endif // BOOST_GEOMETRY_SETOPS_LA_OLD_BEHAVIOR
  448. #if defined(BOOST_GEOMETRY_DEBUG_FOLLOW)
  449. int index = 0;
  450. for(typename std::deque<turn_info>::const_iterator
  451. it = turns.begin(); it != turns.end(); ++it)
  452. {
  453. debug_follow(*it, it->operations[0], index++);
  454. }
  455. #endif
  456. return follower::apply
  457. (
  458. linestring, areal,
  459. geometry::detail::overlay::operation_intersection,
  460. turns, robust_policy, out, strategy
  461. );
  462. }
  463. };
  464. template <typename Turns, typename OutputIterator>
  465. inline OutputIterator intersection_output_turn_points(Turns const& turns,
  466. OutputIterator out)
  467. {
  468. for (typename Turns::const_iterator
  469. it = turns.begin(); it != turns.end(); ++it)
  470. {
  471. *out++ = it->point;
  472. }
  473. return out;
  474. }
  475. template <typename PointOut>
  476. struct intersection_areal_areal_point
  477. {
  478. template
  479. <
  480. typename Geometry1, typename Geometry2,
  481. typename RobustPolicy,
  482. typename OutputIterator,
  483. typename Strategy
  484. >
  485. static inline OutputIterator apply(Geometry1 const& geometry1,
  486. Geometry2 const& geometry2,
  487. RobustPolicy const& robust_policy,
  488. OutputIterator out,
  489. Strategy const& strategy)
  490. {
  491. typedef detail::overlay::turn_info
  492. <
  493. PointOut,
  494. typename segment_ratio_type<PointOut, RobustPolicy>::type
  495. > turn_info;
  496. std::vector<turn_info> turns;
  497. detail::get_turns::no_interrupt_policy policy;
  498. geometry::get_turns
  499. <
  500. false, false, detail::overlay::assign_null_policy
  501. >(geometry1, geometry2, strategy, robust_policy, turns, policy);
  502. return intersection_output_turn_points(turns, out);
  503. }
  504. };
  505. template <typename PointOut>
  506. struct intersection_linear_areal_point
  507. {
  508. template
  509. <
  510. typename Geometry1, typename Geometry2,
  511. typename RobustPolicy,
  512. typename OutputIterator,
  513. typename Strategy
  514. >
  515. static inline OutputIterator apply(Geometry1 const& geometry1,
  516. Geometry2 const& geometry2,
  517. RobustPolicy const& robust_policy,
  518. OutputIterator out,
  519. Strategy const& strategy)
  520. {
  521. // Make sure this is only called with no rescaling
  522. BOOST_STATIC_ASSERT((boost::is_same
  523. <
  524. no_rescale_policy_tag,
  525. typename rescale_policy_type<RobustPolicy>::type
  526. >::value));
  527. typedef geometry::segment_ratio<typename geometry::coordinate_type<PointOut>::type> ratio_type;
  528. typedef detail::overlay::turn_info
  529. <
  530. PointOut,
  531. ratio_type,
  532. detail::overlay::turn_operation_linear
  533. <
  534. PointOut,
  535. ratio_type
  536. >
  537. > turn_info;
  538. typedef detail::overlay::get_turn_info_linear_areal
  539. <
  540. detail::overlay::assign_null_policy
  541. > turn_policy;
  542. std::vector<turn_info> turns;
  543. detail::get_turns::no_interrupt_policy interrupt_policy;
  544. dispatch::get_turns
  545. <
  546. typename geometry::tag<Geometry1>::type,
  547. typename geometry::tag<Geometry2>::type,
  548. Geometry1,
  549. Geometry2,
  550. false,
  551. false,
  552. turn_policy
  553. >::apply(0, geometry1, 1, geometry2,
  554. strategy, robust_policy,
  555. turns, interrupt_policy);
  556. return intersection_output_turn_points(turns, out);
  557. }
  558. };
  559. template <typename PointOut>
  560. struct intersection_areal_linear_point
  561. {
  562. template
  563. <
  564. typename Geometry1, typename Geometry2,
  565. typename RobustPolicy,
  566. typename OutputIterator,
  567. typename Strategy
  568. >
  569. static inline OutputIterator apply(Geometry1 const& geometry1,
  570. Geometry2 const& geometry2,
  571. RobustPolicy const& robust_policy,
  572. OutputIterator out,
  573. Strategy const& strategy)
  574. {
  575. return intersection_linear_areal_point
  576. <
  577. PointOut
  578. >::apply(geometry2, geometry1, robust_policy, out, strategy);
  579. }
  580. };
  581. }} // namespace detail::intersection
  582. #endif // DOXYGEN_NO_DETAIL
  583. #ifndef DOXYGEN_NO_DISPATCH
  584. namespace dispatch
  585. {
  586. template
  587. <
  588. // real types
  589. typename Geometry1,
  590. typename Geometry2,
  591. typename GeometryOut,
  592. overlay_type OverlayType,
  593. // orientation
  594. bool Reverse1 = detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
  595. bool Reverse2 = detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
  596. bool ReverseOut = detail::overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value,
  597. // tag dispatching:
  598. typename TagIn1 = typename geometry::tag<Geometry1>::type,
  599. typename TagIn2 = typename geometry::tag<Geometry2>::type,
  600. typename TagOut = typename geometry::tag<GeometryOut>::type,
  601. // metafunction finetuning helpers:
  602. typename CastedTagIn1 = typename geometry::tag_cast<TagIn1, areal_tag, linear_tag, pointlike_tag>::type,
  603. typename CastedTagIn2 = typename geometry::tag_cast<TagIn2, areal_tag, linear_tag, pointlike_tag>::type,
  604. typename CastedTagOut = typename geometry::tag_cast<TagOut, areal_tag, linear_tag, pointlike_tag>::type
  605. >
  606. struct intersection_insert
  607. {
  608. BOOST_MPL_ASSERT_MSG
  609. (
  610. false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPES_OR_ORIENTATIONS
  611. , (types<Geometry1, Geometry2, GeometryOut>)
  612. );
  613. };
  614. template
  615. <
  616. typename Geometry1, typename Geometry2,
  617. typename GeometryOut,
  618. overlay_type OverlayType,
  619. bool Reverse1, bool Reverse2, bool ReverseOut,
  620. typename TagIn1, typename TagIn2, typename TagOut
  621. >
  622. struct intersection_insert
  623. <
  624. Geometry1, Geometry2,
  625. GeometryOut,
  626. OverlayType,
  627. Reverse1, Reverse2, ReverseOut,
  628. TagIn1, TagIn2, TagOut,
  629. areal_tag, areal_tag, areal_tag
  630. > : detail::overlay::overlay
  631. <Geometry1, Geometry2, Reverse1, Reverse2, ReverseOut, GeometryOut, OverlayType>
  632. {};
  633. // Any areal type with box:
  634. template
  635. <
  636. typename Geometry, typename Box,
  637. typename GeometryOut,
  638. overlay_type OverlayType,
  639. bool Reverse1, bool Reverse2, bool ReverseOut,
  640. typename TagIn, typename TagOut
  641. >
  642. struct intersection_insert
  643. <
  644. Geometry, Box,
  645. GeometryOut,
  646. OverlayType,
  647. Reverse1, Reverse2, ReverseOut,
  648. TagIn, box_tag, TagOut,
  649. areal_tag, areal_tag, areal_tag
  650. > : detail::overlay::overlay
  651. <Geometry, Box, Reverse1, Reverse2, ReverseOut, GeometryOut, OverlayType>
  652. {};
  653. template
  654. <
  655. typename Segment1, typename Segment2,
  656. typename GeometryOut,
  657. overlay_type OverlayType,
  658. bool Reverse1, bool Reverse2, bool ReverseOut
  659. >
  660. struct intersection_insert
  661. <
  662. Segment1, Segment2,
  663. GeometryOut,
  664. OverlayType,
  665. Reverse1, Reverse2, ReverseOut,
  666. segment_tag, segment_tag, point_tag,
  667. linear_tag, linear_tag, pointlike_tag
  668. > : detail::intersection::intersection_segment_segment_point<GeometryOut>
  669. {};
  670. template
  671. <
  672. typename Linestring1, typename Linestring2,
  673. typename GeometryOut,
  674. overlay_type OverlayType,
  675. bool Reverse1, bool Reverse2, bool ReverseOut
  676. >
  677. struct intersection_insert
  678. <
  679. Linestring1, Linestring2,
  680. GeometryOut,
  681. OverlayType,
  682. Reverse1, Reverse2, ReverseOut,
  683. linestring_tag, linestring_tag, point_tag,
  684. linear_tag, linear_tag, pointlike_tag
  685. > : detail::intersection::intersection_linestring_linestring_point<GeometryOut>
  686. {};
  687. template
  688. <
  689. typename Linestring, typename Box,
  690. typename GeometryOut,
  691. bool Reverse1, bool Reverse2, bool ReverseOut
  692. >
  693. struct intersection_insert
  694. <
  695. Linestring, Box,
  696. GeometryOut,
  697. overlay_intersection,
  698. Reverse1, Reverse2, ReverseOut,
  699. linestring_tag, box_tag, linestring_tag,
  700. linear_tag, areal_tag, linear_tag
  701. >
  702. {
  703. template <typename RobustPolicy, typename OutputIterator, typename Strategy>
  704. static inline OutputIterator apply(Linestring const& linestring,
  705. Box const& box,
  706. RobustPolicy const& robust_policy,
  707. OutputIterator out, Strategy const& )
  708. {
  709. typedef typename point_type<GeometryOut>::type point_type;
  710. strategy::intersection::liang_barsky<Box, point_type> lb_strategy;
  711. return detail::intersection::clip_range_with_box
  712. <GeometryOut>(box, linestring, robust_policy, out, lb_strategy);
  713. }
  714. };
  715. template
  716. <
  717. typename Linestring, typename Polygon,
  718. typename GeometryOut,
  719. overlay_type OverlayType,
  720. bool ReverseLinestring, bool ReversePolygon, bool ReverseOut
  721. >
  722. struct intersection_insert
  723. <
  724. Linestring, Polygon,
  725. GeometryOut,
  726. OverlayType,
  727. ReverseLinestring, ReversePolygon, ReverseOut,
  728. linestring_tag, polygon_tag, linestring_tag,
  729. linear_tag, areal_tag, linear_tag
  730. > : detail::intersection::intersection_of_linestring_with_areal
  731. <
  732. ReversePolygon,
  733. GeometryOut,
  734. OverlayType
  735. >
  736. {};
  737. template
  738. <
  739. typename Linestring, typename Ring,
  740. typename GeometryOut,
  741. overlay_type OverlayType,
  742. bool ReverseLinestring, bool ReverseRing, bool ReverseOut
  743. >
  744. struct intersection_insert
  745. <
  746. Linestring, Ring,
  747. GeometryOut,
  748. OverlayType,
  749. ReverseLinestring, ReverseRing, ReverseOut,
  750. linestring_tag, ring_tag, linestring_tag,
  751. linear_tag, areal_tag, linear_tag
  752. > : detail::intersection::intersection_of_linestring_with_areal
  753. <
  754. ReverseRing,
  755. GeometryOut,
  756. OverlayType
  757. >
  758. {};
  759. template
  760. <
  761. typename Segment, typename Box,
  762. typename GeometryOut,
  763. overlay_type OverlayType,
  764. bool Reverse1, bool Reverse2, bool ReverseOut
  765. >
  766. struct intersection_insert
  767. <
  768. Segment, Box,
  769. GeometryOut,
  770. OverlayType,
  771. Reverse1, Reverse2, ReverseOut,
  772. segment_tag, box_tag, linestring_tag,
  773. linear_tag, areal_tag, linear_tag
  774. >
  775. {
  776. template <typename RobustPolicy, typename OutputIterator, typename Strategy>
  777. static inline OutputIterator apply(Segment const& segment,
  778. Box const& box,
  779. RobustPolicy const& robust_policy,
  780. OutputIterator out, Strategy const& )
  781. {
  782. geometry::segment_view<Segment> range(segment);
  783. typedef typename point_type<GeometryOut>::type point_type;
  784. strategy::intersection::liang_barsky<Box, point_type> lb_strategy;
  785. return detail::intersection::clip_range_with_box
  786. <GeometryOut>(box, range, robust_policy, out, lb_strategy);
  787. }
  788. };
  789. template
  790. <
  791. typename Geometry1, typename Geometry2,
  792. typename PointOut,
  793. overlay_type OverlayType,
  794. bool Reverse1, bool Reverse2, bool ReverseOut,
  795. typename Tag1, typename Tag2
  796. >
  797. struct intersection_insert
  798. <
  799. Geometry1, Geometry2,
  800. PointOut,
  801. OverlayType,
  802. Reverse1, Reverse2, ReverseOut,
  803. Tag1, Tag2, point_tag,
  804. areal_tag, areal_tag, pointlike_tag
  805. >
  806. : public detail::intersection::intersection_areal_areal_point
  807. <
  808. PointOut
  809. >
  810. {};
  811. template
  812. <
  813. typename Geometry1, typename Geometry2,
  814. typename PointOut,
  815. overlay_type OverlayType,
  816. bool Reverse1, bool Reverse2, bool ReverseOut,
  817. typename Tag1, typename Tag2
  818. >
  819. struct intersection_insert
  820. <
  821. Geometry1, Geometry2,
  822. PointOut,
  823. OverlayType,
  824. Reverse1, Reverse2, ReverseOut,
  825. Tag1, Tag2, point_tag,
  826. linear_tag, areal_tag, pointlike_tag
  827. >
  828. : public detail::intersection::intersection_linear_areal_point
  829. <
  830. PointOut
  831. >
  832. {};
  833. template
  834. <
  835. typename Geometry1, typename Geometry2,
  836. typename PointOut,
  837. overlay_type OverlayType,
  838. bool Reverse1, bool Reverse2, bool ReverseOut,
  839. typename Tag1, typename Tag2
  840. >
  841. struct intersection_insert
  842. <
  843. Geometry1, Geometry2,
  844. PointOut,
  845. OverlayType,
  846. Reverse1, Reverse2, ReverseOut,
  847. Tag1, Tag2, point_tag,
  848. areal_tag, linear_tag, pointlike_tag
  849. >
  850. : public detail::intersection::intersection_areal_linear_point
  851. <
  852. PointOut
  853. >
  854. {};
  855. template
  856. <
  857. typename Geometry1, typename Geometry2, typename GeometryOut,
  858. overlay_type OverlayType,
  859. bool Reverse1, bool Reverse2, bool ReverseOut
  860. >
  861. struct intersection_insert_reversed
  862. {
  863. template <typename RobustPolicy, typename OutputIterator, typename Strategy>
  864. static inline OutputIterator apply(Geometry1 const& g1,
  865. Geometry2 const& g2,
  866. RobustPolicy const& robust_policy,
  867. OutputIterator out,
  868. Strategy const& strategy)
  869. {
  870. return intersection_insert
  871. <
  872. Geometry2, Geometry1, GeometryOut,
  873. OverlayType,
  874. Reverse2, Reverse1, ReverseOut
  875. >::apply(g2, g1, robust_policy, out, strategy);
  876. }
  877. };
  878. // dispatch for intersection(areal, areal, linear)
  879. template
  880. <
  881. typename Geometry1, typename Geometry2,
  882. typename LinestringOut,
  883. bool Reverse1, bool Reverse2, bool ReverseOut,
  884. typename Tag1, typename Tag2
  885. >
  886. struct intersection_insert
  887. <
  888. Geometry1, Geometry2,
  889. LinestringOut,
  890. overlay_intersection,
  891. Reverse1, Reverse2, ReverseOut,
  892. Tag1, Tag2, linestring_tag,
  893. areal_tag, areal_tag, linear_tag
  894. >
  895. {
  896. template
  897. <
  898. typename RobustPolicy, typename OutputIterator, typename Strategy
  899. >
  900. static inline OutputIterator apply(Geometry1 const& geometry1,
  901. Geometry2 const& geometry2,
  902. RobustPolicy const& robust_policy,
  903. OutputIterator oit,
  904. Strategy const& strategy)
  905. {
  906. detail::boundary_view<Geometry1 const> view1(geometry1);
  907. detail::boundary_view<Geometry2 const> view2(geometry2);
  908. return detail::overlay::linear_linear_linestring
  909. <
  910. detail::boundary_view<Geometry1 const>,
  911. detail::boundary_view<Geometry2 const>,
  912. LinestringOut,
  913. overlay_intersection
  914. >::apply(view1, view2, robust_policy, oit, strategy);
  915. }
  916. };
  917. // dispatch for difference/intersection of linear geometries
  918. template
  919. <
  920. typename Linear1, typename Linear2, typename LineStringOut,
  921. overlay_type OverlayType,
  922. bool Reverse1, bool Reverse2, bool ReverseOut,
  923. typename TagIn1, typename TagIn2
  924. >
  925. struct intersection_insert
  926. <
  927. Linear1, Linear2, LineStringOut, OverlayType,
  928. Reverse1, Reverse2, ReverseOut,
  929. TagIn1, TagIn2, linestring_tag,
  930. linear_tag, linear_tag, linear_tag
  931. > : detail::overlay::linear_linear_linestring
  932. <
  933. Linear1, Linear2, LineStringOut, OverlayType
  934. >
  935. {};
  936. // dispatch for difference/intersection of point-like geometries
  937. template
  938. <
  939. typename Point1, typename Point2, typename PointOut,
  940. overlay_type OverlayType,
  941. bool Reverse1, bool Reverse2, bool ReverseOut
  942. >
  943. struct intersection_insert
  944. <
  945. Point1, Point2, PointOut, OverlayType,
  946. Reverse1, Reverse2, ReverseOut,
  947. point_tag, point_tag, point_tag,
  948. pointlike_tag, pointlike_tag, pointlike_tag
  949. > : detail::overlay::point_point_point
  950. <
  951. Point1, Point2, PointOut, OverlayType
  952. >
  953. {};
  954. template
  955. <
  956. typename MultiPoint, typename Point, typename PointOut,
  957. overlay_type OverlayType,
  958. bool Reverse1, bool Reverse2, bool ReverseOut
  959. >
  960. struct intersection_insert
  961. <
  962. MultiPoint, Point, PointOut, OverlayType,
  963. Reverse1, Reverse2, ReverseOut,
  964. multi_point_tag, point_tag, point_tag,
  965. pointlike_tag, pointlike_tag, pointlike_tag
  966. > : detail::overlay::multipoint_point_point
  967. <
  968. MultiPoint, Point, PointOut, OverlayType
  969. >
  970. {};
  971. template
  972. <
  973. typename Point, typename MultiPoint, typename PointOut,
  974. overlay_type OverlayType,
  975. bool Reverse1, bool Reverse2, bool ReverseOut
  976. >
  977. struct intersection_insert
  978. <
  979. Point, MultiPoint, PointOut, OverlayType,
  980. Reverse1, Reverse2, ReverseOut,
  981. point_tag, multi_point_tag, point_tag,
  982. pointlike_tag, pointlike_tag, pointlike_tag
  983. > : detail::overlay::point_multipoint_point
  984. <
  985. Point, MultiPoint, PointOut, OverlayType
  986. >
  987. {};
  988. template
  989. <
  990. typename MultiPoint1, typename MultiPoint2, typename PointOut,
  991. overlay_type OverlayType,
  992. bool Reverse1, bool Reverse2, bool ReverseOut
  993. >
  994. struct intersection_insert
  995. <
  996. MultiPoint1, MultiPoint2, PointOut, OverlayType,
  997. Reverse1, Reverse2, ReverseOut,
  998. multi_point_tag, multi_point_tag, point_tag,
  999. pointlike_tag, pointlike_tag, pointlike_tag
  1000. > : detail::overlay::multipoint_multipoint_point
  1001. <
  1002. MultiPoint1, MultiPoint2, PointOut, OverlayType
  1003. >
  1004. {};
  1005. // dispatch for difference/intersection of pointlike-linear geometries
  1006. template
  1007. <
  1008. typename Point, typename Linear, typename PointOut,
  1009. overlay_type OverlayType,
  1010. bool Reverse1, bool Reverse2, bool ReverseOut,
  1011. typename Tag
  1012. >
  1013. struct intersection_insert
  1014. <
  1015. Point, Linear, PointOut, OverlayType,
  1016. Reverse1, Reverse2, ReverseOut,
  1017. point_tag, Tag, point_tag,
  1018. pointlike_tag, linear_tag, pointlike_tag
  1019. > : detail_dispatch::overlay::pointlike_linear_point
  1020. <
  1021. Point, Linear, PointOut, OverlayType,
  1022. point_tag, typename tag_cast<Tag, segment_tag, linear_tag>::type
  1023. >
  1024. {};
  1025. template
  1026. <
  1027. typename MultiPoint, typename Linear, typename PointOut,
  1028. overlay_type OverlayType,
  1029. bool Reverse1, bool Reverse2, bool ReverseOut,
  1030. typename Tag
  1031. >
  1032. struct intersection_insert
  1033. <
  1034. MultiPoint, Linear, PointOut, OverlayType,
  1035. Reverse1, Reverse2, ReverseOut,
  1036. multi_point_tag, Tag, point_tag,
  1037. pointlike_tag, linear_tag, pointlike_tag
  1038. > : detail_dispatch::overlay::pointlike_linear_point
  1039. <
  1040. MultiPoint, Linear, PointOut, OverlayType,
  1041. multi_point_tag,
  1042. typename tag_cast<Tag, segment_tag, linear_tag>::type
  1043. >
  1044. {};
  1045. template
  1046. <
  1047. typename Linestring, typename MultiPoint, typename PointOut,
  1048. bool Reverse1, bool Reverse2, bool ReverseOut
  1049. >
  1050. struct intersection_insert
  1051. <
  1052. Linestring, MultiPoint, PointOut, overlay_intersection,
  1053. Reverse1, Reverse2, ReverseOut,
  1054. linestring_tag, multi_point_tag, point_tag,
  1055. linear_tag, pointlike_tag, pointlike_tag
  1056. >
  1057. {
  1058. template <typename RobustPolicy, typename OutputIterator, typename Strategy>
  1059. static inline OutputIterator apply(Linestring const& linestring,
  1060. MultiPoint const& multipoint,
  1061. RobustPolicy const& robust_policy,
  1062. OutputIterator out,
  1063. Strategy const& strategy)
  1064. {
  1065. return detail_dispatch::overlay::pointlike_linear_point
  1066. <
  1067. MultiPoint, Linestring, PointOut, overlay_intersection,
  1068. multi_point_tag, linear_tag
  1069. >::apply(multipoint, linestring, robust_policy, out, strategy);
  1070. }
  1071. };
  1072. } // namespace dispatch
  1073. #endif // DOXYGEN_NO_DISPATCH
  1074. #ifndef DOXYGEN_NO_DETAIL
  1075. namespace detail { namespace intersection
  1076. {
  1077. template
  1078. <
  1079. typename GeometryOut,
  1080. bool ReverseSecond,
  1081. overlay_type OverlayType,
  1082. typename Geometry1, typename Geometry2,
  1083. typename RobustPolicy,
  1084. typename OutputIterator,
  1085. typename Strategy
  1086. >
  1087. inline OutputIterator insert(Geometry1 const& geometry1,
  1088. Geometry2 const& geometry2,
  1089. RobustPolicy robust_policy,
  1090. OutputIterator out,
  1091. Strategy const& strategy)
  1092. {
  1093. return boost::mpl::if_c
  1094. <
  1095. geometry::reverse_dispatch<Geometry1, Geometry2>::type::value,
  1096. geometry::dispatch::intersection_insert_reversed
  1097. <
  1098. Geometry1, Geometry2,
  1099. GeometryOut,
  1100. OverlayType,
  1101. overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
  1102. overlay::do_reverse<geometry::point_order<Geometry2>::value, ReverseSecond>::value,
  1103. overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value
  1104. >,
  1105. geometry::dispatch::intersection_insert
  1106. <
  1107. Geometry1, Geometry2,
  1108. GeometryOut,
  1109. OverlayType,
  1110. geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
  1111. geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value, ReverseSecond>::value
  1112. >
  1113. >::type::apply(geometry1, geometry2, robust_policy, out, strategy);
  1114. }
  1115. /*!
  1116. \brief \brief_calc2{intersection} \brief_strategy
  1117. \ingroup intersection
  1118. \details \details_calc2{intersection_insert, spatial set theoretic intersection}
  1119. \brief_strategy. \details_insert{intersection}
  1120. \tparam GeometryOut \tparam_geometry{\p_l_or_c}
  1121. \tparam Geometry1 \tparam_geometry
  1122. \tparam Geometry2 \tparam_geometry
  1123. \tparam OutputIterator \tparam_out{\p_l_or_c}
  1124. \tparam Strategy \tparam_strategy_overlay
  1125. \param geometry1 \param_geometry
  1126. \param geometry2 \param_geometry
  1127. \param out \param_out{intersection}
  1128. \param strategy \param_strategy{intersection}
  1129. \return \return_out
  1130. \qbk{distinguish,with strategy}
  1131. \qbk{[include reference/algorithms/intersection.qbk]}
  1132. */
  1133. template
  1134. <
  1135. typename GeometryOut,
  1136. typename Geometry1,
  1137. typename Geometry2,
  1138. typename OutputIterator,
  1139. typename Strategy
  1140. >
  1141. inline OutputIterator intersection_insert(Geometry1 const& geometry1,
  1142. Geometry2 const& geometry2,
  1143. OutputIterator out,
  1144. Strategy const& strategy)
  1145. {
  1146. concepts::check<Geometry1 const>();
  1147. concepts::check<Geometry2 const>();
  1148. typedef typename geometry::rescale_overlay_policy_type
  1149. <
  1150. Geometry1,
  1151. Geometry2,
  1152. typename Strategy::cs_tag
  1153. >::type rescale_policy_type;
  1154. rescale_policy_type robust_policy
  1155. = geometry::get_rescale_policy<rescale_policy_type>(
  1156. geometry1, geometry2, strategy);
  1157. return detail::intersection::insert
  1158. <
  1159. GeometryOut, false, overlay_intersection
  1160. >(geometry1, geometry2, robust_policy, out, strategy);
  1161. }
  1162. /*!
  1163. \brief \brief_calc2{intersection}
  1164. \ingroup intersection
  1165. \details \details_calc2{intersection_insert, spatial set theoretic intersection}.
  1166. \details_insert{intersection}
  1167. \tparam GeometryOut \tparam_geometry{\p_l_or_c}
  1168. \tparam Geometry1 \tparam_geometry
  1169. \tparam Geometry2 \tparam_geometry
  1170. \tparam OutputIterator \tparam_out{\p_l_or_c}
  1171. \param geometry1 \param_geometry
  1172. \param geometry2 \param_geometry
  1173. \param out \param_out{intersection}
  1174. \return \return_out
  1175. \qbk{[include reference/algorithms/intersection.qbk]}
  1176. */
  1177. template
  1178. <
  1179. typename GeometryOut,
  1180. typename Geometry1,
  1181. typename Geometry2,
  1182. typename OutputIterator
  1183. >
  1184. inline OutputIterator intersection_insert(Geometry1 const& geometry1,
  1185. Geometry2 const& geometry2,
  1186. OutputIterator out)
  1187. {
  1188. concepts::check<Geometry1 const>();
  1189. concepts::check<Geometry2 const>();
  1190. typedef typename strategy::intersection::services::default_strategy
  1191. <
  1192. typename cs_tag<GeometryOut>::type
  1193. >::type strategy_type;
  1194. return intersection_insert<GeometryOut>(geometry1, geometry2, out,
  1195. strategy_type());
  1196. }
  1197. }} // namespace detail::intersection
  1198. #endif // DOXYGEN_NO_DETAIL
  1199. }} // namespace boost::geometry
  1200. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INTERSECTION_INSERT_HPP