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