annotate DEPENDENCIES/generic/include/boost/geometry/algorithms/detail/occupation_info.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
rev   line source
Chris@16 1 // Boost.Geometry (aka GGL, Generic Geometry Library)
Chris@16 2
Chris@16 3 // Copyright (c) 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_OCCUPATION_INFO_HPP
Chris@16 10 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OCCUPATION_INFO_HPP
Chris@16 11
Chris@16 12 #if ! defined(NDEBUG)
Chris@16 13 // #define BOOST_GEOMETRY_DEBUG_BUFFER_OCCUPATION
Chris@16 14 #endif
Chris@16 15
Chris@16 16 #include <algorithm>
Chris@16 17 #include <boost/range.hpp>
Chris@16 18
Chris@16 19 #include <boost/geometry/core/coordinate_type.hpp>
Chris@16 20 #include <boost/geometry/core/point_type.hpp>
Chris@16 21
Chris@16 22 #include <boost/geometry/algorithms/equals.hpp>
Chris@16 23 #include <boost/geometry/iterators/closing_iterator.hpp>
Chris@16 24
Chris@16 25 #include <boost/geometry/algorithms/detail/get_left_turns.hpp>
Chris@16 26
Chris@16 27
Chris@16 28 namespace boost { namespace geometry
Chris@16 29 {
Chris@16 30
Chris@16 31
Chris@16 32 #ifndef DOXYGEN_NO_DETAIL
Chris@16 33 namespace detail
Chris@16 34 {
Chris@16 35
Chris@16 36 template <typename P>
Chris@16 37 class relaxed_less
Chris@16 38 {
Chris@16 39 typedef typename geometry::coordinate_type<P>::type coordinate_type;
Chris@16 40
Chris@16 41 coordinate_type epsilon;
Chris@16 42
Chris@16 43 public :
Chris@16 44
Chris@16 45 inline relaxed_less()
Chris@16 46 {
Chris@16 47 // TODO: adapt for ttmath, and maybe build the map in another way
Chris@16 48 // (e.g. exact constellations of segment-id's), maybe adaptive.
Chris@16 49 epsilon = std::numeric_limits<double>::epsilon() * 100.0;
Chris@16 50 }
Chris@16 51
Chris@16 52 inline bool operator()(P const& a, P const& b) const
Chris@16 53 {
Chris@16 54 coordinate_type const dx = math::abs(geometry::get<0>(a) - geometry::get<0>(b));
Chris@16 55 coordinate_type const dy = math::abs(geometry::get<1>(a) - geometry::get<1>(b));
Chris@16 56
Chris@16 57
Chris@16 58 if (dx < epsilon && dy < epsilon)
Chris@16 59 {
Chris@16 60 return false;
Chris@16 61 }
Chris@16 62 if (dx < epsilon)
Chris@16 63 {
Chris@16 64 return geometry::get<1>(a) < geometry::get<1>(b);
Chris@16 65 }
Chris@16 66
Chris@16 67 return geometry::get<0>(a) < geometry::get<0>(b);
Chris@16 68 }
Chris@16 69
Chris@16 70 inline bool equals(P const& a, P const& b) const
Chris@16 71 {
Chris@16 72 typedef typename geometry::coordinate_type<P>::type coordinate_type;
Chris@16 73
Chris@16 74 coordinate_type const dx = math::abs(geometry::get<0>(a) - geometry::get<0>(b));
Chris@16 75 coordinate_type const dy = math::abs(geometry::get<1>(a) - geometry::get<1>(b));
Chris@16 76
Chris@16 77 return dx < epsilon && dy < epsilon;
Chris@16 78 };
Chris@16 79 };
Chris@16 80
Chris@16 81
Chris@16 82 template <typename T, typename P1, typename P2>
Chris@16 83 inline T calculate_angle(P1 const& from_point, P2 const& to_point)
Chris@16 84 {
Chris@16 85 typedef P1 vector_type;
Chris@16 86 vector_type v = from_point;
Chris@16 87 geometry::subtract_point(v, to_point);
Chris@16 88 return atan2(geometry::get<1>(v), geometry::get<0>(v));
Chris@16 89 }
Chris@16 90
Chris@16 91 template <typename Iterator, typename Vector>
Chris@16 92 inline Iterator advance_circular(Iterator it, Vector const& vector, segment_identifier& seg_id, bool forward = true)
Chris@16 93 {
Chris@16 94 int const increment = forward ? 1 : -1;
Chris@16 95 if (it == boost::begin(vector) && increment < 0)
Chris@16 96 {
Chris@16 97 it = boost::end(vector);
Chris@16 98 seg_id.segment_index = boost::size(vector);
Chris@16 99 }
Chris@16 100 it += increment;
Chris@16 101 seg_id.segment_index += increment;
Chris@16 102 if (it == boost::end(vector))
Chris@16 103 {
Chris@16 104 seg_id.segment_index = 0;
Chris@16 105 it = boost::begin(vector);
Chris@16 106 }
Chris@16 107 return it;
Chris@16 108 }
Chris@16 109
Chris@16 110 template <typename Point, typename T>
Chris@16 111 struct angle_info
Chris@16 112 {
Chris@16 113 typedef T angle_type;
Chris@16 114 typedef Point point_type;
Chris@16 115
Chris@16 116 segment_identifier seg_id;
Chris@16 117 int turn_index;
Chris@16 118 int operation_index;
Chris@16 119 Point intersection_point;
Chris@16 120 Point direction_point;
Chris@16 121 T angle;
Chris@16 122 bool incoming;
Chris@16 123 };
Chris@16 124
Chris@16 125 template <typename AngleInfo>
Chris@16 126 class occupation_info
Chris@16 127 {
Chris@16 128 typedef std::vector<AngleInfo> collection_type;
Chris@16 129
Chris@16 130 struct angle_sort
Chris@16 131 {
Chris@16 132 inline bool operator()(AngleInfo const& left, AngleInfo const& right) const
Chris@16 133 {
Chris@16 134 // In this case we can compare even double using equals
Chris@16 135 // return geometry::math::equals(left.angle, right.angle)
Chris@16 136 return left.angle == right.angle
Chris@16 137 ? int(left.incoming) < int(right.incoming)
Chris@16 138 : left.angle < right.angle
Chris@16 139 ;
Chris@16 140 }
Chris@16 141 };
Chris@16 142
Chris@16 143 public :
Chris@16 144 collection_type angles;
Chris@16 145 private :
Chris@16 146 bool m_occupied;
Chris@16 147 bool m_calculated;
Chris@16 148
Chris@16 149 inline bool is_occupied()
Chris@16 150 {
Chris@16 151 if (boost::size(angles) <= 1)
Chris@16 152 {
Chris@16 153 return false;
Chris@16 154 }
Chris@16 155
Chris@16 156 std::sort(angles.begin(), angles.end(), angle_sort());
Chris@16 157
Chris@16 158 typedef geometry::closing_iterator<collection_type const> closing_iterator;
Chris@16 159 closing_iterator vit(angles);
Chris@16 160 closing_iterator end(angles, true);
Chris@16 161
Chris@16 162 closing_iterator prev = vit++;
Chris@16 163 for( ; vit != end; prev = vit++)
Chris@16 164 {
Chris@16 165 if (! geometry::math::equals(prev->angle, vit->angle)
Chris@16 166 && ! prev->incoming
Chris@16 167 && vit->incoming)
Chris@16 168 {
Chris@16 169 return false;
Chris@16 170 }
Chris@16 171 }
Chris@16 172 return true;
Chris@16 173 }
Chris@16 174
Chris@16 175 public :
Chris@16 176 inline occupation_info()
Chris@16 177 : m_occupied(false)
Chris@16 178 , m_calculated(false)
Chris@16 179 {}
Chris@16 180
Chris@16 181 template <typename PointC, typename Point1, typename Point2>
Chris@16 182 inline void add(PointC const& map_point, Point1 const& direction_point, Point2 const& intersection_point,
Chris@16 183 int turn_index, int operation_index,
Chris@16 184 segment_identifier const& seg_id, bool incoming)
Chris@16 185 {
Chris@16 186 //std::cout << "-> adding angle " << geometry::wkt(direction_point) << " .. " << geometry::wkt(intersection_point) << " " << int(incoming) << std::endl;
Chris@16 187 if (geometry::equals(direction_point, intersection_point))
Chris@16 188 {
Chris@16 189 //std::cout << "EQUAL! Skipping" << std::endl;
Chris@16 190 return;
Chris@16 191 }
Chris@16 192
Chris@16 193 AngleInfo info;
Chris@16 194 info.incoming = incoming;
Chris@16 195 info.angle = calculate_angle<typename AngleInfo::angle_type>(direction_point, map_point);
Chris@16 196 info.seg_id = seg_id;
Chris@16 197 info.turn_index = turn_index;
Chris@16 198 info.operation_index = operation_index;
Chris@16 199 info.intersection_point = intersection_point;
Chris@16 200 info.direction_point = direction_point;
Chris@16 201 angles.push_back(info);
Chris@16 202
Chris@16 203 m_calculated = false;
Chris@16 204 }
Chris@16 205
Chris@16 206 inline bool occupied()
Chris@16 207 {
Chris@16 208 if (! m_calculated)
Chris@16 209 {
Chris@16 210 m_occupied = is_occupied();
Chris@16 211 m_calculated = true;
Chris@16 212 }
Chris@16 213 return m_occupied;
Chris@16 214 }
Chris@16 215
Chris@16 216 template <typename Turns, typename TurnSegmentIndices>
Chris@16 217 inline void get_left_turns(
Chris@16 218 Turns& turns, TurnSegmentIndices const& turn_segment_indices,
Chris@16 219 std::set<int>& keep_indices)
Chris@16 220 {
Chris@16 221 std::sort(angles.begin(), angles.end(), angle_sort());
Chris@16 222 calculate_left_turns<AngleInfo>(angles, turns, turn_segment_indices, keep_indices);
Chris@16 223 }
Chris@16 224 };
Chris@16 225
Chris@16 226
Chris@16 227 template <typename Point, typename Ring, typename Info>
Chris@16 228 inline void add_incoming_and_outgoing_angles(Point const& map_point, Point const& intersection_point,
Chris@16 229 Ring const& ring,
Chris@16 230 int turn_index,
Chris@16 231 int operation_index,
Chris@16 232 segment_identifier seg_id,
Chris@16 233 Info& info)
Chris@16 234 {
Chris@16 235 typedef typename boost::range_iterator
Chris@16 236 <
Chris@16 237 Ring const
Chris@16 238 >::type iterator_type;
Chris@16 239
Chris@16 240 int const n = boost::size(ring);
Chris@16 241 if (seg_id.segment_index >= n || seg_id.segment_index < 0)
Chris@16 242 {
Chris@16 243 return;
Chris@16 244 }
Chris@16 245
Chris@16 246 segment_identifier real_seg_id = seg_id;
Chris@16 247 iterator_type it = boost::begin(ring) + seg_id.segment_index;
Chris@16 248
Chris@16 249 // TODO: if we use turn-info ("to", "middle"), we know if to advance without resorting to equals
Chris@16 250 relaxed_less<Point> comparator;
Chris@16 251
Chris@16 252 if (comparator.equals(intersection_point, *it))
Chris@16 253 {
Chris@16 254 // It should be equal only once. But otherwise we skip it (in "add")
Chris@16 255 it = advance_circular(it, ring, seg_id, false);
Chris@16 256 }
Chris@16 257
Chris@16 258 info.add(map_point, *it, intersection_point, turn_index, operation_index, real_seg_id, true);
Chris@16 259
Chris@16 260 if (comparator.equals(intersection_point, *it))
Chris@16 261 {
Chris@16 262 it = advance_circular(it, ring, real_seg_id);
Chris@16 263 }
Chris@16 264 else
Chris@16 265 {
Chris@16 266 // Don't upgrade the ID
Chris@16 267 it = advance_circular(it, ring, seg_id);
Chris@16 268 }
Chris@16 269 for (int defensive_check = 0;
Chris@16 270 comparator.equals(intersection_point, *it) && defensive_check < n;
Chris@16 271 defensive_check++)
Chris@16 272 {
Chris@16 273 it = advance_circular(it, ring, real_seg_id);
Chris@16 274 }
Chris@16 275
Chris@16 276 info.add(map_point, *it, intersection_point, turn_index, operation_index, real_seg_id, false);
Chris@16 277 }
Chris@16 278
Chris@16 279
Chris@16 280 // Map in two senses of the word: it is a std::map where the key is a point.
Chris@16 281 // Per point an "occupation_info" record is kept
Chris@16 282 // Used for the buffer (but will also be used for intersections/unions having complex self-tangencies)
Chris@16 283 template <typename Point, typename OccupationInfo>
Chris@16 284 class occupation_map
Chris@16 285 {
Chris@16 286 public :
Chris@16 287 typedef std::map<Point, OccupationInfo, relaxed_less<Point> > map_type;
Chris@16 288
Chris@16 289 map_type map;
Chris@16 290 std::set<int> turn_indices;
Chris@16 291
Chris@16 292 inline OccupationInfo& find_or_insert(Point const& point, Point& mapped_point)
Chris@16 293 {
Chris@16 294 typename map_type::iterator it = map.find(point);
Chris@16 295 if (it == boost::end(map))
Chris@16 296 {
Chris@16 297 std::pair<typename map_type::iterator, bool> pair
Chris@16 298 = map.insert(std::make_pair(point, OccupationInfo()));
Chris@16 299 it = pair.first;
Chris@16 300 }
Chris@16 301 mapped_point = it->first;
Chris@16 302 return it->second;
Chris@16 303 }
Chris@16 304
Chris@16 305 inline bool contains(Point const& point) const
Chris@16 306 {
Chris@16 307 typename map_type::const_iterator it = map.find(point);
Chris@16 308 return it != boost::end(map);
Chris@16 309 }
Chris@16 310
Chris@16 311 inline bool contains_turn_index(int index) const
Chris@16 312 {
Chris@16 313 return turn_indices.count(index) > 0;
Chris@16 314 }
Chris@16 315
Chris@16 316 inline void insert_turn_index(int index)
Chris@16 317 {
Chris@16 318 turn_indices.insert(index);
Chris@16 319 }
Chris@16 320 };
Chris@16 321
Chris@16 322
Chris@16 323 } // namespace detail
Chris@16 324 #endif // DOXYGEN_NO_DETAIL
Chris@16 325
Chris@16 326
Chris@16 327 }} // namespace boost::geometry
Chris@16 328
Chris@16 329 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OCCUPATION_INFO_HPP