Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:35:09

0001 // Boost.Geometry (aka GGL, Generic Geometry Library)
0002 
0003 // Copyright (c) 2019-2021 Barend Gehrels, Amsterdam, the Netherlands.
0004 
0005 // This file was modified by Oracle on 2022.
0006 // Modifications copyright (c) 2022 Oracle and/or its affiliates.
0007 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
0008 
0009 // Use, modification and distribution is subject to the Boost Software License,
0010 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0011 // http://www.boost.org/LICENSE_1_0.txt)
0012 
0013 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_DISTANCE_MEASURE_HPP
0014 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_DISTANCE_MEASURE_HPP
0015 
0016 #include <boost/geometry/core/access.hpp>
0017 #include <boost/geometry/core/coordinate_system.hpp>
0018 #include <boost/geometry/core/coordinate_type.hpp>
0019 #include <boost/geometry/arithmetic/infinite_line_functions.hpp>
0020 #include <boost/geometry/algorithms/detail/make/make.hpp>
0021 #include <boost/geometry/algorithms/not_implemented.hpp>
0022 #include <boost/geometry/util/select_coordinate_type.hpp>
0023 
0024 #include <cmath>
0025 
0026 namespace boost { namespace geometry
0027 {
0028 
0029 #ifndef DOXYGEN_NO_DETAIL
0030 namespace detail
0031 {
0032 
0033 template <typename T>
0034 struct distance_measure
0035 {
0036     T measure;
0037 
0038     distance_measure()
0039         : measure(T())
0040     {}
0041 
0042     // Returns true if the distance measure is absolutely zero
0043     bool is_zero() const
0044     {
0045       return ! is_positive() && ! is_negative();
0046     }
0047 
0048     // Returns true if the distance measure is positive. Distance measure
0049     // algorithm returns positive value if it is located on the left side.
0050     bool is_positive() const { return measure > T(0); }
0051 
0052     // Returns true if the distance measure is negative. Distance measure
0053     // algorithm returns negative value if it is located on the right side.
0054     bool is_negative() const { return measure < T(0); }
0055 };
0056 
0057 } // detail
0058 
0059 
0060 namespace detail_dispatch
0061 {
0062 
0063 // TODO: this is effectively a strategy, but for internal usage.
0064 // It might be moved to the strategies folder.
0065 
0066 template <typename CalculationType, typename CsTag>
0067 struct get_distance_measure
0068     : not_implemented<CsTag>
0069 {};
0070 
0071 template <typename CalculationType>
0072 struct get_distance_measure<CalculationType, spherical_tag>
0073 {
0074     // By default the distance measure is zero, no side difference
0075     using result_type = detail::distance_measure<CalculationType>;
0076 
0077     template <typename SegmentPoint, typename Point>
0078     static result_type apply(SegmentPoint const& , SegmentPoint const& ,
0079                              Point const& )
0080     {
0081         result_type const result;
0082         return result;
0083     }
0084 };
0085 
0086 template <typename CalculationType>
0087 struct get_distance_measure<CalculationType, geographic_tag>
0088     : get_distance_measure<CalculationType, spherical_tag>
0089 {};
0090 
0091 template <typename CalculationType>
0092 struct get_distance_measure<CalculationType, cartesian_tag>
0093 {
0094     using result_type = detail::distance_measure<CalculationType>;
0095 
0096     template <typename SegmentPoint, typename Point>
0097     static result_type apply(SegmentPoint const& p1, SegmentPoint const& p2,
0098                              Point const& p)
0099     {
0100         // Get the distance measure / side value
0101         // It is not a real distance and purpose is
0102         // to detect small differences in collinearity
0103         auto const line = detail::make::make_infinite_line<CalculationType>(p1, p2);
0104         result_type result;
0105         result.measure = arithmetic::side_value(line, p);
0106         return result;
0107     }
0108 };
0109 
0110 } // namespace detail_dispatch
0111 
0112 namespace detail
0113 {
0114 
0115 // Returns a (often very tiny) value to indicate its side, and distance,
0116 // 0 (absolutely 0, not even an epsilon) means collinear. Like side,
0117 // a negative means that p is to the right of p1-p2. And a positive value
0118 // means that p is to the left of p1-p2.
0119 template <typename SegmentPoint, typename Point, typename Strategies>
0120 inline auto get_distance_measure(SegmentPoint const& p1, SegmentPoint const& p2, Point const& p,
0121                                  Strategies const&)
0122 {
0123     using calc_t = typename select_coordinate_type<SegmentPoint, Point>::type;
0124 
0125     // Verify equality, without using a tolerance
0126     // (so don't use equals or equals_point_point)
0127     // because it is about very tiny differences.
0128     auto identical = [](auto const& point1, auto const& point2)
0129     {
0130         return geometry::get<0>(point1) == geometry::get<0>(point2)
0131             && geometry::get<1>(point1) == geometry::get<1>(point2);
0132     };
0133 
0134     if (identical(p1, p) || identical(p2, p))
0135     {
0136         detail::distance_measure<calc_t> const result;
0137         return result;
0138     }
0139 
0140     return detail_dispatch::get_distance_measure
0141         <
0142             calc_t,
0143             typename Strategies::cs_tag
0144         >::apply(p1, p2, p);
0145 }
0146 
0147 } // namespace detail
0148 #endif // DOXYGEN_NO_DETAIL
0149 
0150 }} // namespace boost::geometry
0151 
0152 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_DISTANCE_MEASURE_HPP