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