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