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
28namespace boost { namespace geometry
29{
30
31#ifndef DOXYGEN_NO_DETAIL
32namespace detail
33{
34
35
36template <typename Point>
37struct param
38{
39 typedef typename boost::call_traits
40 <
41 typename coordinate_type<Point>::type
42 >::param_type type;
43};
44
45
46template <typename Value, template <typename> class Function>
47struct 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
70template <typename PointSrc, template <typename> class Function>
71struct 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
95template <typename Value>
96struct 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
111template <typename PointSrc>
112struct 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 */
139template <typename Point>
140inline void add_value(Point& p, typename detail::param<Point>::type value)
141{
142 BOOST_CONCEPT_ASSERT( (concept::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 */
162template <typename Point1, typename Point2>
163inline void add_point(Point1& p1, Point2 const& p2)
164{
165 BOOST_CONCEPT_ASSERT( (concept::Point<Point1>) );
166 BOOST_CONCEPT_ASSERT( (concept::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 */
179template <typename Point>
180inline void subtract_value(Point& p, typename detail::param<Point>::type value)
181{
182 BOOST_CONCEPT_ASSERT( (concept::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 */
202template <typename Point1, typename Point2>
203inline void subtract_point(Point1& p1, Point2 const& p2)
204{
205 BOOST_CONCEPT_ASSERT( (concept::Point<Point1>) );
206 BOOST_CONCEPT_ASSERT( (concept::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 */
219template <typename Point>
220inline void multiply_value(Point& p, typename detail::param<Point>::type value)
221{
222 BOOST_CONCEPT_ASSERT( (concept::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 */
243template <typename Point1, typename Point2>
244inline void multiply_point(Point1& p1, Point2 const& p2)
245{
246 BOOST_CONCEPT_ASSERT( (concept::Point<Point1>) );
247 BOOST_CONCEPT_ASSERT( (concept::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 */
260template <typename Point>
261inline void divide_value(Point& p, typename detail::param<Point>::type value)
262{
263 BOOST_CONCEPT_ASSERT( (concept::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 */
283template <typename Point1, typename Point2>
284inline void divide_point(Point1& p1, Point2 const& p2)
285{
286 BOOST_CONCEPT_ASSERT( (concept::Point<Point1>) );
287 BOOST_CONCEPT_ASSERT( (concept::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 */
300template <typename Point>
301inline void assign_value(Point& p, typename detail::param<Point>::type value)
302{
303 BOOST_CONCEPT_ASSERT( (concept::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 */
322template <typename Point1, typename Point2>
323inline void assign_point(Point1& p1, Point2 const& p2)
324{
325 BOOST_CONCEPT_ASSERT( (concept::Point<Point1>) );
326 BOOST_CONCEPT_ASSERT( (concept::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
336

source code of boost/boost/geometry/arithmetic/arithmetic.hpp