File indexing completed on 2024-11-15 09:10:15
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFERED_PIECE_COLLECTION_HPP
0015 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFERED_PIECE_COLLECTION_HPP
0016
0017 #include <algorithm>
0018 #include <cstddef>
0019 #include <set>
0020
0021 #include <boost/core/ignore_unused.hpp>
0022 #include <boost/range/begin.hpp>
0023 #include <boost/range/empty.hpp>
0024 #include <boost/range/end.hpp>
0025 #include <boost/range/size.hpp>
0026 #include <boost/range/value_type.hpp>
0027
0028 #include <boost/geometry/core/assert.hpp>
0029 #include <boost/geometry/core/coordinate_type.hpp>
0030 #include <boost/geometry/core/point_type.hpp>
0031
0032 #include <boost/geometry/algorithms/covered_by.hpp>
0033 #include <boost/geometry/algorithms/envelope.hpp>
0034
0035 #include <boost/geometry/strategies/buffer.hpp>
0036
0037 #include <boost/geometry/geometries/ring.hpp>
0038
0039 #include <boost/geometry/algorithms/detail/buffer/buffered_ring.hpp>
0040 #include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>
0041 #include <boost/geometry/algorithms/detail/overlay/cluster_info.hpp>
0042 #include <boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp>
0043 #include <boost/geometry/algorithms/detail/buffer/piece_border.hpp>
0044 #include <boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp>
0045 #include <boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp>
0046
0047 #include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
0048 #include <boost/geometry/algorithms/detail/overlay/add_rings.hpp>
0049 #include <boost/geometry/algorithms/detail/overlay/assign_parents.hpp>
0050 #include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp>
0051 #include <boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp>
0052 #include <boost/geometry/algorithms/detail/overlay/ring_properties.hpp>
0053 #include <boost/geometry/algorithms/detail/overlay/select_rings.hpp>
0054 #include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>
0055 #include <boost/geometry/algorithms/detail/overlay/traverse.hpp>
0056 #include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
0057 #include <boost/geometry/algorithms/detail/partition.hpp>
0058 #include <boost/geometry/algorithms/detail/sections/sectionalize.hpp>
0059 #include <boost/geometry/algorithms/detail/sections/section_box_policies.hpp>
0060
0061 #include <boost/geometry/views/detail/closed_clockwise_view.hpp>
0062 #include <boost/geometry/util/for_each_with_index.hpp>
0063 #include <boost/geometry/util/range.hpp>
0064
0065
0066 namespace boost { namespace geometry
0067 {
0068
0069
0070 #ifndef DOXYGEN_NO_DETAIL
0071 namespace detail { namespace buffer
0072 {
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118 template
0119 <
0120 typename Ring,
0121 typename Strategy,
0122 typename DistanceStrategy,
0123 typename RobustPolicy
0124 >
0125 struct buffered_piece_collection
0126 {
0127 typedef typename geometry::point_type<Ring>::type point_type;
0128 typedef typename geometry::coordinate_type<Ring>::type coordinate_type;
0129
0130
0131 typedef geometry::model::ring<point_type> clockwise_ring_type;
0132
0133 typedef geometry::model::box<point_type> box_type;
0134
0135 typedef buffer_turn_info
0136 <
0137 point_type,
0138 typename segment_ratio_type<point_type, RobustPolicy>::type
0139 > buffer_turn_info_type;
0140
0141 typedef buffer_turn_operation
0142 <
0143 point_type,
0144 typename segment_ratio_type<point_type, RobustPolicy>::type
0145 > buffer_turn_operation_type;
0146
0147 typedef std::vector<buffer_turn_info_type> turn_vector_type;
0148
0149 typedef piece_border<Ring, point_type> piece_border_type;
0150
0151 struct piece
0152 {
0153 strategy::buffer::piece_type type;
0154 signed_size_type index;
0155
0156 signed_size_type left_index;
0157 signed_size_type right_index;
0158
0159
0160
0161
0162
0163
0164
0165
0166 segment_identifier first_seg_id;
0167
0168
0169
0170
0171
0172 signed_size_type beyond_last_segment_index;
0173
0174
0175 signed_size_type offsetted_count;
0176
0177 bool is_flat_start;
0178 bool is_flat_end;
0179
0180 bool is_deflated;
0181
0182
0183 piece_border_type m_piece_border;
0184
0185 point_type m_label_point;
0186
0187
0188 point_type m_center;
0189
0190 piece()
0191 : type(strategy::buffer::piece_type_unknown)
0192 , index(-1)
0193 , left_index(-1)
0194 , right_index(-1)
0195 , beyond_last_segment_index(-1)
0196 , offsetted_count(-1)
0197 , is_flat_start(false)
0198 , is_flat_end(false)
0199 , is_deflated(false)
0200 {
0201 }
0202 };
0203
0204 struct original_ring
0205 {
0206 typedef geometry::sections<box_type, 1> sections_type;
0207
0208
0209 inline original_ring()
0210 : m_is_interior(false)
0211 , m_has_interiors(false)
0212 {}
0213
0214 inline original_ring(clockwise_ring_type const& ring,
0215 bool is_interior, bool has_interiors,
0216 Strategy const& strategy)
0217 : m_ring(ring)
0218 , m_is_interior(is_interior)
0219 , m_has_interiors(has_interiors)
0220 {
0221 geometry::envelope(m_ring, m_box, strategy);
0222
0223
0224
0225
0226
0227 typedef std::integer_sequence<std::size_t, 0> dimensions;
0228 geometry::sectionalize
0229 <
0230 false, dimensions
0231 >(m_ring, detail::no_rescale_policy(), m_sections, strategy);
0232 }
0233
0234 clockwise_ring_type m_ring;
0235 box_type m_box;
0236 sections_type m_sections;
0237
0238 bool m_is_interior;
0239 bool m_has_interiors;
0240 };
0241
0242 typedef std::vector<piece> piece_vector_type;
0243
0244 piece_vector_type m_pieces;
0245 turn_vector_type m_turns;
0246 signed_size_type m_first_piece_index;
0247 bool m_deflate;
0248 bool m_has_deflated;
0249
0250
0251
0252 buffered_ring_collection<buffered_ring<Ring> > offsetted_rings;
0253 std::vector<original_ring> original_rings;
0254 std::vector<point_type> m_linear_end_points;
0255
0256 buffered_ring_collection<Ring> traversed_rings;
0257 segment_identifier current_segment_id;
0258
0259
0260
0261
0262 typedef geometry::model::box
0263 <
0264 typename geometry::robust_point_type<point_type, RobustPolicy>::type
0265 > robust_box_type;
0266 typedef geometry::sections <robust_box_type, 2> robust_sections_type;
0267 robust_sections_type monotonic_sections;
0268
0269
0270 typedef std::map
0271 <
0272 signed_size_type,
0273 detail::overlay::cluster_info
0274 > cluster_type;
0275
0276 cluster_type m_clusters;
0277
0278 Strategy m_strategy;
0279 DistanceStrategy m_distance_strategy;
0280 RobustPolicy const& m_robust_policy;
0281
0282 buffered_piece_collection(Strategy const& strategy,
0283 DistanceStrategy const& distance_strategy,
0284 RobustPolicy const& robust_policy)
0285 : m_first_piece_index(-1)
0286 , m_deflate(false)
0287 , m_has_deflated(false)
0288 , m_strategy(strategy)
0289 , m_distance_strategy(distance_strategy)
0290 , m_robust_policy(robust_policy)
0291 {}
0292
0293 inline void check_linear_endpoints(buffer_turn_info_type& turn) const
0294 {
0295
0296
0297
0298
0299 for (auto const& p : m_linear_end_points)
0300 {
0301 if (detail::equals::equals_point_point(turn.point, p, m_strategy))
0302 {
0303 turn.is_linear_end_point = true;
0304 }
0305 }
0306 }
0307
0308 inline void verify_turns()
0309 {
0310 typedef detail::overlay::indexed_turn_operation
0311 <
0312 buffer_turn_operation_type
0313 > indexed_turn_operation;
0314 typedef std::map
0315 <
0316 ring_identifier,
0317 std::vector<indexed_turn_operation>
0318 > mapped_vector_type;
0319 mapped_vector_type mapped_vector;
0320
0321 detail::overlay::create_map(m_turns, mapped_vector,
0322 enriched_map_buffer_include_policy());
0323
0324
0325 for (auto& pair : mapped_vector)
0326 {
0327 std::sort(pair.second.begin(), pair.second.end(), buffer_less());
0328 }
0329 }
0330
0331 inline void deflate_check_turns()
0332 {
0333 if (! m_has_deflated)
0334 {
0335 return;
0336 }
0337
0338
0339
0340 for (auto& turn : m_turns)
0341 {
0342 if (! turn.is_turn_traversable)
0343 {
0344 continue;
0345 }
0346 for (auto& op : turn.operations)
0347 {
0348 if (op.enriched.get_next_turn_index() == static_cast<signed_size_type>(turn.turn_index)
0349 && m_pieces[op.seg_id.piece_index].is_deflated)
0350 {
0351
0352 op.enriched.startable = false;
0353 }
0354 }
0355 }
0356 }
0357
0358
0359 inline void check_turn_in_original()
0360 {
0361 turn_in_original_visitor
0362 <
0363 turn_vector_type,
0364 Strategy
0365 > visitor(m_turns, m_strategy);
0366
0367 geometry::partition
0368 <
0369 box_type,
0370 include_turn_policy,
0371 detail::partition::include_all_policy
0372 >::apply(m_turns, original_rings, visitor,
0373 turn_get_box<Strategy>(m_strategy),
0374 turn_in_original_overlaps_box<Strategy>(m_strategy),
0375 original_get_box<Strategy>(m_strategy),
0376 original_overlaps_box<Strategy>(m_strategy));
0377
0378 bool const deflate = m_distance_strategy.negative();
0379
0380 for (auto& turn : m_turns)
0381 {
0382 if (turn.is_turn_traversable)
0383 {
0384 if (deflate && turn.count_in_original <= 0)
0385 {
0386
0387
0388 turn.is_turn_traversable = false;
0389 }
0390 else if (! deflate && turn.count_in_original > 0)
0391 {
0392
0393 turn.is_turn_traversable = false;
0394 }
0395 }
0396 }
0397 }
0398
0399 inline void update_turn_administration()
0400 {
0401 for_each_with_index(m_turns, [this](std::size_t index, auto& turn)
0402 {
0403 turn.turn_index = index;
0404
0405
0406 if (! turn.is_linear_end_point)
0407 {
0408 this->check_linear_endpoints(turn);
0409 }
0410 });
0411 }
0412
0413
0414
0415
0416
0417
0418
0419
0420 inline void update_piece_administration()
0421 {
0422 for (auto& pc : m_pieces)
0423 {
0424 piece_border_type& border = pc.m_piece_border;
0425 buffered_ring<Ring> const& ring = offsetted_rings[pc.first_seg_id.multi_index];
0426
0427 if (pc.offsetted_count > 0)
0428 {
0429 if (pc.type != strategy::buffer::buffered_concave)
0430 {
0431 border.set_offsetted(ring, pc.first_seg_id.segment_index,
0432 pc.beyond_last_segment_index);
0433 }
0434
0435
0436 border.get_properties_of_border(pc.type == geometry::strategy::buffer::buffered_point,
0437 pc.m_center, m_strategy);
0438 if (! pc.is_flat_end && ! pc.is_flat_start)
0439 {
0440 border.get_properties_of_offsetted_ring_part(m_strategy);
0441 }
0442 }
0443 }
0444 }
0445
0446 inline void get_turns()
0447 {
0448 update_piece_administration();
0449
0450 {
0451
0452 piece_turn_visitor
0453 <
0454 piece_vector_type,
0455 buffered_ring_collection<buffered_ring<Ring> >,
0456 turn_vector_type,
0457 Strategy,
0458 RobustPolicy
0459 > visitor(m_pieces, offsetted_rings, m_turns,
0460 m_strategy, m_robust_policy);
0461
0462 detail::sectionalize::enlarge_sections(monotonic_sections, m_strategy);
0463
0464 geometry::partition
0465 <
0466 robust_box_type
0467 >::apply(monotonic_sections, visitor,
0468 detail::section::get_section_box<Strategy>(m_strategy),
0469 detail::section::overlaps_section_box<Strategy>(m_strategy));
0470 }
0471
0472 update_turn_administration();
0473
0474 {
0475
0476 turn_in_piece_visitor
0477 <
0478 typename geometry::cs_tag<point_type>::type,
0479 turn_vector_type, piece_vector_type, DistanceStrategy, Strategy
0480 > visitor(m_turns, m_pieces, m_distance_strategy, m_strategy);
0481
0482 geometry::partition
0483 <
0484 box_type
0485 >::apply(m_turns, m_pieces, visitor,
0486 turn_get_box<Strategy>(m_strategy),
0487 turn_overlaps_box<Strategy>(m_strategy),
0488 piece_get_box<Strategy>(m_strategy),
0489 piece_overlaps_box<Strategy>(m_strategy));
0490 }
0491 }
0492
0493 inline void start_new_ring(bool deflate)
0494 {
0495 std::size_t const n = offsetted_rings.size();
0496 current_segment_id.source_index = 0;
0497 current_segment_id.multi_index = static_cast<signed_size_type>(n);
0498 current_segment_id.ring_index = -1;
0499 current_segment_id.segment_index = 0;
0500
0501 offsetted_rings.resize(n + 1);
0502 original_rings.resize(n + 1);
0503
0504 m_first_piece_index = static_cast<signed_size_type>(boost::size(m_pieces));
0505 m_deflate = deflate;
0506 if (deflate)
0507 {
0508
0509
0510 m_has_deflated = true;
0511 }
0512 }
0513
0514 inline void abort_ring()
0515 {
0516
0517 while (! m_pieces.empty()
0518 && m_pieces.back().first_seg_id.multi_index
0519 == current_segment_id.multi_index)
0520 {
0521 m_pieces.pop_back();
0522 }
0523
0524 offsetted_rings.pop_back();
0525 original_rings.pop_back();
0526
0527 m_first_piece_index = -1;
0528 }
0529
0530 inline void update_last_point(point_type const& p,
0531 buffered_ring<Ring>& ring)
0532 {
0533
0534
0535
0536
0537
0538
0539
0540
0541
0542 BOOST_GEOMETRY_ASSERT(boost::size(m_pieces) > 0);
0543 if (! ring.empty()
0544 && current_segment_id.segment_index
0545 == m_pieces.back().first_seg_id.segment_index)
0546 {
0547 ring.back() = p;
0548 }
0549 }
0550
0551 inline void set_piece_center(point_type const& center)
0552 {
0553 BOOST_GEOMETRY_ASSERT(! m_pieces.empty());
0554 m_pieces.back().m_center = center;
0555 }
0556
0557 inline bool finish_ring(strategy::buffer::result_code code)
0558 {
0559 if (code == strategy::buffer::result_error_numerical)
0560 {
0561 abort_ring();
0562 return false;
0563 }
0564
0565 if (m_first_piece_index == -1)
0566 {
0567 return false;
0568 }
0569
0570
0571 std::size_t const first_piece_index
0572 = static_cast<std::size_t>(m_first_piece_index);
0573 signed_size_type const last_piece_index
0574 = static_cast<signed_size_type>(boost::size(m_pieces)) - 1;
0575
0576 if (first_piece_index < boost::size(m_pieces))
0577 {
0578
0579
0580 geometry::range::at(m_pieces, first_piece_index).left_index
0581 = last_piece_index;
0582 geometry::range::back(m_pieces).right_index = m_first_piece_index;
0583 }
0584
0585 buffered_ring<Ring>& added = offsetted_rings.back();
0586 if (! boost::empty(added))
0587 {
0588
0589
0590 range::back(added) = range::front(added);
0591 }
0592
0593 for (std::size_t i = first_piece_index; i < boost::size(m_pieces); i++)
0594 {
0595 sectionalize(m_pieces[i], added);
0596 }
0597
0598 m_first_piece_index = -1;
0599 return true;
0600 }
0601
0602 template <typename InputRing>
0603 inline void finish_ring(strategy::buffer::result_code code,
0604 InputRing const& input_ring,
0605 bool is_interior, bool has_interiors)
0606 {
0607 if (! finish_ring(code))
0608 {
0609 return;
0610 }
0611
0612 if (! boost::empty(input_ring))
0613 {
0614
0615
0616
0617
0618 clockwise_ring_type clockwise_ring;
0619
0620 using view_type = detail::closed_clockwise_view<InputRing const>;
0621 view_type const view(input_ring);
0622
0623 for (auto it = boost::begin(view); it != boost::end(view); ++it)
0624 {
0625 clockwise_ring.push_back(*it);
0626 }
0627
0628 original_rings.back()
0629 = original_ring(clockwise_ring,
0630 is_interior, has_interiors,
0631 m_strategy);
0632 }
0633 }
0634
0635 inline void set_current_ring_concave()
0636 {
0637 BOOST_GEOMETRY_ASSERT(boost::size(offsetted_rings) > 0);
0638 offsetted_rings.back().has_concave = true;
0639 }
0640
0641 inline signed_size_type add_point(point_type const& p)
0642 {
0643 BOOST_GEOMETRY_ASSERT(boost::size(offsetted_rings) > 0);
0644
0645 buffered_ring<Ring>& current_ring = offsetted_rings.back();
0646 update_last_point(p, current_ring);
0647
0648 current_segment_id.segment_index++;
0649 current_ring.push_back(p);
0650 return static_cast<signed_size_type>(current_ring.size());
0651 }
0652
0653
0654
0655 inline piece& create_piece(strategy::buffer::piece_type type,
0656 bool decrease_segment_index_by_one)
0657 {
0658 if (type == strategy::buffer::buffered_concave)
0659 {
0660 offsetted_rings.back().has_concave = true;
0661 }
0662
0663 piece pc;
0664 pc.type = type;
0665 pc.index = static_cast<signed_size_type>(boost::size(m_pieces));
0666 pc.is_deflated = m_deflate;
0667
0668 current_segment_id.piece_index = pc.index;
0669
0670 pc.first_seg_id = current_segment_id;
0671
0672
0673 pc.left_index = pc.index - 1;
0674 pc.right_index = pc.index + 1;
0675
0676 std::size_t const n = boost::size(offsetted_rings.back());
0677 pc.first_seg_id.segment_index = decrease_segment_index_by_one ? n - 1 : n;
0678 pc.beyond_last_segment_index = pc.first_seg_id.segment_index;
0679
0680 m_pieces.push_back(pc);
0681 return m_pieces.back();
0682 }
0683
0684 inline void init_rescale_piece(piece& pc)
0685 {
0686 if (pc.first_seg_id.segment_index < 0)
0687 {
0688
0689
0690 pc.offsetted_count = 0;
0691 return;
0692 }
0693
0694 BOOST_GEOMETRY_ASSERT(pc.first_seg_id.multi_index >= 0);
0695 BOOST_GEOMETRY_ASSERT(pc.beyond_last_segment_index >= 0);
0696
0697 pc.offsetted_count = pc.beyond_last_segment_index - pc.first_seg_id.segment_index;
0698 BOOST_GEOMETRY_ASSERT(pc.offsetted_count >= 0);
0699 }
0700
0701 inline void add_piece_point(piece& pc, point_type const& point, bool add_to_original)
0702 {
0703 if (add_to_original && pc.type != strategy::buffer::buffered_concave)
0704 {
0705 pc.m_piece_border.add_original_point(point);
0706 }
0707 else
0708 {
0709 pc.m_label_point = point;
0710 }
0711 }
0712
0713 inline void sectionalize(piece const& pc, buffered_ring<Ring> const& ring)
0714 {
0715 using sectionalizer = geometry::detail::sectionalize::sectionalize_part
0716 <
0717 std::integer_sequence<std::size_t, 0, 1>
0718 >;
0719
0720
0721
0722
0723 ring_identifier const ring_id(pc.index, pc.first_seg_id.multi_index, -1);
0724
0725 sectionalizer::apply(monotonic_sections,
0726 boost::begin(ring) + pc.first_seg_id.segment_index,
0727 boost::begin(ring) + pc.beyond_last_segment_index,
0728 m_robust_policy,
0729 m_strategy,
0730 ring_id, 10);
0731 }
0732
0733 inline void finish_piece(piece& pc)
0734 {
0735 init_rescale_piece(pc);
0736 }
0737
0738 inline void finish_piece(piece& pc,
0739 point_type const& point1,
0740 point_type const& point2,
0741 point_type const& point3)
0742 {
0743 init_rescale_piece(pc);
0744 if (pc.offsetted_count == 0)
0745 {
0746 return;
0747 }
0748
0749 add_piece_point(pc, point1, false);
0750 add_piece_point(pc, point2, true);
0751 add_piece_point(pc, point3, false);
0752 }
0753
0754 inline void finish_piece(piece& pc,
0755 point_type const& point1,
0756 point_type const& point2,
0757 point_type const& point3,
0758 point_type const& point4)
0759 {
0760 init_rescale_piece(pc);
0761
0762
0763
0764
0765 add_piece_point(pc, point1, false);
0766 add_piece_point(pc, point2, true);
0767 add_piece_point(pc, point3, true);
0768 add_piece_point(pc, point4, false);
0769 }
0770
0771 template <typename Range>
0772 inline void add_range_to_piece(piece& pc, Range const& range, bool add_front)
0773 {
0774 BOOST_GEOMETRY_ASSERT(boost::size(range) != 0u);
0775
0776 auto it = boost::begin(range);
0777
0778
0779
0780
0781 if (add_front)
0782 {
0783 add_point(*it);
0784 }
0785
0786 for (++it; it != boost::end(range); ++it)
0787 {
0788 pc.beyond_last_segment_index = add_point(*it);
0789 }
0790 }
0791
0792 inline void add_piece(strategy::buffer::piece_type type, point_type const& p,
0793 point_type const& b1, point_type const& b2)
0794 {
0795 piece& pc = create_piece(type, false);
0796 add_point(b1);
0797 pc.beyond_last_segment_index = add_point(b2);
0798 finish_piece(pc, b2, p, b1);
0799 }
0800
0801 template <typename Range>
0802 inline void add_piece(strategy::buffer::piece_type type, Range const& range,
0803 bool decrease_segment_index_by_one)
0804 {
0805 piece& pc = create_piece(type, decrease_segment_index_by_one);
0806
0807 if (boost::size(range) > 0u)
0808 {
0809 add_range_to_piece(pc, range, offsetted_rings.back().empty());
0810 }
0811 finish_piece(pc);
0812 }
0813
0814 template <typename Range>
0815 inline void add_piece(strategy::buffer::piece_type type,
0816 point_type const& p, Range const& range)
0817 {
0818 piece& pc = create_piece(type, true);
0819
0820 if (boost::size(range) > 0u)
0821 {
0822 add_range_to_piece(pc, range, offsetted_rings.back().empty());
0823 finish_piece(pc, range.back(), p, range.front());
0824 }
0825 else
0826 {
0827 finish_piece(pc);
0828 }
0829 }
0830
0831 template <typename Range>
0832 inline void add_side_piece(point_type const& original_point1,
0833 point_type const& original_point2,
0834 Range const& range, bool is_first, bool is_empty)
0835 {
0836 BOOST_GEOMETRY_ASSERT(boost::size(range) >= 2u);
0837
0838 auto const piece_type = is_empty
0839 ? strategy::buffer::buffered_empty_side
0840 : strategy::buffer::buffered_segment;
0841
0842 piece& pc = create_piece(piece_type, ! is_first);
0843 add_range_to_piece(pc, range, is_first);
0844
0845
0846
0847 finish_piece(pc, range.back(), original_point2, original_point1, range.front());
0848 }
0849
0850 template <typename EndcapStrategy, typename Range>
0851 inline void add_endcap(EndcapStrategy const& strategy, Range const& range,
0852 point_type const& end_point)
0853 {
0854 boost::ignore_unused(strategy);
0855
0856 if (range.empty())
0857 {
0858 return;
0859 }
0860 strategy::buffer::piece_type pt = strategy.get_piece_type();
0861 if (pt == strategy::buffer::buffered_flat_end)
0862 {
0863
0864 add_piece(pt, range, true);
0865 }
0866 else
0867 {
0868
0869 add_piece(pt, end_point, range);
0870 }
0871 }
0872
0873 inline void mark_flat_start(point_type const& point)
0874 {
0875 if (! m_pieces.empty())
0876 {
0877 piece& back = m_pieces.back();
0878 back.is_flat_start = true;
0879
0880
0881
0882
0883
0884
0885 m_linear_end_points.push_back(point);
0886 }
0887 }
0888
0889 inline void mark_flat_end(point_type const& point)
0890 {
0891 if (! m_pieces.empty())
0892 {
0893 piece& back = m_pieces.back();
0894 back.is_flat_end = true;
0895 m_linear_end_points.push_back(point);
0896 }
0897 }
0898
0899
0900
0901 inline void enrich()
0902 {
0903 enrich_intersection_points<false, false, overlay_buffer>(m_turns,
0904 m_clusters, offsetted_rings, offsetted_rings,
0905 m_robust_policy,
0906 m_strategy);
0907 }
0908
0909
0910
0911 inline void discard_rings()
0912 {
0913 for (auto const& turn : m_turns)
0914 {
0915 if (turn.is_turn_traversable)
0916 {
0917 offsetted_rings[turn.operations[0].seg_id.multi_index].has_accepted_intersections = true;
0918 offsetted_rings[turn.operations[1].seg_id.multi_index].has_accepted_intersections = true;
0919 }
0920 else
0921 {
0922 offsetted_rings[turn.operations[0].seg_id.multi_index].has_discarded_intersections = true;
0923 offsetted_rings[turn.operations[1].seg_id.multi_index].has_discarded_intersections = true;
0924 }
0925 }
0926 }
0927
0928 inline bool point_coveredby_original(point_type const& point)
0929 {
0930 signed_size_type count_in_original = 0;
0931
0932
0933
0934
0935
0936 for (auto const& original : original_rings)
0937 {
0938 if (original.m_ring.empty())
0939 {
0940 continue;
0941 }
0942 if (detail::disjoint::disjoint_point_box(point, original.m_box,m_strategy))
0943 {
0944 continue;
0945 }
0946
0947 int const geometry_code
0948 = detail::within::point_in_geometry(point, original.m_ring, m_strategy);
0949
0950 if (geometry_code == -1)
0951 {
0952
0953 continue;
0954 }
0955
0956
0957 if (original.m_is_interior)
0958 {
0959 count_in_original--;
0960 }
0961 else if (original.m_has_interiors)
0962 {
0963 count_in_original++;
0964 }
0965 else
0966 {
0967
0968 return true;
0969 }
0970 }
0971 return count_in_original > 0;
0972 }
0973
0974
0975
0976
0977 inline void discard_nonintersecting_deflated_rings()
0978 {
0979 for (auto& ring : offsetted_rings)
0980 {
0981 if (! ring.has_intersections()
0982 && boost::size(ring) > 0u
0983 && geometry::area(ring, m_strategy) < 0)
0984 {
0985 if (! point_coveredby_original(geometry::range::front(ring)))
0986 {
0987 ring.is_untouched_outside_original = true;
0988 }
0989 }
0990 }
0991 }
0992
0993 inline void block_turns()
0994 {
0995 for (auto& turn : m_turns)
0996 {
0997 if (! turn.is_turn_traversable)
0998 {
0999
1000
1001 turn.discarded = true;
1002 }
1003 }
1004 }
1005
1006 inline void traverse()
1007 {
1008 typedef detail::overlay::traverse
1009 <
1010 false, false,
1011 buffered_ring_collection<buffered_ring<Ring> >,
1012 buffered_ring_collection<buffered_ring<Ring > >,
1013 overlay_buffer,
1014 backtrack_for_buffer
1015 > traverser;
1016 std::map<ring_identifier, overlay::ring_turn_info> turn_info_per_ring;
1017
1018 traversed_rings.clear();
1019 buffer_overlay_visitor visitor;
1020 traverser::apply(offsetted_rings, offsetted_rings,
1021 m_strategy, m_robust_policy,
1022 m_turns, traversed_rings,
1023 turn_info_per_ring,
1024 m_clusters, visitor);
1025 }
1026
1027 inline void reverse()
1028 {
1029 for (auto& ring : offsetted_rings)
1030 {
1031 if (! ring.has_intersections())
1032 {
1033 std::reverse(ring.begin(), ring.end());
1034 }
1035 }
1036 for (auto& ring : traversed_rings)
1037 {
1038 std::reverse(ring.begin(), ring.end());
1039 }
1040 }
1041
1042 template <typename GeometryOutput, typename OutputIterator>
1043 inline OutputIterator assign(OutputIterator out) const
1044 {
1045 typedef typename geometry::area_result
1046 <
1047 buffered_ring<Ring>, Strategy
1048 >::type area_result_type;
1049 typedef detail::overlay::ring_properties
1050 <
1051 point_type, area_result_type
1052 > properties;
1053
1054 std::map<ring_identifier, properties> selected;
1055
1056
1057
1058
1059
1060 for_each_with_index(offsetted_rings, [&](std::size_t index, auto const& ring)
1061 {
1062 if (! ring.has_intersections()
1063 && ! ring.is_untouched_outside_original)
1064 {
1065 properties p = properties(ring, m_strategy);
1066 if (p.valid)
1067 {
1068 ring_identifier id(0, index, -1);
1069 selected[id] = p;
1070 }
1071 }
1072 });
1073
1074
1075 for_each_with_index(traversed_rings, [&](std::size_t index, auto const& ring)
1076 {
1077 properties p = properties(ring, m_strategy);
1078 if (p.valid)
1079 {
1080 ring_identifier id(2, index, -1);
1081 selected[id] = p;
1082 }
1083 });
1084
1085 detail::overlay::assign_parents<overlay_buffer>(offsetted_rings, traversed_rings,
1086 selected, m_strategy);
1087 return detail::overlay::add_rings<GeometryOutput>(selected, offsetted_rings, traversed_rings, out,
1088 m_strategy);
1089 }
1090
1091 };
1092
1093
1094 }}
1095 #endif
1096
1097
1098 }}
1099
1100 #endif