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, 2017. 8 // Modifications copyright (c) 2016-2017, 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/strategies/area.hpp> 29 #include <boost/geometry/util/select_most_precise.hpp> 30 31 32 namespace boost { namespace geometry 33 { 34 35 namespace strategy { namespace area 36 { 37 38 /*! 39 \brief Area calculation for cartesian points 40 \ingroup strategies 41 \details Calculates area using the Surveyor's formula, a well-known 42 triangulation algorithm 43 \tparam PointOfSegment \tparam_segment_point 44 \tparam CalculationType \tparam_calculation 45 46 \qbk{ 47 [heading See also] 48 [link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)] 49 } 50 51 */ 52 template 53 < 54 typename PointOfSegment, 55 typename CalculationType = void 56 > 57 class surveyor 58 { 59 public : 60 // If user specified a calculation type, use that type, 61 // whatever it is and whatever the point-type is. 62 // Else, use the pointtype, but at least double 63 typedef typename 64 boost::mpl::if_c 65 < 66 boost::is_void<CalculationType>::type::value, 67 typename select_most_precise 68 < 69 typename coordinate_type<PointOfSegment>::type, 70 double 71 >::type, 72 CalculationType 73 >::type return_type; 74 75 76 private : 77 78 class summation 79 { 80 friend class surveyor; 81 82 return_type sum; 83 public : 84 summation()85 inline summation() : sum(return_type()) 86 { 87 // Strategy supports only 2D areas 88 assert_dimension<PointOfSegment, 2>(); 89 } area() const90 inline return_type area() const 91 { 92 return_type result = sum; 93 return_type const two = 2; 94 result /= two; 95 return result; 96 } 97 }; 98 99 public : 100 typedef summation state_type; 101 typedef PointOfSegment segment_point_type; 102 apply(PointOfSegment const & p1,PointOfSegment const & p2,summation & state)103 static inline void apply(PointOfSegment const& p1, 104 PointOfSegment const& p2, 105 summation& state) 106 { 107 // Below formulas are equivalent, however the two lower ones 108 // suffer less from accuracy loss for great values of coordinates. 109 // See: https://svn.boost.org/trac/boost/ticket/11928 110 111 // SUM += x2 * y1 - x1 * y2; 112 // state.sum += detail::determinant<return_type>(p2, p1); 113 114 // SUM += (x2 - x1) * (y2 + y1) 115 //state.sum += (return_type(get<0>(p2)) - return_type(get<0>(p1))) 116 // * (return_type(get<1>(p2)) + return_type(get<1>(p1))); 117 118 // SUM += (x1 + x2) * (y1 - y2) 119 state.sum += (return_type(get<0>(p1)) + return_type(get<0>(p2))) 120 * (return_type(get<1>(p1)) - return_type(get<1>(p2))); 121 } 122 result(summation const & state)123 static inline return_type result(summation const& state) 124 { 125 return state.area(); 126 } 127 128 }; 129 130 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS 131 132 namespace services 133 { 134 template <typename Point> 135 struct default_strategy<cartesian_tag, Point> 136 { 137 typedef strategy::area::surveyor<Point> type; 138 }; 139 140 } // namespace services 141 142 #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS 143 144 145 }} // namespace strategy::area 146 147 148 149 }} // namespace boost::geometry 150 151 152 #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_SURVEYOR_HPP 153