annotate DEPENDENCIES/generic/include/boost/geometry/strategies/cartesian/buffer_join_round.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents f46d142149f5
children
rev   line source
Chris@102 1 // Boost.Geometry (aka GGL, Generic Geometry Library)
Chris@102 2
Chris@102 3 // Copyright (c) 2012-2015 Barend Gehrels, Amsterdam, the Netherlands.
Chris@102 4
Chris@102 5 // Use, modification and distribution is subject to the Boost Software License,
Chris@102 6 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@102 7 // http://www.boost.org/LICENSE_1_0.txt)
Chris@102 8
Chris@102 9 #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_HPP
Chris@102 10 #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_HPP
Chris@102 11
Chris@102 12 #include <algorithm>
Chris@102 13
Chris@102 14 #include <boost/assert.hpp>
Chris@102 15 #include <boost/geometry/core/cs.hpp>
Chris@102 16 #include <boost/geometry/policies/compare.hpp>
Chris@102 17 #include <boost/geometry/strategies/buffer.hpp>
Chris@102 18 #include <boost/geometry/util/math.hpp>
Chris@102 19 #include <boost/geometry/util/select_most_precise.hpp>
Chris@102 20
Chris@102 21 #ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN
Chris@102 22 #include <boost/geometry/io/wkt/wkt.hpp>
Chris@102 23 #endif
Chris@102 24
Chris@102 25
Chris@102 26 namespace boost { namespace geometry
Chris@102 27 {
Chris@102 28
Chris@102 29
Chris@102 30 namespace strategy { namespace buffer
Chris@102 31 {
Chris@102 32
Chris@102 33 /*!
Chris@102 34 \brief Let the buffer create rounded corners
Chris@102 35 \ingroup strategies
Chris@102 36 \details This strategy can be used as JoinStrategy for the buffer algorithm.
Chris@102 37 It creates a rounded corners around each convex vertex. It can be applied
Chris@102 38 for (multi)linestrings and (multi)polygons.
Chris@102 39 This strategy is only applicable for Cartesian coordinate systems.
Chris@102 40
Chris@102 41 \qbk{
Chris@102 42 [heading Example]
Chris@102 43 [buffer_join_round]
Chris@102 44 [heading Output]
Chris@102 45 [$img/strategies/buffer_join_round.png]
Chris@102 46 [heading See also]
Chris@102 47 \* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]
Chris@102 48 \* [link geometry.reference.strategies.strategy_buffer_join_miter join_miter]
Chris@102 49 }
Chris@102 50 */
Chris@102 51 class join_round
Chris@102 52 {
Chris@102 53 public :
Chris@102 54
Chris@102 55 //! \brief Constructs the strategy
Chris@102 56 //! \param points_per_circle points which would be used for a full circle
Chris@102 57 explicit inline join_round(std::size_t points_per_circle = 90)
Chris@102 58 : m_points_per_circle(points_per_circle)
Chris@102 59 {}
Chris@102 60
Chris@102 61 private :
Chris@102 62 template
Chris@102 63 <
Chris@102 64 typename PromotedType,
Chris@102 65 typename Point,
Chris@102 66 typename DistanceType,
Chris@102 67 typename RangeOut
Chris@102 68 >
Chris@102 69 inline void generate_points(Point const& vertex,
Chris@102 70 Point const& perp1, Point const& perp2,
Chris@102 71 DistanceType const& buffer_distance,
Chris@102 72 RangeOut& range_out) const
Chris@102 73 {
Chris@102 74 PromotedType const dx1 = get<0>(perp1) - get<0>(vertex);
Chris@102 75 PromotedType const dy1 = get<1>(perp1) - get<1>(vertex);
Chris@102 76 PromotedType const dx2 = get<0>(perp2) - get<0>(vertex);
Chris@102 77 PromotedType const dy2 = get<1>(perp2) - get<1>(vertex);
Chris@102 78
Chris@102 79 PromotedType const two = 2.0;
Chris@102 80 PromotedType const two_pi = two * geometry::math::pi<PromotedType>();
Chris@102 81
Chris@102 82 PromotedType const angle1 = atan2(dy1, dx1);
Chris@102 83 PromotedType angle2 = atan2(dy2, dx2);
Chris@102 84 while (angle2 > angle1)
Chris@102 85 {
Chris@102 86 angle2 -= two_pi;
Chris@102 87 }
Chris@102 88 PromotedType const angle_diff = angle1 - angle2;
Chris@102 89
Chris@102 90 // Divide the angle into an integer amount of steps to make it
Chris@102 91 // visually correct also for a low number of points / circle
Chris@102 92
Chris@102 93 // If a full circle is divided into 3 parts (e.g. angle is 125),
Chris@102 94 // the one point in between must still be generated
Chris@102 95 // The calculation below:
Chris@102 96 // - generates 1 point in between for an angle of 125 based on 3 points
Chris@102 97 // - generates 0 points in between for an angle of 90 based on 4 points
Chris@102 98
Chris@102 99 int const n = (std::max)(static_cast<int>(
Chris@102 100 ceil(m_points_per_circle * angle_diff / two_pi)), 1);
Chris@102 101
Chris@102 102 PromotedType const diff = angle_diff / static_cast<PromotedType>(n);
Chris@102 103 PromotedType a = angle1 - diff;
Chris@102 104
Chris@102 105 // Walk to n - 1 to avoid generating the last point
Chris@102 106 for (int i = 0; i < n - 1; i++, a -= diff)
Chris@102 107 {
Chris@102 108 Point p;
Chris@102 109 set<0>(p, get<0>(vertex) + buffer_distance * cos(a));
Chris@102 110 set<1>(p, get<1>(vertex) + buffer_distance * sin(a));
Chris@102 111 range_out.push_back(p);
Chris@102 112 }
Chris@102 113 }
Chris@102 114
Chris@102 115 public :
Chris@102 116
Chris@102 117
Chris@102 118 #ifndef DOXYGEN_SHOULD_SKIP_THIS
Chris@102 119 //! Fills output_range with a rounded shape around a vertex
Chris@102 120 template <typename Point, typename DistanceType, typename RangeOut>
Chris@102 121 inline bool apply(Point const& ip, Point const& vertex,
Chris@102 122 Point const& perp1, Point const& perp2,
Chris@102 123 DistanceType const& buffer_distance,
Chris@102 124 RangeOut& range_out) const
Chris@102 125 {
Chris@102 126 typedef typename coordinate_type<Point>::type coordinate_type;
Chris@102 127 typedef typename boost::range_value<RangeOut>::type output_point_type;
Chris@102 128
Chris@102 129 typedef typename geometry::select_most_precise
Chris@102 130 <
Chris@102 131 typename geometry::select_most_precise
Chris@102 132 <
Chris@102 133 coordinate_type,
Chris@102 134 typename geometry::coordinate_type<output_point_type>::type
Chris@102 135 >::type,
Chris@102 136 double
Chris@102 137 >::type promoted_type;
Chris@102 138
Chris@102 139 geometry::equal_to<Point> equals;
Chris@102 140 if (equals(perp1, perp2))
Chris@102 141 {
Chris@102 142 #ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN
Chris@102 143 std::cout << "Corner for equal points " << geometry::wkt(ip) << " " << geometry::wkt(perp1) << std::endl;
Chris@102 144 #endif
Chris@102 145 return false;
Chris@102 146 }
Chris@102 147
Chris@102 148 // Generate 'vectors'
Chris@102 149 coordinate_type vix = (get<0>(ip) - get<0>(vertex));
Chris@102 150 coordinate_type viy = (get<1>(ip) - get<1>(vertex));
Chris@102 151
Chris@102 152 promoted_type length_i = geometry::math::sqrt(vix * vix + viy * viy);
Chris@102 153 DistanceType const bd = geometry::math::abs(buffer_distance);
Chris@102 154 promoted_type prop = bd / length_i;
Chris@102 155
Chris@102 156 Point bp;
Chris@102 157 set<0>(bp, get<0>(vertex) + vix * prop);
Chris@102 158 set<1>(bp, get<1>(vertex) + viy * prop);
Chris@102 159
Chris@102 160 range_out.push_back(perp1);
Chris@102 161 generate_points<promoted_type>(vertex, perp1, perp2, bd, range_out);
Chris@102 162 range_out.push_back(perp2);
Chris@102 163 return true;
Chris@102 164 }
Chris@102 165
Chris@102 166 template <typename NumericType>
Chris@102 167 static inline NumericType max_distance(NumericType const& distance)
Chris@102 168 {
Chris@102 169 return distance;
Chris@102 170 }
Chris@102 171
Chris@102 172 #endif // DOXYGEN_SHOULD_SKIP_THIS
Chris@102 173
Chris@102 174 private :
Chris@102 175 std::size_t m_points_per_circle;
Chris@102 176 };
Chris@102 177
Chris@102 178
Chris@102 179 }} // namespace strategy::buffer
Chris@102 180
Chris@102 181 }} // namespace boost::geometry
Chris@102 182
Chris@102 183 #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_HPP