File indexing completed on 2025-07-15 08:33:47
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_INSERTER_HPP
0015 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_INSERTER_HPP
0016
0017 #include <cstddef>
0018 #include <iterator>
0019
0020 #include <boost/core/ignore_unused.hpp>
0021 #include <boost/range/begin.hpp>
0022 #include <boost/range/end.hpp>
0023 #include <boost/range/rbegin.hpp>
0024 #include <boost/range/rend.hpp>
0025 #include <boost/range/size.hpp>
0026 #include <boost/range/value_type.hpp>
0027
0028 #include <boost/geometry/algorithms/detail/direction_code.hpp>
0029 #include <boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp>
0030 #include <boost/geometry/algorithms/detail/buffer/line_line_intersection.hpp>
0031
0032 #include <boost/geometry/algorithms/num_interior_rings.hpp>
0033 #include <boost/geometry/algorithms/simplify.hpp>
0034
0035 #include <boost/geometry/core/assert.hpp>
0036 #include <boost/geometry/core/closure.hpp>
0037 #include <boost/geometry/core/exterior_ring.hpp>
0038 #include <boost/geometry/core/interior_rings.hpp>
0039
0040 #include <boost/geometry/geometries/linestring.hpp>
0041 #include <boost/geometry/geometries/ring.hpp>
0042
0043 #include <boost/geometry/strategies/buffer.hpp>
0044 #include <boost/geometry/strategies/side.hpp>
0045
0046 #include <boost/geometry/util/constexpr.hpp>
0047 #include <boost/geometry/util/math.hpp>
0048 #include <boost/geometry/util/type_traits.hpp>
0049
0050 #include <boost/geometry/views/detail/closed_clockwise_view.hpp>
0051
0052
0053 namespace boost { namespace geometry
0054 {
0055
0056 #ifndef DOXYGEN_NO_DETAIL
0057 namespace detail { namespace buffer
0058 {
0059
0060 template <typename RangeIn, typename DistanceStrategy, typename RangeOut, typename Strategies>
0061 inline void simplify_input(RangeIn const& range,
0062 DistanceStrategy const& distance,
0063 RangeOut& simplified,
0064 Strategies const& strategies)
0065 {
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076 geometry::detail::simplify::simplify_range<2>::apply(range,
0077 simplified, distance.simplify_distance(),
0078 detail::simplify::douglas_peucker(),
0079 strategies);
0080
0081 }
0082
0083
0084 template <typename RingOutput>
0085 struct buffer_range
0086 {
0087 typedef typename point_type<RingOutput>::type output_point_type;
0088 typedef typename coordinate_type<RingOutput>::type coordinate_type;
0089
0090 template
0091 <
0092 typename Collection,
0093 typename Point,
0094 typename DistanceStrategy,
0095 typename SegmentStrategy,
0096 typename JoinStrategy,
0097 typename EndStrategy,
0098 typename RobustPolicy,
0099 typename Strategies
0100 >
0101 static inline
0102 void add_join(Collection& collection,
0103 Point const& penultimate_input,
0104 Point const& previous_input,
0105 output_point_type const& prev_perp1,
0106 output_point_type const& prev_perp2,
0107 Point const& input,
0108 output_point_type const& perp1,
0109 output_point_type const& perp2,
0110 geometry::strategy::buffer::buffer_side_selector side,
0111 DistanceStrategy const& distance,
0112 SegmentStrategy const& segment_strategy,
0113 JoinStrategy const& join_strategy,
0114 EndStrategy const& end_strategy,
0115 RobustPolicy const& ,
0116 Strategies const& strategies)
0117 {
0118 geometry::strategy::buffer::join_selector const join
0119 = get_join_type(penultimate_input, previous_input, input,
0120 strategies);
0121
0122 switch(join)
0123 {
0124 case geometry::strategy::buffer::join_continue :
0125
0126 break;
0127 case geometry::strategy::buffer::join_concave :
0128 {
0129 std::vector<output_point_type> range_out;
0130 range_out.push_back(prev_perp2);
0131 range_out.push_back(previous_input);
0132 collection.add_piece(geometry::strategy::buffer::buffered_concave, previous_input, range_out);
0133
0134 range_out.clear();
0135 range_out.push_back(previous_input);
0136 range_out.push_back(perp1);
0137 collection.add_piece(geometry::strategy::buffer::buffered_concave, previous_input, range_out);
0138 }
0139 break;
0140 case geometry::strategy::buffer::join_spike :
0141 {
0142
0143
0144 std::vector<output_point_type> range_out;
0145 end_strategy.apply(penultimate_input, prev_perp2, previous_input, perp1, side, distance, range_out);
0146 collection.add_endcap(end_strategy, range_out, previous_input);
0147 collection.set_current_ring_concave();
0148 }
0149 break;
0150 case geometry::strategy::buffer::join_convex :
0151 {
0152
0153
0154 output_point_type intersection_point;
0155 if (line_line_intersection::apply(prev_perp1, prev_perp2,
0156 perp1, perp2, previous_input,
0157 segment_strategy.equidistant(),
0158 intersection_point))
0159 {
0160 std::vector<output_point_type> range_out;
0161 if (join_strategy.apply(intersection_point,
0162 previous_input, prev_perp2, perp1,
0163 distance.apply(previous_input, input, side),
0164 range_out))
0165 {
0166 collection.add_piece(geometry::strategy::buffer::buffered_join,
0167 previous_input, range_out);
0168 }
0169 }
0170 }
0171 break;
0172 }
0173 }
0174
0175
0176
0177 static inline bool same_direction(output_point_type const& p0,
0178 output_point_type const& p1,
0179 output_point_type const& p2)
0180 {
0181 typedef typename cs_tag<output_point_type>::type cs_tag;
0182 return direction_code<cs_tag>(p0, p1, p2) == 1;
0183 }
0184
0185 template <typename Strategies>
0186 static inline geometry::strategy::buffer::join_selector get_join_type(
0187 output_point_type const& p0,
0188 output_point_type const& p1,
0189 output_point_type const& p2,
0190 Strategies const& strategies)
0191 {
0192 int const side = strategies.side().apply(p0, p1, p2);
0193 return side == -1 ? geometry::strategy::buffer::join_convex
0194 : side == 1 ? geometry::strategy::buffer::join_concave
0195 : same_direction(p0, p1, p2) ? geometry::strategy::buffer::join_continue
0196 : geometry::strategy::buffer::join_spike;
0197 }
0198
0199 template
0200 <
0201 typename Collection,
0202 typename Iterator,
0203 typename DistanceStrategy,
0204 typename SegmentStrategy,
0205 typename JoinStrategy,
0206 typename EndStrategy,
0207 typename RobustPolicy,
0208 typename Strategies
0209 >
0210 static inline geometry::strategy::buffer::result_code iterate(Collection& collection,
0211 Iterator begin, Iterator end,
0212 geometry::strategy::buffer::buffer_side_selector side,
0213 DistanceStrategy const& distance_strategy,
0214 SegmentStrategy const& segment_strategy,
0215 JoinStrategy const& join_strategy,
0216 EndStrategy const& end_strategy,
0217 RobustPolicy const& robust_policy,
0218 Strategies const& strategies,
0219 bool linear,
0220 output_point_type& first_p1,
0221 output_point_type& first_p2,
0222 output_point_type& last_p1,
0223 output_point_type& last_p2)
0224 {
0225 boost::ignore_unused(segment_strategy);
0226
0227 typedef typename std::iterator_traits
0228 <
0229 Iterator
0230 >::value_type point_type;
0231
0232 point_type second_point, penultimate_point, ultimate_point;
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251 bool const mark_flat
0252 = linear
0253 && end_strategy.get_piece_type() == geometry::strategy::buffer::buffered_flat_end;
0254
0255 geometry::strategy::buffer::result_code result = geometry::strategy::buffer::result_no_output;
0256 bool first = true;
0257
0258 Iterator it = begin;
0259
0260 std::vector<output_point_type> generated_side;
0261 generated_side.reserve(2);
0262
0263 for (Iterator prev = it++; it != end; ++it)
0264 {
0265 generated_side.clear();
0266 geometry::strategy::buffer::result_code error_code
0267 = segment_strategy.apply(*prev, *it, side,
0268 distance_strategy, generated_side);
0269
0270 if (error_code == geometry::strategy::buffer::result_no_output)
0271 {
0272
0273
0274
0275 continue;
0276 }
0277 else if (error_code == geometry::strategy::buffer::result_error_numerical)
0278 {
0279 return error_code;
0280 }
0281
0282 BOOST_GEOMETRY_ASSERT(! generated_side.empty());
0283
0284 result = geometry::strategy::buffer::result_normal;
0285
0286 if (! first)
0287 {
0288 add_join(collection,
0289 penultimate_point,
0290 *prev, last_p1, last_p2,
0291 *it, generated_side.front(), generated_side.back(),
0292 side,
0293 distance_strategy, segment_strategy, join_strategy, end_strategy,
0294 robust_policy, strategies);
0295 }
0296
0297 collection.add_side_piece(*prev, *it, generated_side, first, distance_strategy.empty(side));
0298
0299 if (first && mark_flat)
0300 {
0301 collection.mark_flat_start(*prev);
0302 }
0303
0304 penultimate_point = *prev;
0305 ultimate_point = *it;
0306 last_p1 = generated_side.front();
0307 last_p2 = generated_side.back();
0308 prev = it;
0309 if (first)
0310 {
0311 first = false;
0312 second_point = *it;
0313 first_p1 = generated_side.front();
0314 first_p2 = generated_side.back();
0315 }
0316 }
0317
0318 if (mark_flat)
0319 {
0320 collection.mark_flat_end(ultimate_point);
0321 }
0322
0323 return result;
0324 }
0325 };
0326
0327 template
0328 <
0329 typename Multi,
0330 typename PolygonOutput,
0331 typename Policy
0332 >
0333 struct buffer_multi
0334 {
0335 template
0336 <
0337 typename Collection,
0338 typename DistanceStrategy,
0339 typename SegmentStrategy,
0340 typename JoinStrategy,
0341 typename EndStrategy,
0342 typename PointStrategy,
0343 typename RobustPolicy,
0344 typename Strategies
0345 >
0346 static inline void apply(Multi const& multi,
0347 Collection& collection,
0348 DistanceStrategy const& distance_strategy,
0349 SegmentStrategy const& segment_strategy,
0350 JoinStrategy const& join_strategy,
0351 EndStrategy const& end_strategy,
0352 PointStrategy const& point_strategy,
0353 RobustPolicy const& robust_policy,
0354 Strategies const& strategies)
0355 {
0356 for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
0357 {
0358 Policy::apply(*it, collection,
0359 distance_strategy, segment_strategy,
0360 join_strategy, end_strategy, point_strategy,
0361 robust_policy, strategies);
0362 }
0363 }
0364 };
0365
0366 struct visit_pieces_default_policy
0367 {
0368 template <typename Collection>
0369 static inline void apply(Collection const&, int)
0370 {}
0371 };
0372
0373 template
0374 <
0375 typename OutputPointType,
0376 typename Point,
0377 typename Collection,
0378 typename DistanceStrategy,
0379 typename PointStrategy
0380 >
0381 inline void buffer_point(Point const& point, Collection& collection,
0382 DistanceStrategy const& distance_strategy,
0383 PointStrategy const& point_strategy)
0384 {
0385 collection.start_new_ring(false);
0386 std::vector<OutputPointType> range_out;
0387 point_strategy.apply(point, distance_strategy, range_out);
0388 collection.add_piece(geometry::strategy::buffer::buffered_point, range_out, false);
0389 collection.set_piece_center(point);
0390 collection.finish_ring(geometry::strategy::buffer::result_normal);
0391 }
0392
0393
0394 }}
0395 #endif
0396
0397
0398 #ifndef DOXYGEN_NO_DISPATCH
0399 namespace dispatch
0400 {
0401
0402 template
0403 <
0404 typename Tag,
0405 typename RingInput,
0406 typename RingOutput
0407 >
0408 struct buffer_inserter
0409 {};
0410
0411
0412
0413 template
0414 <
0415 typename Point,
0416 typename RingOutput
0417 >
0418 struct buffer_inserter<point_tag, Point, RingOutput>
0419 {
0420 template
0421 <
0422 typename Collection,
0423 typename DistanceStrategy,
0424 typename SegmentStrategy,
0425 typename JoinStrategy,
0426 typename EndStrategy,
0427 typename PointStrategy,
0428 typename RobustPolicy,
0429 typename Strategies
0430 >
0431 static inline void apply(Point const& point, Collection& collection,
0432 DistanceStrategy const& distance_strategy,
0433 SegmentStrategy const& ,
0434 JoinStrategy const& ,
0435 EndStrategy const& ,
0436 PointStrategy const& point_strategy,
0437 RobustPolicy const& ,
0438 Strategies const& )
0439 {
0440 detail::buffer::buffer_point
0441 <
0442 typename point_type<RingOutput>::type
0443 >(point, collection, distance_strategy, point_strategy);
0444 }
0445 };
0446
0447
0448
0449 template
0450 <
0451 typename RingInput,
0452 typename RingOutput
0453 >
0454 struct buffer_inserter_ring
0455 {
0456 using output_point_type = typename point_type<RingOutput>::type;
0457
0458 template
0459 <
0460 typename Collection,
0461 typename Iterator,
0462 typename DistanceStrategy,
0463 typename SegmentStrategy,
0464 typename JoinStrategy,
0465 typename EndStrategy,
0466 typename RobustPolicy,
0467 typename Strategies
0468 >
0469 static inline geometry::strategy::buffer::result_code iterate(Collection& collection,
0470 Iterator begin, Iterator end,
0471 geometry::strategy::buffer::buffer_side_selector side,
0472 DistanceStrategy const& distance_strategy,
0473 SegmentStrategy const& segment_strategy,
0474 JoinStrategy const& join_strategy,
0475 EndStrategy const& end_strategy,
0476 RobustPolicy const& robust_policy,
0477 Strategies const& strategies)
0478 {
0479 output_point_type first_p1, first_p2, last_p1, last_p2;
0480
0481 typedef detail::buffer::buffer_range<RingOutput> buffer_range;
0482
0483 geometry::strategy::buffer::result_code result
0484 = buffer_range::iterate(collection, begin, end,
0485 side,
0486 distance_strategy, segment_strategy, join_strategy, end_strategy,
0487 robust_policy, strategies,
0488 false, first_p1, first_p2, last_p1, last_p2);
0489
0490
0491 if (result == geometry::strategy::buffer::result_normal)
0492 {
0493 buffer_range::add_join(collection,
0494 *(end - 2),
0495 *(end - 1), last_p1, last_p2,
0496 *(begin + 1), first_p1, first_p2,
0497 side,
0498 distance_strategy, segment_strategy, join_strategy, end_strategy,
0499 robust_policy, strategies);
0500 }
0501
0502
0503 return result;
0504 }
0505
0506 template
0507 <
0508 typename Collection,
0509 typename DistanceStrategy,
0510 typename SegmentStrategy,
0511 typename JoinStrategy,
0512 typename EndStrategy,
0513 typename PointStrategy,
0514 typename RobustPolicy,
0515 typename Strategies
0516 >
0517 static inline geometry::strategy::buffer::result_code apply(RingInput const& ring,
0518 Collection& collection,
0519 DistanceStrategy const& distance,
0520 SegmentStrategy const& segment_strategy,
0521 JoinStrategy const& join_strategy,
0522 EndStrategy const& end_strategy,
0523 PointStrategy const& point_strategy,
0524 RobustPolicy const& robust_policy,
0525 Strategies const& strategies)
0526 {
0527
0528 using simplified_ring_t = model::ring
0529 <
0530 output_point_type,
0531 point_order<RingInput>::value != counterclockwise,
0532 closure<RingInput>::value != open
0533 >;
0534 simplified_ring_t simplified;
0535 detail::buffer::simplify_input(ring, distance, simplified, strategies);
0536
0537 geometry::strategy::buffer::result_code code = geometry::strategy::buffer::result_no_output;
0538
0539 std::size_t n = boost::size(simplified);
0540 std::size_t const min_points = core_detail::closure::minimum_ring_size
0541 <
0542 geometry::closure<simplified_ring_t>::value
0543 >::value;
0544
0545 if (n >= min_points)
0546 {
0547 detail::closed_clockwise_view<simplified_ring_t const> view(simplified);
0548 if (distance.negative())
0549 {
0550
0551 code = iterate(collection, boost::rbegin(view), boost::rend(view),
0552 geometry::strategy::buffer::buffer_side_right,
0553 distance, segment_strategy, join_strategy, end_strategy,
0554 robust_policy, strategies);
0555 }
0556 else
0557 {
0558 code = iterate(collection, boost::begin(view), boost::end(view),
0559 geometry::strategy::buffer::buffer_side_left,
0560 distance, segment_strategy, join_strategy, end_strategy,
0561 robust_policy, strategies);
0562 }
0563 }
0564
0565 if (code == geometry::strategy::buffer::result_no_output && n >= 1)
0566 {
0567
0568 detail::buffer::buffer_point<output_point_type>
0569 (
0570 geometry::range::front(simplified),
0571 collection, distance, point_strategy
0572 );
0573 }
0574 return code;
0575 }
0576 };
0577
0578
0579 template
0580 <
0581 typename RingInput,
0582 typename RingOutput
0583 >
0584 struct buffer_inserter<ring_tag, RingInput, RingOutput>
0585 {
0586 template
0587 <
0588 typename Collection,
0589 typename DistanceStrategy,
0590 typename SegmentStrategy,
0591 typename JoinStrategy,
0592 typename EndStrategy,
0593 typename PointStrategy,
0594 typename RobustPolicy,
0595 typename Strategies
0596 >
0597 static inline geometry::strategy::buffer::result_code apply(RingInput const& ring,
0598 Collection& collection,
0599 DistanceStrategy const& distance,
0600 SegmentStrategy const& segment_strategy,
0601 JoinStrategy const& join_strategy,
0602 EndStrategy const& end_strategy,
0603 PointStrategy const& point_strategy,
0604 RobustPolicy const& robust_policy,
0605 Strategies const& strategies)
0606 {
0607 collection.start_new_ring(distance.negative());
0608 geometry::strategy::buffer::result_code const code
0609 = buffer_inserter_ring<RingInput, RingOutput>::apply(ring,
0610 collection, distance,
0611 segment_strategy, join_strategy, end_strategy, point_strategy,
0612 robust_policy, strategies);
0613 collection.finish_ring(code, ring, false, false);
0614 return code;
0615 }
0616 };
0617
0618 template
0619 <
0620 typename Linestring,
0621 typename Polygon
0622 >
0623 struct buffer_inserter<linestring_tag, Linestring, Polygon>
0624 {
0625 using output_ring_type = typename ring_type<Polygon>::type;
0626 using output_point_type = typename point_type<output_ring_type>::type;
0627
0628 template
0629 <
0630 typename Collection,
0631 typename Iterator,
0632 typename DistanceStrategy,
0633 typename SegmentStrategy,
0634 typename JoinStrategy,
0635 typename EndStrategy,
0636 typename RobustPolicy,
0637 typename Strategies
0638 >
0639 static inline geometry::strategy::buffer::result_code iterate(Collection& collection,
0640 Iterator begin, Iterator end,
0641 geometry::strategy::buffer::buffer_side_selector side,
0642 DistanceStrategy const& distance_strategy,
0643 SegmentStrategy const& segment_strategy,
0644 JoinStrategy const& join_strategy,
0645 EndStrategy const& end_strategy,
0646 RobustPolicy const& robust_policy,
0647 Strategies const& strategies,
0648 output_point_type& first_p1)
0649 {
0650 output_point_type const& ultimate_point = *(end - 1);
0651 output_point_type const& penultimate_point = *(end - 2);
0652
0653
0654
0655
0656
0657 output_point_type reverse_p1;
0658 if (side == geometry::strategy::buffer::buffer_side_right)
0659 {
0660 reverse_p1 = first_p1;
0661 }
0662 else
0663 {
0664 std::vector<output_point_type> generated_side;
0665 geometry::strategy::buffer::result_code code
0666 = segment_strategy.apply(ultimate_point, penultimate_point,
0667 geometry::strategy::buffer::buffer_side_right,
0668 distance_strategy, generated_side);
0669 if (code != geometry::strategy::buffer::result_normal)
0670 {
0671
0672 return code;
0673 }
0674 reverse_p1 = generated_side.front();
0675 }
0676
0677 output_point_type first_p2, last_p1, last_p2;
0678
0679 geometry::strategy::buffer::result_code result
0680 = detail::buffer::buffer_range<output_ring_type>::iterate(collection,
0681 begin, end, side,
0682 distance_strategy, segment_strategy, join_strategy, end_strategy,
0683 robust_policy, strategies,
0684 true, first_p1, first_p2, last_p1, last_p2);
0685
0686 if (result == geometry::strategy::buffer::result_normal)
0687 {
0688 std::vector<output_point_type> range_out;
0689 end_strategy.apply(penultimate_point, last_p2, ultimate_point, reverse_p1,
0690 side, distance_strategy, range_out);
0691 collection.add_endcap(end_strategy, range_out, ultimate_point);
0692 }
0693 return result;
0694 }
0695
0696 template
0697 <
0698 typename Collection,
0699 typename DistanceStrategy,
0700 typename SegmentStrategy,
0701 typename JoinStrategy,
0702 typename EndStrategy,
0703 typename PointStrategy,
0704 typename RobustPolicy,
0705 typename Strategies
0706 >
0707 static inline geometry::strategy::buffer::result_code apply(Linestring const& linestring,
0708 Collection& collection,
0709 DistanceStrategy const& distance,
0710 SegmentStrategy const& segment_strategy,
0711 JoinStrategy const& join_strategy,
0712 EndStrategy const& end_strategy,
0713 PointStrategy const& point_strategy,
0714 RobustPolicy const& robust_policy,
0715 Strategies const& strategies)
0716 {
0717
0718 model::linestring<output_point_type> simplified;
0719 detail::buffer::simplify_input(linestring, distance, simplified, strategies);
0720
0721 geometry::strategy::buffer::result_code code = geometry::strategy::buffer::result_no_output;
0722 std::size_t n = boost::size(simplified);
0723 if (n > 1)
0724 {
0725 collection.start_new_ring(false);
0726 output_point_type first_p1;
0727 code = iterate(collection,
0728 boost::begin(simplified), boost::end(simplified),
0729 geometry::strategy::buffer::buffer_side_left,
0730 distance, segment_strategy, join_strategy, end_strategy,
0731 robust_policy, strategies,
0732 first_p1);
0733
0734 if (code == geometry::strategy::buffer::result_normal)
0735 {
0736 code = iterate(collection,
0737 boost::rbegin(simplified), boost::rend(simplified),
0738 geometry::strategy::buffer::buffer_side_right,
0739 distance, segment_strategy, join_strategy, end_strategy,
0740 robust_policy, strategies,
0741 first_p1);
0742 }
0743 collection.finish_ring(code);
0744 }
0745 if (code == geometry::strategy::buffer::result_no_output && n >= 1)
0746 {
0747
0748 detail::buffer::buffer_point<output_point_type>
0749 (
0750 geometry::range::front(simplified),
0751 collection, distance, point_strategy
0752 );
0753 }
0754 return code;
0755 }
0756 };
0757
0758
0759 template
0760 <
0761 typename PolygonInput,
0762 typename PolygonOutput
0763 >
0764 struct buffer_inserter<polygon_tag, PolygonInput, PolygonOutput>
0765 {
0766 private:
0767 typedef typename ring_type<PolygonInput>::type input_ring_type;
0768 typedef typename ring_type<PolygonOutput>::type output_ring_type;
0769
0770 typedef buffer_inserter_ring<input_ring_type, output_ring_type> policy;
0771
0772
0773 template
0774 <
0775 typename Iterator,
0776 typename Collection,
0777 typename DistanceStrategy,
0778 typename SegmentStrategy,
0779 typename JoinStrategy,
0780 typename EndStrategy,
0781 typename PointStrategy,
0782 typename RobustPolicy,
0783 typename Strategies
0784 >
0785 static inline
0786 void iterate(Iterator begin, Iterator end,
0787 Collection& collection,
0788 DistanceStrategy const& distance,
0789 SegmentStrategy const& segment_strategy,
0790 JoinStrategy const& join_strategy,
0791 EndStrategy const& end_strategy,
0792 PointStrategy const& point_strategy,
0793 RobustPolicy const& robust_policy,
0794 Strategies const& strategies,
0795 bool is_interior)
0796 {
0797 for (Iterator it = begin; it != end; ++it)
0798 {
0799
0800
0801 bool const deflate = is_interior
0802 ? ! distance.negative()
0803 : distance.negative();
0804
0805 collection.start_new_ring(deflate);
0806 geometry::strategy::buffer::result_code const code
0807 = policy::apply(*it, collection, distance, segment_strategy,
0808 join_strategy, end_strategy, point_strategy,
0809 robust_policy, strategies);
0810
0811 collection.finish_ring(code, *it, is_interior, false);
0812 }
0813 }
0814
0815 template
0816 <
0817 typename InteriorRings,
0818 typename Collection,
0819 typename DistanceStrategy,
0820 typename SegmentStrategy,
0821 typename JoinStrategy,
0822 typename EndStrategy,
0823 typename PointStrategy,
0824 typename RobustPolicy,
0825 typename Strategies
0826 >
0827 static inline
0828 void apply_interior_rings(InteriorRings const& interior_rings,
0829 Collection& collection,
0830 DistanceStrategy const& distance,
0831 SegmentStrategy const& segment_strategy,
0832 JoinStrategy const& join_strategy,
0833 EndStrategy const& end_strategy,
0834 PointStrategy const& point_strategy,
0835 RobustPolicy const& robust_policy,
0836 Strategies const& strategies)
0837 {
0838 iterate(boost::begin(interior_rings), boost::end(interior_rings),
0839 collection, distance, segment_strategy,
0840 join_strategy, end_strategy, point_strategy,
0841 robust_policy, strategies, true);
0842 }
0843
0844 public:
0845 template
0846 <
0847 typename Collection,
0848 typename DistanceStrategy,
0849 typename SegmentStrategy,
0850 typename JoinStrategy,
0851 typename EndStrategy,
0852 typename PointStrategy,
0853 typename RobustPolicy,
0854 typename Strategies
0855 >
0856 static inline void apply(PolygonInput const& polygon,
0857 Collection& collection,
0858 DistanceStrategy const& distance,
0859 SegmentStrategy const& segment_strategy,
0860 JoinStrategy const& join_strategy,
0861 EndStrategy const& end_strategy,
0862 PointStrategy const& point_strategy,
0863 RobustPolicy const& robust_policy,
0864 Strategies const& strategies)
0865 {
0866 {
0867 collection.start_new_ring(distance.negative());
0868
0869 geometry::strategy::buffer::result_code const code
0870 = policy::apply(exterior_ring(polygon), collection,
0871 distance, segment_strategy,
0872 join_strategy, end_strategy, point_strategy,
0873 robust_policy, strategies);
0874
0875 collection.finish_ring(code, exterior_ring(polygon), false,
0876 geometry::num_interior_rings(polygon) > 0u);
0877 }
0878
0879 apply_interior_rings(interior_rings(polygon),
0880 collection, distance, segment_strategy,
0881 join_strategy, end_strategy, point_strategy,
0882 robust_policy, strategies);
0883 }
0884 };
0885
0886
0887 template
0888 <
0889 typename Multi,
0890 typename PolygonOutput
0891 >
0892 struct buffer_inserter<multi_tag, Multi, PolygonOutput>
0893 : public detail::buffer::buffer_multi
0894 <
0895 Multi,
0896 PolygonOutput,
0897 dispatch::buffer_inserter
0898 <
0899 typename single_tag_of
0900 <
0901 typename tag<Multi>::type
0902 >::type,
0903 typename boost::range_value<Multi const>::type,
0904 typename geometry::ring_type<PolygonOutput>::type
0905 >
0906 >
0907 {};
0908
0909
0910 }
0911 #endif
0912
0913 #ifndef DOXYGEN_NO_DETAIL
0914 namespace detail { namespace buffer
0915 {
0916
0917 template
0918 <
0919 typename GeometryOutput,
0920 typename GeometryInput,
0921 typename OutputIterator,
0922 typename DistanceStrategy,
0923 typename SegmentStrategy,
0924 typename JoinStrategy,
0925 typename EndStrategy,
0926 typename PointStrategy,
0927 typename Strategies,
0928 typename RobustPolicy,
0929 typename VisitPiecesPolicy
0930 >
0931 inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator out,
0932 DistanceStrategy const& distance_strategy,
0933 SegmentStrategy const& segment_strategy,
0934 JoinStrategy const& join_strategy,
0935 EndStrategy const& end_strategy,
0936 PointStrategy const& point_strategy,
0937 Strategies const& strategies,
0938 RobustPolicy const& robust_policy,
0939 VisitPiecesPolicy& visit_pieces_policy
0940 )
0941 {
0942 boost::ignore_unused(visit_pieces_policy);
0943
0944 using collection_type = detail::buffer::buffered_piece_collection
0945 <
0946 typename geometry::ring_type<GeometryOutput>::type,
0947 Strategies,
0948 DistanceStrategy,
0949 RobustPolicy
0950 >;
0951 collection_type collection(strategies, distance_strategy, robust_policy);
0952 collection_type const& const_collection = collection;
0953
0954 static constexpr bool areal = util::is_areal<GeometryInput>::value;
0955
0956 dispatch::buffer_inserter
0957 <
0958 typename tag_cast
0959 <
0960 typename tag<GeometryInput>::type,
0961 multi_tag
0962 >::type,
0963 GeometryInput,
0964 GeometryOutput
0965 >::apply(geometry_input, collection,
0966 distance_strategy, segment_strategy, join_strategy,
0967 end_strategy, point_strategy,
0968 robust_policy, strategies);
0969
0970 collection.get_turns();
0971 if BOOST_GEOMETRY_CONSTEXPR (areal)
0972 {
0973 collection.check_turn_in_original();
0974 }
0975 collection.handle_colocations();
0976 collection.check_turn_in_pieces();
0977 collection.make_traversable_consistent_per_cluster();
0978
0979
0980
0981
0982
0983 visit_pieces_policy.apply(const_collection, 0);
0984
0985 collection.discard_rings();
0986 collection.block_turns();
0987 collection.enrich();
0988
0989
0990 visit_pieces_policy.apply(const_collection, 1);
0991
0992 if BOOST_GEOMETRY_CONSTEXPR (areal)
0993 {
0994 collection.deflate_check_turns();
0995 }
0996
0997 collection.traverse();
0998
0999
1000
1001
1002
1003 bool reverse = distance_strategy.negative() && areal;
1004 if BOOST_GEOMETRY_CONSTEXPR (geometry::point_order<GeometryOutput>::value == counterclockwise)
1005 {
1006 reverse = ! reverse;
1007 }
1008 if (reverse)
1009 {
1010 collection.reverse();
1011 }
1012
1013 if BOOST_GEOMETRY_CONSTEXPR (areal)
1014 {
1015 if (distance_strategy.negative())
1016 {
1017 collection.discard_nonintersecting_deflated_rings();
1018 }
1019 }
1020
1021 collection.template assign<GeometryOutput>(out);
1022
1023
1024
1025 visit_pieces_policy.apply(const_collection, 2);
1026 }
1027
1028 template
1029 <
1030 typename GeometryOutput,
1031 typename GeometryInput,
1032 typename OutputIterator,
1033 typename DistanceStrategy,
1034 typename SegmentStrategy,
1035 typename JoinStrategy,
1036 typename EndStrategy,
1037 typename PointStrategy,
1038 typename Strategies,
1039 typename RobustPolicy
1040 >
1041 inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator out,
1042 DistanceStrategy const& distance_strategy,
1043 SegmentStrategy const& segment_strategy,
1044 JoinStrategy const& join_strategy,
1045 EndStrategy const& end_strategy,
1046 PointStrategy const& point_strategy,
1047 Strategies const& strategies,
1048 RobustPolicy const& robust_policy)
1049 {
1050 detail::buffer::visit_pieces_default_policy visitor;
1051 buffer_inserter<GeometryOutput>(geometry_input, out,
1052 distance_strategy, segment_strategy, join_strategy,
1053 end_strategy, point_strategy,
1054 strategies, robust_policy, visitor);
1055 }
1056 #endif
1057
1058 }}
1059
1060 }}
1061
1062 #endif