polygon_45_touch.hpp 9.1 KB

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