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 
value_operationboost::geometry::detail::value_operation51     inline value_operation(Value const &value)
52         : m_value(value)
53     {}
54 
55     template <typename PointDst, std::size_t Index>
applyboost::geometry::detail::value_operation56     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 
point_operationboost::geometry::detail::point_operation75     inline point_operation(PointSrc const& point)
76         : m_point_src(point)
77     {}
78 
79     template <typename PointDst, std::size_t Index>
applyboost::geometry::detail::point_operation80     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 
value_assignmentboost::geometry::detail::value_assignment100     inline value_assignment(Value const &value)
101         : m_value(value)
102     {}
103 
104     template <typename PointDst, std::size_t Index>
applyboost::geometry::detail::value_assignment105     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 
point_assignmentboost::geometry::detail::point_assignment116     inline point_assignment(PointSrc const& point)
117         : m_point_src(point)
118     {}
119 
120     template <typename PointDst, std::size_t Index>
applyboost::geometry::detail::point_assignment121     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>
add_value(Point & p,typename detail::param<Point>::type value)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>
add_point(Point1 & p1,Point2 const & p2)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>
subtract_value(Point & p,typename detail::param<Point>::type value)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>
subtract_point(Point1 & p1,Point2 const & p2)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>
multiply_value(Point & p,typename detail::param<Point>::type value)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>
multiply_point(Point1 & p1,Point2 const & p2)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>
divide_value(Point & p,typename detail::param<Point>::type value)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>
divide_point(Point1 & p1,Point2 const & p2)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>
assign_value(Point & p,typename detail::param<Point>::type value)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>
assign_point(Point1 & p1,Point2 const & p2)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
336