1 // Boost.Geometry (aka GGL, Generic Geometry Library) 2 3 // Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands. 4 5 // This file was modified by Oracle on 2018. 6 // Modifications copyright (c) 2018, Oracle and/or its affiliates. 7 8 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle 9 10 // Use, modification and distribution is subject to the Boost Software License, 11 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 12 // http://www.boost.org/LICENSE_1_0.txt) 13 14 #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_END_FLAT_HPP 15 #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_END_FLAT_HPP 16 17 #include <boost/geometry/core/coordinate_type.hpp> 18 #include <boost/geometry/strategies/buffer.hpp> 19 #include <boost/geometry/strategies/tags.hpp> 20 #include <boost/geometry/strategies/side.hpp> 21 #include <boost/geometry/util/math.hpp> 22 #include <boost/geometry/util/select_most_precise.hpp> 23 24 namespace boost { namespace geometry 25 { 26 27 28 namespace strategy { namespace buffer 29 { 30 31 32 /*! 33 \brief Let the buffer create flat ends 34 \ingroup strategies 35 \details This strategy can be used as EndStrategy for the buffer algorithm. 36 It creates a flat end for each linestring-end. It can be applied 37 for (multi)linestrings. Also it is applicable for spikes in (multi)polygons. 38 This strategy is only applicable for Cartesian coordinate systems. 39 40 \qbk{ 41 [heading Example] 42 [buffer_end_flat] 43 [heading Output] 44 [$img/strategies/buffer_end_flat.png] 45 [heading See also] 46 \* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)] 47 \* [link geometry.reference.strategies.strategy_buffer_end_round end_round] 48 } 49 */ 50 class end_flat 51 { 52 53 public : 54 55 #ifndef DOXYGEN_SHOULD_SKIP_THIS 56 //! Fills output_range with a flat end 57 template <typename Point, typename RangeOut, typename DistanceStrategy> apply(Point const & penultimate_point,Point const & perp_left_point,Point const & ultimate_point,Point const & perp_right_point,buffer_side_selector side,DistanceStrategy const & distance,RangeOut & range_out) const58 inline void apply(Point const& penultimate_point, 59 Point const& perp_left_point, 60 Point const& ultimate_point, 61 Point const& perp_right_point, 62 buffer_side_selector side, 63 DistanceStrategy const& distance, 64 RangeOut& range_out) const 65 { 66 typedef typename coordinate_type<Point>::type coordinate_type; 67 68 typedef typename geometry::select_most_precise 69 < 70 coordinate_type, 71 double 72 >::type promoted_type; 73 74 promoted_type const dist_left = distance.apply(penultimate_point, ultimate_point, buffer_side_left); 75 promoted_type const dist_right = distance.apply(penultimate_point, ultimate_point, buffer_side_right); 76 77 bool reversed = (side == buffer_side_left && dist_right < 0 && -dist_right > dist_left) 78 || (side == buffer_side_right && dist_left < 0 && -dist_left > dist_right) 79 ; 80 if (reversed) 81 { 82 range_out.push_back(perp_right_point); 83 range_out.push_back(perp_left_point); 84 } 85 else 86 { 87 range_out.push_back(perp_left_point); 88 range_out.push_back(perp_right_point); 89 } 90 // Don't add the ultimate_point (endpoint of the linestring). 91 // The buffer might be generated completely at one side. 92 // In other cases it does no harm but is further useless 93 } 94 95 template <typename NumericType> max_distance(NumericType const & distance)96 static inline NumericType max_distance(NumericType const& distance) 97 { 98 return distance; 99 } 100 101 //! Returns the piece_type (flat end) get_piece_type()102 static inline piece_type get_piece_type() 103 { 104 return buffered_flat_end; 105 } 106 #endif // DOXYGEN_SHOULD_SKIP_THIS 107 }; 108 109 110 }} // namespace strategy::buffer 111 112 }} // namespace boost::geometry 113 114 #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_END_FLAT_HPP 115