Chris@16: /* Chris@16: Copyright 2008 Intel Corporation Chris@16: Chris@16: Use, modification and distribution are subject to the Boost Software License, Chris@16: Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at Chris@16: http://www.boost.org/LICENSE_1_0.txt). Chris@16: */ Chris@16: #ifndef BOOST_POLYGON_POLYGON_45_TOUCH_HPP Chris@16: #define BOOST_POLYGON_POLYGON_45_TOUCH_HPP Chris@16: namespace boost { namespace polygon{ Chris@16: Chris@16: template Chris@16: struct polygon_45_touch { Chris@16: Chris@16: typedef point_data Point; Chris@16: typedef typename coordinate_traits::manhattan_area_type LongUnit; Chris@16: Chris@16: template Chris@16: static inline void merge_property_maps(property_map& mp, const property_map& mp2, bool subtract = false) { Chris@16: property_map newmp; Chris@16: newmp.reserve(mp.size() + mp2.size()); Chris@16: std::size_t i = 0; Chris@16: std::size_t j = 0; Chris@16: while(i != mp.size() && j != mp2.size()) { Chris@16: if(mp[i].first < mp2[j].first) { Chris@16: newmp.push_back(mp[i]); Chris@16: ++i; Chris@16: } else if(mp[i].first > mp2[j].first) { Chris@16: newmp.push_back(mp2[j]); Chris@16: if(subtract) newmp.back().second *= -1; Chris@16: ++j; Chris@16: } else { Chris@16: int count = mp[i].second; Chris@16: if(subtract) count -= mp2[j].second; Chris@16: else count += mp2[j].second; Chris@16: if(count) { Chris@16: newmp.push_back(mp[i]); Chris@16: newmp.back().second = count; Chris@16: } Chris@16: ++i; Chris@16: ++j; Chris@16: } Chris@16: } Chris@16: while(i != mp.size()) { Chris@16: newmp.push_back(mp[i]); Chris@16: ++i; Chris@16: } Chris@16: while(j != mp2.size()) { Chris@16: newmp.push_back(mp2[j]); Chris@16: if(subtract) newmp.back().second *= -1; Chris@16: ++j; Chris@16: } Chris@16: mp.swap(newmp); Chris@16: } Chris@16: Chris@16: class CountTouch { Chris@16: public: Chris@16: inline CountTouch() : counts() {} Chris@16: //inline CountTouch(int count) { counts[0] = counts[1] = count; } Chris@16: //inline CountTouch(int count1, int count2) { counts[0] = count1; counts[1] = count2; } Chris@16: inline CountTouch(const CountTouch& count) : counts(count.counts) {} Chris@16: inline bool operator==(const CountTouch& count) const { return counts == count.counts; } Chris@16: inline bool operator!=(const CountTouch& count) const { return !((*this) == count); } Chris@16: //inline CountTouch& operator=(int count) { counts[0] = counts[1] = count; return *this; } Chris@16: inline CountTouch& operator=(const CountTouch& count) { counts = count.counts; return *this; } Chris@16: inline int& operator[](int index) { Chris@16: std::vector >::iterator itr = Chris@16: std::lower_bound(counts.begin(), counts.end(), Chris@16: std::make_pair(index, int(0))); Chris@16: if(itr != counts.end() && itr->first == index) { Chris@16: return itr->second; Chris@16: } Chris@16: itr = counts.insert(itr, std::make_pair(index, int(0))); Chris@16: return itr->second; Chris@16: } Chris@16: // inline int operator[](int index) const { Chris@16: // std::vector >::const_iterator itr = counts.begin(); Chris@16: // for( ; itr != counts.end() && itr->first <= index; ++itr) { Chris@16: // if(itr->first == index) { Chris@16: // return itr->second; Chris@16: // } Chris@16: // } Chris@16: // return 0; Chris@16: // } Chris@16: inline CountTouch& operator+=(const CountTouch& count){ Chris@16: merge_property_maps(counts, count.counts, false); Chris@16: return *this; Chris@16: } Chris@16: inline CountTouch& operator-=(const CountTouch& count){ Chris@16: merge_property_maps(counts, count.counts, true); Chris@16: return *this; Chris@16: } Chris@16: inline CountTouch operator+(const CountTouch& count) const { Chris@16: return CountTouch(*this)+=count; Chris@16: } Chris@16: inline CountTouch operator-(const CountTouch& count) const { Chris@16: return CountTouch(*this)-=count; Chris@16: } Chris@16: inline CountTouch invert() const { Chris@16: CountTouch retval; Chris@16: retval -= *this; Chris@16: return retval; Chris@16: } Chris@16: std::vector > counts; Chris@16: }; Chris@16: Chris@16: typedef std::pair > >, std::map > > map_graph_o; Chris@16: typedef std::pair > >, std::vector > > vector_graph_o; Chris@16: Chris@16: template Chris@16: static void process_previous_x(cT& output) { Chris@16: std::map >& y_prop_map = output.first.second; Chris@16: for(typename std::map >::iterator itr = y_prop_map.begin(); Chris@16: itr != y_prop_map.end(); ++itr) { Chris@16: for(std::set::iterator inner_itr = itr->second.begin(); Chris@16: inner_itr != itr->second.end(); ++inner_itr) { Chris@16: std::set& output_edges = (*(output.second))[*inner_itr]; Chris@16: std::set::iterator inner_inner_itr = inner_itr; Chris@16: ++inner_inner_itr; Chris@16: for( ; inner_inner_itr != itr->second.end(); ++inner_inner_itr) { Chris@16: output_edges.insert(output_edges.end(), *inner_inner_itr); Chris@16: std::set& output_edges_2 = (*(output.second))[*inner_inner_itr]; Chris@16: output_edges_2.insert(output_edges_2.end(), *inner_itr); Chris@16: } Chris@16: } Chris@16: } Chris@16: y_prop_map.clear(); Chris@16: } Chris@16: Chris@16: struct touch_45_output_functor { Chris@16: template Chris@16: void operator()(cT& output, const CountTouch& count1, const CountTouch& count2, Chris@16: const Point& pt, int , direction_1d ) { Chris@16: Unit& x = output.first.first; Chris@16: std::map >& y_prop_map = output.first.second; Chris@16: if(pt.x() != x) process_previous_x(output); Chris@16: x = pt.x(); Chris@16: std::set& output_set = y_prop_map[pt.y()]; Chris@16: for(std::vector >::const_iterator itr1 = count1.counts.begin(); Chris@16: itr1 != count1.counts.end(); ++itr1) { Chris@16: if(itr1->second > 0) { Chris@16: output_set.insert(output_set.end(), itr1->first); Chris@16: } Chris@16: } Chris@16: for(std::vector >::const_iterator itr2 = count2.counts.begin(); Chris@16: itr2 != count2.counts.end(); ++itr2) { Chris@16: if(itr2->second > 0) { Chris@16: output_set.insert(output_set.end(), itr2->first); Chris@16: } Chris@16: } Chris@16: } Chris@16: }; Chris@16: typedef typename std::pair::template Scan45CountT > Vertex45Compact; Chris@16: typedef std::vector TouchSetData; Chris@16: Chris@16: struct lessVertex45Compact { Chris@16: bool operator()(const Vertex45Compact& l, const Vertex45Compact& r) { Chris@16: return l.first < r.first; Chris@16: } Chris@16: }; Chris@16: Chris@16: // template Chris@16: // static void print_tsd(TSD& tsd) { Chris@16: // for(std::size_t i = 0; i < tsd.size(); ++i) { Chris@16: // std::cout << tsd[i].first << ": "; Chris@16: // for(unsigned int r = 0; r < 4; ++r) { Chris@16: // std::cout << r << " { "; Chris@16: // for(std::vector >::iterator itr = tsd[i].second[r].counts.begin(); Chris@16: // itr != tsd[i].second[r].counts.end(); ++itr) { Chris@16: // std::cout << itr->first << "," << itr->second << " "; Chris@16: // } std::cout << "} "; Chris@16: // } Chris@16: // } std::cout << std::endl; Chris@16: // } Chris@16: Chris@16: // template Chris@16: // static void print_scanline(T& t) { Chris@16: // for(typename T::iterator itr = t.begin(); itr != t.end(); ++itr) { Chris@16: // std::cout << itr->x << "," << itr->y << " " << itr->rise << " "; Chris@16: // for(std::vector >::iterator itr2 = itr->count.counts.begin(); Chris@16: // itr2 != itr->count.counts.end(); ++itr2) { Chris@16: // std::cout << itr2->first << ":" << itr2->second << " "; Chris@16: // } std::cout << std::endl; Chris@16: // } Chris@16: // } Chris@16: Chris@16: template Chris@16: static void performTouch(graph_type& graph, TouchSetData& tsd) { Chris@16: Chris@16: polygon_sort(tsd.begin(), tsd.end(), lessVertex45Compact()); Chris@16: typedef std::vector::template Scan45CountT > > TSD; Chris@16: TSD tsd_; Chris@16: tsd_.reserve(tsd.size()); Chris@16: for(typename TouchSetData::iterator itr = tsd.begin(); itr != tsd.end(); ) { Chris@16: typename TouchSetData::iterator itr2 = itr; Chris@16: ++itr2; Chris@16: for(; itr2 != tsd.end() && itr2->first == itr->first; ++itr2) { Chris@16: (itr->second) += (itr2->second); //accumulate Chris@16: } Chris@16: tsd_.push_back(std::make_pair(itr->first, itr->second)); Chris@16: itr = itr2; Chris@16: } Chris@16: std::pair > >, graph_type*> output Chris@16: (std::make_pair(std::make_pair((std::numeric_limits::max)(), std::map >()), &graph)); Chris@16: typename boolean_op_45::template Scan45 scanline; Chris@16: for(typename TSD::iterator itr = tsd_.begin(); itr != tsd_.end(); ) { Chris@16: typename TSD::iterator itr2 = itr; Chris@16: ++itr2; Chris@16: while(itr2 != tsd_.end() && itr2->first.x() == itr->first.x()) { Chris@16: ++itr2; Chris@16: } Chris@16: scanline.scan(output, itr, itr2); Chris@16: itr = itr2; Chris@16: } Chris@16: process_previous_x(output); Chris@16: } Chris@16: Chris@16: template Chris@16: static void populateTouchSetData(TouchSetData& tsd, iT begin, iT end, int nodeCount) { Chris@16: for( ; begin != end; ++begin) { Chris@16: Vertex45Compact vertex; Chris@16: vertex.first = typename Vertex45Compact::first_type(begin->pt.x() * 2, begin->pt.y() * 2); Chris@16: tsd.push_back(vertex); Chris@16: for(unsigned int i = 0; i < 4; ++i) { Chris@16: if(begin->count[i]) { Chris@16: tsd.back().second[i][nodeCount] += begin->count[i]; Chris@16: } Chris@16: } Chris@16: } Chris@16: } Chris@16: Chris@16: }; Chris@16: Chris@16: Chris@16: } Chris@16: } Chris@16: #endif