File indexing completed on 2025-01-18 09:36:42
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CLOSEST_POINTS_PT_SEG_HPP
0011 #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CLOSEST_POINTS_PT_SEG_HPP
0012
0013 #include <boost/geometry/algorithms/convert.hpp>
0014
0015 #include <boost/geometry/core/coordinate_promotion.hpp>
0016
0017 #include <boost/geometry/geometries/point.hpp>
0018
0019 #include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
0020 #include <boost/geometry/strategies/closest_points/services.hpp>
0021
0022 namespace boost { namespace geometry
0023 {
0024
0025 namespace strategy { namespace closest_points
0026 {
0027
0028 #ifndef DOXYGEN_NO_DETAIL
0029 namespace detail
0030 {
0031
0032 template <typename CalculationType>
0033 struct compute_closest_point_to_segment
0034 {
0035 template <typename Point, typename PointOfSegment>
0036 static inline auto
0037 apply(Point const& p, PointOfSegment const& p1, PointOfSegment const& p2)
0038 {
0039
0040
0041 using fp_point_type = model::point
0042 <
0043 CalculationType,
0044 dimension<PointOfSegment>::value,
0045 typename coordinate_system<PointOfSegment>::type
0046 >;
0047
0048
0049 using fp_vector_type = fp_point_type;
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063 fp_vector_type v, w, projected;
0064
0065 geometry::convert(p2, v);
0066 geometry::convert(p, w);
0067 geometry::convert(p1, projected);
0068 subtract_point(v, projected);
0069 subtract_point(w, projected);
0070
0071 CalculationType const zero = CalculationType();
0072 CalculationType const c1 = dot_product(w, v);
0073 if (c1 <= zero)
0074 {
0075 fp_vector_type fp_p1;
0076 geometry::convert(p1, fp_p1);
0077 return fp_p1;
0078 }
0079 CalculationType const c2 = dot_product(v, v);
0080 if (c2 <= c1)
0081 {
0082 fp_vector_type fp_p2;
0083 geometry::convert(p2, fp_p2);
0084 return fp_p2;
0085 }
0086
0087
0088 CalculationType const b = c1 / c2;
0089
0090 multiply_value(v, b);
0091 add_point(projected, v);
0092
0093 return projected;
0094 }
0095 };
0096
0097 }
0098 #endif
0099
0100 template
0101 <
0102 typename CalculationType = void
0103 >
0104 class projected_point
0105 {
0106 public:
0107
0108
0109
0110
0111
0112
0113
0114 template <typename Point, typename PointOfSegment>
0115 struct calculation_type
0116 : promote_floating_point
0117 <
0118 typename select_most_precise
0119 <
0120 typename coordinate_type<Point>::type,
0121 typename coordinate_type<PointOfSegment>::type,
0122 CalculationType
0123 >::type
0124 >
0125 {};
0126
0127 template <typename Point, typename PointOfSegment>
0128 inline auto
0129 apply(Point const& p, PointOfSegment const& p1, PointOfSegment const& p2) const
0130 {
0131 assert_dimension_equal<Point, PointOfSegment>();
0132
0133 using calculation_type = typename calculation_type<Point, PointOfSegment>::type;
0134
0135 return detail::compute_closest_point_to_segment<calculation_type>::apply(p, p1, p2);
0136 }
0137
0138 };
0139
0140 }}
0141
0142
0143 }}
0144
0145
0146 #endif