File indexing completed on 2025-09-17 08:32:21
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 #ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_BY_TRIANGLE_HPP
0022 #define BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_BY_TRIANGLE_HPP
0023
0024
0025 #include <type_traits>
0026
0027 #include <boost/geometry/core/config.hpp>
0028 #include <boost/geometry/arithmetic/determinant.hpp>
0029
0030 #include <boost/geometry/core/access.hpp>
0031
0032 #include <boost/geometry/strategies/cartesian/point_in_point.hpp>
0033 #include <boost/geometry/strategies/compare.hpp>
0034 #include <boost/geometry/strategies/side.hpp>
0035
0036 #include <boost/geometry/util/promote_integral.hpp>
0037 #include <boost/geometry/util/select_calculation_type.hpp>
0038 #include <boost/geometry/util/select_most_precise.hpp>
0039
0040
0041 namespace boost { namespace geometry
0042 {
0043
0044 namespace strategy { namespace side
0045 {
0046
0047
0048
0049
0050
0051
0052
0053 template <typename CalculationType = void>
0054 class side_by_triangle
0055 {
0056 template <typename Policy>
0057 struct eps_policy
0058 {
0059 eps_policy() {}
0060 template <typename Type>
0061 eps_policy(Type const& a, Type const& b, Type const& c, Type const& d)
0062 : policy(a, b, c, d)
0063 {}
0064 Policy policy;
0065 };
0066
0067 struct eps_empty
0068 {
0069 eps_empty() {}
0070 template <typename Type>
0071 eps_empty(Type const&, Type const&, Type const&, Type const&) {}
0072 };
0073
0074 public :
0075 using cs_tag = cartesian_tag;
0076
0077
0078
0079
0080
0081
0082
0083
0084 template
0085 <
0086 typename CoordinateType,
0087 typename PromotedType,
0088 typename P1,
0089 typename P2,
0090 typename P,
0091 typename EpsPolicy
0092 >
0093 static inline
0094 PromotedType side_value(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & eps_policy)
0095 {
0096 CoordinateType const x = get<0>(p);
0097 CoordinateType const y = get<1>(p);
0098
0099 CoordinateType const sx1 = get<0>(p1);
0100 CoordinateType const sy1 = get<1>(p1);
0101 CoordinateType const sx2 = get<0>(p2);
0102 CoordinateType const sy2 = get<1>(p2);
0103
0104 PromotedType const dx = sx2 - sx1;
0105 PromotedType const dy = sy2 - sy1;
0106 PromotedType const dpx = x - sx1;
0107 PromotedType const dpy = y - sy1;
0108
0109 eps_policy = EpsPolicy(dx, dy, dpx, dpy);
0110
0111 return geometry::detail::determinant<PromotedType>
0112 (
0113 dx, dy,
0114 dpx, dpy
0115 );
0116
0117 }
0118
0119 template
0120 <
0121 typename CoordinateType,
0122 typename PromotedType,
0123 typename P1,
0124 typename P2,
0125 typename P
0126 >
0127 static inline
0128 PromotedType side_value(P1 const& p1, P2 const& p2, P const& p)
0129 {
0130 eps_empty dummy;
0131 return side_value<CoordinateType, PromotedType>(p1, p2, p, dummy);
0132 }
0133
0134
0135 template
0136 <
0137 typename CoordinateType,
0138 typename PromotedType,
0139 bool AreAllIntegralCoordinates
0140 >
0141 struct compute_side_value
0142 {
0143 template <typename P1, typename P2, typename P, typename EpsPolicy>
0144 static inline PromotedType apply(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & epsp)
0145 {
0146 return side_value<CoordinateType, PromotedType>(p1, p2, p, epsp);
0147 }
0148 };
0149
0150 template <typename CoordinateType, typename PromotedType>
0151 struct compute_side_value<CoordinateType, PromotedType, false>
0152 {
0153 template <typename P1, typename P2, typename P, typename EpsPolicy>
0154 static inline PromotedType apply(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & epsp)
0155 {
0156
0157
0158
0159 if (equals_point_point(p1, p2)
0160 || equals_point_point(p1, p)
0161 || equals_point_point(p2, p))
0162 {
0163 return PromotedType(0);
0164 }
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176 using less = compare::cartesian<compare::less, compare::equals_epsilon>;
0177
0178 if (less::apply(p, p1))
0179 {
0180 if (less::apply(p, p2))
0181 {
0182
0183 return side_value<CoordinateType, PromotedType>(p, p1, p2, epsp);
0184 }
0185 else
0186 {
0187
0188 return side_value<CoordinateType, PromotedType>(p2, p, p1, epsp);
0189 }
0190 }
0191
0192 if (less::apply(p1, p2))
0193 {
0194
0195 return side_value<CoordinateType, PromotedType>(p1, p2, p, epsp);
0196 }
0197 else
0198 {
0199
0200 return side_value<CoordinateType, PromotedType>(p2, p, p1, epsp);
0201 }
0202 }
0203 };
0204
0205
0206 template <typename P1, typename P2, typename P>
0207 static inline int apply(P1 const& p1, P2 const& p2, P const& p)
0208 {
0209 constexpr bool are_all_integral_coordinates =
0210 std::is_integral<coordinate_type_t<P1>>::value
0211 && std::is_integral<coordinate_type_t<P2>>::value
0212 && std::is_integral<coordinate_type_t<P>>::value;
0213
0214
0215
0216
0217 using coor_t = typename select_calculation_type_alt<CalculationType, P1, P2, P>::type;
0218 using promoted_t = std::conditional_t
0219 <
0220 are_all_integral_coordinates,
0221 typename promote_integral<coor_t>::type,
0222 typename select_most_precise<coor_t, double>::type
0223 >;
0224
0225 eps_policy< math::detail::equals_factor_policy<promoted_t> > epsp;
0226 promoted_t const s = compute_side_value
0227 <
0228 coor_t, promoted_t, are_all_integral_coordinates
0229 >::apply(p1, p2, p, epsp);
0230
0231 static promoted_t const zero = promoted_t();
0232 return math::detail::equals_by_policy(s, zero, epsp.policy) ? 0
0233 : s > zero ? 1
0234 : -1;
0235 }
0236
0237 private:
0238 template <typename P1, typename P2>
0239 static inline bool equals_point_point(P1 const& p1, P2 const& p2)
0240 {
0241 return strategy::within::cartesian_point_point::apply(p1, p2);
0242 }
0243 };
0244
0245 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
0246
0247 namespace services
0248 {
0249
0250 template <typename CalculationType>
0251 struct default_strategy<cartesian_tag, CalculationType>
0252 {
0253 using type = side_by_triangle<CalculationType>;
0254 };
0255
0256 }
0257
0258 #endif
0259
0260 }}
0261
0262 }}
0263
0264
0265 #endif