File indexing completed on 2025-01-18 09:36:42
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_BY_DIVIDE_HPP
0010 #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_BY_DIVIDE_HPP
0011
0012 #include <boost/geometry/core/cs.hpp>
0013 #include <boost/geometry/policies/compare.hpp>
0014 #include <boost/geometry/strategies/buffer.hpp>
0015 #include <boost/geometry/util/math.hpp>
0016 #include <boost/geometry/util/select_most_precise.hpp>
0017
0018 #ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN
0019 #include <boost/geometry/io/wkt/wkt.hpp>
0020 #endif
0021
0022 namespace boost { namespace geometry
0023 {
0024
0025
0026 namespace strategy { namespace buffer
0027 {
0028
0029
0030 class join_round_by_divide
0031 {
0032 public :
0033
0034 inline join_round_by_divide(std::size_t max_level = 4)
0035 : m_max_level(max_level)
0036 {}
0037
0038 template
0039 <
0040 typename PromotedType,
0041 typename Point,
0042 typename DistanceType,
0043 typename RangeOut
0044 >
0045 inline void mid_points(Point const& vertex,
0046 Point const& p1, Point const& p2,
0047 DistanceType const& buffer_distance,
0048 RangeOut& range_out,
0049 std::size_t level = 1) const
0050 {
0051
0052 PromotedType const vp1_x = get<0>(p1) - get<0>(vertex);
0053 PromotedType const vp1_y = get<1>(p1) - get<1>(vertex);
0054
0055 PromotedType const vp2_x = (get<0>(p2) - get<0>(vertex));
0056 PromotedType const vp2_y = (get<1>(p2) - get<1>(vertex));
0057
0058
0059 PromotedType const two = 2;
0060 PromotedType const v_x = (vp1_x + vp2_x) / two;
0061 PromotedType const v_y = (vp1_y + vp2_y) / two;
0062
0063 PromotedType const length2 = geometry::math::sqrt(v_x * v_x + v_y * v_y);
0064
0065 PromotedType const prop = buffer_distance / length2;
0066
0067 Point mid_point;
0068 set<0>(mid_point, get<0>(vertex) + v_x * prop);
0069 set<1>(mid_point, get<1>(vertex) + v_y * prop);
0070
0071 if (level < m_max_level)
0072 {
0073 mid_points<PromotedType>(vertex, p1, mid_point, buffer_distance, range_out, level + 1);
0074 }
0075 range_out.push_back(mid_point);
0076 if (level < m_max_level)
0077 {
0078 mid_points<PromotedType>(vertex, mid_point, p2, buffer_distance, range_out, level + 1);
0079 }
0080 }
0081
0082 template <typename Point, typename DistanceType, typename RangeOut>
0083 inline bool apply(Point const& ip, Point const& vertex,
0084 Point const& perp1, Point const& perp2,
0085 DistanceType const& buffer_distance,
0086 RangeOut& range_out) const
0087 {
0088 typedef typename coordinate_type<Point>::type coordinate_type;
0089
0090 typedef typename geometry::select_most_precise
0091 <
0092 coordinate_type,
0093 double
0094 >::type promoted_type;
0095
0096 geometry::equal_to<Point> equals;
0097
0098 if (equals(perp1, perp2))
0099 {
0100 #ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN
0101 std::cout << "Corner for equal points " << geometry::wkt(ip) << " " << geometry::wkt(perp1) << std::endl;
0102 #endif
0103 return false;
0104 }
0105
0106
0107 promoted_type const vix = (get<0>(ip) - get<0>(vertex));
0108 promoted_type const viy = (get<1>(ip) - get<1>(vertex));
0109
0110 promoted_type const length_i = geometry::math::sqrt(vix * vix + viy * viy);
0111
0112 promoted_type const bd = geometry::math::abs(buffer_distance);
0113 promoted_type const prop = bd / length_i;
0114
0115 Point bp;
0116 set<0>(bp, get<0>(vertex) + vix * prop);
0117 set<1>(bp, get<1>(vertex) + viy * prop);
0118
0119 range_out.push_back(perp1);
0120
0121 if (m_max_level > 1)
0122 {
0123 mid_points<promoted_type>(vertex, perp1, bp, bd, range_out);
0124 range_out.push_back(bp);
0125 mid_points<promoted_type>(vertex, bp, perp2, bd, range_out);
0126 }
0127 else if (m_max_level == 1)
0128 {
0129 range_out.push_back(bp);
0130 }
0131
0132 range_out.push_back(perp2);
0133 return true;
0134 }
0135
0136 template <typename NumericType>
0137 static inline NumericType max_distance(NumericType const& distance)
0138 {
0139 return distance;
0140 }
0141
0142 private :
0143 std::size_t m_max_level;
0144 };
0145
0146
0147 }}
0148
0149
0150 }}
0151
0152 #endif