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_PROPERTY_MERGE_45_HPP Chris@16: #define BOOST_POLYGON_PROPERTY_MERGE_45_HPP Chris@16: namespace boost { namespace polygon{ Chris@16: Chris@16: template Chris@16: struct polygon_45_property_merge { 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: polygon_45_touch::merge_property_maps(mp, mp2, subtract); Chris@16: } Chris@16: Chris@16: class CountMerge { Chris@16: public: Chris@16: inline CountMerge() : counts() {} Chris@16: //inline CountMerge(int count) { counts[0] = counts[1] = count; } Chris@16: //inline CountMerge(int count1, int count2) { counts[0] = count1; counts[1] = count2; } Chris@16: inline CountMerge(const CountMerge& count) : counts(count.counts) {} Chris@16: inline bool operator==(const CountMerge& count) const { return counts == count.counts; } Chris@16: inline bool operator!=(const CountMerge& count) const { return !((*this) == count); } Chris@16: //inline CountMerge& operator=(int count) { counts[0] = counts[1] = count; return *this; } Chris@16: inline CountMerge& operator=(const CountMerge& count) { counts = count.counts; return *this; } Chris@16: inline int& operator[](property_type index) { Chris@16: std::vector >::iterator itr = lower_bound(counts.begin(), counts.end(), 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 CountMerge& operator+=(const CountMerge& count){ Chris@16: merge_property_maps(counts, count.counts, false); Chris@16: return *this; Chris@16: } Chris@16: inline CountMerge& operator-=(const CountMerge& count){ Chris@16: merge_property_maps(counts, count.counts, true); Chris@16: return *this; Chris@16: } Chris@16: inline CountMerge operator+(const CountMerge& count) const { Chris@16: return CountMerge(*this)+=count; Chris@16: } Chris@16: inline CountMerge operator-(const CountMerge& count) const { Chris@16: return CountMerge(*this)-=count; Chris@16: } Chris@16: inline CountMerge invert() const { Chris@16: CountMerge retval; Chris@16: retval -= *this; Chris@16: return retval; Chris@16: } Chris@16: std::vector > counts; Chris@16: }; Chris@16: Chris@16: //output is a std::map, polygon_45_set_data > Chris@16: struct merge_45_output_functor { Chris@16: template Chris@16: void operator()(cT& output, const CountMerge& count1, const CountMerge& count2, Chris@16: const Point& pt, int rise, direction_1d end) { Chris@16: typedef typename cT::key_type keytype; Chris@16: keytype left; Chris@16: keytype right; Chris@16: int edgeType = end == LOW ? -1 : 1; Chris@16: for(typename std::vector >::const_iterator itr = count1.counts.begin(); Chris@16: itr != count1.counts.end(); ++itr) { Chris@16: left.insert(left.end(), (*itr).first); Chris@16: } Chris@16: for(typename std::vector >::const_iterator itr = count2.counts.begin(); Chris@16: itr != count2.counts.end(); ++itr) { Chris@16: right.insert(right.end(), (*itr).first); Chris@16: } Chris@16: if(left == right) return; Chris@16: if(!left.empty()) { Chris@16: //std::cout << pt.x() << " " << pt.y() << " " << rise << " " << edgeType << std::endl; Chris@16: output[left].insert_clean(typename boolean_op_45::Vertex45(pt, rise, -edgeType)); Chris@16: } Chris@16: if(!right.empty()) { Chris@16: //std::cout << pt.x() << " " << pt.y() << " " << rise << " " << -edgeType << std::endl; Chris@16: output[right].insert_clean(typename boolean_op_45::Vertex45(pt, rise, edgeType)); Chris@16: } Chris@16: } Chris@16: }; Chris@16: Chris@16: typedef typename std::pair::template Scan45CountT > Vertex45Compact; Chris@16: typedef std::vector MergeSetData; 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 performMerge(output_type& result, MergeSetData& 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 MergeSetData::iterator itr = tsd.begin(); itr != tsd.end(); ) { Chris@16: typename MergeSetData::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: 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(result, itr, itr2); Chris@16: itr = itr2; Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: static void populateMergeSetData(MergeSetData& tsd, iT begin, iT end, property_type property) { 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][property] += 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: } Chris@16: Chris@16: #endif