Chris@16
|
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
|
Chris@16
|
2
|
Chris@101
|
3 // Copyright (c) 2012-2014 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 #include <algorithm>
|
Chris@16
|
13 #include <boost/range.hpp>
|
Chris@16
|
14
|
Chris@16
|
15 #include <boost/geometry/core/coordinate_type.hpp>
|
Chris@16
|
16 #include <boost/geometry/core/point_type.hpp>
|
Chris@16
|
17
|
Chris@101
|
18 #include <boost/geometry/policies/compare.hpp>
|
Chris@16
|
19 #include <boost/geometry/iterators/closing_iterator.hpp>
|
Chris@16
|
20
|
Chris@16
|
21 #include <boost/geometry/algorithms/detail/get_left_turns.hpp>
|
Chris@16
|
22
|
Chris@16
|
23
|
Chris@16
|
24 namespace boost { namespace geometry
|
Chris@16
|
25 {
|
Chris@16
|
26
|
Chris@16
|
27
|
Chris@16
|
28 #ifndef DOXYGEN_NO_DETAIL
|
Chris@16
|
29 namespace detail
|
Chris@16
|
30 {
|
Chris@16
|
31
|
Chris@16
|
32 template <typename Point, typename T>
|
Chris@16
|
33 struct angle_info
|
Chris@16
|
34 {
|
Chris@16
|
35 typedef T angle_type;
|
Chris@16
|
36 typedef Point point_type;
|
Chris@16
|
37
|
Chris@16
|
38 segment_identifier seg_id;
|
Chris@16
|
39 int turn_index;
|
Chris@16
|
40 int operation_index;
|
Chris@101
|
41 std::size_t cluster_index;
|
Chris@16
|
42 Point intersection_point;
|
Chris@101
|
43 Point point; // either incoming or outgoing point
|
Chris@16
|
44 bool incoming;
|
Chris@101
|
45 bool blocked;
|
Chris@101
|
46 bool included;
|
Chris@101
|
47
|
Chris@101
|
48 inline angle_info()
|
Chris@101
|
49 : blocked(false)
|
Chris@101
|
50 , included(false)
|
Chris@101
|
51 {}
|
Chris@16
|
52 };
|
Chris@16
|
53
|
Chris@16
|
54 template <typename AngleInfo>
|
Chris@16
|
55 class occupation_info
|
Chris@16
|
56 {
|
Chris@101
|
57 public :
|
Chris@16
|
58 typedef std::vector<AngleInfo> collection_type;
|
Chris@16
|
59
|
Chris@101
|
60 int count;
|
Chris@16
|
61
|
Chris@16
|
62 inline occupation_info()
|
Chris@101
|
63 : count(0)
|
Chris@16
|
64 {}
|
Chris@16
|
65
|
Chris@101
|
66 template <typename RobustPoint>
|
Chris@101
|
67 inline void add(RobustPoint const& incoming_point,
|
Chris@101
|
68 RobustPoint const& outgoing_point,
|
Chris@101
|
69 RobustPoint const& intersection_point,
|
Chris@16
|
70 int turn_index, int operation_index,
|
Chris@101
|
71 segment_identifier const& seg_id)
|
Chris@16
|
72 {
|
Chris@101
|
73 geometry::equal_to<RobustPoint> comparator;
|
Chris@101
|
74 if (comparator(incoming_point, intersection_point))
|
Chris@16
|
75 {
|
Chris@101
|
76 return;
|
Chris@101
|
77 }
|
Chris@101
|
78 if (comparator(outgoing_point, intersection_point))
|
Chris@101
|
79 {
|
Chris@16
|
80 return;
|
Chris@16
|
81 }
|
Chris@16
|
82
|
Chris@16
|
83 AngleInfo info;
|
Chris@16
|
84 info.seg_id = seg_id;
|
Chris@16
|
85 info.turn_index = turn_index;
|
Chris@16
|
86 info.operation_index = operation_index;
|
Chris@16
|
87 info.intersection_point = intersection_point;
|
Chris@16
|
88
|
Chris@101
|
89 {
|
Chris@101
|
90 info.point = incoming_point;
|
Chris@101
|
91 info.incoming = true;
|
Chris@101
|
92 m_angles.push_back(info);
|
Chris@101
|
93 }
|
Chris@101
|
94 {
|
Chris@101
|
95 info.point = outgoing_point;
|
Chris@101
|
96 info.incoming = false;
|
Chris@101
|
97 m_angles.push_back(info);
|
Chris@101
|
98 }
|
Chris@16
|
99 }
|
Chris@16
|
100
|
Chris@101
|
101 template <typename RobustPoint, typename Turns>
|
Chris@101
|
102 inline void get_left_turns(RobustPoint const& origin, Turns& turns)
|
Chris@16
|
103 {
|
Chris@101
|
104 // Sort on angle
|
Chris@101
|
105 std::sort(m_angles.begin(), m_angles.end(),
|
Chris@101
|
106 detail::left_turns::angle_less<typename AngleInfo::point_type>(origin));
|
Chris@101
|
107
|
Chris@101
|
108 // Group same-angled elements
|
Chris@101
|
109 std::size_t cluster_size = detail::left_turns::assign_cluster_indices(m_angles, origin);
|
Chris@101
|
110 // Block all turns on the right side of any turn
|
Chris@101
|
111 detail::left_turns::block_turns(m_angles, cluster_size);
|
Chris@101
|
112 detail::left_turns::get_left_turns(m_angles, turns);
|
Chris@16
|
113 }
|
Chris@16
|
114
|
Chris@101
|
115 #if defined(BOOST_GEOMETRY_BUFFER_ENLARGED_CLUSTERS)
|
Chris@101
|
116 template <typename RobustPoint>
|
Chris@101
|
117 inline bool has_rounding_issues(RobustPoint const& origin) const
|
Chris@16
|
118 {
|
Chris@101
|
119 return detail::left_turns::has_rounding_issues(angles, origin);
|
Chris@16
|
120 }
|
Chris@101
|
121 #endif
|
Chris@101
|
122
|
Chris@101
|
123 private :
|
Chris@101
|
124 collection_type m_angles; // each turn splitted in incoming/outgoing vectors
|
Chris@16
|
125 };
|
Chris@16
|
126
|
Chris@101
|
127 template<typename Pieces>
|
Chris@101
|
128 inline void move_index(Pieces const& pieces, int& index, int& piece_index, int direction)
|
Chris@101
|
129 {
|
Chris@101
|
130 BOOST_ASSERT(direction == 1 || direction == -1);
|
Chris@101
|
131 BOOST_ASSERT(piece_index >= 0 && piece_index < static_cast<int>(boost::size(pieces)) );
|
Chris@101
|
132 BOOST_ASSERT(index >= 0 && index < static_cast<int>(boost::size(pieces[piece_index].robust_ring)));
|
Chris@16
|
133
|
Chris@101
|
134 index += direction;
|
Chris@101
|
135 if (direction == -1 && index < 0)
|
Chris@101
|
136 {
|
Chris@101
|
137 piece_index--;
|
Chris@101
|
138 if (piece_index < 0)
|
Chris@101
|
139 {
|
Chris@101
|
140 piece_index = boost::size(pieces) - 1;
|
Chris@101
|
141 }
|
Chris@101
|
142 index = boost::size(pieces[piece_index].robust_ring) - 1;
|
Chris@101
|
143 }
|
Chris@101
|
144 if (direction == 1
|
Chris@101
|
145 && index >= static_cast<int>(boost::size(pieces[piece_index].robust_ring)))
|
Chris@101
|
146 {
|
Chris@101
|
147 piece_index++;
|
Chris@101
|
148 if (piece_index >= static_cast<int>(boost::size(pieces)))
|
Chris@101
|
149 {
|
Chris@101
|
150 piece_index = 0;
|
Chris@101
|
151 }
|
Chris@101
|
152 index = 0;
|
Chris@101
|
153 }
|
Chris@101
|
154 }
|
Chris@101
|
155
|
Chris@101
|
156
|
Chris@101
|
157 template
|
Chris@101
|
158 <
|
Chris@101
|
159 typename RobustPoint,
|
Chris@101
|
160 typename Turn,
|
Chris@101
|
161 typename Pieces,
|
Chris@101
|
162 typename Info
|
Chris@101
|
163 >
|
Chris@101
|
164 inline void add_incoming_and_outgoing_angles(
|
Chris@101
|
165 RobustPoint const& intersection_point, // rescaled
|
Chris@101
|
166 Turn const& turn,
|
Chris@101
|
167 Pieces const& pieces, // using rescaled offsets of it
|
Chris@16
|
168 int operation_index,
|
Chris@16
|
169 segment_identifier seg_id,
|
Chris@16
|
170 Info& info)
|
Chris@16
|
171 {
|
Chris@101
|
172 segment_identifier real_seg_id = seg_id;
|
Chris@101
|
173 geometry::equal_to<RobustPoint> comparator;
|
Chris@16
|
174
|
Chris@101
|
175 // Move backward and forward
|
Chris@101
|
176 RobustPoint direction_points[2];
|
Chris@101
|
177 for (int i = 0; i < 2; i++)
|
Chris@16
|
178 {
|
Chris@101
|
179 int index = turn.operations[operation_index].index_in_robust_ring;
|
Chris@101
|
180 int piece_index = turn.operations[operation_index].piece_index;
|
Chris@101
|
181 while(comparator(pieces[piece_index].robust_ring[index], intersection_point))
|
Chris@101
|
182 {
|
Chris@101
|
183 move_index(pieces, index, piece_index, i == 0 ? -1 : 1);
|
Chris@101
|
184 }
|
Chris@101
|
185 direction_points[i] = pieces[piece_index].robust_ring[index];
|
Chris@16
|
186 }
|
Chris@16
|
187
|
Chris@101
|
188 info.add(direction_points[0], direction_points[1], intersection_point,
|
Chris@101
|
189 turn.turn_index, operation_index, real_seg_id);
|
Chris@16
|
190 }
|
Chris@16
|
191
|
Chris@16
|
192
|
Chris@16
|
193 } // namespace detail
|
Chris@16
|
194 #endif // DOXYGEN_NO_DETAIL
|
Chris@16
|
195
|
Chris@16
|
196
|
Chris@16
|
197 }} // namespace boost::geometry
|
Chris@16
|
198
|
Chris@16
|
199 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OCCUPATION_INFO_HPP
|