File indexing completed on 2026-08-26 08:45:54
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_PROPERTIES_AHEAD_HPP
0010 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_PROPERTIES_AHEAD_HPP
0011
0012 #include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
0013 #include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
0014 #include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp>
0015 #include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
0016
0017 #if defined(BOOST_GEOMETRY_DEBUG_GET_PROPERTIES_AHEAD)
0018 #include <boost/geometry/io/wkt/wkt.hpp>
0019 #endif
0020
0021 namespace boost { namespace geometry
0022 {
0023
0024 #ifndef DOXYGEN_NO_DETAIL
0025 namespace detail { namespace overlay
0026 {
0027
0028
0029
0030
0031
0032
0033 template
0034 <
0035 bool Reverse1, bool Reverse2,
0036 typename Turns, typename Clusters,
0037 typename Geometry1, typename Geometry2,
0038 typename IntersectionStrategy
0039 >
0040 void get_properties_ahead(Turns& turns, Clusters const& clusters,
0041 Geometry1 const& geometry1, Geometry2 const& geometry2,
0042 IntersectionStrategy const& intersection_strategy)
0043 {
0044 using point_type = typename Turns::value_type::point_type;
0045 auto const side_strategy = intersection_strategy.side();
0046 auto const comparable_distance_strategy
0047 = intersection_strategy.comparable_distance(point_type(), point_type());
0048
0049 auto walk_ahead = [&](auto const& turn, auto& op)
0050 {
0051 auto current_ring_id = ring_id_by_seg_id(op.seg_id);
0052 auto const& next_turn = turns[op.enriched.travels_to_ip_index];
0053 auto const next_ring_id0 = ring_id_by_seg_id(next_turn.operations[0].seg_id);
0054 auto const next_op_index = next_ring_id0 == current_ring_id ? 0 : 1;
0055 auto const& next_op = next_turn.operations[next_op_index];
0056 signed_size_type const point_count_to_next_turn = current_ring_id.source_index == 0
0057 ? segment_distance(geometry1, op.seg_id, next_op.seg_id)
0058 : segment_distance(geometry2, op.seg_id, next_op.seg_id);
0059
0060 int offset = 0;
0061 point_type point_of_segment0;
0062 geometry::copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, op.seg_id,
0063 offset++, point_of_segment0);
0064
0065 #if defined(BOOST_GEOMETRY_DEBUG_GET_PROPERTIES_AHEAD)
0066 std::cout << " EXAMINE AHEAD: ring " << current_ring_id
0067 << " segment: " << op.seg_id.segment_index
0068 << " [ until turn: " << op.enriched.travels_to_ip_index
0069 << " at: " << next_op.seg_id.segment_index
0070 << " count: " << point_count_to_next_turn
0071 << " " << geometry::wkt(next_turn.point)
0072 << " ]"
0073 << std::endl;
0074 #endif
0075
0076
0077
0078 point_type point_of_segment1;
0079 point_type side_changing_point_ahead = turn.point;
0080 bool found = false;
0081 int final_side = 0;
0082 for (auto i = 0; i <= point_count_to_next_turn; i++, offset++)
0083 {
0084 point_type current_point;
0085 if (i == point_count_to_next_turn)
0086 {
0087 current_point = next_turn.point;
0088 }
0089 else
0090 {
0091 geometry::copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2,
0092 op.seg_id, offset, current_point);
0093 }
0094 if (i == 0)
0095 {
0096 point_of_segment1 = current_point;
0097 }
0098 int const side = side_strategy.apply(point_of_segment0, point_of_segment1,
0099 current_point);
0100 #if defined(BOOST_GEOMETRY_DEBUG_GET_PROPERTIES_AHEAD)
0101 std::cout << " " << i << " " << geometry::wkt(current_point)
0102 << " side: " << side
0103 << std::endl;
0104 #endif
0105 if (side != 0)
0106 {
0107 found = true;
0108 final_side = side;
0109 break;
0110 }
0111 if (! found)
0112 {
0113 side_changing_point_ahead = current_point;
0114 }
0115 }
0116
0117 op.enriched.ahead_distance_of_side_change
0118 = comparable_distance_strategy.apply(point_of_segment0, side_changing_point_ahead);
0119 op.enriched.ahead_side = final_side;
0120 #if defined(BOOST_GEOMETRY_DEBUG_GET_PROPERTIES_AHEAD)
0121 std::cout << " result: " << op.enriched.ahead_distance_of_side_change
0122 << " side: " << op.enriched.ahead_side
0123 << std::endl;
0124 #endif
0125 };
0126
0127
0128 for (const auto& key_value : clusters)
0129 {
0130 auto const& cluster = key_value.second;
0131 for (auto const& index : cluster.turn_indices)
0132 {
0133 auto& turn = turns[index];
0134 for (auto& op : turn.operations)
0135 {
0136 if (op.enriched.travels_to_ip_index == -1)
0137 {
0138 continue;
0139 }
0140 #ifdef BOOST_GEOMETRY_DEBUG_GET_PROPERTIES_AHEAD
0141 std::cout << "Cluster " << turn.cluster_id
0142 << " turn " << index
0143 << " " << operation_char(op.operation)
0144 << " travels to " << op.enriched.travels_to_ip_index
0145 << std::endl;
0146 #endif
0147 walk_ahead(turn, op);
0148 }
0149 }
0150 }
0151
0152
0153 for (auto& turn : turns)
0154 {
0155 if (turn.discarded || turn.is_clustered() || ! turn.both(operation_continue))
0156 {
0157 continue;
0158 }
0159
0160 auto& op0 = turn.operations[0];
0161 auto& op1 = turn.operations[1];
0162
0163
0164
0165
0166 if (op0.enriched.travels_to_ip_index == -1 || op1.enriched.travels_to_ip_index == -1)
0167 {
0168 continue;
0169 }
0170
0171 walk_ahead(turn, op0);
0172 walk_ahead(turn, op1);
0173 }
0174 }
0175
0176
0177 }}
0178 #endif
0179
0180
0181 }}
0182
0183 #endif