Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-21 08:45:50

0001 // Boost.Geometry
0002 
0003 // Copyright (c) 2025 Barend Gehrels, Amsterdam, the Netherlands.
0004 
0005 // Use, modification and distribution is subject to the Boost Software License,
0006 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0007 // http://www.boost.org/LICENSE_1_0.txt)
0008 
0009 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ASSIGN_COUNTS_HPP
0010 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ASSIGN_COUNTS_HPP
0011 
0012 #include <boost/geometry/algorithms/detail/overlay/cluster_info.hpp>
0013 #include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
0014 #include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
0015 #include <boost/geometry/algorithms/detail/overlay/turn_operation_id.hpp>
0016 
0017 namespace boost { namespace geometry
0018 {
0019 
0020 #ifndef DOXYGEN_NO_DETAIL
0021 namespace detail { namespace overlay
0022 {
0023 
0024 template <typename Turns, typename Clusters>
0025 void assign_clustered_self_counts(Turns& turns, Clusters const& clusters)
0026 {
0027     auto is_self_cluster = [&turns](auto const& cinfo)
0028     {
0029         return std::all_of(cinfo.turn_indices.cbegin(), cinfo.turn_indices.cend(),
0030             [&](auto index) { return turns[index].is_self(); });
0031     };
0032 
0033     for (auto const& cluster : clusters)
0034     {
0035         if (! is_self_cluster(cluster.second))
0036         {
0037             continue;
0038         }
0039 
0040         // If a cluster only contains self-intersections, their previously assigned right counts
0041         // should be adapted, they are within the other geometry,
0042         // and otherwise they were discarded already in handle_self_turns
0043         for (auto index : cluster.second.turn_indices)
0044         {
0045             for (auto& op : turns[index].operations)
0046             {
0047                 op.enriched.count_right += 1;
0048             }
0049         }
0050     }
0051 }
0052 
0053 template <typename Turn>
0054 void assign_counts(Turn& turn)
0055 {
0056     using counts_per_op_t = std::pair<operation_type, std::size_t>;
0057 
0058     auto assign_left = [&turn](std::size_t count)
0059     {
0060         for (auto& op : turn.operations)
0061         {
0062             op.enriched.count_left = count;
0063         }
0064     };
0065 
0066     auto assign_right = [&turn](std::size_t count)
0067     {
0068         for (auto& op : turn.operations)
0069         {
0070             op.enriched.count_right = count;
0071         }
0072     };
0073 
0074     auto assign_for = [&turn](counts_per_op_t const& op1, counts_per_op_t op2, auto&& assign)
0075     {
0076         for (auto& op : turn.operations)
0077         {
0078             if (op.operation == op1.first) { assign(op.enriched, op1.second); }
0079             else if (op.operation == op2.first) { assign(op.enriched, op2.second); }
0080         }
0081     };
0082 
0083     auto assign_left_for = [&assign_for](counts_per_op_t const& op1, counts_per_op_t op2)
0084     {
0085         assign_for(op1, op2, [](auto& enriched, auto count) { enriched.count_left = count; });
0086     };
0087 
0088     auto assign_right_for = [&assign_for](counts_per_op_t const& op1, counts_per_op_t op2)
0089     {
0090         assign_for(op1, op2, [](auto& enriched, auto count) { enriched.count_right = count; });
0091     };
0092 
0093     auto assign_left_incoming_for = [&assign_for](counts_per_op_t const& op1, counts_per_op_t op2)
0094     {
0095         assign_for(op1, op2, [](auto& enriched, auto count) { enriched.count_left_incoming = count; });
0096     };
0097 
0098     auto assign_right_incoming_for = [&assign_for](counts_per_op_t const& op1, counts_per_op_t op2)
0099     {
0100         assign_for(op1, op2, [](auto& enriched, auto count) { enriched.count_right_incoming = count; });
0101     };
0102 
0103     if (turn.combination(operation_intersection, operation_union))
0104     {
0105         assign_left_for({operation_union, 0}, {operation_intersection, 1});
0106         assign_right_for({operation_union, 1}, {operation_intersection, 2});
0107 
0108         // For i/u (either originating from a "cross" or from a touch, but the segments cross
0109         // one another), the incoming counts can be assigned.
0110 
0111         // For other operations, this is not trivial (without retrieving the geometry).
0112         // It is only necessary for some collinear cases to see how they arrive at the target.
0113         // If it is not available, distance ahead is used.
0114         assign_left_incoming_for({operation_union, 1}, {operation_intersection, 0});
0115         assign_right_incoming_for({operation_union, 2}, {operation_intersection, 1});
0116     }
0117     else if (turn.combination(operation_blocked, operation_union))
0118     {
0119         assign_left_for({operation_union, 0}, {operation_blocked, 1});
0120         assign_right(1);
0121     }
0122     else if (turn.combination(operation_blocked, operation_intersection))
0123     {
0124         assign_left(1);
0125         assign_right_for({operation_blocked, 1}, {operation_intersection, 2});
0126     }
0127     else if (turn.both(operation_continue))
0128     {
0129         assign_left(0);
0130         assign_right(2);
0131     }
0132     else if (turn.both(operation_union))
0133     {
0134         assign_left(0);
0135         assign_right(1);
0136     }
0137     else if (turn.both(operation_intersection))
0138     {
0139         assign_left(1);
0140         assign_right(2);
0141     }
0142 }
0143 
0144 template <typename Turns>
0145 void assign_unclustered_counts(Turns& turns)
0146 {
0147     for (auto& turn : turns)
0148     {
0149         if (turn.is_clustered() || turn.discarded)
0150         {
0151             continue;
0152         }
0153         assign_counts(turn);
0154     }
0155 }
0156 
0157 }} // namespace detail::overlay
0158 #endif // DOXYGEN_NO_DETAIL
0159 
0160 }} // namespace boost::geometry
0161 
0162 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ASSIGN_COUNTS_HPP