File indexing completed on 2025-12-15 09:50:18
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SORT_ON_SEGMENT_RATIO_HPP
0015 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SORT_ON_SEGMENT_RATIO_HPP
0016
0017 #include <cstddef>
0018 #include <algorithm>
0019 #include <map>
0020 #include <set>
0021 #include <vector>
0022
0023 #include <boost/core/addressof.hpp>
0024 #include <boost/range/value_type.hpp>
0025
0026 #include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp>
0027 #include <boost/geometry/algorithms/detail/overlay/sort_by_side.hpp>
0028 #include <boost/geometry/strategies/side.hpp>
0029
0030 namespace boost { namespace geometry
0031 {
0032
0033 #ifndef DOXYGEN_NO_DETAIL
0034 namespace detail { namespace overlay
0035 {
0036
0037
0038
0039 template <typename TurnOperation>
0040 struct indexed_turn_operation
0041 {
0042 using type = TurnOperation;
0043
0044 std::size_t turn_index;
0045 std::size_t operation_index;
0046
0047 segment_identifier const* other_seg_id;
0048 TurnOperation const* subject;
0049
0050 inline indexed_turn_operation(std::size_t ti, std::size_t oi,
0051 TurnOperation const& sub,
0052 segment_identifier const& oid)
0053 : turn_index(ti)
0054 , operation_index(oi)
0055 , other_seg_id(&oid)
0056 , subject(boost::addressof(sub))
0057 {}
0058
0059 };
0060
0061 template
0062 <
0063 typename Turns,
0064 typename Indexed,
0065 typename Geometry1, typename Geometry2,
0066 typename Strategy,
0067 bool Reverse1, bool Reverse2
0068 >
0069 struct less_by_segment_ratio
0070 {
0071 inline less_by_segment_ratio(Turns const& turns
0072 , Geometry1 const& geometry1
0073 , Geometry2 const& geometry2
0074 , Strategy const& strategy)
0075 : m_turns(turns)
0076 , m_geometry1(geometry1)
0077 , m_geometry2(geometry2)
0078 , m_strategy(strategy)
0079 {
0080 }
0081
0082 private :
0083
0084 Turns const& m_turns;
0085 Geometry1 const& m_geometry1;
0086 Geometry2 const& m_geometry2;
0087 Strategy const& m_strategy;
0088
0089 using point_type = geometry::point_type_t<Geometry1>;
0090
0091 inline bool default_order(Indexed const& left, Indexed const& right) const
0092 {
0093
0094 return left.turn_index < right.turn_index;
0095 }
0096
0097 inline bool consider_relative_order(Indexed const& left,
0098 Indexed const& right) const
0099 {
0100 point_type pi, pj, ri, rj, si, sj;
0101
0102 geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,
0103 left.subject->seg_id,
0104 pi, pj);
0105 geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,
0106 *left.other_seg_id,
0107 ri, rj);
0108 geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,
0109 *right.other_seg_id,
0110 si, sj);
0111
0112 auto side_strategy = m_strategy.side();
0113 int const side_rj_p = side_strategy.apply(pi, pj, rj);
0114 int const side_sj_p = side_strategy.apply(pi, pj, sj);
0115
0116
0117 if (side_rj_p != side_sj_p)
0118 {
0119 return side_rj_p < side_sj_p;
0120 }
0121
0122 int const side_sj_r = side_strategy.apply(ri, rj, sj);
0123 int const side_rj_s = side_strategy.apply(si, sj, rj);
0124
0125
0126
0127 if (side_rj_s != side_sj_r)
0128 {
0129 return side_rj_s < side_sj_r;
0130 }
0131
0132 return default_order(left, right);
0133 }
0134
0135
0136 public :
0137
0138
0139
0140 inline bool operator()(Indexed const& left, Indexed const& right) const
0141 {
0142 if (! (left.subject->seg_id == right.subject->seg_id))
0143 {
0144 return left.subject->seg_id < right.subject->seg_id;
0145 }
0146
0147
0148
0149 if (! (left.subject->fraction == right.subject->fraction))
0150 {
0151 return left.subject->fraction < right.subject->fraction;
0152 }
0153
0154 auto const& left_turn = m_turns[left.turn_index];
0155 auto const& right_turn = m_turns[right.turn_index];
0156
0157
0158
0159 if (left_turn.method == method_crosses
0160 && right_turn.method == method_crosses)
0161 {
0162 return consider_relative_order(left, right);
0163 }
0164
0165 bool const left_both_xx = left_turn.both(operation_blocked);
0166 bool const right_both_xx = right_turn.both(operation_blocked);
0167 if (left_both_xx && ! right_both_xx)
0168 {
0169 return true;
0170 }
0171 if (! left_both_xx && right_both_xx)
0172 {
0173 return false;
0174 }
0175
0176 bool const left_both_uu = left_turn.both(operation_union);
0177 bool const right_both_uu = right_turn.both(operation_union);
0178 if (left_both_uu && ! right_both_uu)
0179 {
0180 return true;
0181 }
0182 if (! left_both_uu && right_both_uu)
0183 {
0184 return false;
0185 }
0186
0187 return default_order(left, right);
0188 }
0189 };
0190
0191
0192 }}
0193 #endif
0194
0195
0196 }}
0197
0198 #endif