annotate DEPENDENCIES/generic/include/boost/geometry/algorithms/detail/partition.hpp @ 46:d572322e2efe

Fix to .cat file check (was susceptible to DOS line-endings) and subrepo update
author Chris Cannam
date Thu, 07 Aug 2014 14:39:38 +0100
parents 2665513ce2d3
children c530137014c0
rev   line source
Chris@16 1 // Boost.Geometry (aka GGL, Generic Geometry Library)
Chris@16 2
Chris@16 3 // Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.
Chris@16 4
Chris@16 5 // Use, modification and distribution is subject to the Boost Software License,
Chris@16 6 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 7 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 8
Chris@16 9 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_PARTITION_HPP
Chris@16 10 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_PARTITION_HPP
Chris@16 11
Chris@16 12 #include <vector>
Chris@16 13 #include <boost/range/algorithm/copy.hpp>
Chris@16 14 #include <boost/geometry/algorithms/assign.hpp>
Chris@16 15 #include <boost/geometry/core/coordinate_type.hpp>
Chris@16 16
Chris@16 17 namespace boost { namespace geometry
Chris@16 18 {
Chris@16 19
Chris@16 20 namespace detail { namespace partition
Chris@16 21 {
Chris@16 22
Chris@16 23 typedef std::vector<std::size_t> index_vector_type;
Chris@16 24
Chris@16 25 template <int Dimension, typename Box>
Chris@16 26 inline void divide_box(Box const& box, Box& lower_box, Box& upper_box)
Chris@16 27 {
Chris@16 28 typedef typename coordinate_type<Box>::type ctype;
Chris@16 29
Chris@16 30 // Divide input box into two parts, e.g. left/right
Chris@16 31 ctype two = 2;
Chris@16 32 ctype mid = (geometry::get<min_corner, Dimension>(box)
Chris@16 33 + geometry::get<max_corner, Dimension>(box)) / two;
Chris@16 34
Chris@16 35 lower_box = box;
Chris@16 36 upper_box = box;
Chris@16 37 geometry::set<max_corner, Dimension>(lower_box, mid);
Chris@16 38 geometry::set<min_corner, Dimension>(upper_box, mid);
Chris@16 39 }
Chris@16 40
Chris@16 41 // Divide collection into three subsets: lower, upper and oversized
Chris@16 42 // (not-fitting)
Chris@16 43 // (lower == left or bottom, upper == right or top)
Chris@16 44 template <typename OverlapsPolicy, typename InputCollection, typename Box>
Chris@16 45 static inline void divide_into_subsets(Box const& lower_box,
Chris@16 46 Box const& upper_box,
Chris@16 47 InputCollection const& collection,
Chris@16 48 index_vector_type const& input,
Chris@16 49 index_vector_type& lower,
Chris@16 50 index_vector_type& upper,
Chris@16 51 index_vector_type& exceeding)
Chris@16 52 {
Chris@16 53 typedef boost::range_iterator
Chris@16 54 <
Chris@16 55 index_vector_type const
Chris@16 56 >::type index_iterator_type;
Chris@16 57
Chris@16 58 for(index_iterator_type it = boost::begin(input);
Chris@16 59 it != boost::end(input);
Chris@16 60 ++it)
Chris@16 61 {
Chris@16 62 bool const lower_overlapping = OverlapsPolicy::apply(lower_box,
Chris@16 63 collection[*it]);
Chris@16 64 bool const upper_overlapping = OverlapsPolicy::apply(upper_box,
Chris@16 65 collection[*it]);
Chris@16 66
Chris@16 67 if (lower_overlapping && upper_overlapping)
Chris@16 68 {
Chris@16 69 exceeding.push_back(*it);
Chris@16 70 }
Chris@16 71 else if (lower_overlapping)
Chris@16 72 {
Chris@16 73 lower.push_back(*it);
Chris@16 74 }
Chris@16 75 else if (upper_overlapping)
Chris@16 76 {
Chris@16 77 upper.push_back(*it);
Chris@16 78 }
Chris@16 79 else
Chris@16 80 {
Chris@16 81 // Is nowhere! Should not occur!
Chris@16 82 BOOST_ASSERT(true);
Chris@16 83 }
Chris@16 84 }
Chris@16 85 }
Chris@16 86
Chris@16 87 // Match collection with itself
Chris@16 88 template <typename InputCollection, typename Policy>
Chris@16 89 static inline void handle_one(InputCollection const& collection,
Chris@16 90 index_vector_type const& input,
Chris@16 91 Policy& policy)
Chris@16 92 {
Chris@16 93 typedef boost::range_iterator<index_vector_type const>::type
Chris@16 94 index_iterator_type;
Chris@16 95 // Quadratic behaviour at lowest level (lowest quad, or all exceeding)
Chris@16 96 for(index_iterator_type it1 = boost::begin(input);
Chris@16 97 it1 != boost::end(input);
Chris@16 98 ++it1)
Chris@16 99 {
Chris@16 100 index_iterator_type it2 = it1;
Chris@16 101 for(++it2; it2 != boost::end(input); ++it2)
Chris@16 102 {
Chris@16 103 policy.apply(collection[*it1], collection[*it2]);
Chris@16 104 }
Chris@16 105 }
Chris@16 106 }
Chris@16 107
Chris@16 108 // Match collection 1 with collection 2
Chris@16 109 template <typename InputCollection, typename Policy>
Chris@16 110 static inline void handle_two(
Chris@16 111 InputCollection const& collection1, index_vector_type const& input1,
Chris@16 112 InputCollection const& collection2, index_vector_type const& input2,
Chris@16 113 Policy& policy)
Chris@16 114 {
Chris@16 115 typedef boost::range_iterator
Chris@16 116 <
Chris@16 117 index_vector_type const
Chris@16 118 >::type index_iterator_type;
Chris@16 119
Chris@16 120 for(index_iterator_type it1 = boost::begin(input1);
Chris@16 121 it1 != boost::end(input1);
Chris@16 122 ++it1)
Chris@16 123 {
Chris@16 124 for(index_iterator_type it2 = boost::begin(input2);
Chris@16 125 it2 != boost::end(input2);
Chris@16 126 ++it2)
Chris@16 127 {
Chris@16 128 policy.apply(collection1[*it1], collection2[*it2]);
Chris@16 129 }
Chris@16 130 }
Chris@16 131 }
Chris@16 132
Chris@16 133 template
Chris@16 134 <
Chris@16 135 int Dimension,
Chris@16 136 typename Box,
Chris@16 137 typename OverlapsPolicy,
Chris@16 138 typename VisitBoxPolicy
Chris@16 139 >
Chris@16 140 class partition_one_collection
Chris@16 141 {
Chris@16 142 typedef std::vector<std::size_t> index_vector_type;
Chris@16 143 typedef typename coordinate_type<Box>::type ctype;
Chris@16 144 typedef partition_one_collection
Chris@16 145 <
Chris@16 146 1 - Dimension,
Chris@16 147 Box,
Chris@16 148 OverlapsPolicy,
Chris@16 149 VisitBoxPolicy
Chris@16 150 > sub_divide;
Chris@16 151
Chris@16 152 template <typename InputCollection, typename Policy>
Chris@16 153 static inline void next_level(Box const& box,
Chris@16 154 InputCollection const& collection,
Chris@16 155 index_vector_type const& input,
Chris@16 156 int level, std::size_t min_elements,
Chris@16 157 Policy& policy, VisitBoxPolicy& box_policy)
Chris@16 158 {
Chris@16 159 if (boost::size(input) > 0)
Chris@16 160 {
Chris@16 161 if (std::size_t(boost::size(input)) > min_elements && level < 100)
Chris@16 162 {
Chris@16 163 sub_divide::apply(box, collection, input, level + 1,
Chris@16 164 min_elements, policy, box_policy);
Chris@16 165 }
Chris@16 166 else
Chris@16 167 {
Chris@16 168 handle_one(collection, input, policy);
Chris@16 169 }
Chris@16 170 }
Chris@16 171 }
Chris@16 172
Chris@16 173 public :
Chris@16 174 template <typename InputCollection, typename Policy>
Chris@16 175 static inline void apply(Box const& box,
Chris@16 176 InputCollection const& collection,
Chris@16 177 index_vector_type const& input,
Chris@16 178 int level,
Chris@16 179 std::size_t min_elements,
Chris@16 180 Policy& policy, VisitBoxPolicy& box_policy)
Chris@16 181 {
Chris@16 182 box_policy.apply(box, level);
Chris@16 183
Chris@16 184 Box lower_box, upper_box;
Chris@16 185 divide_box<Dimension>(box, lower_box, upper_box);
Chris@16 186
Chris@16 187 index_vector_type lower, upper, exceeding;
Chris@16 188 divide_into_subsets<OverlapsPolicy>(lower_box, upper_box, collection,
Chris@16 189 input, lower, upper, exceeding);
Chris@16 190
Chris@16 191 if (boost::size(exceeding) > 0)
Chris@16 192 {
Chris@16 193 // All what is not fitting a partition should be combined
Chris@16 194 // with each other, and with all which is fitting.
Chris@16 195 handle_one(collection, exceeding, policy);
Chris@16 196 handle_two(collection, exceeding, collection, lower, policy);
Chris@16 197 handle_two(collection, exceeding, collection, upper, policy);
Chris@16 198 }
Chris@16 199
Chris@16 200 // Recursively call operation both parts
Chris@16 201 next_level(lower_box, collection, lower, level, min_elements,
Chris@16 202 policy, box_policy);
Chris@16 203 next_level(upper_box, collection, upper, level, min_elements,
Chris@16 204 policy, box_policy);
Chris@16 205 }
Chris@16 206 };
Chris@16 207
Chris@16 208 template
Chris@16 209 <
Chris@16 210 int Dimension,
Chris@16 211 typename Box,
Chris@16 212 typename OverlapsPolicy,
Chris@16 213 typename VisitBoxPolicy
Chris@16 214 >
Chris@16 215 class partition_two_collections
Chris@16 216 {
Chris@16 217 typedef std::vector<std::size_t> index_vector_type;
Chris@16 218 typedef typename coordinate_type<Box>::type ctype;
Chris@16 219 typedef partition_two_collections
Chris@16 220 <
Chris@16 221 1 - Dimension,
Chris@16 222 Box,
Chris@16 223 OverlapsPolicy,
Chris@16 224 VisitBoxPolicy
Chris@16 225 > sub_divide;
Chris@16 226
Chris@16 227 template <typename InputCollection, typename Policy>
Chris@16 228 static inline void next_level(Box const& box,
Chris@16 229 InputCollection const& collection1,
Chris@16 230 index_vector_type const& input1,
Chris@16 231 InputCollection const& collection2,
Chris@16 232 index_vector_type const& input2,
Chris@16 233 int level, std::size_t min_elements,
Chris@16 234 Policy& policy, VisitBoxPolicy& box_policy)
Chris@16 235 {
Chris@16 236 if (boost::size(input1) > 0 && boost::size(input2) > 0)
Chris@16 237 {
Chris@16 238 if (std::size_t(boost::size(input1)) > min_elements
Chris@16 239 && std::size_t(boost::size(input2)) > min_elements
Chris@16 240 && level < 100)
Chris@16 241 {
Chris@16 242 sub_divide::apply(box, collection1, input1, collection2,
Chris@16 243 input2, level + 1, min_elements,
Chris@16 244 policy, box_policy);
Chris@16 245 }
Chris@16 246 else
Chris@16 247 {
Chris@16 248 box_policy.apply(box, level + 1);
Chris@16 249 handle_two(collection1, input1, collection2, input2, policy);
Chris@16 250 }
Chris@16 251 }
Chris@16 252 }
Chris@16 253
Chris@16 254 public :
Chris@16 255 template <typename InputCollection, typename Policy>
Chris@16 256 static inline void apply(Box const& box,
Chris@16 257 InputCollection const& collection1, index_vector_type const& input1,
Chris@16 258 InputCollection const& collection2, index_vector_type const& input2,
Chris@16 259 int level,
Chris@16 260 std::size_t min_elements,
Chris@16 261 Policy& policy, VisitBoxPolicy& box_policy)
Chris@16 262 {
Chris@16 263 box_policy.apply(box, level);
Chris@16 264
Chris@16 265 Box lower_box, upper_box;
Chris@16 266 divide_box<Dimension>(box, lower_box, upper_box);
Chris@16 267
Chris@16 268 index_vector_type lower1, upper1, exceeding1;
Chris@16 269 index_vector_type lower2, upper2, exceeding2;
Chris@16 270 divide_into_subsets<OverlapsPolicy>(lower_box, upper_box, collection1,
Chris@16 271 input1, lower1, upper1, exceeding1);
Chris@16 272 divide_into_subsets<OverlapsPolicy>(lower_box, upper_box, collection2,
Chris@16 273 input2, lower2, upper2, exceeding2);
Chris@16 274
Chris@16 275 if (boost::size(exceeding1) > 0)
Chris@16 276 {
Chris@16 277 // All exceeding from 1 with 2:
Chris@16 278 handle_two(collection1, exceeding1, collection2, exceeding2,
Chris@16 279 policy);
Chris@16 280
Chris@16 281 // All exceeding from 1 with lower and upper of 2:
Chris@16 282 handle_two(collection1, exceeding1, collection2, lower2, policy);
Chris@16 283 handle_two(collection1, exceeding1, collection2, upper2, policy);
Chris@16 284 }
Chris@16 285 if (boost::size(exceeding2) > 0)
Chris@16 286 {
Chris@16 287 // All exceeding from 2 with lower and upper of 1:
Chris@16 288 handle_two(collection1, lower1, collection2, exceeding2, policy);
Chris@16 289 handle_two(collection1, upper1, collection2, exceeding2, policy);
Chris@16 290 }
Chris@16 291
Chris@16 292 next_level(lower_box, collection1, lower1, collection2, lower2, level,
Chris@16 293 min_elements, policy, box_policy);
Chris@16 294 next_level(upper_box, collection1, upper1, collection2, upper2, level,
Chris@16 295 min_elements, policy, box_policy);
Chris@16 296 }
Chris@16 297 };
Chris@16 298
Chris@16 299 }} // namespace detail::partition
Chris@16 300
Chris@16 301 struct visit_no_policy
Chris@16 302 {
Chris@16 303 template <typename Box>
Chris@16 304 static inline void apply(Box const&, int )
Chris@16 305 {}
Chris@16 306 };
Chris@16 307
Chris@16 308 template
Chris@16 309 <
Chris@16 310 typename Box,
Chris@16 311 typename ExpandPolicy,
Chris@16 312 typename OverlapsPolicy,
Chris@16 313 typename VisitBoxPolicy = visit_no_policy
Chris@16 314 >
Chris@16 315 class partition
Chris@16 316 {
Chris@16 317 typedef std::vector<std::size_t> index_vector_type;
Chris@16 318
Chris@16 319 template <typename InputCollection>
Chris@16 320 static inline void expand_to_collection(InputCollection const& collection,
Chris@16 321 Box& total, index_vector_type& index_vector)
Chris@16 322 {
Chris@16 323 std::size_t index = 0;
Chris@16 324 for(typename boost::range_iterator<InputCollection const>::type it
Chris@16 325 = boost::begin(collection);
Chris@16 326 it != boost::end(collection);
Chris@16 327 ++it, ++index)
Chris@16 328 {
Chris@16 329 ExpandPolicy::apply(total, *it);
Chris@16 330 index_vector.push_back(index);
Chris@16 331 }
Chris@16 332 }
Chris@16 333
Chris@16 334 public :
Chris@16 335 template <typename InputCollection, typename VisitPolicy>
Chris@16 336 static inline void apply(InputCollection const& collection,
Chris@16 337 VisitPolicy& visitor,
Chris@16 338 std::size_t min_elements = 16,
Chris@16 339 VisitBoxPolicy box_visitor = visit_no_policy()
Chris@16 340 )
Chris@16 341 {
Chris@16 342 if (std::size_t(boost::size(collection)) > min_elements)
Chris@16 343 {
Chris@16 344 index_vector_type index_vector;
Chris@16 345 Box total;
Chris@16 346 assign_inverse(total);
Chris@16 347 expand_to_collection(collection, total, index_vector);
Chris@16 348
Chris@16 349 detail::partition::partition_one_collection
Chris@16 350 <
Chris@16 351 0, Box,
Chris@16 352 OverlapsPolicy,
Chris@16 353 VisitBoxPolicy
Chris@16 354 >::apply(total, collection, index_vector, 0, min_elements,
Chris@16 355 visitor, box_visitor);
Chris@16 356 }
Chris@16 357 else
Chris@16 358 {
Chris@16 359 typedef typename boost::range_iterator
Chris@16 360 <
Chris@16 361 InputCollection const
Chris@16 362 >::type iterator_type;
Chris@16 363 for(iterator_type it1 = boost::begin(collection);
Chris@16 364 it1 != boost::end(collection);
Chris@16 365 ++it1)
Chris@16 366 {
Chris@16 367 iterator_type it2 = it1;
Chris@16 368 for(++it2; it2 != boost::end(collection); ++it2)
Chris@16 369 {
Chris@16 370 visitor.apply(*it1, *it2);
Chris@16 371 }
Chris@16 372 }
Chris@16 373 }
Chris@16 374 }
Chris@16 375
Chris@16 376 template <typename InputCollection, typename VisitPolicy>
Chris@16 377 static inline void apply(InputCollection const& collection1,
Chris@16 378 InputCollection const& collection2,
Chris@16 379 VisitPolicy& visitor,
Chris@16 380 std::size_t min_elements = 16,
Chris@16 381 VisitBoxPolicy box_visitor = visit_no_policy()
Chris@16 382 )
Chris@16 383 {
Chris@16 384 if (std::size_t(boost::size(collection1)) > min_elements
Chris@16 385 && std::size_t(boost::size(collection2)) > min_elements)
Chris@16 386 {
Chris@16 387 index_vector_type index_vector1, index_vector2;
Chris@16 388 Box total;
Chris@16 389 assign_inverse(total);
Chris@16 390 expand_to_collection(collection1, total, index_vector1);
Chris@16 391 expand_to_collection(collection2, total, index_vector2);
Chris@16 392
Chris@16 393 detail::partition::partition_two_collections
Chris@16 394 <
Chris@16 395 0, Box, OverlapsPolicy, VisitBoxPolicy
Chris@16 396 >::apply(total,
Chris@16 397 collection1, index_vector1,
Chris@16 398 collection2, index_vector2,
Chris@16 399 0, min_elements, visitor, box_visitor);
Chris@16 400 }
Chris@16 401 else
Chris@16 402 {
Chris@16 403 typedef typename boost::range_iterator
Chris@16 404 <
Chris@16 405 InputCollection const
Chris@16 406 >::type iterator_type;
Chris@16 407 for(iterator_type it1 = boost::begin(collection1);
Chris@16 408 it1 != boost::end(collection1);
Chris@16 409 ++it1)
Chris@16 410 {
Chris@16 411 for(iterator_type it2 = boost::begin(collection2);
Chris@16 412 it2 != boost::end(collection2);
Chris@16 413 ++it2)
Chris@16 414 {
Chris@16 415 visitor.apply(*it1, *it2);
Chris@16 416 }
Chris@16 417 }
Chris@16 418 }
Chris@16 419 }
Chris@16 420
Chris@16 421 };
Chris@16 422
Chris@16 423 }} // namespace boost::geometry
Chris@16 424
Chris@16 425 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_PARTITION_HPP