1 // Boost.Geometry 2 3 // Copyright (c) 2017-2018, Oracle and/or its affiliates. 4 5 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle 6 7 // Licensed under the Boost Software License version 1.0. 8 // http://www.boost.org/users/license.html 9 10 #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DENSIFY_HPP 11 #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DENSIFY_HPP 12 13 14 #include <boost/geometry/algorithms/detail/convert_point_to_point.hpp> 15 #include <boost/geometry/algorithms/detail/signed_size_type.hpp> 16 #include <boost/geometry/arithmetic/arithmetic.hpp> 17 #include <boost/geometry/arithmetic/dot_product.hpp> 18 #include <boost/geometry/core/assert.hpp> 19 #include <boost/geometry/core/coordinate_dimension.hpp> 20 #include <boost/geometry/core/coordinate_type.hpp> 21 #include <boost/geometry/geometries/point.hpp> 22 #include <boost/geometry/strategies/densify.hpp> 23 #include <boost/geometry/util/math.hpp> 24 #include <boost/geometry/util/select_most_precise.hpp> 25 26 27 namespace boost { namespace geometry 28 { 29 30 namespace strategy { namespace densify 31 { 32 33 34 /*! 35 \brief Densification of cartesian segment. 36 \ingroup strategies 37 \tparam CalculationType \tparam_calculation 38 39 \qbk{ 40 [heading See also] 41 [link geometry.reference.algorithms.densify.densify_4_with_strategy densify (with strategy)] 42 } 43 */ 44 template 45 < 46 typename CalculationType = void 47 > 48 class cartesian 49 { 50 public: 51 template <typename Point, typename AssignPolicy, typename T> apply(Point const & p0,Point const & p1,AssignPolicy & policy,T const & length_threshold)52 static inline void apply(Point const& p0, Point const& p1, AssignPolicy & policy, T const& length_threshold) 53 { 54 typedef typename AssignPolicy::point_type out_point_t; 55 typedef typename select_most_precise 56 < 57 typename coordinate_type<Point>::type, 58 typename coordinate_type<out_point_t>::type, 59 CalculationType 60 >::type calc_t; 61 62 typedef model::point<calc_t, geometry::dimension<Point>::value, cs::cartesian> calc_point_t; 63 64 calc_point_t cp0, cp1; 65 geometry::detail::conversion::convert_point_to_point(p0, cp0); 66 geometry::detail::conversion::convert_point_to_point(p1, cp1); 67 68 // dir01 = xy1 - xy0 69 calc_point_t dir01 = cp1; 70 geometry::subtract_point(dir01, cp0); 71 calc_t const dot01 = geometry::dot_product(dir01, dir01); 72 calc_t const len = math::sqrt(dot01); 73 74 BOOST_GEOMETRY_ASSERT(length_threshold > T(0)); 75 76 signed_size_type n = signed_size_type(len / length_threshold); 77 if (n <= 0) 78 { 79 return; 80 } 81 82 // NOTE: Normalization will not work for integral coordinates 83 // normalize 84 //geometry::divide_value(dir01, len); 85 86 calc_t step = len / (n + 1); 87 88 calc_t d = step; 89 for (signed_size_type i = 0 ; i < n ; ++i, d += step) 90 { 91 // pd = xy0 + d * dir01 92 calc_point_t pd = dir01; 93 94 // without normalization 95 geometry::multiply_value(pd, calc_t(i + 1)); 96 geometry::divide_value(pd, calc_t(n + 1)); 97 // with normalization 98 //geometry::multiply_value(pd, d); 99 100 geometry::add_point(pd, cp0); 101 102 // NOTE: Only needed if types calc_point_t and out_point_t are different 103 // otherwise pd could simply be passed into policy 104 out_point_t p; 105 assert_dimension_equal<calc_point_t, out_point_t>(); 106 geometry::detail::conversion::convert_point_to_point(pd, p); 107 108 policy.apply(p); 109 } 110 } 111 }; 112 113 114 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS 115 namespace services 116 { 117 118 template <> 119 struct default_strategy<cartesian_tag> 120 { 121 typedef strategy::densify::cartesian<> type; 122 }; 123 124 125 } // namespace services 126 #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS 127 128 129 }} // namespace strategy::densify 130 131 132 }} // namespace boost::geometry 133 134 #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DENSIFY_HPP 135