property_merge_45.hpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  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_PROPERTY_MERGE_45_HPP
  8. #define BOOST_POLYGON_PROPERTY_MERGE_45_HPP
  9. namespace boost { namespace polygon{
  10. template <typename Unit, typename property_type>
  11. struct polygon_45_property_merge {
  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. polygon_45_touch<Unit>::merge_property_maps(mp, mp2, subtract);
  17. }
  18. class CountMerge {
  19. public:
  20. inline CountMerge() : counts() {}
  21. //inline CountMerge(int count) { counts[0] = counts[1] = count; }
  22. //inline CountMerge(int count1, int count2) { counts[0] = count1; counts[1] = count2; }
  23. inline CountMerge(const CountMerge& count) : counts(count.counts) {}
  24. inline bool operator==(const CountMerge& count) const { return counts == count.counts; }
  25. inline bool operator!=(const CountMerge& count) const { return !((*this) == count); }
  26. //inline CountMerge& operator=(int count) { counts[0] = counts[1] = count; return *this; }
  27. inline CountMerge& operator=(const CountMerge& count) { counts = count.counts; return *this; }
  28. inline int& operator[](property_type index) {
  29. std::vector<std::pair<int, int> >::iterator itr = lower_bound(counts.begin(), counts.end(), std::make_pair(index, int(0)));
  30. if(itr != counts.end() && itr->first == index) {
  31. return itr->second;
  32. }
  33. itr = counts.insert(itr, std::make_pair(index, int(0)));
  34. return itr->second;
  35. }
  36. // inline int operator[](int index) const {
  37. // std::vector<std::pair<int, int> >::const_iterator itr = counts.begin();
  38. // for( ; itr != counts.end() && itr->first <= index; ++itr) {
  39. // if(itr->first == index) {
  40. // return itr->second;
  41. // }
  42. // }
  43. // return 0;
  44. // }
  45. inline CountMerge& operator+=(const CountMerge& count){
  46. merge_property_maps(counts, count.counts, false);
  47. return *this;
  48. }
  49. inline CountMerge& operator-=(const CountMerge& count){
  50. merge_property_maps(counts, count.counts, true);
  51. return *this;
  52. }
  53. inline CountMerge operator+(const CountMerge& count) const {
  54. return CountMerge(*this)+=count;
  55. }
  56. inline CountMerge operator-(const CountMerge& count) const {
  57. return CountMerge(*this)-=count;
  58. }
  59. inline CountMerge invert() const {
  60. CountMerge retval;
  61. retval -= *this;
  62. return retval;
  63. }
  64. std::vector<std::pair<property_type, int> > counts;
  65. };
  66. //output is a std::map<std::set<property_type>, polygon_45_set_data<Unit> >
  67. struct merge_45_output_functor {
  68. template <typename cT>
  69. void operator()(cT& output, const CountMerge& count1, const CountMerge& count2,
  70. const Point& pt, int rise, direction_1d end) {
  71. typedef typename cT::key_type keytype;
  72. keytype left;
  73. keytype right;
  74. int edgeType = end == LOW ? -1 : 1;
  75. for(typename std::vector<std::pair<property_type, int> >::const_iterator itr = count1.counts.begin();
  76. itr != count1.counts.end(); ++itr) {
  77. left.insert(left.end(), (*itr).first);
  78. }
  79. for(typename std::vector<std::pair<property_type, int> >::const_iterator itr = count2.counts.begin();
  80. itr != count2.counts.end(); ++itr) {
  81. right.insert(right.end(), (*itr).first);
  82. }
  83. if(left == right) return;
  84. if(!left.empty()) {
  85. //std::cout << pt.x() << " " << pt.y() << " " << rise << " " << edgeType << std::endl;
  86. output[left].insert_clean(typename boolean_op_45<Unit>::Vertex45(pt, rise, -edgeType));
  87. }
  88. if(!right.empty()) {
  89. //std::cout << pt.x() << " " << pt.y() << " " << rise << " " << -edgeType << std::endl;
  90. output[right].insert_clean(typename boolean_op_45<Unit>::Vertex45(pt, rise, edgeType));
  91. }
  92. }
  93. };
  94. typedef typename std::pair<Point,
  95. typename boolean_op_45<Unit>::template Scan45CountT<CountMerge> > Vertex45Compact;
  96. typedef std::vector<Vertex45Compact> MergeSetData;
  97. struct lessVertex45Compact {
  98. bool operator()(const Vertex45Compact& l, const Vertex45Compact& r) {
  99. return l.first < r.first;
  100. }
  101. };
  102. template <typename output_type>
  103. static void performMerge(output_type& result, MergeSetData& tsd) {
  104. polygon_sort(tsd.begin(), tsd.end(), lessVertex45Compact());
  105. typedef std::vector<std::pair<Point, typename boolean_op_45<Unit>::template Scan45CountT<CountMerge> > > TSD;
  106. TSD tsd_;
  107. tsd_.reserve(tsd.size());
  108. for(typename MergeSetData::iterator itr = tsd.begin(); itr != tsd.end(); ) {
  109. typename MergeSetData::iterator itr2 = itr;
  110. ++itr2;
  111. for(; itr2 != tsd.end() && itr2->first == itr->first; ++itr2) {
  112. (itr->second) += (itr2->second); //accumulate
  113. }
  114. tsd_.push_back(std::make_pair(itr->first, itr->second));
  115. itr = itr2;
  116. }
  117. typename boolean_op_45<Unit>::template Scan45<CountMerge, merge_45_output_functor> scanline;
  118. for(typename TSD::iterator itr = tsd_.begin(); itr != tsd_.end(); ) {
  119. typename TSD::iterator itr2 = itr;
  120. ++itr2;
  121. while(itr2 != tsd_.end() && itr2->first.x() == itr->first.x()) {
  122. ++itr2;
  123. }
  124. scanline.scan(result, itr, itr2);
  125. itr = itr2;
  126. }
  127. }
  128. template <typename iT>
  129. static void populateMergeSetData(MergeSetData& tsd, iT begin, iT end, property_type property) {
  130. for( ; begin != end; ++begin) {
  131. Vertex45Compact vertex;
  132. vertex.first = typename Vertex45Compact::first_type(begin->pt.x() * 2, begin->pt.y() * 2);
  133. tsd.push_back(vertex);
  134. for(unsigned int i = 0; i < 4; ++i) {
  135. if(begin->count[i]) {
  136. tsd.back().second[i][property] += begin->count[i];
  137. }
  138. }
  139. }
  140. }
  141. };
  142. }
  143. }
  144. #endif