annotate DEPENDENCIES/generic/include/boost/geometry/algorithms/detail/overlay/overlay.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 // Boost.Geometry (aka GGL, Generic Geometry Library)
Chris@16 2
Chris@16 3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
Chris@101 4 // Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland
Chris@16 5
Chris@16 6 // Use, modification and distribution is subject to the Boost Software License,
Chris@16 7 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 8 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 9
Chris@16 10 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_OVERLAY_HPP
Chris@16 11 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_OVERLAY_HPP
Chris@16 12
Chris@16 13
Chris@16 14 #include <deque>
Chris@16 15 #include <map>
Chris@16 16
Chris@16 17 #include <boost/range.hpp>
Chris@16 18 #include <boost/mpl/assert.hpp>
Chris@16 19
Chris@16 20
Chris@16 21 #include <boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp>
Chris@16 22 #include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp>
Chris@16 23 #include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
Chris@16 24 #include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
Chris@16 25 #include <boost/geometry/algorithms/detail/overlay/traverse.hpp>
Chris@16 26 #include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>
Chris@16 27 #include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
Chris@16 28
Chris@101 29 #include <boost/geometry/algorithms/detail/recalculate.hpp>
Chris@16 30
Chris@16 31 #include <boost/geometry/algorithms/num_points.hpp>
Chris@16 32 #include <boost/geometry/algorithms/reverse.hpp>
Chris@16 33
Chris@16 34 #include <boost/geometry/algorithms/detail/overlay/add_rings.hpp>
Chris@16 35 #include <boost/geometry/algorithms/detail/overlay/assign_parents.hpp>
Chris@16 36 #include <boost/geometry/algorithms/detail/overlay/ring_properties.hpp>
Chris@16 37 #include <boost/geometry/algorithms/detail/overlay/select_rings.hpp>
Chris@101 38 #include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
Chris@101 39
Chris@101 40 #include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
Chris@16 41
Chris@16 42
Chris@16 43 #ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
Chris@16 44 # include <boost/geometry/io/dsv/write.hpp>
Chris@16 45 #endif
Chris@16 46
Chris@16 47
Chris@16 48 namespace boost { namespace geometry
Chris@16 49 {
Chris@16 50
Chris@16 51
Chris@16 52 #ifndef DOXYGEN_NO_DETAIL
Chris@16 53 namespace detail { namespace overlay
Chris@16 54 {
Chris@16 55
Chris@16 56
Chris@101 57 template <typename TurnPoints, typename TurnInfoMap>
Chris@101 58 inline void get_ring_turn_info(TurnInfoMap& turn_info_map,
Chris@101 59 TurnPoints const& turn_points)
Chris@16 60 {
Chris@16 61 typedef typename boost::range_value<TurnPoints>::type turn_point_type;
Chris@16 62 typedef typename turn_point_type::container_type container_type;
Chris@16 63
Chris@16 64 for (typename boost::range_iterator<TurnPoints const>::type
Chris@16 65 it = boost::begin(turn_points);
Chris@16 66 it != boost::end(turn_points);
Chris@101 67 ++it)
Chris@16 68 {
Chris@101 69 typename boost::range_value<TurnPoints>::type const& turn_info = *it;
Chris@101 70 bool both_uu = turn_info.both(operation_union);
Chris@101 71 bool skip = (turn_info.discarded || both_uu)
Chris@101 72 && ! turn_info.any_blocked()
Chris@101 73 && ! turn_info.both(operation_intersection)
Chris@101 74 ;
Chris@101 75
Chris@101 76 for (typename boost::range_iterator<container_type const>::type
Chris@101 77 op_it = boost::begin(turn_info.operations);
Chris@101 78 op_it != boost::end(turn_info.operations);
Chris@101 79 ++op_it)
Chris@16 80 {
Chris@101 81 ring_identifier ring_id
Chris@101 82 (
Chris@101 83 op_it->seg_id.source_index,
Chris@101 84 op_it->seg_id.multi_index,
Chris@101 85 op_it->seg_id.ring_index
Chris@101 86 );
Chris@101 87
Chris@101 88 if (! skip)
Chris@16 89 {
Chris@101 90 turn_info_map[ring_id].has_normal_turn = true;
Chris@101 91 }
Chris@101 92 else if (both_uu)
Chris@101 93 {
Chris@101 94 turn_info_map[ring_id].has_uu_turn = true;
Chris@16 95 }
Chris@16 96 }
Chris@16 97 }
Chris@16 98 }
Chris@16 99
Chris@16 100
Chris@16 101 template
Chris@16 102 <
Chris@16 103 typename GeometryOut, overlay_type Direction, bool ReverseOut,
Chris@16 104 typename Geometry1, typename Geometry2,
Chris@16 105 typename OutputIterator
Chris@16 106 >
Chris@16 107 inline OutputIterator return_if_one_input_is_empty(Geometry1 const& geometry1,
Chris@16 108 Geometry2 const& geometry2,
Chris@16 109 OutputIterator out)
Chris@16 110 {
Chris@16 111 typedef std::deque
Chris@16 112 <
Chris@16 113 typename geometry::ring_type<GeometryOut>::type
Chris@16 114 > ring_container_type;
Chris@16 115
Chris@16 116 typedef ring_properties<typename geometry::point_type<Geometry1>::type> properties;
Chris@16 117
Chris@16 118 // Silence warning C4127: conditional expression is constant
Chris@16 119 #if defined(_MSC_VER)
Chris@101 120 #pragma warning(push)
Chris@101 121 #pragma warning(disable : 4127)
Chris@16 122 #endif
Chris@16 123
Chris@16 124 // Union: return either of them
Chris@16 125 // Intersection: return nothing
Chris@16 126 // Difference: return first of them
Chris@16 127 if (Direction == overlay_intersection
Chris@16 128 || (Direction == overlay_difference
Chris@16 129 && geometry::num_points(geometry1) == 0))
Chris@16 130 {
Chris@16 131 return out;
Chris@16 132 }
Chris@16 133
Chris@16 134 #if defined(_MSC_VER)
Chris@101 135 #pragma warning(pop)
Chris@16 136 #endif
Chris@16 137
Chris@16 138
Chris@101 139 std::map<ring_identifier, ring_turn_info> empty;
Chris@16 140 std::map<ring_identifier, properties> all_of_one_of_them;
Chris@16 141
Chris@101 142 select_rings<Direction>(geometry1, geometry2, empty, all_of_one_of_them);
Chris@16 143 ring_container_type rings;
Chris@16 144 assign_parents(geometry1, geometry2, rings, all_of_one_of_them);
Chris@16 145 return add_rings<GeometryOut>(all_of_one_of_them, geometry1, geometry2, rings, out);
Chris@16 146 }
Chris@16 147
Chris@16 148
Chris@16 149 template
Chris@16 150 <
Chris@16 151 typename Geometry1, typename Geometry2,
Chris@16 152 bool Reverse1, bool Reverse2, bool ReverseOut,
Chris@16 153 typename GeometryOut,
Chris@16 154 overlay_type Direction
Chris@16 155 >
Chris@16 156 struct overlay
Chris@16 157 {
Chris@101 158 template <typename RobustPolicy, typename OutputIterator, typename Strategy>
Chris@16 159 static inline OutputIterator apply(
Chris@16 160 Geometry1 const& geometry1, Geometry2 const& geometry2,
Chris@101 161 RobustPolicy const& robust_policy,
Chris@16 162 OutputIterator out,
Chris@16 163 Strategy const& )
Chris@16 164 {
Chris@101 165 if ( geometry::num_points(geometry1) == 0
Chris@101 166 && geometry::num_points(geometry2) == 0 )
Chris@16 167 {
Chris@16 168 return out;
Chris@16 169 }
Chris@16 170
Chris@101 171 if ( geometry::num_points(geometry1) == 0
Chris@101 172 || geometry::num_points(geometry2) == 0 )
Chris@16 173 {
Chris@16 174 return return_if_one_input_is_empty
Chris@16 175 <
Chris@16 176 GeometryOut, Direction, ReverseOut
Chris@16 177 >(geometry1, geometry2, out);
Chris@16 178 }
Chris@16 179
Chris@16 180 typedef typename geometry::point_type<GeometryOut>::type point_type;
Chris@101 181 typedef detail::overlay::traversal_turn_info
Chris@101 182 <
Chris@101 183 point_type,
Chris@101 184 typename geometry::segment_ratio_type<point_type, RobustPolicy>::type
Chris@101 185 > turn_info;
Chris@16 186 typedef std::deque<turn_info> container_type;
Chris@16 187
Chris@16 188 typedef std::deque
Chris@16 189 <
Chris@16 190 typename geometry::ring_type<GeometryOut>::type
Chris@16 191 > ring_container_type;
Chris@16 192
Chris@16 193 container_type turn_points;
Chris@16 194
Chris@16 195 #ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
Chris@16 196 std::cout << "get turns" << std::endl;
Chris@16 197 #endif
Chris@16 198 detail::get_turns::no_interrupt_policy policy;
Chris@16 199 geometry::get_turns
Chris@16 200 <
Chris@16 201 Reverse1, Reverse2,
Chris@101 202 detail::overlay::assign_null_policy
Chris@101 203 >(geometry1, geometry2, robust_policy, turn_points, policy);
Chris@16 204
Chris@16 205 #ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
Chris@16 206 std::cout << "enrich" << std::endl;
Chris@16 207 #endif
Chris@16 208 typename Strategy::side_strategy_type side_strategy;
Chris@16 209 geometry::enrich_intersection_points<Reverse1, Reverse2>(turn_points,
Chris@16 210 Direction == overlay_union
Chris@16 211 ? geometry::detail::overlay::operation_union
Chris@16 212 : geometry::detail::overlay::operation_intersection,
Chris@16 213 geometry1, geometry2,
Chris@101 214 robust_policy,
Chris@16 215 side_strategy);
Chris@16 216
Chris@16 217 #ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
Chris@16 218 std::cout << "traverse" << std::endl;
Chris@16 219 #endif
Chris@16 220 // Traverse through intersection/turn points and create rings of them.
Chris@16 221 // Note that these rings are always in clockwise order, even in CCW polygons,
Chris@16 222 // and are marked as "to be reversed" below
Chris@16 223 ring_container_type rings;
Chris@16 224 traverse<Reverse1, Reverse2, Geometry1, Geometry2>::apply
Chris@16 225 (
Chris@16 226 geometry1, geometry2,
Chris@16 227 Direction == overlay_union
Chris@16 228 ? geometry::detail::overlay::operation_union
Chris@16 229 : geometry::detail::overlay::operation_intersection,
Chris@101 230 robust_policy,
Chris@16 231 turn_points, rings
Chris@16 232 );
Chris@16 233
Chris@101 234 std::map<ring_identifier, ring_turn_info> turn_info_per_ring;
Chris@101 235 get_ring_turn_info(turn_info_per_ring, turn_points);
Chris@16 236
Chris@101 237 typedef ring_properties
Chris@101 238 <
Chris@101 239 typename geometry::point_type<GeometryOut>::type
Chris@101 240 > properties;
Chris@16 241
Chris@101 242 // Select all rings which are NOT touched by any intersection point
Chris@101 243 std::map<ring_identifier, properties> selected_ring_properties;
Chris@101 244 select_rings<Direction>(geometry1, geometry2, turn_info_per_ring,
Chris@101 245 selected_ring_properties);
Chris@16 246
Chris@16 247 // Add rings created during traversal
Chris@16 248 {
Chris@16 249 ring_identifier id(2, 0, -1);
Chris@16 250 for (typename boost::range_iterator<ring_container_type>::type
Chris@16 251 it = boost::begin(rings);
Chris@101 252 it != boost::end(rings);
Chris@101 253 ++it)
Chris@16 254 {
Chris@101 255 selected_ring_properties[id] = properties(*it);
Chris@101 256 selected_ring_properties[id].reversed = ReverseOut;
Chris@16 257 id.multi_index++;
Chris@16 258 }
Chris@16 259 }
Chris@16 260
Chris@101 261 assign_parents(geometry1, geometry2, rings, selected_ring_properties);
Chris@16 262
Chris@101 263 return add_rings<GeometryOut>(selected_ring_properties, geometry1, geometry2, rings, out);
Chris@16 264 }
Chris@16 265 };
Chris@16 266
Chris@16 267
Chris@16 268 }} // namespace detail::overlay
Chris@16 269 #endif // DOXYGEN_NO_DETAIL
Chris@16 270
Chris@16 271
Chris@16 272 }} // namespace boost::geometry
Chris@16 273
Chris@16 274
Chris@16 275 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_OVERLAY_HPP