Chris@102
|
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
|
Chris@102
|
2
|
Chris@102
|
3 // Copyright (c) 2013 Barend Gehrels, Amsterdam, the Netherlands.
|
Chris@102
|
4 // Copyright (c) 2013 Bruno Lalande, Paris, France.
|
Chris@102
|
5 // Copyright (c) 2013 Mateusz Loskot, London, UK.
|
Chris@102
|
6 // Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland.
|
Chris@102
|
7
|
Chris@102
|
8 // Use, modification and distribution is subject to the Boost Software License,
|
Chris@102
|
9 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@102
|
10 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@102
|
11
|
Chris@102
|
12 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RECALCULATE_HPP
|
Chris@102
|
13 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RECALCULATE_HPP
|
Chris@102
|
14
|
Chris@102
|
15
|
Chris@102
|
16 #include <cstddef>
|
Chris@102
|
17
|
Chris@102
|
18 #include <boost/concept/requires.hpp>
|
Chris@102
|
19 #include <boost/concept_check.hpp>
|
Chris@102
|
20 #include <boost/mpl/assert.hpp>
|
Chris@102
|
21 #include <boost/mpl/if.hpp>
|
Chris@102
|
22 #include <boost/numeric/conversion/bounds.hpp>
|
Chris@102
|
23 #include <boost/numeric/conversion/cast.hpp>
|
Chris@102
|
24 #include <boost/type_traits.hpp>
|
Chris@102
|
25
|
Chris@102
|
26 #include <boost/geometry/arithmetic/arithmetic.hpp>
|
Chris@102
|
27 #include <boost/geometry/algorithms/append.hpp>
|
Chris@102
|
28 #include <boost/geometry/algorithms/clear.hpp>
|
Chris@102
|
29 #include <boost/geometry/core/access.hpp>
|
Chris@102
|
30 #include <boost/geometry/core/interior_rings.hpp>
|
Chris@102
|
31 #include <boost/geometry/core/exterior_ring.hpp>
|
Chris@102
|
32 #include <boost/geometry/core/tags.hpp>
|
Chris@102
|
33
|
Chris@102
|
34 #include <boost/geometry/geometries/concepts/check.hpp>
|
Chris@102
|
35
|
Chris@102
|
36
|
Chris@102
|
37 namespace boost { namespace geometry
|
Chris@102
|
38 {
|
Chris@102
|
39
|
Chris@102
|
40 #ifndef DOXYGEN_NO_DETAIL
|
Chris@102
|
41 namespace detail { namespace recalculate
|
Chris@102
|
42 {
|
Chris@102
|
43
|
Chris@102
|
44 template <std::size_t Dimension>
|
Chris@102
|
45 struct recalculate_point
|
Chris@102
|
46 {
|
Chris@102
|
47 template <typename Point1, typename Point2, typename Strategy>
|
Chris@102
|
48 static inline void apply(Point1& point1, Point2 const& point2, Strategy const& strategy)
|
Chris@102
|
49 {
|
Chris@102
|
50 std::size_t const dim = Dimension - 1;
|
Chris@102
|
51 geometry::set<dim>(point1, strategy.template apply<dim>(geometry::get<dim>(point2)));
|
Chris@102
|
52 recalculate_point<dim>::apply(point1, point2, strategy);
|
Chris@102
|
53 }
|
Chris@102
|
54 };
|
Chris@102
|
55
|
Chris@102
|
56 template <>
|
Chris@102
|
57 struct recalculate_point<0>
|
Chris@102
|
58 {
|
Chris@102
|
59 template <typename Point1, typename Point2, typename Strategy>
|
Chris@102
|
60 static inline void apply(Point1&, Point2 const&, Strategy const&)
|
Chris@102
|
61 {
|
Chris@102
|
62 }
|
Chris@102
|
63 };
|
Chris@102
|
64
|
Chris@102
|
65
|
Chris@102
|
66 template <std::size_t Dimension>
|
Chris@102
|
67 struct recalculate_indexed
|
Chris@102
|
68 {
|
Chris@102
|
69 template <typename Geometry1, typename Geometry2, typename Strategy>
|
Chris@102
|
70 static inline void apply(Geometry1& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
|
Chris@102
|
71 {
|
Chris@102
|
72 // Do it for both indices in one dimension
|
Chris@102
|
73 static std::size_t const dim = Dimension - 1;
|
Chris@102
|
74 geometry::set<0, dim>(geometry1, strategy.template apply<dim>(geometry::get<0, dim>(geometry2)));
|
Chris@102
|
75 geometry::set<1, dim>(geometry1, strategy.template apply<dim>(geometry::get<1, dim>(geometry2)));
|
Chris@102
|
76 recalculate_indexed<dim>::apply(geometry1, geometry2, strategy);
|
Chris@102
|
77 }
|
Chris@102
|
78 };
|
Chris@102
|
79
|
Chris@102
|
80 template <>
|
Chris@102
|
81 struct recalculate_indexed<0>
|
Chris@102
|
82 {
|
Chris@102
|
83
|
Chris@102
|
84 template <typename Geometry1, typename Geometry2, typename Strategy>
|
Chris@102
|
85 static inline void apply(Geometry1& , Geometry2 const& , Strategy const& )
|
Chris@102
|
86 {
|
Chris@102
|
87 }
|
Chris@102
|
88 };
|
Chris@102
|
89
|
Chris@102
|
90 struct range_to_range
|
Chris@102
|
91 {
|
Chris@102
|
92 template
|
Chris@102
|
93 <
|
Chris@102
|
94 typename Range1,
|
Chris@102
|
95 typename Range2,
|
Chris@102
|
96 typename Strategy
|
Chris@102
|
97 >
|
Chris@102
|
98 static inline void apply(Range1& destination, Range2 const& source,
|
Chris@102
|
99 Strategy const& strategy)
|
Chris@102
|
100 {
|
Chris@102
|
101 typedef typename geometry::point_type<Range2>::type point_type;
|
Chris@102
|
102 typedef recalculate_point<geometry::dimension<point_type>::value> per_point;
|
Chris@102
|
103 geometry::clear(destination);
|
Chris@102
|
104
|
Chris@102
|
105 for (typename boost::range_iterator<Range2 const>::type it
|
Chris@102
|
106 = boost::begin(source);
|
Chris@102
|
107 it != boost::end(source);
|
Chris@102
|
108 ++it)
|
Chris@102
|
109 {
|
Chris@102
|
110 point_type p;
|
Chris@102
|
111 per_point::apply(p, *it, strategy);
|
Chris@102
|
112 geometry::append(destination, p);
|
Chris@102
|
113 }
|
Chris@102
|
114 }
|
Chris@102
|
115 };
|
Chris@102
|
116
|
Chris@102
|
117 struct polygon_to_polygon
|
Chris@102
|
118 {
|
Chris@102
|
119 private:
|
Chris@102
|
120 template
|
Chris@102
|
121 <
|
Chris@102
|
122 typename IteratorIn,
|
Chris@102
|
123 typename IteratorOut,
|
Chris@102
|
124 typename Strategy
|
Chris@102
|
125 >
|
Chris@102
|
126 static inline void iterate(IteratorIn begin, IteratorIn end,
|
Chris@102
|
127 IteratorOut it_out,
|
Chris@102
|
128 Strategy const& strategy)
|
Chris@102
|
129 {
|
Chris@102
|
130 for (IteratorIn it_in = begin; it_in != end; ++it_in, ++it_out)
|
Chris@102
|
131 {
|
Chris@102
|
132 range_to_range::apply(*it_out, *it_in, strategy);
|
Chris@102
|
133 }
|
Chris@102
|
134 }
|
Chris@102
|
135
|
Chris@102
|
136 template
|
Chris@102
|
137 <
|
Chris@102
|
138 typename InteriorRingsOut,
|
Chris@102
|
139 typename InteriorRingsIn,
|
Chris@102
|
140 typename Strategy
|
Chris@102
|
141 >
|
Chris@102
|
142 static inline void apply_interior_rings(
|
Chris@102
|
143 InteriorRingsOut& interior_rings_out,
|
Chris@102
|
144 InteriorRingsIn const& interior_rings_in,
|
Chris@102
|
145 Strategy const& strategy)
|
Chris@102
|
146 {
|
Chris@102
|
147 traits::resize<InteriorRingsOut>::apply(interior_rings_out,
|
Chris@102
|
148 boost::size(interior_rings_in));
|
Chris@102
|
149
|
Chris@102
|
150 iterate(
|
Chris@102
|
151 boost::begin(interior_rings_in), boost::end(interior_rings_in),
|
Chris@102
|
152 boost::begin(interior_rings_out),
|
Chris@102
|
153 strategy);
|
Chris@102
|
154 }
|
Chris@102
|
155
|
Chris@102
|
156 public:
|
Chris@102
|
157 template
|
Chris@102
|
158 <
|
Chris@102
|
159 typename Polygon1,
|
Chris@102
|
160 typename Polygon2,
|
Chris@102
|
161 typename Strategy
|
Chris@102
|
162 >
|
Chris@102
|
163 static inline void apply(Polygon1& destination, Polygon2 const& source,
|
Chris@102
|
164 Strategy const& strategy)
|
Chris@102
|
165 {
|
Chris@102
|
166 range_to_range::apply(geometry::exterior_ring(destination),
|
Chris@102
|
167 geometry::exterior_ring(source), strategy);
|
Chris@102
|
168
|
Chris@102
|
169 apply_interior_rings(geometry::interior_rings(destination),
|
Chris@102
|
170 geometry::interior_rings(source), strategy);
|
Chris@102
|
171 }
|
Chris@102
|
172 };
|
Chris@102
|
173
|
Chris@102
|
174 }} // namespace detail::recalculate
|
Chris@102
|
175 #endif // DOXYGEN_NO_DETAIL
|
Chris@102
|
176
|
Chris@102
|
177 #ifndef DOXYGEN_NO_DISPATCH
|
Chris@102
|
178 namespace dispatch
|
Chris@102
|
179 {
|
Chris@102
|
180
|
Chris@102
|
181 template
|
Chris@102
|
182 <
|
Chris@102
|
183 typename Geometry1,
|
Chris@102
|
184 typename Geometry2,
|
Chris@102
|
185 typename Tag1 = typename geometry::tag<Geometry1>::type,
|
Chris@102
|
186 typename Tag2 = typename geometry::tag<Geometry2>::type
|
Chris@102
|
187 >
|
Chris@102
|
188 struct recalculate : not_implemented<Tag1, Tag2>
|
Chris@102
|
189 {};
|
Chris@102
|
190
|
Chris@102
|
191 template <typename Point1, typename Point2>
|
Chris@102
|
192 struct recalculate<Point1, Point2, point_tag, point_tag>
|
Chris@102
|
193 : detail::recalculate::recalculate_point<geometry::dimension<Point1>::value>
|
Chris@102
|
194 {};
|
Chris@102
|
195
|
Chris@102
|
196 template <typename Box1, typename Box2>
|
Chris@102
|
197 struct recalculate<Box1, Box2, box_tag, box_tag>
|
Chris@102
|
198 : detail::recalculate::recalculate_indexed<geometry::dimension<Box1>::value>
|
Chris@102
|
199 {};
|
Chris@102
|
200
|
Chris@102
|
201 template <typename Segment1, typename Segment2>
|
Chris@102
|
202 struct recalculate<Segment1, Segment2, segment_tag, segment_tag>
|
Chris@102
|
203 : detail::recalculate::recalculate_indexed<geometry::dimension<Segment1>::value>
|
Chris@102
|
204 {};
|
Chris@102
|
205
|
Chris@102
|
206 template <typename Polygon1, typename Polygon2>
|
Chris@102
|
207 struct recalculate<Polygon1, Polygon2, polygon_tag, polygon_tag>
|
Chris@102
|
208 : detail::recalculate::polygon_to_polygon
|
Chris@102
|
209 {};
|
Chris@102
|
210
|
Chris@102
|
211 } // namespace dispatch
|
Chris@102
|
212 #endif // DOXYGEN_NO_DISPATCH
|
Chris@102
|
213
|
Chris@102
|
214
|
Chris@102
|
215
|
Chris@102
|
216 template <typename Geometry1, typename Geometry2, typename Strategy>
|
Chris@102
|
217 inline void recalculate(Geometry1& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
|
Chris@102
|
218 {
|
Chris@102
|
219 concept::check<Geometry1>();
|
Chris@102
|
220 concept::check<Geometry2 const>();
|
Chris@102
|
221
|
Chris@102
|
222 // static assert dimensions (/types) are the same
|
Chris@102
|
223
|
Chris@102
|
224 dispatch::recalculate<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
|
Chris@102
|
225 }
|
Chris@102
|
226
|
Chris@102
|
227
|
Chris@102
|
228 }} // namespace boost::geometry
|
Chris@102
|
229
|
Chris@102
|
230
|
Chris@102
|
231 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RECALCULATE_HPP
|