sectionalize.hpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
  4. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
  5. // Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
  6. // This file was modified by Oracle on 2013-2024.
  7. // Modifications copyright (c) 2013-2024 Oracle and/or its affiliates.
  8. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
  9. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
  10. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  11. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
  12. // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
  13. // Use, modification and distribution is subject to the Boost Software License,
  14. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  15. // http://www.boost.org/LICENSE_1_0.txt)
  16. #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_SECTIONALIZE_HPP
  17. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_SECTIONALIZE_HPP
  18. #include <cstddef>
  19. #include <type_traits>
  20. #include <vector>
  21. #include <boost/concept/requires.hpp>
  22. #include <boost/core/ignore_unused.hpp>
  23. #include <boost/range/begin.hpp>
  24. #include <boost/range/end.hpp>
  25. #include <boost/range/size.hpp>
  26. #include <boost/range/value_type.hpp>
  27. #include <boost/geometry/core/config.hpp>
  28. #include <boost/geometry/algorithms/assign.hpp>
  29. #include <boost/geometry/algorithms/envelope.hpp>
  30. #include <boost/geometry/algorithms/expand.hpp>
  31. #include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
  32. #include <boost/geometry/algorithms/detail/ring_identifier.hpp>
  33. #include <boost/geometry/algorithms/detail/signed_size_type.hpp>
  34. #include <boost/geometry/core/access.hpp>
  35. #include <boost/geometry/core/closure.hpp>
  36. #include <boost/geometry/core/exterior_ring.hpp>
  37. #include <boost/geometry/core/point_order.hpp>
  38. #include <boost/geometry/core/static_assert.hpp>
  39. #include <boost/geometry/core/tag_cast.hpp>
  40. #include <boost/geometry/core/tags.hpp>
  41. #include <boost/geometry/geometries/concepts/check.hpp>
  42. #include <boost/geometry/geometries/box.hpp>
  43. #include <boost/geometry/geometries/segment.hpp>
  44. #include <boost/geometry/util/math.hpp>
  45. #include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
  46. #include <boost/geometry/util/sequence.hpp>
  47. #include <boost/geometry/views/detail/closed_clockwise_view.hpp>
  48. // TEMP
  49. #include <boost/geometry/strategy/envelope.hpp>
  50. #include <boost/geometry/strategy/expand.hpp>
  51. namespace boost { namespace geometry
  52. {
  53. /*!
  54. \brief Structure containing section information
  55. \details Section information consists of a bounding box, direction
  56. information (if it is increasing or decreasing, per dimension),
  57. index information (begin-end, ring, multi) and the number of
  58. segments in this section
  59. \tparam Box box-type
  60. \tparam DimensionCount number of dimensions for this section
  61. \ingroup sectionalize
  62. */
  63. template
  64. <
  65. typename Box,
  66. std::size_t DimensionCount
  67. >
  68. struct section
  69. {
  70. using box_type = Box;
  71. static std::size_t const dimension_count = DimensionCount;
  72. int directions[DimensionCount];
  73. ring_identifier ring_id;
  74. Box bounding_box;
  75. // NOTE: size_type could be passed as template parameter
  76. // NOTE: these probably also could be of type std::size_t
  77. signed_size_type begin_index;
  78. signed_size_type end_index;
  79. std::size_t count;
  80. std::size_t range_count;
  81. bool duplicate;
  82. signed_size_type non_duplicate_index;
  83. bool is_non_duplicate_first;
  84. bool is_non_duplicate_last;
  85. inline section()
  86. : begin_index(-1)
  87. , end_index(-1)
  88. , count(0)
  89. , range_count(0)
  90. , duplicate(false)
  91. , non_duplicate_index(-1)
  92. , is_non_duplicate_first(false)
  93. , is_non_duplicate_last(false)
  94. {
  95. assign_inverse(bounding_box);
  96. for (std::size_t i = 0; i < DimensionCount; i++)
  97. {
  98. directions[i] = 0;
  99. }
  100. }
  101. };
  102. /*!
  103. \brief Structure containing a collection of sections
  104. \note Derived from a vector, proves to be faster than of deque
  105. \note vector might be templated in the future
  106. \ingroup sectionalize
  107. */
  108. template <typename Box, std::size_t DimensionCount>
  109. struct sections : std::vector<section<Box, DimensionCount> >
  110. {
  111. using box_type = Box;
  112. static std::size_t const value = DimensionCount;
  113. };
  114. #ifndef DOXYGEN_NO_DETAIL
  115. namespace detail { namespace sectionalize
  116. {
  117. // NOTE: This utility will NOT work for latitudes, dimension 1 in spherical
  118. // and geographic coordinate system because in these coordinate systems
  119. // e.g. a segment on northern hemisphere may go towards greater latitude
  120. // and then towards lesser latitude.
  121. template
  122. <
  123. typename Point,
  124. typename DimensionVector,
  125. std::size_t Index,
  126. std::size_t Count,
  127. typename CastedCSTag = tag_cast_t<cs_tag_t<Point>, spherical_tag>
  128. >
  129. struct get_direction_loop
  130. {
  131. using dimension = typename util::sequence_element<Index, DimensionVector>::type;
  132. template <typename Segment>
  133. static inline void apply(Segment const& seg,
  134. int directions[Count])
  135. {
  136. auto const& c0 = geometry::get<0, dimension::value>(seg);
  137. auto const& c1 = geometry::get<1, dimension::value>(seg);
  138. directions[Index] = c1 > c0 ? 1 : c1 < c0 ? -1 : 0;
  139. get_direction_loop
  140. <
  141. Point,
  142. DimensionVector,
  143. Index + 1,
  144. Count,
  145. CastedCSTag
  146. >::apply(seg, directions);
  147. }
  148. };
  149. template
  150. <
  151. typename Point,
  152. typename DimensionVector,
  153. std::size_t Count
  154. >
  155. struct get_direction_loop<Point, DimensionVector, 0, Count, spherical_tag>
  156. {
  157. using dimension = typename util::sequence_element<0, DimensionVector>::type;
  158. template <typename Segment>
  159. static inline void apply(Segment const& seg,
  160. int directions[Count])
  161. {
  162. using coordinate_type = coordinate_type_t<Segment>;
  163. using units_t = detail::coordinate_system_units_t<Point>;
  164. coordinate_type const diff = math::longitude_distance_signed
  165. <
  166. units_t, coordinate_type
  167. >(geometry::get<0, 0>(seg),
  168. geometry::get<1, 0>(seg));
  169. coordinate_type zero = coordinate_type();
  170. directions[0] = diff > zero ? 1 : diff < zero ? -1 : 0;
  171. get_direction_loop
  172. <
  173. Point,
  174. DimensionVector,
  175. 1,
  176. Count,
  177. spherical_tag
  178. >::apply(seg, directions);
  179. }
  180. };
  181. template
  182. <
  183. typename Point,
  184. typename DimensionVector,
  185. std::size_t Count,
  186. typename CastedCSTag
  187. >
  188. struct get_direction_loop<Point, DimensionVector, Count, Count, CastedCSTag>
  189. {
  190. template <typename Segment>
  191. static inline void apply(Segment const&, int [Count])
  192. {}
  193. };
  194. //! Copy one static array to another
  195. template <typename T, std::size_t Index, std::size_t Count>
  196. struct copy_loop
  197. {
  198. static inline void apply(T const source[Count], T target[Count])
  199. {
  200. target[Index] = source[Index];
  201. copy_loop<T, Index + 1, Count>::apply(source, target);
  202. }
  203. };
  204. template <typename T, std::size_t Count>
  205. struct copy_loop<T, Count, Count>
  206. {
  207. static inline void apply(T const [Count], T [Count])
  208. {}
  209. };
  210. //! Compare two static arrays
  211. template <typename T, std::size_t Index, std::size_t Count>
  212. struct compare_loop
  213. {
  214. static inline bool apply(T const array1[Count], T const array2[Count])
  215. {
  216. return array1[Index] != array2[Index]
  217. ? false
  218. : compare_loop
  219. <
  220. T, Index + 1, Count
  221. >::apply(array1, array2);
  222. }
  223. };
  224. template <typename T, std::size_t Count>
  225. struct compare_loop<T, Count, Count>
  226. {
  227. static inline bool apply(T const [Count], T const [Count])
  228. {
  229. return true;
  230. }
  231. };
  232. template <std::size_t Dimension, std::size_t DimensionCount>
  233. struct check_duplicate_loop
  234. {
  235. template <typename Segment>
  236. static inline bool apply(Segment const& seg)
  237. {
  238. if (! geometry::math::equals
  239. (
  240. geometry::get<0, Dimension>(seg),
  241. geometry::get<1, Dimension>(seg)
  242. )
  243. )
  244. {
  245. return false;
  246. }
  247. return check_duplicate_loop
  248. <
  249. Dimension + 1, DimensionCount
  250. >::apply(seg);
  251. }
  252. };
  253. template <std::size_t DimensionCount>
  254. struct check_duplicate_loop<DimensionCount, DimensionCount>
  255. {
  256. template <typename Segment>
  257. static inline bool apply(Segment const&)
  258. {
  259. return true;
  260. }
  261. };
  262. //! Assign a value to a static array
  263. template <typename T, std::size_t Index, std::size_t Count>
  264. struct assign_loop
  265. {
  266. static inline void apply(T dims[Count], T const value)
  267. {
  268. dims[Index] = value;
  269. assign_loop<T, Index + 1, Count>::apply(dims, value);
  270. }
  271. };
  272. template <typename T, std::size_t Count>
  273. struct assign_loop<T, Count, Count>
  274. {
  275. static inline void apply(T [Count], T const)
  276. {
  277. }
  278. };
  279. template <typename CSTag>
  280. struct box_first_in_section
  281. {
  282. template <typename Box, typename Point, typename Strategy>
  283. static inline void apply(Box & box, Point const& prev, Point const& curr,
  284. Strategy const& strategy)
  285. {
  286. geometry::model::referring_segment<Point const> seg(prev, curr);
  287. geometry::envelope(seg, box, strategy);
  288. }
  289. };
  290. template <>
  291. struct box_first_in_section<cartesian_tag>
  292. {
  293. template <typename Box, typename Point, typename Strategy>
  294. static inline void apply(Box & box, Point const& prev, Point const& curr,
  295. Strategy const& strategy)
  296. {
  297. geometry::envelope(prev, box, strategy);
  298. geometry::expand(box, curr, strategy);
  299. }
  300. };
  301. template <typename CSTag>
  302. struct box_next_in_section
  303. {
  304. template <typename Box, typename Point, typename Strategy>
  305. static inline void apply(Box & box, Point const& prev, Point const& curr,
  306. Strategy const& strategy)
  307. {
  308. geometry::model::referring_segment<Point const> seg(prev, curr);
  309. geometry::expand(box, seg, strategy);
  310. }
  311. };
  312. template <>
  313. struct box_next_in_section<cartesian_tag>
  314. {
  315. template <typename Box, typename Point, typename Strategy>
  316. static inline void apply(Box & box, Point const& , Point const& curr,
  317. Strategy const& strategy)
  318. {
  319. geometry::expand(box, curr, strategy);
  320. }
  321. };
  322. /// @brief Helper class to create sections of a part of a range, on the fly
  323. template<typename DimensionVector>
  324. struct sectionalize_part
  325. {
  326. static const std::size_t dimension_count
  327. = util::sequence_size<DimensionVector>::value;
  328. template
  329. <
  330. typename Iterator,
  331. typename Sections,
  332. typename Strategy
  333. >
  334. static inline void apply(Sections& sections,
  335. Iterator begin, Iterator end,
  336. Strategy const& strategy,
  337. ring_identifier ring_id,
  338. std::size_t max_count)
  339. {
  340. using section_type = typename boost::range_value<Sections>::type;
  341. using box_type = typename section_type::box_type;
  342. using point_type = geometry::point_type_t<box_type>;
  343. BOOST_STATIC_ASSERT
  344. (
  345. section_type::dimension_count
  346. == util::sequence_size<DimensionVector>::value
  347. );
  348. std::size_t const count = std::distance(begin, end);
  349. if (count == 0)
  350. {
  351. return;
  352. }
  353. signed_size_type index = 0;
  354. signed_size_type ndi = 0; // non duplicate index
  355. section_type section;
  356. bool mark_first_non_duplicated = true;
  357. std::size_t last_non_duplicate_index = sections.size();
  358. Iterator it = begin;
  359. point_type previous_point;
  360. geometry::detail::conversion::convert_point_to_point(*it, previous_point);
  361. for (Iterator previous = it++; it != end; ++previous, ++it, index++)
  362. {
  363. point_type current_point;
  364. geometry::detail::conversion::convert_point_to_point(*it, current_point);
  365. model::referring_segment<point_type> segment(previous_point, current_point);
  366. int direction_classes[dimension_count] = {0};
  367. get_direction_loop
  368. <
  369. point_type, DimensionVector, 0, dimension_count
  370. >::apply(segment, direction_classes);
  371. // if "dir" == 0 for all point-dimensions, it is duplicate.
  372. // Those sections might be omitted, if wished, lateron
  373. bool duplicate = false;
  374. if (direction_classes[0] == 0)
  375. {
  376. // Recheck because ALL dimensions should be checked,
  377. // not only first one.
  378. // (dimension_count might be < dimension<P>::value)
  379. if (check_duplicate_loop
  380. <
  381. 0, geometry::dimension<point_type>::type::value
  382. >::apply(segment)
  383. )
  384. {
  385. duplicate = true;
  386. // Change direction-info to force new section
  387. // Note that wo consecutive duplicate segments will generate
  388. // only one duplicate-section.
  389. // Actual value is not important as long as it is not -1,0,1
  390. assign_loop
  391. <
  392. int, 0, dimension_count
  393. >::apply(direction_classes, -99);
  394. }
  395. }
  396. if (section.count > 0
  397. && (! compare_loop
  398. <
  399. int, 0, dimension_count
  400. >::apply(direction_classes, section.directions)
  401. || section.count > max_count)
  402. )
  403. {
  404. if (! section.duplicate)
  405. {
  406. last_non_duplicate_index = sections.size();
  407. }
  408. sections.push_back(section);
  409. section = section_type();
  410. }
  411. if (section.count == 0)
  412. {
  413. section.begin_index = index;
  414. section.ring_id = ring_id;
  415. section.duplicate = duplicate;
  416. section.non_duplicate_index = ndi;
  417. section.range_count = count;
  418. if (mark_first_non_duplicated && ! duplicate)
  419. {
  420. section.is_non_duplicate_first = true;
  421. mark_first_non_duplicated = false;
  422. }
  423. copy_loop
  424. <
  425. int, 0, dimension_count
  426. >::apply(direction_classes, section.directions);
  427. // In cartesian this is envelope of previous point expanded with current point
  428. // in non-cartesian this is envelope of a segment
  429. box_first_in_section<cs_tag_t<point_type>>
  430. ::apply(section.bounding_box, previous_point, current_point, strategy);
  431. }
  432. else
  433. {
  434. // In cartesian this is expand with current point
  435. // in non-cartesian this is expand with a segment
  436. box_next_in_section<cs_tag_t<point_type>>
  437. ::apply(section.bounding_box, previous_point, current_point, strategy);
  438. }
  439. section.end_index = index + 1;
  440. section.count++;
  441. if (! duplicate)
  442. {
  443. ndi++;
  444. }
  445. previous_point = current_point;
  446. }
  447. // Add last section if applicable
  448. if (section.count > 0)
  449. {
  450. if (! section.duplicate)
  451. {
  452. last_non_duplicate_index = sections.size();
  453. }
  454. sections.push_back(section);
  455. }
  456. if (last_non_duplicate_index < sections.size()
  457. && ! sections[last_non_duplicate_index].duplicate)
  458. {
  459. sections[last_non_duplicate_index].is_non_duplicate_last = true;
  460. }
  461. }
  462. };
  463. template
  464. <
  465. closure_selector Closure,
  466. bool Reverse,
  467. typename DimensionVector
  468. >
  469. struct sectionalize_range
  470. {
  471. template
  472. <
  473. typename Range,
  474. typename Sections,
  475. typename Strategy
  476. >
  477. static inline void apply(Range const& range,
  478. Sections& sections,
  479. Strategy const& strategy,
  480. ring_identifier ring_id,
  481. std::size_t max_count)
  482. {
  483. detail::closed_clockwise_view
  484. <
  485. Range const,
  486. Closure,
  487. Reverse ? counterclockwise : clockwise
  488. > const view(range);
  489. std::size_t const n = boost::size(view);
  490. if (n == 0)
  491. {
  492. // Zero points, no section
  493. return;
  494. }
  495. if (n == 1)
  496. {
  497. // Line with one point ==> no sections
  498. return;
  499. }
  500. sectionalize_part<DimensionVector>::apply(sections,
  501. boost::begin(view), boost::end(view),
  502. strategy,
  503. ring_id, max_count);
  504. }
  505. };
  506. template
  507. <
  508. bool Reverse,
  509. typename DimensionVector
  510. >
  511. struct sectionalize_polygon
  512. {
  513. template
  514. <
  515. typename Polygon,
  516. typename Sections,
  517. typename Strategy
  518. >
  519. static inline void apply(Polygon const& poly,
  520. Sections& sections,
  521. Strategy const& strategy,
  522. ring_identifier ring_id,
  523. std::size_t max_count)
  524. {
  525. using sectionalizer = sectionalize_range
  526. <
  527. closure<Polygon>::value, Reverse, DimensionVector
  528. >;
  529. ring_id.ring_index = -1;
  530. sectionalizer::apply(exterior_ring(poly), sections,
  531. strategy, ring_id, max_count);
  532. ring_id.ring_index++;
  533. auto const& rings = interior_rings(poly);
  534. for (auto it = boost::begin(rings); it != boost::end(rings);
  535. ++it, ++ring_id.ring_index)
  536. {
  537. sectionalizer::apply(*it, sections,
  538. strategy, ring_id, max_count);
  539. }
  540. }
  541. };
  542. template <typename DimensionVector>
  543. struct sectionalize_box
  544. {
  545. template
  546. <
  547. typename Box,
  548. typename Sections,
  549. typename Strategy
  550. >
  551. static inline void apply(Box const& box,
  552. Sections& sections,
  553. Strategy const& strategy,
  554. ring_identifier const& ring_id, std::size_t max_count)
  555. {
  556. using point_type = point_type_t<Box>;
  557. assert_dimension<Box, 2>();
  558. // Add all four sides of the 2D-box as separate section.
  559. // Easiest is to convert it to a polygon.
  560. // However, we don't have the polygon type
  561. // (or polygon would be a helper-type).
  562. // Therefore we mimic a linestring/std::vector of 5 points
  563. // TODO: might be replaced by assign_box_corners_oriented
  564. // or just "convert"
  565. point_type ll, lr, ul, ur;
  566. geometry::detail::assign_box_corners(box, ll, lr, ul, ur);
  567. std::vector<point_type> points;
  568. points.push_back(ll);
  569. points.push_back(ul);
  570. points.push_back(ur);
  571. points.push_back(lr);
  572. points.push_back(ll);
  573. // NOTE: Use cartesian envelope strategy in all coordinate systems
  574. // because edges of a box are not geodesic segments
  575. sectionalize_range
  576. <
  577. closed, false, DimensionVector
  578. >::apply(points, sections,
  579. strategy, ring_id, max_count);
  580. }
  581. };
  582. template <typename DimensionVector, typename Policy>
  583. struct sectionalize_multi
  584. {
  585. template
  586. <
  587. typename MultiGeometry,
  588. typename Sections,
  589. typename Strategy
  590. >
  591. static inline void apply(MultiGeometry const& multi,
  592. Sections& sections,
  593. Strategy const& strategy,
  594. ring_identifier ring_id,
  595. std::size_t max_count)
  596. {
  597. ring_id.multi_index = 0;
  598. for (auto it = boost::begin(multi); it != boost::end(multi); ++it, ++ring_id.multi_index)
  599. {
  600. Policy::apply(*it, sections,
  601. strategy,
  602. ring_id, max_count);
  603. }
  604. }
  605. };
  606. template <typename Sections, typename Strategy>
  607. inline void enlarge_sections(Sections& sections, Strategy const&)
  608. {
  609. // Expand the box to avoid missing any intersection.
  610. // About the value itself: the smaller it is,
  611. // the higher the risk to miss intersections.
  612. // The larger it is, the more comparisons are made,
  613. // which is not harmful for the result,
  614. // but it might be for the performance.
  615. // So it should be on the higher side.
  616. //
  617. // The current value:
  618. // - for double :~ 2.22e-13
  619. // - for float :~ 1e-4
  620. // - for Boost.Multiprecision (50) :~ 5.35e-48
  621. // - for Boost.Rational : 0/1
  622. // WARNING: don't use decltype here.
  623. // Earlier code used decltype(section.bonding_box) below,
  624. // but that somehow is not accepted by the NVCC (CUDA 12.4) compiler.
  625. using section_t = typename boost::range_value<Sections>::type;
  626. using box_t = typename section_t::box_type;
  627. using coor_t = geometry::coordinate_type_t<box_t>;
  628. static auto const eps = math::scaled_epsilon<coor_t>(1000);
  629. for (auto& section : sections)
  630. {
  631. expand_by_epsilon(section.bounding_box, eps);
  632. }
  633. }
  634. }} // namespace detail::sectionalize
  635. #endif // DOXYGEN_NO_DETAIL
  636. #ifndef DOXYGEN_NO_DISPATCH
  637. namespace dispatch
  638. {
  639. template
  640. <
  641. typename Tag,
  642. typename Geometry,
  643. bool Reverse,
  644. typename DimensionVector
  645. >
  646. struct sectionalize
  647. {
  648. BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
  649. "Not or not yet implemented for this Geometry type.",
  650. Tag, Geometry);
  651. };
  652. template
  653. <
  654. typename Box,
  655. bool Reverse,
  656. typename DimensionVector
  657. >
  658. struct sectionalize<box_tag, Box, Reverse, DimensionVector>
  659. : detail::sectionalize::sectionalize_box<DimensionVector>
  660. {};
  661. template
  662. <
  663. typename LineString,
  664. typename DimensionVector
  665. >
  666. struct sectionalize
  667. <
  668. linestring_tag,
  669. LineString,
  670. false,
  671. DimensionVector
  672. >
  673. : detail::sectionalize::sectionalize_range<closed, false, DimensionVector>
  674. {};
  675. template
  676. <
  677. typename Ring,
  678. bool Reverse,
  679. typename DimensionVector
  680. >
  681. struct sectionalize<ring_tag, Ring, Reverse, DimensionVector>
  682. : detail::sectionalize::sectionalize_range
  683. <
  684. geometry::closure<Ring>::value, Reverse,
  685. DimensionVector
  686. >
  687. {};
  688. template
  689. <
  690. typename Polygon,
  691. bool Reverse,
  692. typename DimensionVector
  693. >
  694. struct sectionalize<polygon_tag, Polygon, Reverse, DimensionVector>
  695. : detail::sectionalize::sectionalize_polygon
  696. <
  697. Reverse, DimensionVector
  698. >
  699. {};
  700. template
  701. <
  702. typename MultiPolygon,
  703. bool Reverse,
  704. typename DimensionVector
  705. >
  706. struct sectionalize<multi_polygon_tag, MultiPolygon, Reverse, DimensionVector>
  707. : detail::sectionalize::sectionalize_multi
  708. <
  709. DimensionVector,
  710. detail::sectionalize::sectionalize_polygon
  711. <
  712. Reverse,
  713. DimensionVector
  714. >
  715. >
  716. {};
  717. template
  718. <
  719. typename MultiLinestring,
  720. bool Reverse,
  721. typename DimensionVector
  722. >
  723. struct sectionalize<multi_linestring_tag, MultiLinestring, Reverse, DimensionVector>
  724. : detail::sectionalize::sectionalize_multi
  725. <
  726. DimensionVector,
  727. detail::sectionalize::sectionalize_range<closed, false, DimensionVector>
  728. >
  729. {};
  730. } // namespace dispatch
  731. #endif
  732. /*!
  733. \brief Split a geometry into monotonic sections
  734. \ingroup sectionalize
  735. \tparam Geometry type of geometry to check
  736. \tparam Sections type of sections to create
  737. \param geometry geometry to create sections from
  738. \param sections structure with sections
  739. \param strategy strategy for envelope calculation
  740. \param source_index index to assign to the ring_identifiers
  741. \param max_count maximal number of points per section
  742. (defaults to 10, this seems to give the fastest results)
  743. */
  744. template
  745. <
  746. bool Reverse,
  747. typename DimensionVector,
  748. typename Geometry,
  749. typename Sections,
  750. typename Strategy
  751. >
  752. inline void sectionalize(Geometry const& geometry,
  753. Sections& sections,
  754. Strategy const& strategy,
  755. int source_index = 0,
  756. std::size_t max_count = 10)
  757. {
  758. concepts::check<Geometry const>();
  759. sections.clear();
  760. ring_identifier ring_id;
  761. ring_id.source_index = source_index;
  762. dispatch::sectionalize
  763. <
  764. tag_t<Geometry>,
  765. Geometry,
  766. Reverse,
  767. DimensionVector
  768. >::apply(geometry, sections,
  769. strategy,
  770. ring_id, max_count);
  771. detail::sectionalize::enlarge_sections(sections, strategy);
  772. }
  773. template
  774. <
  775. bool Reverse,
  776. typename DimensionVector,
  777. typename Geometry,
  778. typename Sections
  779. >
  780. inline void sectionalize(Geometry const& geometry,
  781. Sections& sections,
  782. int source_index = 0,
  783. std::size_t max_count = 10)
  784. {
  785. using box_type = typename Sections::box_type;
  786. using strategy_type = typename strategies::envelope::services::default_strategy
  787. <
  788. Geometry,
  789. box_type
  790. >::type;
  791. boost::geometry::sectionalize
  792. <
  793. Reverse, DimensionVector
  794. >(geometry, sections,
  795. strategy_type(),
  796. source_index, max_count);
  797. }
  798. }} // namespace boost::geometry
  799. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_SECTIONALIZE_HPP