]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Boost.Geometry (aka GGL, Generic Geometry Library) |
2 | ||
3 | // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. | |
4 | // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. | |
5 | // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. | |
6 | ||
7 | // This file was modified by Oracle on 2016. | |
8 | // Modifications copyright (c) 2016, Oracle and/or its affiliates. | |
9 | ||
10 | // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle | |
11 | ||
12 | // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library | |
13 | // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. | |
14 | ||
15 | // Use, modification and distribution is subject to the Boost Software License, | |
16 | // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
17 | // http://www.boost.org/LICENSE_1_0.txt) | |
18 | ||
19 | #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_SURVEYOR_HPP | |
20 | #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_SURVEYOR_HPP | |
21 | ||
22 | ||
23 | #include <boost/mpl/if.hpp> | |
24 | ||
25 | //#include <boost/geometry/arithmetic/determinant.hpp> | |
26 | #include <boost/geometry/core/coordinate_type.hpp> | |
27 | #include <boost/geometry/core/coordinate_dimension.hpp> | |
28 | #include <boost/geometry/util/select_most_precise.hpp> | |
29 | ||
30 | ||
31 | namespace boost { namespace geometry | |
32 | { | |
33 | ||
34 | namespace strategy { namespace area | |
35 | { | |
36 | ||
37 | /*! | |
38 | \brief Area calculation for cartesian points | |
39 | \ingroup strategies | |
40 | \details Calculates area using the Surveyor's formula, a well-known | |
41 | triangulation algorithm | |
42 | \tparam PointOfSegment \tparam_segment_point | |
43 | \tparam CalculationType \tparam_calculation | |
44 | ||
45 | \qbk{ | |
46 | [heading See also] | |
47 | [link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)] | |
48 | } | |
49 | ||
50 | */ | |
51 | template | |
52 | < | |
53 | typename PointOfSegment, | |
54 | typename CalculationType = void | |
55 | > | |
56 | class surveyor | |
57 | { | |
58 | public : | |
59 | // If user specified a calculation type, use that type, | |
60 | // whatever it is and whatever the point-type is. | |
61 | // Else, use the pointtype, but at least double | |
62 | typedef typename | |
63 | boost::mpl::if_c | |
64 | < | |
65 | boost::is_void<CalculationType>::type::value, | |
66 | typename select_most_precise | |
67 | < | |
68 | typename coordinate_type<PointOfSegment>::type, | |
69 | double | |
70 | >::type, | |
71 | CalculationType | |
72 | >::type return_type; | |
73 | ||
74 | ||
75 | private : | |
76 | ||
77 | class summation | |
78 | { | |
79 | friend class surveyor; | |
80 | ||
81 | return_type sum; | |
82 | public : | |
83 | ||
84 | inline summation() : sum(return_type()) | |
85 | { | |
86 | // Strategy supports only 2D areas | |
87 | assert_dimension<PointOfSegment, 2>(); | |
88 | } | |
89 | inline return_type area() const | |
90 | { | |
91 | return_type result = sum; | |
92 | return_type const two = 2; | |
93 | result /= two; | |
94 | return result; | |
95 | } | |
96 | }; | |
97 | ||
98 | public : | |
99 | typedef summation state_type; | |
100 | typedef PointOfSegment segment_point_type; | |
101 | ||
102 | static inline void apply(PointOfSegment const& p1, | |
103 | PointOfSegment const& p2, | |
104 | summation& state) | |
105 | { | |
106 | // Below formulas are equivalent, however the two lower ones | |
107 | // suffer less from accuracy loss for great values of coordinates. | |
108 | // See: https://svn.boost.org/trac/boost/ticket/11928 | |
109 | ||
110 | // SUM += x2 * y1 - x1 * y2; | |
111 | // state.sum += detail::determinant<return_type>(p2, p1); | |
112 | ||
113 | // SUM += (x2 - x1) * (y2 + y1) | |
114 | //state.sum += (return_type(get<0>(p2)) - return_type(get<0>(p1))) | |
115 | // * (return_type(get<1>(p2)) + return_type(get<1>(p1))); | |
116 | ||
117 | // SUM += (x1 + x2) * (y1 - y2) | |
118 | state.sum += (return_type(get<0>(p1)) + return_type(get<0>(p2))) | |
119 | * (return_type(get<1>(p1)) - return_type(get<1>(p2))); | |
120 | } | |
121 | ||
122 | static inline return_type result(summation const& state) | |
123 | { | |
124 | return state.area(); | |
125 | } | |
126 | ||
127 | }; | |
128 | ||
129 | #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS | |
130 | ||
131 | namespace services | |
132 | { | |
133 | template <typename Point> | |
134 | struct default_strategy<cartesian_tag, Point> | |
135 | { | |
136 | typedef strategy::area::surveyor<Point> type; | |
137 | }; | |
138 | ||
139 | } // namespace services | |
140 | ||
141 | #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS | |
142 | ||
143 | ||
144 | }} // namespace strategy::area | |
145 | ||
146 | ||
147 | ||
148 | }} // namespace boost::geometry | |
149 | ||
150 | ||
151 | #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_SURVEYOR_HPP |