annotate DEPENDENCIES/generic/include/boost/geometry/strategies/cartesian/buffer_join_miter.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +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-2014 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_MITER_HPP
Chris@102 10 #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_MITER_HPP
Chris@102 11
Chris@102 12 #include <boost/assert.hpp>
Chris@102 13 #include <boost/geometry/core/cs.hpp>
Chris@102 14 #include <boost/geometry/policies/compare.hpp>
Chris@102 15 #include <boost/geometry/util/math.hpp>
Chris@102 16 #include <boost/geometry/util/select_most_precise.hpp>
Chris@102 17
Chris@102 18 #include <boost/geometry/strategies/buffer.hpp>
Chris@102 19
Chris@102 20
Chris@102 21 namespace boost { namespace geometry
Chris@102 22 {
Chris@102 23
Chris@102 24 namespace strategy { namespace buffer
Chris@102 25 {
Chris@102 26
Chris@102 27 /*!
Chris@102 28 \brief Let the buffer create sharp corners
Chris@102 29 \ingroup strategies
Chris@102 30 \details This strategy can be used as JoinStrategy for the buffer algorithm.
Chris@102 31 It creates a sharp corners around each convex vertex. It can be applied
Chris@102 32 for (multi)linestrings and (multi)polygons.
Chris@102 33 If corners are sharp by themselves, the miters might become very long. Therefore
Chris@102 34 there is a limit (miter_limit), in terms of the used distance, which limits
Chris@102 35 their length. The miter is not changed to a bevel form (as done in some
Chris@102 36 other software), it is just adapted to the specified miter_limit but keeps
Chris@102 37 its miter form.
Chris@102 38 If the buffer distance is 5.0, and the miter limit is 2.0, generated points
Chris@102 39 will be located at a distance of at most 10.0 (2*5) units.
Chris@102 40 This strategy is only applicable for Cartesian coordinate systems.
Chris@102 41
Chris@102 42 \qbk{
Chris@102 43 [heading Example]
Chris@102 44 [buffer_join_miter]
Chris@102 45 [heading Output]
Chris@102 46 [$img/strategies/buffer_join_miter.png]
Chris@102 47 [heading See also]
Chris@102 48 \* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]
Chris@102 49 \* [link geometry.reference.strategies.strategy_buffer_join_round join_round]
Chris@102 50 }
Chris@102 51 */
Chris@102 52 class join_miter
Chris@102 53 {
Chris@102 54 public:
Chris@102 55
Chris@102 56 //! \brief Constructs the strategy
Chris@102 57 //! \param miter_limit The miter limit, to avoid excessively long miters around sharp corners
Chris@102 58 explicit inline join_miter(double miter_limit = 5.0)
Chris@102 59 : m_miter_limit(valid_limit(miter_limit))
Chris@102 60 {}
Chris@102 61
Chris@102 62 #ifndef DOXYGEN_SHOULD_SKIP_THIS
Chris@102 63 //! Fills output_range with a sharp shape around a vertex
Chris@102 64 template <typename Point, typename DistanceType, typename RangeOut>
Chris@102 65 inline bool apply(Point const& ip, Point const& vertex,
Chris@102 66 Point const& perp1, Point const& perp2,
Chris@102 67 DistanceType const& buffer_distance,
Chris@102 68 RangeOut& range_out) const
Chris@102 69 {
Chris@102 70 geometry::equal_to<Point> equals;
Chris@102 71 if (equals(ip, vertex))
Chris@102 72 {
Chris@102 73 return false;
Chris@102 74 }
Chris@102 75 if (equals(perp1, perp2))
Chris@102 76 {
Chris@102 77 return false;
Chris@102 78 }
Chris@102 79
Chris@102 80 typedef typename coordinate_type<Point>::type coordinate_type;
Chris@102 81 typedef typename geometry::select_most_precise
Chris@102 82 <
Chris@102 83 coordinate_type,
Chris@102 84 double
Chris@102 85 >::type promoted_type;
Chris@102 86
Chris@102 87 Point p = ip;
Chris@102 88
Chris@102 89 // Check the distance ip-vertex (= miter distance)
Chris@102 90 // (We calculate it manually (not using Pythagoras strategy) to reuse
Chris@102 91 // dx and dy)
Chris@102 92 coordinate_type const dx = get<0>(p) - get<0>(vertex);
Chris@102 93 coordinate_type const dy = get<1>(p) - get<1>(vertex);
Chris@102 94
Chris@102 95 promoted_type const distance = geometry::math::sqrt(dx * dx + dy * dy);
Chris@102 96
Chris@102 97 promoted_type const max_distance
Chris@102 98 = m_miter_limit * geometry::math::abs(buffer_distance);
Chris@102 99
Chris@102 100 if (distance > max_distance)
Chris@102 101 {
Chris@102 102 BOOST_ASSERT(distance != 0.0);
Chris@102 103
Chris@102 104 promoted_type const proportion = max_distance / distance;
Chris@102 105 set<0>(p, get<0>(vertex) + dx * proportion);
Chris@102 106 set<1>(p, get<1>(vertex) + dy * proportion);
Chris@102 107 }
Chris@102 108
Chris@102 109 range_out.push_back(perp1);
Chris@102 110 range_out.push_back(p);
Chris@102 111 range_out.push_back(perp2);
Chris@102 112 return true;
Chris@102 113 }
Chris@102 114
Chris@102 115 template <typename NumericType>
Chris@102 116 inline NumericType max_distance(NumericType const& distance) const
Chris@102 117 {
Chris@102 118 return distance * m_miter_limit;
Chris@102 119 }
Chris@102 120
Chris@102 121 #endif // DOXYGEN_SHOULD_SKIP_THIS
Chris@102 122
Chris@102 123 private :
Chris@102 124 double valid_limit(double miter_limit) const
Chris@102 125 {
Chris@102 126 if (miter_limit < 1.0)
Chris@102 127 {
Chris@102 128 // It should always exceed the buffer distance
Chris@102 129 miter_limit = 1.0;
Chris@102 130 }
Chris@102 131 return miter_limit;
Chris@102 132 }
Chris@102 133
Chris@102 134 double m_miter_limit;
Chris@102 135 };
Chris@102 136
Chris@102 137 }} // namespace strategy::buffer
Chris@102 138
Chris@102 139
Chris@102 140 }} // namespace boost::geometry
Chris@102 141
Chris@102 142 #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_MITER_HPP