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