]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Boost.Geometry (aka GGL, Generic Geometry Library) |
2 | ||
3 | // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. | |
4 | // Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands. | |
5 | // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. | |
6 | ||
7 | // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library | |
8 | // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. | |
9 | ||
10 | // Use, modification and distribution is subject to the Boost Software License, | |
11 | // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
12 | // http://www.boost.org/LICENSE_1_0.txt) | |
13 | ||
14 | #ifndef BOOST_GEOMETRY_ARITHMETIC_ARITHMETIC_HPP | |
15 | #define BOOST_GEOMETRY_ARITHMETIC_ARITHMETIC_HPP | |
16 | ||
17 | #include <functional> | |
18 | ||
19 | #include <boost/call_traits.hpp> | |
20 | #include <boost/concept/requires.hpp> | |
21 | ||
22 | #include <boost/geometry/core/coordinate_type.hpp> | |
23 | #include <boost/geometry/geometries/concepts/point_concept.hpp> | |
24 | #include <boost/geometry/util/for_each_coordinate.hpp> | |
25 | #include <boost/geometry/util/select_most_precise.hpp> | |
26 | ||
27 | ||
28 | namespace boost { namespace geometry | |
29 | { | |
30 | ||
31 | #ifndef DOXYGEN_NO_DETAIL | |
32 | namespace detail | |
33 | { | |
34 | ||
35 | ||
36 | template <typename Point> | |
37 | struct param | |
38 | { | |
39 | typedef typename boost::call_traits | |
40 | < | |
41 | typename coordinate_type<Point>::type | |
42 | >::param_type type; | |
43 | }; | |
44 | ||
45 | ||
46 | template <typename Value, template <typename> class Function> | |
47 | struct value_operation | |
48 | { | |
49 | Value m_value; | |
50 | ||
51 | inline value_operation(Value const &value) | |
52 | : m_value(value) | |
53 | {} | |
54 | ||
55 | template <typename PointDst, std::size_t Index> | |
56 | inline void apply(PointDst& point_dst) const | |
57 | { | |
58 | set<Index>(point_dst, | |
59 | Function | |
60 | < | |
61 | typename geometry::select_most_precise | |
62 | < | |
63 | Value, | |
64 | typename geometry::coordinate_type<PointDst>::type | |
65 | >::type | |
66 | >()(get<Index>(point_dst), m_value)); | |
67 | } | |
68 | }; | |
69 | ||
70 | template <typename PointSrc, template <typename> class Function> | |
71 | struct point_operation | |
72 | { | |
73 | PointSrc const& m_point_src; | |
74 | ||
75 | inline point_operation(PointSrc const& point) | |
76 | : m_point_src(point) | |
77 | {} | |
78 | ||
79 | template <typename PointDst, std::size_t Index> | |
80 | inline void apply(PointDst& point_dst) const | |
81 | { | |
82 | set<Index>(point_dst, | |
83 | Function | |
84 | < | |
85 | typename geometry::select_most_precise | |
86 | < | |
87 | typename geometry::coordinate_type<PointSrc>::type, | |
88 | typename geometry::coordinate_type<PointDst>::type | |
89 | >::type | |
90 | >()(get<Index>(point_dst), get<Index>(m_point_src))); | |
91 | } | |
92 | }; | |
93 | ||
94 | ||
95 | template <typename Value> | |
96 | struct value_assignment | |
97 | { | |
98 | Value m_value; | |
99 | ||
100 | inline value_assignment(Value const &value) | |
101 | : m_value(value) | |
102 | {} | |
103 | ||
104 | template <typename PointDst, std::size_t Index> | |
105 | inline void apply(PointDst& point_dst) const | |
106 | { | |
107 | set<Index>(point_dst, m_value); | |
108 | } | |
109 | }; | |
110 | ||
111 | template <typename PointSrc> | |
112 | struct point_assignment | |
113 | { | |
114 | PointSrc const& m_point_src; | |
115 | ||
116 | inline point_assignment(PointSrc const& point) | |
117 | : m_point_src(point) | |
118 | {} | |
119 | ||
120 | template <typename PointDst, std::size_t Index> | |
121 | inline void apply(PointDst& point_dst) const | |
122 | { | |
123 | set<Index>(point_dst, get<Index>(m_point_src)); | |
124 | } | |
125 | }; | |
126 | ||
127 | ||
128 | } // namespace detail | |
129 | #endif // DOXYGEN_NO_DETAIL | |
130 | ||
131 | /*! | |
132 | \brief Adds the same value to each coordinate of a point | |
133 | \ingroup arithmetic | |
134 | \details | |
135 | \tparam Point \tparam_point | |
136 | \param p point | |
137 | \param value value to add | |
138 | */ | |
139 | template <typename Point> | |
140 | inline void add_value(Point& p, typename detail::param<Point>::type value) | |
141 | { | |
142 | BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) ); | |
143 | ||
144 | for_each_coordinate(p, | |
145 | detail::value_operation | |
146 | < | |
147 | typename coordinate_type<Point>::type, | |
148 | std::plus | |
149 | >(value)); | |
150 | } | |
151 | ||
152 | /*! | |
153 | \brief Adds a point to another | |
154 | \ingroup arithmetic | |
155 | \details The coordinates of the second point will be added to those of the first point. | |
156 | The second point is not modified. | |
157 | \tparam Point1 \tparam_point | |
158 | \tparam Point2 \tparam_point | |
159 | \param p1 first point | |
160 | \param p2 second point | |
161 | */ | |
162 | template <typename Point1, typename Point2> | |
163 | inline void add_point(Point1& p1, Point2 const& p2) | |
164 | { | |
165 | BOOST_CONCEPT_ASSERT( (concepts::Point<Point1>) ); | |
166 | BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) ); | |
167 | ||
168 | for_each_coordinate(p1, detail::point_operation<Point2, std::plus>(p2)); | |
169 | } | |
170 | ||
171 | /*! | |
172 | \brief Subtracts the same value to each coordinate of a point | |
173 | \ingroup arithmetic | |
174 | \details | |
175 | \tparam Point \tparam_point | |
176 | \param p point | |
177 | \param value value to subtract | |
178 | */ | |
179 | template <typename Point> | |
180 | inline void subtract_value(Point& p, typename detail::param<Point>::type value) | |
181 | { | |
182 | BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) ); | |
183 | ||
184 | for_each_coordinate(p, | |
185 | detail::value_operation | |
186 | < | |
187 | typename coordinate_type<Point>::type, | |
188 | std::minus | |
189 | >(value)); | |
190 | } | |
191 | ||
192 | /*! | |
193 | \brief Subtracts a point to another | |
194 | \ingroup arithmetic | |
195 | \details The coordinates of the second point will be subtracted to those of the first point. | |
196 | The second point is not modified. | |
197 | \tparam Point1 \tparam_point | |
198 | \tparam Point2 \tparam_point | |
199 | \param p1 first point | |
200 | \param p2 second point | |
201 | */ | |
202 | template <typename Point1, typename Point2> | |
203 | inline void subtract_point(Point1& p1, Point2 const& p2) | |
204 | { | |
205 | BOOST_CONCEPT_ASSERT( (concepts::Point<Point1>) ); | |
206 | BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) ); | |
207 | ||
208 | for_each_coordinate(p1, detail::point_operation<Point2, std::minus>(p2)); | |
209 | } | |
210 | ||
211 | /*! | |
212 | \brief Multiplies each coordinate of a point by the same value | |
213 | \ingroup arithmetic | |
214 | \details | |
215 | \tparam Point \tparam_point | |
216 | \param p point | |
217 | \param value value to multiply by | |
218 | */ | |
219 | template <typename Point> | |
220 | inline void multiply_value(Point& p, typename detail::param<Point>::type value) | |
221 | { | |
222 | BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) ); | |
223 | ||
224 | for_each_coordinate(p, | |
225 | detail::value_operation | |
226 | < | |
227 | typename coordinate_type<Point>::type, | |
228 | std::multiplies | |
229 | >(value)); | |
230 | } | |
231 | ||
232 | /*! | |
233 | \brief Multiplies a point by another | |
234 | \ingroup arithmetic | |
235 | \details The coordinates of the first point will be multiplied by those of the second point. | |
236 | The second point is not modified. | |
237 | \tparam Point1 \tparam_point | |
238 | \tparam Point2 \tparam_point | |
239 | \param p1 first point | |
240 | \param p2 second point | |
241 | \note This is *not* a dot, cross or wedge product. It is a mere field-by-field multiplication. | |
242 | */ | |
243 | template <typename Point1, typename Point2> | |
244 | inline void multiply_point(Point1& p1, Point2 const& p2) | |
245 | { | |
246 | BOOST_CONCEPT_ASSERT( (concepts::Point<Point1>) ); | |
247 | BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) ); | |
248 | ||
249 | for_each_coordinate(p1, detail::point_operation<Point2, std::multiplies>(p2)); | |
250 | } | |
251 | ||
252 | /*! | |
253 | \brief Divides each coordinate of the same point by a value | |
254 | \ingroup arithmetic | |
255 | \details | |
256 | \tparam Point \tparam_point | |
257 | \param p point | |
258 | \param value value to divide by | |
259 | */ | |
260 | template <typename Point> | |
261 | inline void divide_value(Point& p, typename detail::param<Point>::type value) | |
262 | { | |
263 | BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) ); | |
264 | ||
265 | for_each_coordinate(p, | |
266 | detail::value_operation | |
267 | < | |
268 | typename coordinate_type<Point>::type, | |
269 | std::divides | |
270 | >(value)); | |
271 | } | |
272 | ||
273 | /*! | |
274 | \brief Divides a point by another | |
275 | \ingroup arithmetic | |
276 | \details The coordinates of the first point will be divided by those of the second point. | |
277 | The second point is not modified. | |
278 | \tparam Point1 \tparam_point | |
279 | \tparam Point2 \tparam_point | |
280 | \param p1 first point | |
281 | \param p2 second point | |
282 | */ | |
283 | template <typename Point1, typename Point2> | |
284 | inline void divide_point(Point1& p1, Point2 const& p2) | |
285 | { | |
286 | BOOST_CONCEPT_ASSERT( (concepts::Point<Point1>) ); | |
287 | BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) ); | |
288 | ||
289 | for_each_coordinate(p1, detail::point_operation<Point2, std::divides>(p2)); | |
290 | } | |
291 | ||
292 | /*! | |
293 | \brief Assign each coordinate of a point the same value | |
294 | \ingroup arithmetic | |
295 | \details | |
296 | \tparam Point \tparam_point | |
297 | \param p point | |
298 | \param value value to assign | |
299 | */ | |
300 | template <typename Point> | |
301 | inline void assign_value(Point& p, typename detail::param<Point>::type value) | |
302 | { | |
303 | BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) ); | |
304 | ||
305 | for_each_coordinate(p, | |
306 | detail::value_assignment | |
307 | < | |
308 | typename coordinate_type<Point>::type | |
309 | >(value)); | |
310 | } | |
311 | ||
312 | /*! | |
313 | \brief Assign a point with another | |
314 | \ingroup arithmetic | |
315 | \details The coordinates of the first point will be assigned those of the second point. | |
316 | The second point is not modified. | |
317 | \tparam Point1 \tparam_point | |
318 | \tparam Point2 \tparam_point | |
319 | \param p1 first point | |
320 | \param p2 second point | |
321 | */ | |
322 | template <typename Point1, typename Point2> | |
323 | inline void assign_point(Point1& p1, Point2 const& p2) | |
324 | { | |
325 | BOOST_CONCEPT_ASSERT( (concepts::Point<Point1>) ); | |
326 | BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) ); | |
327 | ||
328 | for_each_coordinate(p1, detail::point_assignment<Point2>(p2)); | |
329 | } | |
330 | ||
331 | ||
332 | }} // namespace boost::geometry | |
333 | ||
334 | ||
335 | #endif // BOOST_GEOMETRY_ARITHMETIC_ARITHMETIC_HPP |