annotate DEPENDENCIES/generic/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp @ 133:4acb5d8d80b6 tip

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