Chris@16
|
1 /*
|
Chris@16
|
2 Copyright 2008 Intel Corporation
|
Chris@16
|
3
|
Chris@16
|
4 Use, modification and distribution are subject to the Boost Software License,
|
Chris@16
|
5 Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
6 http://www.boost.org/LICENSE_1_0.txt).
|
Chris@16
|
7 */
|
Chris@16
|
8 #ifndef BOOST_POLYGON_POLYGON_45_TOUCH_HPP
|
Chris@16
|
9 #define BOOST_POLYGON_POLYGON_45_TOUCH_HPP
|
Chris@16
|
10 namespace boost { namespace polygon{
|
Chris@16
|
11
|
Chris@16
|
12 template <typename Unit>
|
Chris@16
|
13 struct polygon_45_touch {
|
Chris@16
|
14
|
Chris@16
|
15 typedef point_data<Unit> Point;
|
Chris@16
|
16 typedef typename coordinate_traits<Unit>::manhattan_area_type LongUnit;
|
Chris@16
|
17
|
Chris@16
|
18 template <typename property_map>
|
Chris@16
|
19 static inline void merge_property_maps(property_map& mp, const property_map& mp2, bool subtract = false) {
|
Chris@16
|
20 property_map newmp;
|
Chris@16
|
21 newmp.reserve(mp.size() + mp2.size());
|
Chris@16
|
22 std::size_t i = 0;
|
Chris@16
|
23 std::size_t j = 0;
|
Chris@16
|
24 while(i != mp.size() && j != mp2.size()) {
|
Chris@16
|
25 if(mp[i].first < mp2[j].first) {
|
Chris@16
|
26 newmp.push_back(mp[i]);
|
Chris@16
|
27 ++i;
|
Chris@16
|
28 } else if(mp[i].first > mp2[j].first) {
|
Chris@16
|
29 newmp.push_back(mp2[j]);
|
Chris@16
|
30 if(subtract) newmp.back().second *= -1;
|
Chris@16
|
31 ++j;
|
Chris@16
|
32 } else {
|
Chris@16
|
33 int count = mp[i].second;
|
Chris@16
|
34 if(subtract) count -= mp2[j].second;
|
Chris@16
|
35 else count += mp2[j].second;
|
Chris@16
|
36 if(count) {
|
Chris@16
|
37 newmp.push_back(mp[i]);
|
Chris@16
|
38 newmp.back().second = count;
|
Chris@16
|
39 }
|
Chris@16
|
40 ++i;
|
Chris@16
|
41 ++j;
|
Chris@16
|
42 }
|
Chris@16
|
43 }
|
Chris@16
|
44 while(i != mp.size()) {
|
Chris@16
|
45 newmp.push_back(mp[i]);
|
Chris@16
|
46 ++i;
|
Chris@16
|
47 }
|
Chris@16
|
48 while(j != mp2.size()) {
|
Chris@16
|
49 newmp.push_back(mp2[j]);
|
Chris@16
|
50 if(subtract) newmp.back().second *= -1;
|
Chris@16
|
51 ++j;
|
Chris@16
|
52 }
|
Chris@16
|
53 mp.swap(newmp);
|
Chris@16
|
54 }
|
Chris@16
|
55
|
Chris@16
|
56 class CountTouch {
|
Chris@16
|
57 public:
|
Chris@16
|
58 inline CountTouch() : counts() {}
|
Chris@16
|
59 //inline CountTouch(int count) { counts[0] = counts[1] = count; }
|
Chris@16
|
60 //inline CountTouch(int count1, int count2) { counts[0] = count1; counts[1] = count2; }
|
Chris@16
|
61 inline CountTouch(const CountTouch& count) : counts(count.counts) {}
|
Chris@16
|
62 inline bool operator==(const CountTouch& count) const { return counts == count.counts; }
|
Chris@16
|
63 inline bool operator!=(const CountTouch& count) const { return !((*this) == count); }
|
Chris@16
|
64 //inline CountTouch& operator=(int count) { counts[0] = counts[1] = count; return *this; }
|
Chris@16
|
65 inline CountTouch& operator=(const CountTouch& count) { counts = count.counts; return *this; }
|
Chris@16
|
66 inline int& operator[](int index) {
|
Chris@16
|
67 std::vector<std::pair<int, int> >::iterator itr =
|
Chris@16
|
68 std::lower_bound(counts.begin(), counts.end(),
|
Chris@16
|
69 std::make_pair(index, int(0)));
|
Chris@16
|
70 if(itr != counts.end() && itr->first == index) {
|
Chris@16
|
71 return itr->second;
|
Chris@16
|
72 }
|
Chris@16
|
73 itr = counts.insert(itr, std::make_pair(index, int(0)));
|
Chris@16
|
74 return itr->second;
|
Chris@16
|
75 }
|
Chris@16
|
76 // inline int operator[](int index) const {
|
Chris@16
|
77 // std::vector<std::pair<int, int> >::const_iterator itr = counts.begin();
|
Chris@16
|
78 // for( ; itr != counts.end() && itr->first <= index; ++itr) {
|
Chris@16
|
79 // if(itr->first == index) {
|
Chris@16
|
80 // return itr->second;
|
Chris@16
|
81 // }
|
Chris@16
|
82 // }
|
Chris@16
|
83 // return 0;
|
Chris@16
|
84 // }
|
Chris@16
|
85 inline CountTouch& operator+=(const CountTouch& count){
|
Chris@16
|
86 merge_property_maps(counts, count.counts, false);
|
Chris@16
|
87 return *this;
|
Chris@16
|
88 }
|
Chris@16
|
89 inline CountTouch& operator-=(const CountTouch& count){
|
Chris@16
|
90 merge_property_maps(counts, count.counts, true);
|
Chris@16
|
91 return *this;
|
Chris@16
|
92 }
|
Chris@16
|
93 inline CountTouch operator+(const CountTouch& count) const {
|
Chris@16
|
94 return CountTouch(*this)+=count;
|
Chris@16
|
95 }
|
Chris@16
|
96 inline CountTouch operator-(const CountTouch& count) const {
|
Chris@16
|
97 return CountTouch(*this)-=count;
|
Chris@16
|
98 }
|
Chris@16
|
99 inline CountTouch invert() const {
|
Chris@16
|
100 CountTouch retval;
|
Chris@16
|
101 retval -= *this;
|
Chris@16
|
102 return retval;
|
Chris@16
|
103 }
|
Chris@16
|
104 std::vector<std::pair<int, int> > counts;
|
Chris@16
|
105 };
|
Chris@16
|
106
|
Chris@16
|
107 typedef std::pair<std::pair<Unit, std::map<Unit, std::set<int> > >, std::map<int, std::set<int> > > map_graph_o;
|
Chris@16
|
108 typedef std::pair<std::pair<Unit, std::map<Unit, std::set<int> > >, std::vector<std::set<int> > > vector_graph_o;
|
Chris@16
|
109
|
Chris@16
|
110 template <typename cT>
|
Chris@16
|
111 static void process_previous_x(cT& output) {
|
Chris@16
|
112 std::map<Unit, std::set<int> >& y_prop_map = output.first.second;
|
Chris@16
|
113 for(typename std::map<Unit, std::set<int> >::iterator itr = y_prop_map.begin();
|
Chris@16
|
114 itr != y_prop_map.end(); ++itr) {
|
Chris@16
|
115 for(std::set<int>::iterator inner_itr = itr->second.begin();
|
Chris@16
|
116 inner_itr != itr->second.end(); ++inner_itr) {
|
Chris@16
|
117 std::set<int>& output_edges = (*(output.second))[*inner_itr];
|
Chris@16
|
118 std::set<int>::iterator inner_inner_itr = inner_itr;
|
Chris@16
|
119 ++inner_inner_itr;
|
Chris@16
|
120 for( ; inner_inner_itr != itr->second.end(); ++inner_inner_itr) {
|
Chris@16
|
121 output_edges.insert(output_edges.end(), *inner_inner_itr);
|
Chris@16
|
122 std::set<int>& output_edges_2 = (*(output.second))[*inner_inner_itr];
|
Chris@16
|
123 output_edges_2.insert(output_edges_2.end(), *inner_itr);
|
Chris@16
|
124 }
|
Chris@16
|
125 }
|
Chris@16
|
126 }
|
Chris@16
|
127 y_prop_map.clear();
|
Chris@16
|
128 }
|
Chris@16
|
129
|
Chris@16
|
130 struct touch_45_output_functor {
|
Chris@16
|
131 template <typename cT>
|
Chris@16
|
132 void operator()(cT& output, const CountTouch& count1, const CountTouch& count2,
|
Chris@16
|
133 const Point& pt, int , direction_1d ) {
|
Chris@16
|
134 Unit& x = output.first.first;
|
Chris@16
|
135 std::map<Unit, std::set<int> >& y_prop_map = output.first.second;
|
Chris@16
|
136 if(pt.x() != x) process_previous_x(output);
|
Chris@16
|
137 x = pt.x();
|
Chris@16
|
138 std::set<int>& output_set = y_prop_map[pt.y()];
|
Chris@16
|
139 for(std::vector<std::pair<int, int> >::const_iterator itr1 = count1.counts.begin();
|
Chris@16
|
140 itr1 != count1.counts.end(); ++itr1) {
|
Chris@16
|
141 if(itr1->second > 0) {
|
Chris@16
|
142 output_set.insert(output_set.end(), itr1->first);
|
Chris@16
|
143 }
|
Chris@16
|
144 }
|
Chris@16
|
145 for(std::vector<std::pair<int, int> >::const_iterator itr2 = count2.counts.begin();
|
Chris@16
|
146 itr2 != count2.counts.end(); ++itr2) {
|
Chris@16
|
147 if(itr2->second > 0) {
|
Chris@16
|
148 output_set.insert(output_set.end(), itr2->first);
|
Chris@16
|
149 }
|
Chris@16
|
150 }
|
Chris@16
|
151 }
|
Chris@16
|
152 };
|
Chris@16
|
153 typedef typename std::pair<Point,
|
Chris@16
|
154 typename boolean_op_45<Unit>::template Scan45CountT<CountTouch> > Vertex45Compact;
|
Chris@16
|
155 typedef std::vector<Vertex45Compact> TouchSetData;
|
Chris@16
|
156
|
Chris@16
|
157 struct lessVertex45Compact {
|
Chris@16
|
158 bool operator()(const Vertex45Compact& l, const Vertex45Compact& r) {
|
Chris@16
|
159 return l.first < r.first;
|
Chris@16
|
160 }
|
Chris@16
|
161 };
|
Chris@16
|
162
|
Chris@16
|
163 // template <typename TSD>
|
Chris@16
|
164 // static void print_tsd(TSD& tsd) {
|
Chris@16
|
165 // for(std::size_t i = 0; i < tsd.size(); ++i) {
|
Chris@16
|
166 // std::cout << tsd[i].first << ": ";
|
Chris@16
|
167 // for(unsigned int r = 0; r < 4; ++r) {
|
Chris@16
|
168 // std::cout << r << " { ";
|
Chris@16
|
169 // for(std::vector<std::pair<int, int> >::iterator itr = tsd[i].second[r].counts.begin();
|
Chris@16
|
170 // itr != tsd[i].second[r].counts.end(); ++itr) {
|
Chris@16
|
171 // std::cout << itr->first << "," << itr->second << " ";
|
Chris@16
|
172 // } std::cout << "} ";
|
Chris@16
|
173 // }
|
Chris@16
|
174 // } std::cout << std::endl;
|
Chris@16
|
175 // }
|
Chris@16
|
176
|
Chris@16
|
177 // template <typename T>
|
Chris@16
|
178 // static void print_scanline(T& t) {
|
Chris@16
|
179 // for(typename T::iterator itr = t.begin(); itr != t.end(); ++itr) {
|
Chris@16
|
180 // std::cout << itr->x << "," << itr->y << " " << itr->rise << " ";
|
Chris@16
|
181 // for(std::vector<std::pair<int, int> >::iterator itr2 = itr->count.counts.begin();
|
Chris@16
|
182 // itr2 != itr->count.counts.end(); ++itr2) {
|
Chris@16
|
183 // std::cout << itr2->first << ":" << itr2->second << " ";
|
Chris@16
|
184 // } std::cout << std::endl;
|
Chris@16
|
185 // }
|
Chris@16
|
186 // }
|
Chris@16
|
187
|
Chris@16
|
188 template <typename graph_type>
|
Chris@16
|
189 static void performTouch(graph_type& graph, TouchSetData& tsd) {
|
Chris@16
|
190
|
Chris@16
|
191 polygon_sort(tsd.begin(), tsd.end(), lessVertex45Compact());
|
Chris@16
|
192 typedef std::vector<std::pair<Point, typename boolean_op_45<Unit>::template Scan45CountT<CountTouch> > > TSD;
|
Chris@16
|
193 TSD tsd_;
|
Chris@16
|
194 tsd_.reserve(tsd.size());
|
Chris@16
|
195 for(typename TouchSetData::iterator itr = tsd.begin(); itr != tsd.end(); ) {
|
Chris@16
|
196 typename TouchSetData::iterator itr2 = itr;
|
Chris@16
|
197 ++itr2;
|
Chris@16
|
198 for(; itr2 != tsd.end() && itr2->first == itr->first; ++itr2) {
|
Chris@16
|
199 (itr->second) += (itr2->second); //accumulate
|
Chris@16
|
200 }
|
Chris@16
|
201 tsd_.push_back(std::make_pair(itr->first, itr->second));
|
Chris@16
|
202 itr = itr2;
|
Chris@16
|
203 }
|
Chris@16
|
204 std::pair<std::pair<Unit, std::map<Unit, std::set<int> > >, graph_type*> output
|
Chris@16
|
205 (std::make_pair(std::make_pair((std::numeric_limits<Unit>::max)(), std::map<Unit, std::set<int> >()), &graph));
|
Chris@16
|
206 typename boolean_op_45<Unit>::template Scan45<CountTouch, touch_45_output_functor> scanline;
|
Chris@16
|
207 for(typename TSD::iterator itr = tsd_.begin(); itr != tsd_.end(); ) {
|
Chris@16
|
208 typename TSD::iterator itr2 = itr;
|
Chris@16
|
209 ++itr2;
|
Chris@16
|
210 while(itr2 != tsd_.end() && itr2->first.x() == itr->first.x()) {
|
Chris@16
|
211 ++itr2;
|
Chris@16
|
212 }
|
Chris@16
|
213 scanline.scan(output, itr, itr2);
|
Chris@16
|
214 itr = itr2;
|
Chris@16
|
215 }
|
Chris@16
|
216 process_previous_x(output);
|
Chris@16
|
217 }
|
Chris@16
|
218
|
Chris@16
|
219 template <typename iT>
|
Chris@16
|
220 static void populateTouchSetData(TouchSetData& tsd, iT begin, iT end, int nodeCount) {
|
Chris@16
|
221 for( ; begin != end; ++begin) {
|
Chris@16
|
222 Vertex45Compact vertex;
|
Chris@16
|
223 vertex.first = typename Vertex45Compact::first_type(begin->pt.x() * 2, begin->pt.y() * 2);
|
Chris@16
|
224 tsd.push_back(vertex);
|
Chris@16
|
225 for(unsigned int i = 0; i < 4; ++i) {
|
Chris@16
|
226 if(begin->count[i]) {
|
Chris@16
|
227 tsd.back().second[i][nodeCount] += begin->count[i];
|
Chris@16
|
228 }
|
Chris@16
|
229 }
|
Chris@16
|
230 }
|
Chris@16
|
231 }
|
Chris@16
|
232
|
Chris@16
|
233 };
|
Chris@16
|
234
|
Chris@16
|
235
|
Chris@16
|
236 }
|
Chris@16
|
237 }
|
Chris@16
|
238 #endif
|