buffer_end_flat.hpp 3.5 KB

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