// Boost.Geometry // Copyright (c) 2020, Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html #ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_PRECISE_AREA_HPP #define BOOST_GEOMETRY_STRATEGY_CARTESIAN_PRECISE_AREA_HPP #include //#include #include #include #include #include #include #include namespace boost { namespace geometry { namespace strategy { namespace area { /*! \brief Cartesian area calculation \ingroup strategies \details Calculates cartesian area using the trapezoidal rule and precise summation (useful to increase precision with floating point arithmetic) \tparam CalculationType \tparam_calculation \qbk{ [heading See also] [link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)] } */ template < typename CalculationType = void > class precise_cartesian { public : template struct result_type : strategy::area::detail::result_type < Geometry, CalculationType > {}; template class state { friend class precise_cartesian; typedef typename result_type::type return_type; public: inline state() : sum1(0) , sum2(0) { // Strategy supports only 2D areas assert_dimension(); } private: inline return_type area() const { return_type const two = 2; return (sum1 + sum2) / two; } return_type sum1; return_type sum2; }; template static inline void apply(PointOfSegment const& p1, PointOfSegment const& p2, state& st) { typedef typename state::return_type return_type; auto const det = (return_type(get<0>(p1)) + return_type(get<0>(p2))) * (return_type(get<1>(p1)) - return_type(get<1>(p2))); auto const res = boost::geometry::detail::precise_math::two_sum(st.sum1, det); st.sum1 = res[0]; st.sum2 += res[1]; } template static inline auto result(state& st) { return st.area(); } }; }} // namespace strategy::area }} // namespace boost::geometry #endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_PRECISE_AREA_HPP