precise_area.hpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. // Boost.Geometry
  2. // Copyright (c) 2020, Oracle and/or its affiliates.
  3. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
  4. // Licensed under the Boost Software License version 1.0.
  5. // http://www.boost.org/users/license.html
  6. #ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_PRECISE_AREA_HPP
  7. #define BOOST_GEOMETRY_STRATEGY_CARTESIAN_PRECISE_AREA_HPP
  8. #include <boost/mpl/if.hpp>
  9. //#include <boost/geometry/arithmetic/determinant.hpp>
  10. #include <boost/geometry/core/access.hpp>
  11. #include <boost/geometry/core/coordinate_type.hpp>
  12. #include <boost/geometry/core/coordinate_dimension.hpp>
  13. #include <boost/geometry/strategy/area.hpp>
  14. #include <boost/geometry/util/select_most_precise.hpp>
  15. #include <boost/geometry/util/precise_math.hpp>
  16. namespace boost { namespace geometry
  17. {
  18. namespace strategy { namespace area
  19. {
  20. /*!
  21. \brief Cartesian area calculation
  22. \ingroup strategies
  23. \details Calculates cartesian area using the trapezoidal rule and precise
  24. summation (useful to increase precision with floating point arithmetic)
  25. \tparam CalculationType \tparam_calculation
  26. \qbk{
  27. [heading See also]
  28. [link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)]
  29. }
  30. */
  31. template
  32. <
  33. typename CalculationType = void
  34. >
  35. class precise_cartesian
  36. {
  37. public :
  38. template <typename Geometry>
  39. struct result_type
  40. : strategy::area::detail::result_type
  41. <
  42. Geometry,
  43. CalculationType
  44. >
  45. {};
  46. template <typename Geometry>
  47. class state
  48. {
  49. friend class precise_cartesian;
  50. typedef typename result_type<Geometry>::type return_type;
  51. public:
  52. inline state()
  53. : sum1(0)
  54. , sum2(0)
  55. {
  56. // Strategy supports only 2D areas
  57. assert_dimension<Geometry, 2>();
  58. }
  59. private:
  60. inline return_type area() const
  61. {
  62. return_type const two = 2;
  63. return (sum1 + sum2) / two;
  64. }
  65. return_type sum1;
  66. return_type sum2;
  67. };
  68. template <typename PointOfSegment, typename Geometry>
  69. static inline void apply(PointOfSegment const& p1,
  70. PointOfSegment const& p2,
  71. state<Geometry>& st)
  72. {
  73. typedef typename state<Geometry>::return_type return_type;
  74. auto const det = (return_type(get<0>(p1)) + return_type(get<0>(p2)))
  75. * (return_type(get<1>(p1)) - return_type(get<1>(p2)));
  76. auto const res = boost::geometry::detail::precise_math::two_sum(st.sum1, det);
  77. st.sum1 = res[0];
  78. st.sum2 += res[1];
  79. }
  80. template <typename Geometry>
  81. static inline auto result(state<Geometry>& st)
  82. {
  83. return st.area();
  84. }
  85. };
  86. }} // namespace strategy::area
  87. }} // namespace boost::geometry
  88. #endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_PRECISE_AREA_HPP