File indexing completed on 2025-11-04 09:46:27
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TURNS_HPP
0016 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TURNS_HPP
0017
0018
0019 #include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
0020 #include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
0021 #include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
0022
0023 #include <boost/geometry/geometries/helper_geometry.hpp>
0024
0025 #include <boost/geometry/strategies/cartesian/point_in_point.hpp>
0026 #include <boost/geometry/strategies/spherical/point_in_point.hpp>
0027 #include <boost/geometry/strategies/distance.hpp>
0028
0029
0030 namespace boost { namespace geometry {
0031
0032 #ifndef DOXYGEN_NO_DETAIL
0033 namespace detail { namespace relate { namespace turns {
0034
0035 template <bool IncludeDegenerate = false>
0036 struct assign_policy
0037 : overlay::assign_null_policy
0038 {
0039 static bool const include_degenerate = IncludeDegenerate;
0040 };
0041
0042
0043
0044 template
0045 <
0046 typename Geometry1,
0047 typename Geometry2,
0048 typename GetTurnPolicy = detail::get_turns::get_turn_info_type
0049 <
0050 Geometry1, Geometry2, assign_policy<>
0051 >
0052 >
0053 struct get_turns
0054 {
0055 using turn_point_type = typename helper_geometry
0056 <
0057 geometry::point_type_t<Geometry1>
0058 >::type;
0059
0060 template
0061 <
0062 typename Strategy
0063 >
0064 struct turn_info_type
0065 {
0066 using ratio_type = typename segment_ratio_type<turn_point_type>::type;
0067 using type = overlay::turn_info
0068 <
0069 turn_point_type,
0070 ratio_type,
0071 typename detail::get_turns::turn_operation_type
0072 <
0073 Geometry1, Geometry2, turn_point_type, ratio_type
0074 >::type
0075 >;
0076 };
0077
0078 template <typename Turns, typename InterruptPolicy, typename Strategy>
0079 static inline void apply(Turns & turns,
0080 Geometry1 const& geometry1,
0081 Geometry2 const& geometry2,
0082 InterruptPolicy & interrupt_policy,
0083 Strategy const& strategy)
0084 {
0085 static const bool reverse1 = detail::overlay::do_reverse
0086 <
0087 geometry::point_order<Geometry1>::value
0088 >::value;
0089
0090 static const bool reverse2 = detail::overlay::do_reverse
0091 <
0092 geometry::point_order<Geometry2>::value
0093 >::value;
0094
0095 dispatch::get_turns
0096 <
0097 geometry::tag_t<Geometry1>,
0098 geometry::tag_t<Geometry2>,
0099 Geometry1,
0100 Geometry2,
0101 reverse1,
0102 reverse2,
0103 GetTurnPolicy
0104 >::apply(0, geometry1, 1, geometry2,
0105 strategy,
0106 turns, interrupt_policy);
0107 }
0108 };
0109
0110
0111
0112 template <int N = 0, int U = 1, int I = 2, int B = 3, int C = 4, int O = 0>
0113 struct op_to_int
0114 {
0115 template <typename Operation>
0116 inline int operator()(Operation const& op) const
0117 {
0118 switch(op.operation)
0119 {
0120 case detail::overlay::operation_none : return N;
0121 case detail::overlay::operation_union : return U;
0122 case detail::overlay::operation_intersection : return I;
0123 case detail::overlay::operation_blocked : return B;
0124 case detail::overlay::operation_continue : return C;
0125 case detail::overlay::operation_opposite : return O;
0126 }
0127 return -1;
0128 }
0129 };
0130
0131 template <std::size_t OpId, typename OpToInt>
0132 struct less_op_xxx_linear
0133 {
0134 template <typename Turn>
0135 inline bool operator()(Turn const& left, Turn const& right) const
0136 {
0137 static OpToInt op_to_int;
0138 return op_to_int(left.operations[OpId]) < op_to_int(right.operations[OpId]);
0139 }
0140 };
0141
0142 template <std::size_t OpId>
0143 struct less_op_linear_linear
0144 : less_op_xxx_linear< OpId, op_to_int<0,2,3,1,4,0> >
0145 {};
0146
0147 template <std::size_t OpId>
0148 struct less_op_linear_areal_single
0149 {
0150 template <typename Turn>
0151 inline bool operator()(Turn const& left, Turn const& right) const
0152 {
0153 static const std::size_t other_op_id = (OpId + 1) % 2;
0154 static turns::op_to_int<0,2,3,1,4,0> op_to_int_xuic;
0155 static turns::op_to_int<0,3,2,1,4,0> op_to_int_xiuc;
0156
0157 segment_identifier const& left_other_seg_id = left.operations[other_op_id].seg_id;
0158 segment_identifier const& right_other_seg_id = right.operations[other_op_id].seg_id;
0159
0160 typedef typename Turn::turn_operation_type operation_type;
0161 operation_type const& left_operation = left.operations[OpId];
0162 operation_type const& right_operation = right.operations[OpId];
0163
0164 if ( left_other_seg_id.ring_index == right_other_seg_id.ring_index )
0165 {
0166 return op_to_int_xuic(left_operation)
0167 < op_to_int_xuic(right_operation);
0168 }
0169 else
0170 {
0171 return op_to_int_xiuc(left_operation)
0172 < op_to_int_xiuc(right_operation);
0173 }
0174 }
0175 };
0176
0177 template <std::size_t OpId>
0178 struct less_op_areal_linear
0179 : less_op_xxx_linear< OpId, op_to_int<0,1,0,0,2,0> >
0180 {};
0181
0182 template <std::size_t OpId>
0183 struct less_op_areal_areal
0184 {
0185 template <typename Turn>
0186 inline bool operator()(Turn const& left, Turn const& right) const
0187 {
0188 static const std::size_t other_op_id = (OpId + 1) % 2;
0189 static op_to_int<0, 1, 2, 3, 4, 0> op_to_int_uixc;
0190 static op_to_int<0, 2, 1, 3, 4, 0> op_to_int_iuxc;
0191
0192 segment_identifier const& left_other_seg_id = left.operations[other_op_id].seg_id;
0193 segment_identifier const& right_other_seg_id = right.operations[other_op_id].seg_id;
0194
0195 typedef typename Turn::turn_operation_type operation_type;
0196 operation_type const& left_operation = left.operations[OpId];
0197 operation_type const& right_operation = right.operations[OpId];
0198
0199 if ( left_other_seg_id.multi_index == right_other_seg_id.multi_index )
0200 {
0201 if ( left_other_seg_id.ring_index == right_other_seg_id.ring_index )
0202 {
0203 return op_to_int_uixc(left_operation) < op_to_int_uixc(right_operation);
0204 }
0205 else
0206 {
0207 if ( left_other_seg_id.ring_index == -1 )
0208 {
0209 if ( left_operation.operation == overlay::operation_union )
0210 return false;
0211 else if ( left_operation.operation == overlay::operation_intersection )
0212 return true;
0213 }
0214 else if ( right_other_seg_id.ring_index == -1 )
0215 {
0216 if ( right_operation.operation == overlay::operation_union )
0217 return true;
0218 else if ( right_operation.operation == overlay::operation_intersection )
0219 return false;
0220 }
0221
0222 return op_to_int_iuxc(left_operation) < op_to_int_iuxc(right_operation);
0223 }
0224 }
0225 else
0226 {
0227 return op_to_int_uixc(left_operation) < op_to_int_uixc(right_operation);
0228 }
0229 }
0230 };
0231
0232 template <std::size_t OpId>
0233 struct less_other_multi_index
0234 {
0235 static const std::size_t other_op_id = (OpId + 1) % 2;
0236
0237 template <typename Turn>
0238 inline bool operator()(Turn const& left, Turn const& right) const
0239 {
0240 return left.operations[other_op_id].seg_id.multi_index
0241 < right.operations[other_op_id].seg_id.multi_index;
0242 }
0243 };
0244
0245
0246
0247 template <std::size_t OpId, typename LessOp, typename Strategy>
0248 struct less
0249 {
0250 BOOST_STATIC_ASSERT(OpId < 2);
0251
0252 template <typename Turn>
0253 static inline bool use_fraction(Turn const& left, Turn const& right)
0254 {
0255 using eq_pp_strategy_type = decltype(std::declval<Strategy>().relate(
0256 detail::dummy_point(), detail::dummy_point()));
0257
0258 static LessOp less_op;
0259
0260
0261
0262 return geometry::math::equals(left.operations[OpId].fraction,
0263 right.operations[OpId].fraction)
0264 && eq_pp_strategy_type::apply(left.point, right.point)
0265 ?
0266 less_op(left, right)
0267 :
0268 (left.operations[OpId].fraction < right.operations[OpId].fraction)
0269 ;
0270 }
0271
0272 template <typename Turn>
0273 inline bool operator()(Turn const& left, Turn const& right) const
0274 {
0275 segment_identifier const& sl = left.operations[OpId].seg_id;
0276 segment_identifier const& sr = right.operations[OpId].seg_id;
0277
0278 return sl < sr || ( sl == sr && use_fraction(left, right) );
0279 }
0280 };
0281
0282 }}}
0283 #endif
0284
0285 }}
0286
0287 #endif