Chris@16
|
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
|
Chris@16
|
2
|
Chris@16
|
3 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
Chris@16
|
4 // Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
Chris@16
|
5
|
Chris@16
|
6 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
Chris@16
|
7 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
Chris@16
|
8
|
Chris@16
|
9 // Use, modification and distribution is subject to the Boost Software License,
|
Chris@16
|
10 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
11 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
12
|
Chris@16
|
13 #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_WEIGHTED_LENGTH_HPP
|
Chris@16
|
14 #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_WEIGHTED_LENGTH_HPP
|
Chris@16
|
15
|
Chris@101
|
16 #include <boost/geometry/algorithms/detail/distance/interface.hpp>
|
Chris@101
|
17 #include <boost/geometry/algorithms/detail/distance/point_to_geometry.hpp>
|
Chris@16
|
18 #include <boost/geometry/arithmetic/arithmetic.hpp>
|
Chris@16
|
19 #include <boost/geometry/util/select_most_precise.hpp>
|
Chris@16
|
20 #include <boost/geometry/strategies/centroid.hpp>
|
Chris@16
|
21 #include <boost/geometry/strategies/default_distance_result.hpp>
|
Chris@16
|
22
|
Chris@16
|
23 // Helper geometry
|
Chris@16
|
24 #include <boost/geometry/geometries/point.hpp>
|
Chris@16
|
25
|
Chris@16
|
26
|
Chris@16
|
27 namespace boost { namespace geometry
|
Chris@16
|
28 {
|
Chris@16
|
29
|
Chris@16
|
30 namespace strategy { namespace centroid
|
Chris@16
|
31 {
|
Chris@16
|
32
|
Chris@16
|
33 namespace detail
|
Chris@16
|
34 {
|
Chris@16
|
35
|
Chris@16
|
36 template <typename Type, std::size_t DimensionCount>
|
Chris@16
|
37 struct weighted_length_sums
|
Chris@16
|
38 {
|
Chris@16
|
39 typedef typename geometry::model::point
|
Chris@16
|
40 <
|
Chris@16
|
41 Type, DimensionCount,
|
Chris@16
|
42 cs::cartesian
|
Chris@16
|
43 > work_point;
|
Chris@16
|
44
|
Chris@16
|
45 Type length;
|
Chris@16
|
46 work_point average_sum;
|
Chris@16
|
47
|
Chris@16
|
48 inline weighted_length_sums()
|
Chris@16
|
49 : length(Type())
|
Chris@16
|
50 {
|
Chris@16
|
51 geometry::assign_zero(average_sum);
|
Chris@16
|
52 }
|
Chris@16
|
53 };
|
Chris@16
|
54 }
|
Chris@16
|
55
|
Chris@16
|
56 template
|
Chris@16
|
57 <
|
Chris@16
|
58 typename Point,
|
Chris@16
|
59 typename PointOfSegment = Point
|
Chris@16
|
60 >
|
Chris@16
|
61 class weighted_length
|
Chris@16
|
62 {
|
Chris@16
|
63 private :
|
Chris@16
|
64 typedef typename select_most_precise
|
Chris@16
|
65 <
|
Chris@16
|
66 typename default_distance_result<Point>::type,
|
Chris@16
|
67 typename default_distance_result<PointOfSegment>::type
|
Chris@16
|
68 >::type distance_type;
|
Chris@16
|
69
|
Chris@16
|
70 public :
|
Chris@16
|
71 typedef detail::weighted_length_sums
|
Chris@16
|
72 <
|
Chris@16
|
73 distance_type,
|
Chris@16
|
74 geometry::dimension<Point>::type::value
|
Chris@16
|
75 > state_type;
|
Chris@16
|
76
|
Chris@16
|
77 static inline void apply(PointOfSegment const& p1,
|
Chris@16
|
78 PointOfSegment const& p2, state_type& state)
|
Chris@16
|
79 {
|
Chris@16
|
80 distance_type const d = geometry::distance(p1, p2);
|
Chris@16
|
81 state.length += d;
|
Chris@16
|
82
|
Chris@16
|
83 typename state_type::work_point weighted_median;
|
Chris@16
|
84 geometry::assign_zero(weighted_median);
|
Chris@16
|
85 geometry::add_point(weighted_median, p1);
|
Chris@16
|
86 geometry::add_point(weighted_median, p2);
|
Chris@16
|
87 geometry::multiply_value(weighted_median, d/2);
|
Chris@16
|
88 geometry::add_point(state.average_sum, weighted_median);
|
Chris@16
|
89 }
|
Chris@16
|
90
|
Chris@16
|
91 static inline bool result(state_type const& state, Point& centroid)
|
Chris@16
|
92 {
|
Chris@16
|
93 distance_type const zero = distance_type();
|
Chris@16
|
94 if (! geometry::math::equals(state.length, zero))
|
Chris@16
|
95 {
|
Chris@16
|
96 assign_zero(centroid);
|
Chris@16
|
97 add_point(centroid, state.average_sum);
|
Chris@16
|
98 divide_value(centroid, state.length);
|
Chris@16
|
99 return true;
|
Chris@16
|
100 }
|
Chris@16
|
101
|
Chris@16
|
102 return false;
|
Chris@16
|
103 }
|
Chris@16
|
104
|
Chris@16
|
105 };
|
Chris@16
|
106
|
Chris@16
|
107 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
Chris@16
|
108
|
Chris@16
|
109 namespace services
|
Chris@16
|
110 {
|
Chris@16
|
111
|
Chris@16
|
112
|
Chris@16
|
113 // Register this strategy for linear geometries, in all dimensions
|
Chris@16
|
114
|
Chris@16
|
115 template <std::size_t N, typename Point, typename Geometry>
|
Chris@16
|
116 struct default_strategy
|
Chris@16
|
117 <
|
Chris@16
|
118 cartesian_tag,
|
Chris@16
|
119 linear_tag,
|
Chris@16
|
120 N,
|
Chris@16
|
121 Point,
|
Chris@16
|
122 Geometry
|
Chris@16
|
123 >
|
Chris@16
|
124 {
|
Chris@16
|
125 typedef weighted_length
|
Chris@16
|
126 <
|
Chris@16
|
127 Point,
|
Chris@16
|
128 typename point_type<Geometry>::type
|
Chris@16
|
129 > type;
|
Chris@16
|
130 };
|
Chris@16
|
131
|
Chris@16
|
132
|
Chris@16
|
133 } // namespace services
|
Chris@16
|
134
|
Chris@16
|
135
|
Chris@16
|
136 #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
Chris@16
|
137
|
Chris@16
|
138
|
Chris@16
|
139 }} // namespace strategy::centroid
|
Chris@16
|
140
|
Chris@16
|
141
|
Chris@16
|
142 }} // namespace boost::geometry
|
Chris@16
|
143
|
Chris@16
|
144
|
Chris@16
|
145 #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_WEIGHTED_LENGTH_HPP
|