From 75b5c2474f150fa3878523b8fc211ead3c552e22 Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Sat, 31 Jul 2010 14:26:07 +0200 Subject: [PATCH] Updated boost::polygon from http://svn.boost.org/svn/boost/trunk/boost/polygon (boost 1.44) Seems fix some issues. --- CMakeLists.txt | 4 +- .../detail/iterator_geometry_to_set.hpp | 14 +- .../polygon/detail/polygon_45_formation.hpp | 14 +- .../polygon/detail/polygon_45_set_view.hpp | 4 +- .../polygon/detail/polygon_90_set_view.hpp | 4 +- .../boost/polygon/detail/polygon_90_touch.hpp | 2 +- .../detail/polygon_arbitrary_formation.hpp | 63 +- .../polygon/detail/polygon_formation.hpp | 2 +- .../boost/polygon/detail/polygon_set_view.hpp | 4 +- .../boost/polygon/detail/scan_arbitrary.hpp | 578 +++++++++--------- include/boost/polygon/point_data.hpp | 18 +- include/boost/polygon/polygon_45_data.hpp | 2 +- include/boost/polygon/polygon_45_set_data.hpp | 6 +- .../boost/polygon/polygon_45_set_traits.hpp | 2 +- .../polygon/polygon_45_with_holes_data.hpp | 4 +- include/boost/polygon/polygon_90_set_data.hpp | 304 ++++++++- include/boost/polygon/polygon_data.hpp | 2 +- include/boost/polygon/polygon_set_data.hpp | 238 ++++++-- include/boost/polygon/polygon_set_traits.hpp | 2 +- .../boost/polygon/polygon_with_holes_data.hpp | 2 +- ...nvert_brd_items_to_polygons_with_Boost.cpp | 99 --- 21 files changed, 878 insertions(+), 490 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b0114ea05..d0f273ff14 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,10 +19,10 @@ option(KICAD_MINIZIP "enable/disable building minizip (default ON)" ON) option(wxUSE_UNICODE "enable/disable building unicode (default OFF)") option(KICAD_GOST "enable/disable building using GOST notation for multiple gates per package (default OFF)") -option(USE_WX_ZOOM "Use wxDC to perform zooming (default OFF). Warning, this is experimental" ) +option(USE_WX_ZOOM "Use wxDC to perform zooming (default OFF). Warning, this is experimental" ) option(USE_WX_GRAPHICS_CONTEXT - "Use wxGraphicsContext for rendering (default OFF). Warning, this is experimental") + "Use wxGraphicsContext for rendering (default OFF). Warning, this is experimental") option(USE_BOOST_POLYGON_LIBRARY "Use boost polygon library instead of Kbool to calculate filled areas in zones (default OFF). Warning, this is experimental") diff --git a/include/boost/polygon/detail/iterator_geometry_to_set.hpp b/include/boost/polygon/detail/iterator_geometry_to_set.hpp index 8162eba181..ede9255b9d 100644 --- a/include/boost/polygon/detail/iterator_geometry_to_set.hpp +++ b/include/boost/polygon/detail/iterator_geometry_to_set.hpp @@ -29,7 +29,7 @@ private: public: iterator_geometry_to_set() : rectangle_(), vertex_(), corner_(4), orient_(), is_hole_() {} iterator_geometry_to_set(const rectangle_type& rectangle, direction_1d dir, - orientation_2d orient = HORIZONTAL, bool is_hole = false) : + orientation_2d orient = HORIZONTAL, bool is_hole = false, bool = false, direction_1d = CLOCKWISE) : rectangle_(), vertex_(), corner_(0), orient_(orient), is_hole_(is_hole) { assign(rectangle_, rectangle); if(dir == HIGH) corner_ = 4; @@ -93,7 +93,7 @@ private: int polygon_index; public: iterator_geometry_to_set() : vertex_(), itrb(), itre(), last_vertex_(), is_hole_(), multiplier_(), first_pt(), second_pt(), pts(), use_wrap(), orient_(), polygon_index(-1) {} - iterator_geometry_to_set(const polygon_type& polygon, direction_1d dir, orientation_2d orient = HORIZONTAL, bool is_hole = false) : + iterator_geometry_to_set(const polygon_type& polygon, direction_1d dir, orientation_2d orient = HORIZONTAL, bool is_hole = false, bool winding_override = false, direction_1d w = CLOCKWISE) : vertex_(), itrb(), itre(), last_vertex_(), is_hole_(is_hole), multiplier_(), first_pt(), second_pt(), pts(), use_wrap(), orient_(orient), polygon_index(0) { @@ -103,7 +103,9 @@ public: if(itrb == itre || dir == HIGH || size(polygon) < 4) { polygon_index = -1; } else { - direction_1d wdir = winding(polygon); + direction_1d wdir = w; + if(!winding_override) + wdir = winding(polygon); multiplier_ = wdir == LOW ? -1 : 1; if(is_hole_) multiplier_ *= -1; first_pt = pts[0] = *itrb; @@ -182,9 +184,7 @@ public: vertex_.second.first =pts[1].get(orient_); if(pts[1] == pts[2]) { vertex_.second.second = 0; - return; - } - if(pts[0].get(HORIZONTAL) != pts[1].get(HORIZONTAL)) { + } else if(pts[0].get(HORIZONTAL) != pts[1].get(HORIZONTAL)) { vertex_.second.second = -1; } else if(pts[0].get(VERTICAL) != pts[1].get(VERTICAL)) { vertex_.second.second = 1; @@ -214,7 +214,7 @@ private: public: iterator_geometry_to_set() : itrb(), itre(), itrhib(), itrhie(), itrhb(), itrhe(), orient_(), is_hole_(), started_holes() {} iterator_geometry_to_set(const polygon_with_holes_type& polygon, direction_1d dir, - orientation_2d orient = HORIZONTAL, bool is_hole = false) : + orientation_2d orient = HORIZONTAL, bool is_hole = false, bool = false, direction_1d = CLOCKWISE) : itrb(), itre(), itrhib(), itrhie(), itrhb(), itrhe(), orient_(orient), is_hole_(is_hole), started_holes() { itre = iterator_geometry_to_set(polygon, HIGH, orient, is_hole_); itrhe = end_holes(polygon); diff --git a/include/boost/polygon/detail/polygon_45_formation.hpp b/include/boost/polygon/detail/polygon_45_formation.hpp index 730025c3c8..67b2ca2d5d 100644 --- a/include/boost/polygon/detail/polygon_45_formation.hpp +++ b/include/boost/polygon/detail/polygon_45_formation.hpp @@ -251,12 +251,14 @@ namespace boost { namespace polygon{ return; } Unit firstY = (*iter).y(); + Unit firstX = (*iter).x(); ++iter; if(iter == tailp_->points.end()) { tailp_->points.push_front(point); return; } - if(iter->y() == point.y() && firstY == point.y()) { + if((iter->y() == point.y() && firstY == point.y()) || + (iter->x() == point.x() && firstX == point.x())){ --iter; *iter = point; } else { @@ -274,12 +276,14 @@ namespace boost { namespace polygon{ return; } Unit firstY = (*iter).y(); + Unit firstX = (*iter).x(); ++iter; if(iter == tailp_->points.rend()) { tailp_->points.push_back(point); return; } - if(iter->y() == point.y() && firstY == point.y()) { + if((iter->y() == point.y() && firstY == point.y()) || + (iter->x() == point.x() && firstX == point.x())){ --iter; *iter = point; } else { @@ -474,7 +478,7 @@ namespace boost { namespace polygon{ ct counts[4]; }; - typedef Vertex45CountT Vertex45Count; + typedef Vertex45CountT Vertex45Count; // inline std::ostream& operator<< (std::ostream& o, const Vertex45Count& c) { // o << c[0] << ", " << c[1] << ", "; @@ -492,7 +496,8 @@ namespace boost { namespace polygon{ inline Vertex45CompactT(const Point& point, int riseIn, int countIn) : pt(point), count() { count[riseIn+1] = countIn; } - inline Vertex45CompactT(const Vertex45T& vertex) : pt(vertex.pt), count() { + template + inline Vertex45CompactT(const typename boolean_op_45::template Vertex45T& vertex) : pt(vertex.pt), count() { count[vertex.rise+1] = vertex.count; } inline Vertex45CompactT(const Vertex45CompactT& vertex) : pt(vertex.pt), count(vertex.count) {} @@ -2244,6 +2249,7 @@ namespace boost { namespace polygon{ struct geometry_concept > { typedef polygon_45_with_holes_concept type; }; template struct geometry_concept > { typedef polygon_45_concept type; }; + } } #endif diff --git a/include/boost/polygon/detail/polygon_45_set_view.hpp b/include/boost/polygon/detail/polygon_45_set_view.hpp index f5cb18e7f7..61f7ec4642 100644 --- a/include/boost/polygon/detail/polygon_45_set_view.hpp +++ b/include/boost/polygon/detail/polygon_45_set_view.hpp @@ -124,13 +124,13 @@ namespace boost { namespace polygon{ }; template - typename polygon_45_set_view::iterator_type + typename polygon_45_set_traits >::iterator_type polygon_45_set_traits >:: begin(const polygon_45_set_view& polygon_45_set) { return polygon_45_set.begin(); } template - typename polygon_45_set_view::iterator_type + typename polygon_45_set_traits >::iterator_type polygon_45_set_traits >:: end(const polygon_45_set_view& polygon_45_set) { return polygon_45_set.end(); diff --git a/include/boost/polygon/detail/polygon_90_set_view.hpp b/include/boost/polygon/detail/polygon_90_set_view.hpp index 2d31c2c3b0..825b1d3278 100644 --- a/include/boost/polygon/detail/polygon_90_set_view.hpp +++ b/include/boost/polygon/detail/polygon_90_set_view.hpp @@ -140,13 +140,13 @@ namespace boost { namespace polygon{ }; template - typename polygon_90_set_view::iterator_type + typename polygon_90_set_traits >::iterator_type polygon_90_set_traits >:: begin(const polygon_90_set_view& polygon_set) { return polygon_set.begin(); } template - typename polygon_90_set_view::iterator_type + typename polygon_90_set_traits >::iterator_type polygon_90_set_traits >:: end(const polygon_90_set_view& polygon_set) { return polygon_set.end(); diff --git a/include/boost/polygon/detail/polygon_90_touch.hpp b/include/boost/polygon/detail/polygon_90_touch.hpp index 38f0fd5278..fdbf261c69 100644 --- a/include/boost/polygon/detail/polygon_90_touch.hpp +++ b/include/boost/polygon/detail/polygon_90_touch.hpp @@ -42,7 +42,7 @@ namespace boost { namespace polygon{ ivlIds_.second = that.ivlIds_.second; incremented_ = that.incremented_; return *this; - }; + } inline bool operator==(const iterator& that) { return itr_ == that.itr_; } inline bool operator!=(const iterator& that) { return itr_ != that.itr_; } inline iterator& operator++() { diff --git a/include/boost/polygon/detail/polygon_arbitrary_formation.hpp b/include/boost/polygon/detail/polygon_arbitrary_formation.hpp index 4d0771ab85..aae4133466 100644 --- a/include/boost/polygon/detail/polygon_arbitrary_formation.hpp +++ b/include/boost/polygon/detail/polygon_arbitrary_formation.hpp @@ -388,7 +388,8 @@ namespace boost { namespace polygon{ struct compute_intersection_pack { typedef typename high_precision_type::type high_precision; high_precision y_high, dx1, dy1, dx2, dy2, x11, x21, y11, y21, x_num, y_num, x_den, y_den, x, y; - static inline bool compute_lazy_intersection(Point& intersection, const half_edge& he1, const half_edge& he2, bool projected = false) { + static inline bool compute_lazy_intersection(Point& intersection, const half_edge& he1, const half_edge& he2, + bool projected = false, bool round_closest = false) { long double y_high, dx1, dy1, dx2, dy2, x11, x21, y11, y21, x_num, y_num, x_den, y_den, x, y; typedef rectangle_data Rectangle; Rectangle rect1, rect2; @@ -445,6 +446,10 @@ namespace boost { namespace polygon{ //std::cout << "cross2 " << dy2 << " " << dx1 << " " << dy2 * dx1 << std::endl; //Unit exp_x = compute_x_intercept(x11, x21, y11, y21, dy1, dy2, dx1, dx2); //Unit exp_y = compute_x_intercept(y11, y21, x11, x21, dx1, dx2, dy1, dy2); + if(round_closest) { + x = x + 0.5; + y = y + 0.5; + } Unit x_unit = (Unit)(x); Unit y_unit = (Unit)(y); //truncate downward if it went up due to negative number @@ -463,12 +468,17 @@ namespace boost { namespace polygon{ (long double) (std::numeric_limits::min)(), (long double)(std::numeric_limits::max)(), (long double) (std::numeric_limits::max)() ); - return contains(inf_rect, intersection, true); + if(contains(inf_rect, intersection, true)) { + intersection = result; + return true; + } else + return false; } intersection = result; return true; } - inline bool compute_intersection(Point& intersection, const half_edge& he1, const half_edge& he2, bool projected = false) { + inline bool compute_intersection(Point& intersection, const half_edge& he1, const half_edge& he2, + bool projected = false, bool round_closest = false) { if(!projected && !intersects(he1, he2)) return false; bool lazy_success = compute_lazy_intersection(intersection, he1, he2, projected); @@ -536,6 +546,10 @@ namespace boost { namespace polygon{ //std::cout << "cross2 " << dy2 << " " << dx1 << " " << dy2 * dx1 << std::endl; //Unit exp_x = compute_x_intercept(x11, x21, y11, y21, dy1, dy2, dx1, dx2); //Unit exp_y = compute_x_intercept(y11, y21, x11, x21, dx1, dx2, dy1, dy2); + if(round_closest) { + x = x + (high_precision)0.5; + y = y + (high_precision)0.5; + } Unit x_unit = convert_high_precision_type(x); Unit y_unit = convert_high_precision_type(y); //truncate downward if it went up due to negative number @@ -549,6 +563,17 @@ namespace boost { namespace polygon{ Point result(x_unit, y_unit); if(!contains(rect1, result, true)) return false; if(!contains(rect2, result, true)) return false; + if(projected) { + rectangle_data inf_rect((long double)(std::numeric_limits::min)(), + (long double) (std::numeric_limits::min)(), + (long double)(std::numeric_limits::max)(), + (long double) (std::numeric_limits::max)() ); + if(contains(inf_rect, intersection, true)) { + intersection = result; + return true; + } else + return false; + } intersection = result; return true; } @@ -872,7 +897,7 @@ namespace boost { namespace polygon{ inline active_tail_arbitrary(const vertex_half_edge& vertex, active_tail_arbitrary* otherTailp = 0) : tailp_(), otherTailp_(), holesList_(), head_() { tailp_ = new poly_line_arbitrary; tailp_->points.push_back(vertex.pt); - bool headArray[4] = {false, true, true, true}; + //bool headArray[4] = {false, true, true, true}; bool inverted = vertex.count == -1; head_ = (!vertex.is_vertical) ^ inverted; otherTailp_ = otherTailp; @@ -1172,7 +1197,7 @@ namespace boost { namespace polygon{ inline less_half_edge_count() : pt_() {} inline less_half_edge_count(Point point) : pt_(point) {} inline bool operator () (const std::pair& elm1, const std::pair& elm2) const { - return less_slope(pt_.get(HORIZONTAL), pt_.get(VERTICAL), elm1.first, elm2.first); + return scanline_base::less_slope(pt_.get(HORIZONTAL), pt_.get(VERTICAL), elm1.first, elm2.first); } }; @@ -1196,7 +1221,7 @@ namespace boost { namespace polygon{ Unit dx2 = elm2.first.first.first.get(HORIZONTAL) - elm2.first.first.second.get(HORIZONTAL); Unit dy1 = elm1.first.first.first.get(VERTICAL) - elm1.first.first.second.get(VERTICAL); Unit dy2 = elm2.first.first.first.get(VERTICAL) - elm2.first.first.second.get(VERTICAL); - return less_slope(dx1, dy1, dx2, dy2); + return scanline_base::less_slope(dx1, dy1, dx2, dy2); } }; @@ -1356,7 +1381,7 @@ namespace boost { namespace polygon{ bool have_vertical_tail_from_below = false; if(c_size && - is_vertical(counts_from_scanline.back().first.first)) { + scanline_base::is_vertical(counts_from_scanline.back().first.first)) { have_vertical_tail_from_below = true; } //assert size = size_less_1 + 1 @@ -1704,7 +1729,7 @@ namespace boost { namespace polygon{ //std::cout << "checking whether ot handle hole\n"; if(currentIter == inputEnd || currentIter->pt.get(HORIZONTAL) != x_ || - on_above_or_below(currentIter->pt, half_edge(iter->first.pt, iter->first.other_pt)) != -1) { + scanline_base::on_above_or_below(currentIter->pt, half_edge(iter->first.pt, iter->first.other_pt)) != -1) { //(high_precision)(currentIter->pt.get(VERTICAL)) >= iter->first.evalAtX(x_)) { //std::cout << "handle hole here\n"; @@ -2041,26 +2066,26 @@ namespace boost { namespace polygon{ he2.first = Point(0, 0); he2.second = Point(10, 20); Point result; - bool b = compute_intersection(result, he1, he2); + bool b = scanline_base::compute_intersection(result, he1, he2); if(!b || result != Point(0, 0)) return false; he1.first = Point(0, 10); - b = compute_intersection(result, he1, he2); + b = scanline_base::compute_intersection(result, he1, he2); if(!b || result != Point(5, 10)) return false; he1.first = Point(0, 11); - b = compute_intersection(result, he1, he2); + b = scanline_base::compute_intersection(result, he1, he2); if(!b || result != Point(5, 10)) return false; he1.first = Point(0, 0); he1.second = Point(1, 9); he2.first = Point(0, 9); he2.second = Point(1, 0); - b = compute_intersection(result, he1, he2); + b = scanline_base::compute_intersection(result, he1, he2); if(!b || result != Point(0, 4)) return false; he1.first = Point(0, -10); he1.second = Point(1, -1); he2.first = Point(0, -1); he2.second = Point(1, -10); - b = compute_intersection(result, he1, he2); + b = scanline_base::compute_intersection(result, he1, he2); if(!b || result != Point(0, -5)) return false; he1.first = Point((std::numeric_limits::max)(), (std::numeric_limits::max)()-1); he1.second = Point((std::numeric_limits::min)(), (std::numeric_limits::max)()); @@ -2068,13 +2093,13 @@ namespace boost { namespace polygon{ he2.first = Point((std::numeric_limits::max)()-1, (std::numeric_limits::max)()); he2.second = Point((std::numeric_limits::max)(), (std::numeric_limits::min)()); //he2.second = Point((std::numeric_limits::max)(), 0); - b = compute_intersection(result, he1, he2); + b = scanline_base::compute_intersection(result, he1, he2); //b is false because of overflow error he1.first = Point(1000, 2000); he1.second = Point(1010, 2010); he2.first = Point(1000, 2000); he2.second = Point(1010, 2020); - b = compute_intersection(result, he1, he2); + b = scanline_base::compute_intersection(result, he1, he2); if(!b || result != Point(1000, 2000)) return false; return b; @@ -2301,7 +2326,7 @@ namespace boost { namespace polygon{ bool have_vertical_tail_from_below = false; if(c_size && - is_vertical(counts_from_scanline.back().first.first)) { + scanline_base::is_vertical(counts_from_scanline.back().first.first)) { have_vertical_tail_from_below = true; } //assert size = size_less_1 + 1 @@ -2607,7 +2632,7 @@ namespace boost { namespace polygon{ //std::cout << "current Y " << currentY << std::endl; //std::cout << "scanline size " << scanData_.size() << std::endl; //print(scanData_); - iterator iter = lookUp_(currentY); + iterator iter = this->lookUp_(currentY); //std::cout << "found element in scanline " << (iter != scanData_.end()) << std::endl; //int counts[4] = {0, 0, 0, 0}; incoming_count counts_from_scanline; @@ -2634,7 +2659,7 @@ namespace boost { namespace polygon{ } Point currentPoint(polygon_arbitrary_formation::x_, currentY); //std::cout << "counts_from_scanline size " << counts_from_scanline.size() << std::endl; - sort_incoming_count(counts_from_scanline, currentPoint); + this->sort_incoming_count(counts_from_scanline, currentPoint); vertex_arbitrary_count incoming; //std::cout << "aggregating\n"; @@ -2646,7 +2671,7 @@ namespace boost { namespace polygon{ } while(currentIter != inputEnd && currentIter->pt.get(VERTICAL) == currentY && currentIter->pt.get(HORIZONTAL) == polygon_arbitrary_formation::x_); //print(incoming); - sort_vertex_arbitrary_count(incoming, currentPoint); + this->sort_vertex_arbitrary_count(incoming, currentPoint); //std::cout << currentPoint.get(HORIZONTAL) << "," << currentPoint.get(VERTICAL) << std::endl; //print(incoming); //std::cout << "incoming counts from input size " << incoming.size() << std::endl; diff --git a/include/boost/polygon/detail/polygon_formation.hpp b/include/boost/polygon/detail/polygon_formation.hpp index f4296bdedf..f478a16a9d 100644 --- a/include/boost/polygon/detail/polygon_formation.hpp +++ b/include/boost/polygon/detail/polygon_formation.hpp @@ -1721,7 +1721,7 @@ namespace polygon_formation { unsigned int get_polygons(output_container& container, iterator_type begin, iterator_type end, orientation_2d orient, bool fracture_holes, concept_type ) { typedef typename output_container::value_type polygon_type; - typedef typename iterator_type::value_type::first_type coordinate_type; + typedef typename std::iterator_traits::value_type::first_type coordinate_type; polygon_type poly; unsigned int countPolygons = 0; typedef typename geometry_concept::type polygon_concept_type; diff --git a/include/boost/polygon/detail/polygon_set_view.hpp b/include/boost/polygon/detail/polygon_set_view.hpp index ee4a409e14..49ac725521 100644 --- a/include/boost/polygon/detail/polygon_set_view.hpp +++ b/include/boost/polygon/detail/polygon_set_view.hpp @@ -153,13 +153,13 @@ namespace boost { namespace polygon{ }; template - typename polygon_set_view::iterator_type + typename polygon_set_traits >::iterator_type polygon_set_traits >:: begin(const polygon_set_view& polygon_set) { return polygon_set.begin(); } template - typename polygon_set_view::iterator_type + typename polygon_set_traits >::iterator_type polygon_set_traits >:: end(const polygon_set_view& polygon_set) { return polygon_set.end(); diff --git a/include/boost/polygon/detail/scan_arbitrary.hpp b/include/boost/polygon/detail/scan_arbitrary.hpp index 01744b4d6a..876fcb0cdd 100644 --- a/include/boost/polygon/detail/scan_arbitrary.hpp +++ b/include/boost/polygon/detail/scan_arbitrary.hpp @@ -33,38 +33,38 @@ namespace boost { namespace polygon{ typedef std::map, less_half_edge> edge_scanline; typedef typename edge_scanline::iterator iterator; - std::map > vertical_data_; - edge_scanline edge_scanline_; - Unit x_; - int just_before_; - segment_id segment_id_; - std::vector > event_edges_; - std::set intersection_queue_; +// std::map > vertical_data_; +// edge_scanline edge_scanline_; +// Unit x_; +// int just_before_; +// segment_id segment_id_; +// std::vector > event_edges_; +// std::set intersection_queue_; public: - inline line_intersection() : vertical_data_(), edge_scanline_(), x_((std::numeric_limits::max)()), just_before_(0), segment_id_(0), event_edges_(), intersection_queue_() { - less_half_edge lessElm(&x_, &just_before_); - edge_scanline_ = edge_scanline(lessElm); - } - inline line_intersection(const line_intersection& that) : vertical_data_(), edge_scanline_(), x_(), just_before_(), segment_id_(), event_edges_(), intersection_queue_() { (*this) = that; } - inline line_intersection& operator=(const line_intersection& that) { - x_ = that.x_; - just_before_ = that.just_before_; - segment_id_ = that.segment_id_; +// inline line_intersection() : vertical_data_(), edge_scanline_(), x_((std::numeric_limits::max)()), just_before_(0), segment_id_(0), event_edges_(), intersection_queue_() { +// less_half_edge lessElm(&x_, &just_before_); +// edge_scanline_ = edge_scanline(lessElm); +// } +// inline line_intersection(const line_intersection& that) : vertical_data_(), edge_scanline_(), x_(), just_before_(), segment_id_(), event_edges_(), intersection_queue_() { (*this) = that; } +// inline line_intersection& operator=(const line_intersection& that) { +// x_ = that.x_; +// just_before_ = that.just_before_; +// segment_id_ = that.segment_id_; - //I cannot simply copy that.edge_scanline_ to this edge_scanline_ becuase the functor store pointers to other members! - less_half_edge lessElm(&x_, &just_before_); - edge_scanline_ = edge_scanline(lessElm); +// //I cannot simply copy that.edge_scanline_ to this edge_scanline_ becuase the functor store pointers to other members! +// less_half_edge lessElm(&x_, &just_before_); +// edge_scanline_ = edge_scanline(lessElm); - edge_scanline_.insert(that.edge_scanline_.begin(), that.edge_scanline_.end()); - return *this; - } +// edge_scanline_.insert(that.edge_scanline_.begin(), that.edge_scanline_.end()); +// return *this; +// } - static inline void between(Point pt, Point pt1, Point pt2) { - less_point lp; - if(lp(pt1, pt2)) - return lp(pt, pt2) && lp(pt1, pt); - return lp(pt, pt1) && lp(pt2, pt); - } +// static inline void between(Point pt, Point pt1, Point pt2) { +// less_point lp; +// if(lp(pt1, pt2)) +// return lp(pt, pt2) && lp(pt1, pt); +// return lp(pt, pt1) && lp(pt2, pt); +// } template static inline void compute_histogram_in_y(iT begin, iT end, std::size_t size, std::vector > >& histogram) { @@ -216,7 +216,7 @@ namespace boost { namespace polygon{ //itr2 = pts.end(); while(lfinger != newend && (*lfinger).x() < startpt.x()) ++lfinger; for(typename std::vector::iterator itr = lfinger ; itr != newend && (*itr).x() <= stoppt.x(); ++itr) { - if(intersects_grid(*itr, he1)) + if(scanline_base::intersects_grid(*itr, he1)) intersection_points[id1].insert(*itr); } } @@ -243,8 +243,8 @@ namespace boost { namespace polygon{ //edge changed orientation, invert count on edge output_segments.back().second.second *= -1; } - if(!is_vertical(input_segments[intermediate_segments[i].second].first) && - is_vertical(output_segments.back().first)) { + if(!scanline_base::is_vertical(input_segments[intermediate_segments[i].second].first) && + scanline_base::is_vertical(output_segments.back().first)) { output_segments.back().second.second *= -1; } if(lp(output_segments.back().first.second, output_segments.back().first.first)) { @@ -349,7 +349,7 @@ namespace boost { namespace polygon{ segment_id id = (*iter).second; const std::set& pts = intersection_points[id]; Point hpt(he.first.get(HORIZONTAL)+1, he.first.get(VERTICAL)); - if(!is_vertical(he) && less_slope(he.first.get(HORIZONTAL), he.first.get(VERTICAL), + if(!scanline_base::is_vertical(he) && scanline_base::less_slope(he.first.get(HORIZONTAL), he.first.get(VERTICAL), he.second, hpt)) { //slope is below horizontal std::vector tmpPts; @@ -365,263 +365,263 @@ namespace boost { namespace polygon{ } } - //iT iterator over unsorted pair representing line segments of input - //output_segments is populated with fully intersected output line segment half - //edges and the index of the input segment that they are assoicated with - //duplicate output half edges with different ids will be generated in the case - //that parallel input segments intersection - //outputs are in sorted order and include both begin and end events for - //each segment - template - inline void scan(std::vector >& output_segments, - iT begin, iT end) { - std::map > intersection_points; - scan(intersection_points, begin, end); - segment_intersections(output_segments, intersection_points, begin, end); - } +// //iT iterator over unsorted pair representing line segments of input +// //output_segments is populated with fully intersected output line segment half +// //edges and the index of the input segment that they are assoicated with +// //duplicate output half edges with different ids will be generated in the case +// //that parallel input segments intersection +// //outputs are in sorted order and include both begin and end events for +// //each segment +// template +// inline void scan(std::vector >& output_segments, +// iT begin, iT end) { +// std::map > intersection_points; +// scan(intersection_points, begin, end); +// segment_intersections(output_segments, intersection_points, begin, end); +// } - //iT iterator over sorted sequence of half edge, segment id pairs representing segment begin and end points - //intersection points provides a mapping from input segment id (vector index) to the set - //of intersection points assocated with that input segment - template - inline void scan(std::map >& intersection_points, - iT begin, iT end) { - for(iT iter = begin; iter != end; ++iter) { - const std::pair& elem = *iter; - const half_edge& he = elem.first; - Unit current_x = he.first.get(HORIZONTAL); - if(current_x != x_) { - process_scan_event(intersection_points); - while(!intersection_queue_.empty() && - (*(intersection_queue_.begin()).get(HORIZONTAL) < current_x)) { - x_ = *(intersection_queue_.begin()).get(HORIZONTAL); - process_intersections_at_scan_event(intersection_points); - } - x_ = current_x; - } - event_edges_.push_back(elem); - } - process_scan_event(intersection_points); - } +// //iT iterator over sorted sequence of half edge, segment id pairs representing segment begin and end points +// //intersection points provides a mapping from input segment id (vector index) to the set +// //of intersection points assocated with that input segment +// template +// inline void scan(std::map >& intersection_points, +// iT begin, iT end) { +// for(iT iter = begin; iter != end; ++iter) { +// const std::pair& elem = *iter; +// const half_edge& he = elem.first; +// Unit current_x = he.first.get(HORIZONTAL); +// if(current_x != x_) { +// process_scan_event(intersection_points); +// while(!intersection_queue_.empty() && +// (*(intersection_queue_.begin()).get(HORIZONTAL) < current_x)) { +// x_ = *(intersection_queue_.begin()).get(HORIZONTAL); +// process_intersections_at_scan_event(intersection_points); +// } +// x_ = current_x; +// } +// event_edges_.push_back(elem); +// } +// process_scan_event(intersection_points); +// } - inline iterator lookup(const half_edge& he) { - return edge_scanline_.find(he); - } +// inline iterator lookup(const half_edge& he) { +// return edge_scanline_.find(he); +// } - inline void insert_into_scanline(const half_edge& he, int id) { - edge_scanline_[he].insert(id); - } +// inline void insert_into_scanline(const half_edge& he, int id) { +// edge_scanline_[he].insert(id); +// } - inline void lookup_and_remove(const half_edge& he, int id) { - iterator remove_iter = lookup(he); - if(remove_iter == edge_scanline_.end()) { - //std::cout << "failed to find removal segment in scanline\n"; - return; - } - std::set& ids = (*remove_iter).second; - std::set::iterator id_iter = ids.find(id); - if(id_iter == ids.end()) { - //std::cout << "failed to find removal segment id in scanline set\n"; - return; - } - ids.erase(id_iter); - if(ids.empty()) - edge_scanline_.erase(remove_iter); - } +// inline void lookup_and_remove(const half_edge& he, int id) { +// iterator remove_iter = lookup(he); +// if(remove_iter == edge_scanline_.end()) { +// //std::cout << "failed to find removal segment in scanline\n"; +// return; +// } +// std::set& ids = (*remove_iter).second; +// std::set::iterator id_iter = ids.find(id); +// if(id_iter == ids.end()) { +// //std::cout << "failed to find removal segment id in scanline set\n"; +// return; +// } +// ids.erase(id_iter); +// if(ids.empty()) +// edge_scanline_.erase(remove_iter); +// } - static inline void update_segments(std::map >& intersection_points, - const std::set& segments, Point pt) { - for(std::set::const_iterator itr = segments.begin(); itr != segments.end(); ++itr) { - intersection_points[*itr].insert(pt); - } - } +// static inline void update_segments(std::map >& intersection_points, +// const std::set& segments, Point pt) { +// for(std::set::const_iterator itr = segments.begin(); itr != segments.end(); ++itr) { +// intersection_points[*itr].insert(pt); +// } +// } - inline void process_intersections_at_scan_event(std::map >& intersection_points) { - //there may be additional intersection points at this x location that haven't been - //found yet if vertical or near vertical line segments intersect more than - //once before the next x location - just_before_ = true; - std::set intersecting_elements; - std::set intersection_locations; - typedef typename std::set::iterator intersection_iterator; - intersection_iterator iter; - //first find all secondary intersection locations and all scanline iterators - //that are intersecting - for(iter = intersection_queue_.begin(); - iter != intersection_queue_.end() && (*iter).get(HORIZONTAL) == x_; ++iter) { - Point pt = *iter; - Unit y = pt.get(VERTICAL); - intersection_locations.insert(y); - //if x_ is max there can be only end events and no sloping edges - if(x_ != (std::numeric_limits::max)()) { - //deal with edges that project to the right of scanline - //first find the edges in the scanline adjacent to primary intersectin points - //lookup segment in scanline at pt - iterator itr = edge_scanline_.lower_bound(half_edge(pt, Point(x_+1, y))); - //look above pt in scanline until reaching end or segment that doesn't intersect - //1x1 grid upper right of pt - //look below pt in scanline until reaching begin or segment that doesn't interset - //1x1 grid upper right of pt +// inline void process_intersections_at_scan_event(std::map >& intersection_points) { +// //there may be additional intersection points at this x location that haven't been +// //found yet if vertical or near vertical line segments intersect more than +// //once before the next x location +// just_before_ = true; +// std::set intersecting_elements; +// std::set intersection_locations; +// typedef typename std::set::iterator intersection_iterator; +// intersection_iterator iter; +// //first find all secondary intersection locations and all scanline iterators +// //that are intersecting +// for(iter = intersection_queue_.begin(); +// iter != intersection_queue_.end() && (*iter).get(HORIZONTAL) == x_; ++iter) { +// Point pt = *iter; +// Unit y = pt.get(VERTICAL); +// intersection_locations.insert(y); +// //if x_ is max there can be only end events and no sloping edges +// if(x_ != (std::numeric_limits::max)()) { +// //deal with edges that project to the right of scanline +// //first find the edges in the scanline adjacent to primary intersectin points +// //lookup segment in scanline at pt +// iterator itr = edge_scanline_.lower_bound(half_edge(pt, Point(x_+1, y))); +// //look above pt in scanline until reaching end or segment that doesn't intersect +// //1x1 grid upper right of pt +// //look below pt in scanline until reaching begin or segment that doesn't interset +// //1x1 grid upper right of pt - //second find edges in scanline on the y interval of each edge found in the previous - //step for x_ to x_ + 1 +// //second find edges in scanline on the y interval of each edge found in the previous +// //step for x_ to x_ + 1 - //third find overlaps in the y intervals of all found edges to find all - //secondary intersection points +// //third find overlaps in the y intervals of all found edges to find all +// //secondary intersection points - } - } - //erase the intersection points from the queue - intersection_queue_.erase(intersection_queue_.begin(), iter); - std::vector insertion_edges; - insertion_edges.reserve(intersecting_elements.size()); - std::vector > sloping_ends; - //do all the work of updating the output of all intersecting - for(typename std::set::iterator inter_iter = intersecting_elements.begin(); - inter_iter != intersecting_elements.end(); ++inter_iter) { - //if it is horizontal update it now and continue - if(is_horizontal((*inter_iter).first)) { - update_segments(intersection_points, (*inter_iter).second, Point(x_, (*inter_iter).first.get(VERTICAL))); - } else { - //if x_ is max there can be only end events and no sloping edges - if(x_ != (std::numeric_limits::max)()) { - //insert its end points into the vector of sloping ends - const half_edge& he = (*inter_iter).first; - Unit y = evalAtXforY(x_, he.first, he.second); - Unit y2 = evalAtXforY(x_+1, he.first, he.second); - if(y2 >= y) y2 +=1; //we round up, in exact case we don't worry about overbite of one - else y += 1; //downward sloping round up - sloping_ends.push_back(std::make_pair(y, inter_iter)); - sloping_ends.push_back(std::make_pair(y2, inter_iter)); - } - } - } +// } +// } +// //erase the intersection points from the queue +// intersection_queue_.erase(intersection_queue_.begin(), iter); +// std::vector insertion_edges; +// insertion_edges.reserve(intersecting_elements.size()); +// std::vector > sloping_ends; +// //do all the work of updating the output of all intersecting +// for(typename std::set::iterator inter_iter = intersecting_elements.begin(); +// inter_iter != intersecting_elements.end(); ++inter_iter) { +// //if it is horizontal update it now and continue +// if(is_horizontal((*inter_iter).first)) { +// update_segments(intersection_points, (*inter_iter).second, Point(x_, (*inter_iter).first.get(VERTICAL))); +// } else { +// //if x_ is max there can be only end events and no sloping edges +// if(x_ != (std::numeric_limits::max)()) { +// //insert its end points into the vector of sloping ends +// const half_edge& he = (*inter_iter).first; +// Unit y = evalAtXforY(x_, he.first, he.second); +// Unit y2 = evalAtXforY(x_+1, he.first, he.second); +// if(y2 >= y) y2 +=1; //we round up, in exact case we don't worry about overbite of one +// else y += 1; //downward sloping round up +// sloping_ends.push_back(std::make_pair(y, inter_iter)); +// sloping_ends.push_back(std::make_pair(y2, inter_iter)); +// } +// } +// } - //merge sloping element data - std::sort(sloping_ends.begin(), sloping_ends.end()); - std::map > sloping_elements; - std::set merge_elements; - for(typename std::vector >::iterator slop_iter = sloping_ends.begin(); - slop_iter = sloping_ends.end(); ++slop_iter) { - //merge into sloping elements - typename std::set::iterator merge_iterator = merge_elements.find((*slop_iter).second); - if(merge_iterator = merge_elements.end()) { - merge_elements.insert((*slop_iter).second); - } else { - merge_elements.erase(merge_iterator); - } - sloping_elements[(*slop_iter).first] = merge_elements; - } +// //merge sloping element data +// std::sort(sloping_ends.begin(), sloping_ends.end()); +// std::map > sloping_elements; +// std::set merge_elements; +// for(typename std::vector >::iterator slop_iter = sloping_ends.begin(); +// slop_iter == sloping_ends.end(); ++slop_iter) { +// //merge into sloping elements +// typename std::set::iterator merge_iterator = merge_elements.find((*slop_iter).second); +// if(merge_iterator == merge_elements.end()) { +// merge_elements.insert((*slop_iter).second); +// } else { +// merge_elements.erase(merge_iterator); +// } +// sloping_elements[(*slop_iter).first] = merge_elements; +// } - //scan intersection points - typename std::map >::iterator vertical_iter = vertical_data_.begin(); - typename std::map >::iterator sloping_iter = sloping_elements.begin(); - for(typename std::set::iterator position_iter = intersection_locations.begin(); - position_iter = intersection_locations.end(); ++position_iter) { - //look for vertical segments that intersect this point and update them - Unit y = *position_iter; - Point pt(x_, y); - //handle vertical segments - if(vertical_iter != vertical_data_.end()) { - typename std::map >::iterator next_vertical = vertical_iter; - for(++next_vertical; next_vertical != vertical_data_.end() && - (*next_vertical).first < y; ++next_vertical) { - vertical_iter = next_vertical; - } - if((*vertical_iter).first < y && !(*vertical_iter).second.empty()) { - update_segments(intersection_points, (*vertical_iter).second, pt); - ++vertical_iter; - if(vertical_iter != vertical_data_.end() && (*vertical_iter).first == y) - update_segments(intersection_points, (*vertical_iter).second, pt); - } - } - //handle sloping segments - if(sloping_iter != sloping_elements.end()) { - typename std::map >::iterator next_sloping = sloping_iter; - for(++next_sloping; next_sloping != sloping_elements.end() && - (*next_sloping).first < y; ++next_sloping) { - sloping_iter = next_sloping; - } - if((*sloping_iter).first < y && !(*sloping_iter).second.empty()) { - for(typename std::set::iterator element_iter = (*sloping_iter).second.begin(); - element_iter != (*sloping_iter).second.end(); ++element_iter) { - const half_edge& he = (*element_iter).first; - if(intersects_grid(pt, he)) { - update_segments(intersection_points, (*element_iter).second, pt); - } - } - ++sloping_iter; - if(sloping_iter != sloping_elements.end() && (*sloping_iter).first == y && - !(*sloping_iter).second.empty()) { - for(typename std::set::iterator element_iter = (*sloping_iter).second.begin(); - element_iter != (*sloping_iter).second.end(); ++element_iter) { - const half_edge& he = (*element_iter).first; - if(intersects_grid(pt, he)) { - update_segments(intersection_points, (*element_iter).second, pt); - } - } - } - } - } - } +// //scan intersection points +// typename std::map >::iterator vertical_iter = vertical_data_.begin(); +// typename std::map >::iterator sloping_iter = sloping_elements.begin(); +// for(typename std::set::iterator position_iter = intersection_locations.begin(); +// position_iter == intersection_locations.end(); ++position_iter) { +// //look for vertical segments that intersect this point and update them +// Unit y = *position_iter; +// Point pt(x_, y); +// //handle vertical segments +// if(vertical_iter != vertical_data_.end()) { +// typename std::map >::iterator next_vertical = vertical_iter; +// for(++next_vertical; next_vertical != vertical_data_.end() && +// (*next_vertical).first < y; ++next_vertical) { +// vertical_iter = next_vertical; +// } +// if((*vertical_iter).first < y && !(*vertical_iter).second.empty()) { +// update_segments(intersection_points, (*vertical_iter).second, pt); +// ++vertical_iter; +// if(vertical_iter != vertical_data_.end() && (*vertical_iter).first == y) +// update_segments(intersection_points, (*vertical_iter).second, pt); +// } +// } +// //handle sloping segments +// if(sloping_iter != sloping_elements.end()) { +// typename std::map >::iterator next_sloping = sloping_iter; +// for(++next_sloping; next_sloping != sloping_elements.end() && +// (*next_sloping).first < y; ++next_sloping) { +// sloping_iter = next_sloping; +// } +// if((*sloping_iter).first < y && !(*sloping_iter).second.empty()) { +// for(typename std::set::iterator element_iter = (*sloping_iter).second.begin(); +// element_iter != (*sloping_iter).second.end(); ++element_iter) { +// const half_edge& he = (*element_iter).first; +// if(intersects_grid(pt, he)) { +// update_segments(intersection_points, (*element_iter).second, pt); +// } +// } +// ++sloping_iter; +// if(sloping_iter != sloping_elements.end() && (*sloping_iter).first == y && +// !(*sloping_iter).second.empty()) { +// for(typename std::set::iterator element_iter = (*sloping_iter).second.begin(); +// element_iter != (*sloping_iter).second.end(); ++element_iter) { +// const half_edge& he = (*element_iter).first; +// if(intersects_grid(pt, he)) { +// update_segments(intersection_points, (*element_iter).second, pt); +// } +// } +// } +// } +// } +// } - //erase and reinsert edges into scanline with check for future intersection - } +// //erase and reinsert edges into scanline with check for future intersection +// } - inline void process_scan_event(std::map >& intersection_points) { - just_before_ = true; +// inline void process_scan_event(std::map >& intersection_points) { +// just_before_ = true; - //process end events by removing those segments from the scanline - //and insert vertices of all events into intersection queue - Point prev_point((std::numeric_limits::min)(), (std::numeric_limits::min)()); - less_point lp; - std::set vertical_ids; - vertical_data_.clear(); - for(std::size_t i = 0; i < event_edges_.size(); ++i) { - segment_id id = event_edges_[i].second; - const half_edge& he = event_edges_[i].first; - //vertical half edges are handled during intersection processing because - //they cannot be inserted into the scanline - if(!is_vertical(he)) { - if(lp(he.second, he.first)) { - //half edge is end event - lookup_and_remove(he, id); - } else { - //half edge is begin event - insert_into_scanline(he, id); - //note that they will be immediately removed and reinserted after - //handling their intersection (vertex) - //an optimization would allow them to be processed specially to avoid the redundant - //removal and reinsertion - } - } else { - //common case if you are lucky - //update the map of y to set of segment id - if(lp(he.second, he.first)) { - //half edge is end event - std::set::iterator itr = vertical_ids.find(id); - if(itr == vertical_ids.end()) { - //std::cout << "Failed to find end event id in vertical ids\n"; - } else { - vertical_ids.erase(itr); - vertical_data_[he.first.get(HORIZONTAL)] = vertical_ids; - } - } else { - //half edge is a begin event - vertical_ids.insert(id); - vertical_data_[he.first.get(HORIZONTAL)] = vertical_ids; - } - } - //prevent repeated insertion of same vertex into intersection queue - if(prev_point != he.first) - intersection_queue_.insert(he.first); - else - prev_point = he.first; - // process intersections at scan event - process_intersections_at_scan_event(intersection_points); - } - event_edges_.clear(); - } +// //process end events by removing those segments from the scanline +// //and insert vertices of all events into intersection queue +// Point prev_point((std::numeric_limits::min)(), (std::numeric_limits::min)()); +// less_point lp; +// std::set vertical_ids; +// vertical_data_.clear(); +// for(std::size_t i = 0; i < event_edges_.size(); ++i) { +// segment_id id = event_edges_[i].second; +// const half_edge& he = event_edges_[i].first; +// //vertical half edges are handled during intersection processing because +// //they cannot be inserted into the scanline +// if(!is_vertical(he)) { +// if(lp(he.second, he.first)) { +// //half edge is end event +// lookup_and_remove(he, id); +// } else { +// //half edge is begin event +// insert_into_scanline(he, id); +// //note that they will be immediately removed and reinserted after +// //handling their intersection (vertex) +// //an optimization would allow them to be processed specially to avoid the redundant +// //removal and reinsertion +// } +// } else { +// //common case if you are lucky +// //update the map of y to set of segment id +// if(lp(he.second, he.first)) { +// //half edge is end event +// std::set::iterator itr = vertical_ids.find(id); +// if(itr == vertical_ids.end()) { +// //std::cout << "Failed to find end event id in vertical ids\n"; +// } else { +// vertical_ids.erase(itr); +// vertical_data_[he.first.get(HORIZONTAL)] = vertical_ids; +// } +// } else { +// //half edge is a begin event +// vertical_ids.insert(id); +// vertical_data_[he.first.get(HORIZONTAL)] = vertical_ids; +// } +// } +// //prevent repeated insertion of same vertex into intersection queue +// if(prev_point != he.first) +// intersection_queue_.insert(he.first); +// else +// prev_point = he.first; +// // process intersections at scan event +// process_intersections_at_scan_event(intersection_points); +// } +// event_edges_.clear(); +// } public: template @@ -892,23 +892,23 @@ namespace boost { namespace polygon{ return false; } edges.pop_back(); - edges.push_back(std::make_pair(half_edge(Point(1, 0), Point(11, 11)), edges.size())); + edges.push_back(std::make_pair(half_edge(Point(1, 0), Point(11, 11)), (segment_id)edges.size())); if(!verify_scan(result, edges.begin(), edges.end())) { stdcout << "fail3\n"; return false; } - edges.push_back(std::make_pair(half_edge(Point(1, 0), Point(10, 11)), edges.size())); + edges.push_back(std::make_pair(half_edge(Point(1, 0), Point(10, 11)), (segment_id)edges.size())); if(verify_scan(result, edges.begin(), edges.end())) { stdcout << "fail4\n"; return false; } edges.pop_back(); - edges.push_back(std::make_pair(half_edge(Point(1, 2), Point(11, 11)), edges.size())); + edges.push_back(std::make_pair(half_edge(Point(1, 2), Point(11, 11)), (segment_id)edges.size())); if(!verify_scan(result, edges.begin(), edges.end())) { stdcout << "fail5 " << result.first << " " << result.second << "\n"; return false; } - edges.push_back(std::make_pair(half_edge(Point(0, 5), Point(0, 11)), edges.size())); + edges.push_back(std::make_pair(half_edge(Point(0, 5), Point(0, 11)), (segment_id)edges.size())); if(verify_scan(result, edges.begin(), edges.end())) { stdcout << "fail6 " << result.first << " " << result.second << "\n"; return false; @@ -1048,7 +1048,7 @@ namespace boost { namespace polygon{ if(current_iter != scan_data_.end()) { //make sure we are looking at element in scanline just below y //if(evalAtXforY(x_, (*current_iter).first.first, (*current_iter).first.second) != y) { - if(on_above_or_below(Point(x_, y), (*current_iter).first) != 0) { + if(scanline_base::on_above_or_below(Point(x_, y), (*current_iter).first) != 0) { Point e2(pt); if(e2.get(VERTICAL) != (std::numeric_limits::max)()) e2.set(VERTICAL, e2.get(VERTICAL) + 1); @@ -1060,12 +1060,12 @@ namespace boost { namespace polygon{ if(current_iter != scan_data_.end()) { //get the bottom iterator for elements at this point //while(evalAtXforY(x_, (*current_iter).first.first, (*current_iter).first.second) >= (high_precision)y && - while(on_above_or_below(Point(x_, y), (*current_iter).first) != 1 && + while(scanline_base::on_above_or_below(Point(x_, y), (*current_iter).first) != 1 && current_iter != scan_data_.begin()) { --current_iter; } //if(evalAtXforY(x_, (*current_iter).first.first, (*current_iter).first.second) >= (high_precision)y) { - if(on_above_or_below(Point(x_, y), (*current_iter).first) != 1) { + if(scanline_base::on_above_or_below(Point(x_, y), (*current_iter).first) != 1) { properties_below.clear(); } else { properties_below = (*current_iter).second; @@ -1078,7 +1078,7 @@ namespace boost { namespace polygon{ while(current_iter != scan_data_.end() && //can only be true if y is integer //evalAtXforY(x_, (*current_iter).first.first, (*current_iter).first.second) == y) { - on_above_or_below(Point(x_, y), (*current_iter).first) == 0) { + scanline_base::on_above_or_below(Point(x_, y), (*current_iter).first) == 0) { //removal_set_.push_back(current_iter); ++current_iter; } @@ -1129,7 +1129,7 @@ namespace boost { namespace polygon{ y = vertical_edge_below.second.get(VERTICAL); continue; } - if(is_vertical(he)) { + if(scanline_base::is_vertical(he)) { update_property_map(vertical_properties_above, vp.second); vertical_edge_above = he; } else { @@ -1556,7 +1556,7 @@ namespace boost { namespace polygon{ sl.scan(result, mof, pmd.begin(), pmd.end()); } - inline bool verify() { + inline bool verify1() { std::pair offenders; std::vector > lines; int count = 0; @@ -1704,8 +1704,8 @@ namespace boost { namespace polygon{ //if half edge 1 is not vertical its slope is less than that of half edge 2 return get(pt1, HORIZONTAL) != get(pt2, HORIZONTAL); } - return less_slope(get(pt_, HORIZONTAL), - get(pt_, VERTICAL), pt1, pt2); + return scanline_base::less_slope(get(pt_, HORIZONTAL), + get(pt_, VERTICAL), pt1, pt2); } }; @@ -2154,7 +2154,7 @@ pts.push_back(Point(12344171, 6695983 )); pts.push_back(Point(12287208, 6672388 si.insert(poly, 444); result.clear(); si.merge(result); - si.verify(); + si.verify1(); print(stdcout, si.pmd) << std::endl; if(!result.empty()) { psd = (*(result.begin())).second; @@ -2534,7 +2534,7 @@ pts.push_back(Point(12344171, 6695983 )); pts.push_back(Point(12287208, 6672388 elem.first = edge; elem.second = 1; if(edge.second < edge.first) elem.second *= -1; - if(is_vertical(edge)) elem.second *= -1; + if(scanline_base::is_vertical(edge)) elem.second *= -1; #ifdef BOOST_POLYGON_MSVC #pragma warning (disable: 4127) #endif diff --git a/include/boost/polygon/point_data.hpp b/include/boost/polygon/point_data.hpp index 7e78e6e45f..af6bd98b97 100644 --- a/include/boost/polygon/point_data.hpp +++ b/include/boost/polygon/point_data.hpp @@ -34,17 +34,29 @@ namespace boost { namespace polygon{ #endif { (*this) = that; } template - point_data(const other& that) : coords_() { (*this) = that; } + point_data(const other& that) +#ifndef BOOST_POLYGON_MSVC + :coords_() +#endif + { (*this) = that; } inline point_data& operator=(const point_data& that) { coords_[0] = that.coords_[0]; coords_[1] = that.coords_[1]; return *this; } template - inline point_data(const T1& x, const T2& y):coords_() { + inline point_data(const T1& x, const T2& y) +#ifndef BOOST_POLYGON_MSVC + :coords_() +#endif + { coords_[HORIZONTAL] = (coordinate_type)x; coords_[VERTICAL] = (coordinate_type)y; } template - inline point_data(const point_data& rvalue):coords_() { + inline point_data(const point_data& rvalue) +#ifndef BOOST_POLYGON_MSVC + :coords_() +#endif + { coords_[HORIZONTAL] = (coordinate_type)(rvalue.x()); coords_[VERTICAL] = (coordinate_type)(rvalue.y()); } diff --git a/include/boost/polygon/polygon_45_data.hpp b/include/boost/polygon/polygon_45_data.hpp index 91ee8db6a8..2b341760dd 100644 --- a/include/boost/polygon/polygon_45_data.hpp +++ b/include/boost/polygon/polygon_45_data.hpp @@ -62,7 +62,7 @@ public: inline std::size_t size() const { return coords_.size(); } -private: +public: std::vector > coords_; }; diff --git a/include/boost/polygon/polygon_45_set_data.hpp b/include/boost/polygon/polygon_45_set_data.hpp index 80d9307e7e..381a3de581 100644 --- a/include/boost/polygon/polygon_45_set_data.hpp +++ b/include/boost/polygon/polygon_45_set_data.hpp @@ -1541,11 +1541,11 @@ namespace boost { namespace polygon{ polygon_90_set_data l90sd(VERTICAL), r90sd(VERTICAL), output(VERTICAL); for(typename value_type::const_iterator itr = data_.begin(); itr != data_.end(); ++itr) { if((*itr).count[3] == 0) continue; //skip all non vertical edges - l90sd.insert(std::make_pair((*itr).pt.x(), std::make_pair((*itr).pt.y(), (*itr).count[3])), false, VERTICAL); + l90sd.insert(std::make_pair((*itr).pt.x(), std::make_pair((*itr).pt.y(), (*itr).count[3])), false, VERTICAL); } for(typename value_type::const_iterator itr = rvalue.data_.begin(); itr != rvalue.data_.end(); ++itr) { if((*itr).count[3] == 0) continue; //skip all non vertical edges - r90sd.insert(std::make_pair((*itr).pt.x(), std::make_pair((*itr).pt.y(), (*itr).count[3])), false, VERTICAL); + r90sd.insert(std::make_pair((*itr).pt.x(), std::make_pair((*itr).pt.y(), (*itr).count[3])), false, VERTICAL); } l90sd.sort(); r90sd.sort(); @@ -1673,7 +1673,7 @@ namespace boost { namespace polygon{ polygon_90_set_data l90sd(VERTICAL); for(typename value_type::const_iterator itr = data_.begin(); itr != data_.end(); ++itr) { if((*itr).count[3] == 0) continue; //skip all non vertical edges - l90sd.insert(std::make_pair((*itr).pt.x(), std::make_pair((*itr).pt.y(), (*itr).count[3])), false, VERTICAL); + l90sd.insert(std::make_pair((*itr).pt.x(), std::make_pair((*itr).pt.y(), (*itr).count[3])), false, VERTICAL); } l90sd.sort(); #ifdef BOOST_POLYGON_MSVC diff --git a/include/boost/polygon/polygon_45_set_traits.hpp b/include/boost/polygon/polygon_45_set_traits.hpp index de185b977d..eb7875d30e 100644 --- a/include/boost/polygon/polygon_45_set_traits.hpp +++ b/include/boost/polygon/polygon_45_set_traits.hpp @@ -137,7 +137,7 @@ namespace boost { namespace polygon{ static inline bool clean(const polygon_45_set_data& polygon_set) { polygon_set.clean(); return true; } - static inline bool sorted(const polygon_45_set_data& polygon_set) { int untested = 0;polygon_set.sort(); return true; } + static inline bool sorted(const polygon_45_set_data& polygon_set) { polygon_set.sort(); return true; } }; } diff --git a/include/boost/polygon/polygon_45_with_holes_data.hpp b/include/boost/polygon/polygon_45_with_holes_data.hpp index 1ed86166bc..835f93d0d5 100644 --- a/include/boost/polygon/polygon_45_with_holes_data.hpp +++ b/include/boost/polygon/polygon_45_with_holes_data.hpp @@ -96,10 +96,12 @@ public: return holes_.size(); } -private: +public: polygon_45_data self_; std::list holes_; }; + + } } #endif diff --git a/include/boost/polygon/polygon_90_set_data.hpp b/include/boost/polygon/polygon_90_set_data.hpp index 54aabc440f..01122591c5 100644 --- a/include/boost/polygon/polygon_90_set_data.hpp +++ b/include/boost/polygon/polygon_90_set_data.hpp @@ -244,6 +244,38 @@ namespace boost { namespace polygon{ // get the scanline orientation of the polygon set inline orientation_2d orient() const { return orient_; } + polygon_90_set_data& operator-=(const polygon_90_set_data& that) { + sort(); + that.sort(); + value_type data; + std::swap(data, data_); + applyBooleanBinaryOp(data.begin(), data.end(), + that.begin(), that.end(), boolean_op::BinaryCount()); + return *this; + } + polygon_90_set_data& operator^=(const polygon_90_set_data& that) { + sort(); + that.sort(); + value_type data; + std::swap(data, data_); + applyBooleanBinaryOp(data.begin(), data.end(), + that.begin(), that.end(), boolean_op::BinaryCount()); + return *this; + } + polygon_90_set_data& operator&=(const polygon_90_set_data& that) { + sort(); + that.sort(); + value_type data; + std::swap(data, data_); + applyBooleanBinaryOp(data.begin(), data.end(), + that.begin(), that.end(), boolean_op::BinaryCount()); + return *this; + } + polygon_90_set_data& operator|=(const polygon_90_set_data& that) { + insert(that); + return *this; + } + void clean() const { sort(); if(dirty_) { @@ -297,7 +329,7 @@ namespace boost { namespace polygon{ } polygon_90_set_data& - bloat(typename coordinate_traits::unsigned_area_type west_bloating, + bloat2(typename coordinate_traits::unsigned_area_type west_bloating, typename coordinate_traits::unsigned_area_type east_bloating, typename coordinate_traits::unsigned_area_type south_bloating, typename coordinate_traits::unsigned_area_type north_bloating) { @@ -318,11 +350,257 @@ namespace boost { namespace polygon{ return *this; } + static void modify_pt(point_data& pt, const point_data& prev_pt, + const point_data& current_pt, const point_data& next_pt, + coordinate_type west_bloating, + coordinate_type east_bloating, + coordinate_type south_bloating, + coordinate_type north_bloating) { + bool pxl = prev_pt.x() < current_pt.x(); + bool pyl = prev_pt.y() < current_pt.y(); + bool nxl = next_pt.x() < current_pt.x(); + bool nyl = next_pt.y() < current_pt.y(); + bool pxg = prev_pt.x() > current_pt.x(); + bool pyg = prev_pt.y() > current_pt.y(); + bool nxg = next_pt.x() > current_pt.x(); + bool nyg = next_pt.y() > current_pt.y(); + //two of the four if statements will execute + if(pxl) + pt.y(current_pt.y() - south_bloating); + if(pxg) + pt.y(current_pt.y() + north_bloating); + if(nxl) + pt.y(current_pt.y() + north_bloating); + if(nxg) + pt.y(current_pt.y() - south_bloating); + if(pyl) + pt.x(current_pt.x() + east_bloating); + if(pyg) + pt.x(current_pt.x() - west_bloating); + if(nyl) + pt.x(current_pt.x() - west_bloating); + if(nyg) + pt.x(current_pt.x() + east_bloating); + } + static void resize_poly_up(std::vector >& poly, + coordinate_type west_bloating, + coordinate_type east_bloating, + coordinate_type south_bloating, + coordinate_type north_bloating) { + point_data first_pt = poly[0]; + point_data second_pt = poly[1]; + point_data prev_pt = poly[0]; + point_data current_pt = poly[1]; + for(std::size_t i = 2; i < poly.size(); ++i) { + point_data next_pt = poly[i]; + modify_pt(poly[i-1], prev_pt, current_pt, next_pt, west_bloating, east_bloating, south_bloating, north_bloating); + prev_pt = current_pt; + current_pt = next_pt; + } + point_data next_pt = first_pt; + modify_pt(poly.back(), prev_pt, current_pt, next_pt, west_bloating, east_bloating, south_bloating, north_bloating); + prev_pt = current_pt; + current_pt = next_pt; + next_pt = second_pt; + modify_pt(poly[0], prev_pt, current_pt, next_pt, west_bloating, east_bloating, south_bloating, north_bloating); + remove_colinear_pts(poly); + } + static bool resize_poly_down(std::vector >& poly, + coordinate_type west_shrinking, + coordinate_type east_shrinking, + coordinate_type south_shrinking, + coordinate_type north_shrinking) { + rectangle_data extents_rectangle; + set_points(extents_rectangle, poly[0], poly[0]); + point_data first_pt = poly[0]; + point_data second_pt = poly[1]; + point_data prev_pt = poly[0]; + point_data current_pt = poly[1]; + encompass(extents_rectangle, current_pt); + for(int i = 2; i < poly.size(); ++i) { + point_data next_pt = poly[i]; + encompass(extents_rectangle, next_pt); + modify_pt(poly[i-1], prev_pt, current_pt, next_pt, west_shrinking, east_shrinking, south_shrinking, north_shrinking); + prev_pt = current_pt; + current_pt = next_pt; + } + if(delta(extents_rectangle, HORIZONTAL) < std::abs(west_shrinking + east_shrinking)) + return false; + if(delta(extents_rectangle, VERTICAL) < std::abs(north_shrinking + south_shrinking)) + return false; + point_data next_pt = first_pt; + modify_pt(poly.back(), prev_pt, current_pt, next_pt, west_shrinking, east_shrinking, south_shrinking, north_shrinking); + prev_pt = current_pt; + current_pt = next_pt; + next_pt = second_pt; + modify_pt(poly[0], prev_pt, current_pt, next_pt, west_shrinking, east_shrinking, south_shrinking, north_shrinking); + return remove_colinear_pts(poly); + } + + static bool remove_colinear_pts(std::vector >& poly) { + bool found_colinear = true; + while(found_colinear) { + found_colinear = false; + typename std::vector >::iterator itr = poly.begin(); + itr += poly.size() - 1; //get last element position + typename std::vector >::iterator itr2 = poly.begin(); + typename std::vector >::iterator itr3 = itr2; + ++itr3; + std::size_t count = 0; + for( ; itr3 < poly.end(); ++itr3) { + if(((*itr).x() == (*itr2).x() && (*itr).x() == (*itr3).x()) || + ((*itr).y() == (*itr2).y() && (*itr).y() == (*itr3).y()) ) { + ++count; + found_colinear = true; + } else { + itr = itr2; + ++itr2; + } + *itr2 = *itr3; + } + itr3 = poly.begin(); + if(((*itr).x() == (*itr2).x() && (*itr).x() == (*itr3).x()) || + ((*itr).y() == (*itr2).y() && (*itr).y() == (*itr3).y()) ) { + ++count; + found_colinear = true; + } + poly.erase(poly.end() - count, poly.end()); + } + return poly.size() >= 4; + } + + polygon_90_set_data& + bloat(typename coordinate_traits::unsigned_area_type west_bloating, + typename coordinate_traits::unsigned_area_type east_bloating, + typename coordinate_traits::unsigned_area_type south_bloating, + typename coordinate_traits::unsigned_area_type north_bloating) { + std::list > polys; + get(polys); + clear(); + for(typename std::list >::iterator itr = polys.begin(); + itr != polys.end(); ++itr) { + //polygon_90_set_data psref; + //psref.insert(view_as((*itr).self_)); + //rectangle_data prerect; + //psref.extents(prerect); + resize_poly_up((*itr).self_.coords_, west_bloating, east_bloating, south_bloating, north_bloating); + iterator_geometry_to_set > > + begin_input(view_as((*itr).self_), LOW, orient_, false, true, COUNTERCLOCKWISE), + end_input(view_as((*itr).self_), HIGH, orient_, false, true, COUNTERCLOCKWISE); + insert(begin_input, end_input, orient_); + //polygon_90_set_data pstest; + //pstest.insert(view_as((*itr).self_)); + //psref.bloat2(west_bloating, east_bloating, south_bloating, north_bloating); + //if(!equivalence(psref, pstest)) { + // std::cout << "test failed\n"; + //} + for(typename std::list >::iterator itrh = (*itr).holes_.begin(); + itrh != (*itr).holes_.end(); ++itrh) { + //rectangle_data rect; + //psref.extents(rect); + //polygon_90_set_data psrefhole; + //psrefhole.insert(prerect); + //psrefhole.insert(view_as(*itrh), true); + //polygon_45_data testpoly(*itrh); + if(resize_poly_down((*itrh).coords_, west_bloating, east_bloating, south_bloating, north_bloating)) { + iterator_geometry_to_set > > + begin_input(view_as(*itrh), LOW, orient_, true, true), + end_input(view_as(*itrh), HIGH, orient_, true, true); + insert(begin_input, end_input, orient_); + //polygon_90_set_data pstesthole; + //pstesthole.insert(rect); + //iterator_geometry_to_set > > + // begin_input2(view_as(*itrh), LOW, orient_, true, true); + //pstesthole.insert(begin_input2, end_input, orient_); + //psrefhole.bloat2(west_bloating, east_bloating, south_bloating, north_bloating); + //if(!equivalence(psrefhole, pstesthole)) { + // std::cout << (winding(testpoly) == CLOCKWISE) << std::endl; + // std::cout << (winding(*itrh) == CLOCKWISE) << std::endl; + // polygon_90_set_data c(psrefhole); + // c.clean(); + // polygon_90_set_data a(pstesthole); + // polygon_90_set_data b(pstesthole); + // a.sort(); + // b.clean(); + // std::cout << "test hole failed\n"; + // //std::cout << testpoly << std::endl; + //} + } + } + } + return *this; + } + polygon_90_set_data& shrink(typename coordinate_traits::unsigned_area_type west_shrinking, typename coordinate_traits::unsigned_area_type east_shrinking, typename coordinate_traits::unsigned_area_type south_shrinking, typename coordinate_traits::unsigned_area_type north_shrinking) { + std::list > polys; + get(polys); + clear(); + for(typename std::list >::iterator itr = polys.begin(); + itr != polys.end(); ++itr) { + //polygon_90_set_data psref; + //psref.insert(view_as((*itr).self_)); + //rectangle_data prerect; + //psref.extents(prerect); + //polygon_45_data testpoly((*itr).self_); + if(resize_poly_down((*itr).self_.coords_, -west_shrinking, -east_shrinking, -south_shrinking, -north_shrinking)) { + iterator_geometry_to_set > > + begin_input(view_as((*itr).self_), LOW, orient_, false, true, COUNTERCLOCKWISE), + end_input(view_as((*itr).self_), HIGH, orient_, false, true, COUNTERCLOCKWISE); + insert(begin_input, end_input, orient_); + //iterator_geometry_to_set > > + // begin_input2(view_as((*itr).self_), LOW, orient_, false, true, COUNTERCLOCKWISE); + //polygon_90_set_data pstest; + //pstest.insert(begin_input2, end_input, orient_); + //psref.shrink2(west_shrinking, east_shrinking, south_shrinking, north_shrinking); + //if(!equivalence(psref, pstest)) { + // std::cout << "test failed\n"; + //} + for(typename std::list >::iterator itrh = (*itr).holes_.begin(); + itrh != (*itr).holes_.end(); ++itrh) { + //rectangle_data rect; + //psref.extents(rect); + //polygon_90_set_data psrefhole; + //psrefhole.insert(prerect); + //psrefhole.insert(view_as(*itrh), true); + //polygon_45_data testpoly(*itrh); + resize_poly_up((*itrh).coords_, -west_shrinking, -east_shrinking, -south_shrinking, -north_shrinking); + iterator_geometry_to_set > > + begin_input(view_as(*itrh), LOW, orient_, true, true), + end_input(view_as(*itrh), HIGH, orient_, true, true); + insert(begin_input, end_input, orient_); + //polygon_90_set_data pstesthole; + //pstesthole.insert(rect); + //iterator_geometry_to_set > > + // begin_input2(view_as(*itrh), LOW, orient_, true, true); + //pstesthole.insert(begin_input2, end_input, orient_); + //psrefhole.shrink2(west_shrinking, east_shrinking, south_shrinking, north_shrinking); + //if(!equivalence(psrefhole, pstesthole)) { + // std::cout << (winding(testpoly) == CLOCKWISE) << std::endl; + // std::cout << (winding(*itrh) == CLOCKWISE) << std::endl; + // polygon_90_set_data c(psrefhole); + // c.clean(); + // polygon_90_set_data a(pstesthole); + // polygon_90_set_data b(pstesthole); + // a.sort(); + // b.clean(); + // std::cout << "test hole failed\n"; + // //std::cout << testpoly << std::endl; + //} + } + } + } + return *this; + } + + polygon_90_set_data& + shrink2(typename coordinate_traits::unsigned_area_type west_shrinking, + typename coordinate_traits::unsigned_area_type east_shrinking, + typename coordinate_traits::unsigned_area_type south_shrinking, + typename coordinate_traits::unsigned_area_type north_shrinking) { rectangle_data externalBoundary; if(!extents(externalBoundary)) return *this; ::boost::polygon::bloat(externalBoundary, 10); //bloat by diferential ammount @@ -352,6 +630,30 @@ namespace boost { namespace polygon{ return *this; } + polygon_90_set_data& + shrink(direction_2d dir, typename coordinate_traits::unsigned_area_type shrinking) { + if(dir == WEST) + return shrink(shrinking, 0, 0, 0); + if(dir == EAST) + return shrink(0, shrinking, 0, 0); + if(dir == SOUTH) + return shrink(0, 0, shrinking, 0); + if(dir == NORTH) + return shrink(0, 0, 0, shrinking); + } + + polygon_90_set_data& + bloat(direction_2d dir, typename coordinate_traits::unsigned_area_type shrinking) { + if(dir == WEST) + return bloat(shrinking, 0, 0, 0); + if(dir == EAST) + return bloat(0, shrinking, 0, 0); + if(dir == SOUTH) + return bloat(0, 0, shrinking, 0); + if(dir == NORTH) + return bloat(0, 0, 0, shrinking); + } + polygon_90_set_data& resize(coordinate_type west, coordinate_type east, coordinate_type south, coordinate_type north); diff --git a/include/boost/polygon/polygon_data.hpp b/include/boost/polygon/polygon_data.hpp index bbe51e4048..edaf77c4a1 100644 --- a/include/boost/polygon/polygon_data.hpp +++ b/include/boost/polygon/polygon_data.hpp @@ -60,7 +60,7 @@ public: inline std::size_t size() const { return coords_.size(); } -private: +public: std::vector > coords_; }; diff --git a/include/boost/polygon/polygon_set_data.hpp b/include/boost/polygon/polygon_set_data.hpp index f55c19e9e2..04c56adb3e 100644 --- a/include/boost/polygon/polygon_set_data.hpp +++ b/include/boost/polygon/polygon_set_data.hpp @@ -120,38 +120,7 @@ namespace boost { namespace polygon { template inline void insert(const polygon_type& polygon_object, bool is_hole, polygon_concept ) { - bool first_iteration = true; - point_type first_point; - point_type previous_point; - point_type current_point; - direction_1d winding_dir = winding(polygon_object); - int multiplier = winding_dir == COUNTERCLOCKWISE ? 1 : -1; - if(is_hole) multiplier *= -1; - for(typename polygon_traits::iterator_type itr = begin_points(polygon_object); - itr != end_points(polygon_object); ++itr) { - assign(current_point, *itr); - if(first_iteration) { - first_iteration = false; - first_point = previous_point = current_point; - } else { - if(previous_point != current_point) { - element_type elem(edge_type(previous_point, current_point), - ( previous_point.get(HORIZONTAL) == current_point.get(HORIZONTAL) ? -1 : 1) * multiplier); - insert_clean(elem); - } - } - previous_point = current_point; - } - current_point = first_point; - if(!first_iteration) { - if(previous_point != current_point) { - element_type elem(edge_type(previous_point, current_point), - ( previous_point.get(HORIZONTAL) == current_point.get(HORIZONTAL) ? -1 : 1) * multiplier); - insert_clean(elem); - } - dirty_ = true; - unsorted_ = true; - } + insert_vertex_sequence(begin_points(polygon_object), end_points(polygon_object), winding(polygon_object), is_hole); } inline void insert(const polygon_set_data& ps, bool is_hole = false) { @@ -229,9 +198,37 @@ namespace boost { namespace polygon { template inline void insert_vertex_sequence(iT begin_vertex, iT end_vertex, direction_1d winding, bool is_hole) { - polygon_data poly; - poly.set(begin_vertex, end_vertex); - insert(poly, is_hole); + bool first_iteration = true; + point_type first_point; + point_type previous_point; + point_type current_point; + direction_1d winding_dir = winding; + int multiplier = winding_dir == COUNTERCLOCKWISE ? 1 : -1; + if(is_hole) multiplier *= -1; + for( ; begin_vertex != end_vertex; ++begin_vertex) { + assign(current_point, *begin_vertex); + if(first_iteration) { + first_iteration = false; + first_point = previous_point = current_point; + } else { + if(previous_point != current_point) { + element_type elem(edge_type(previous_point, current_point), + ( previous_point.get(HORIZONTAL) == current_point.get(HORIZONTAL) ? -1 : 1) * multiplier); + insert_clean(elem); + } + } + previous_point = current_point; + } + current_point = first_point; + if(!first_iteration) { + if(previous_point != current_point) { + element_type elem(edge_type(previous_point, current_point), + ( previous_point.get(HORIZONTAL) == current_point.get(HORIZONTAL) ? -1 : 1) * multiplier); + insert_clean(elem); + } + dirty_ = true; + unsorted_ = true; + } } template @@ -363,6 +360,13 @@ namespace boost { namespace polygon { inline polygon_set_data& resize(coordinate_type resizing, bool corner_fill_arc = false, unsigned int num_circle_segments=0) { + if(!corner_fill_arc) { + if(resizing < 0) + return shrink(-resizing); + if(resizing > 0) + return bloat(-resizing); + return *this; + } if(resizing == 0) return *this; std::list > pl; get(pl); @@ -421,6 +425,139 @@ namespace boost { namespace polygon { return *this; } + static inline void compute_offset_edge(point_data& pt1, point_data& pt2, + const point_data& prev_pt, + const point_data& current_pt, + coordinate_type distance, int multiplier) { + coordinate_type dx = current_pt.x() - prev_pt.x(); + coordinate_type dy = current_pt.y() - prev_pt.y(); + double ddx = (double)dx; + double ddy = (double)dy; + double edge_length = std::sqrt(ddx*ddx + ddy*ddy); + double dnx = dy; + double dny = -dx; + dnx = dnx * (double)distance / edge_length; + dny = dny * (double)distance / edge_length; + dnx = std::floor(dnx+0.5); + dny = std::floor(dny+0.5); + pt1.x(prev_pt.x() + (coordinate_type)dnx * (coordinate_type)multiplier); + pt2.x(current_pt.x() + (coordinate_type)dnx * (coordinate_type)multiplier); + pt1.y(prev_pt.y() + (coordinate_type)dny * (coordinate_type)multiplier); + pt2.y(current_pt.y() + (coordinate_type)dny * (coordinate_type)multiplier); + } + + static inline void modify_pt(point_data& pt, const point_data& prev_pt, + const point_data& current_pt, const point_data& next_pt, + coordinate_type distance, coordinate_type multiplier) { + std::pair, point_data > he1(prev_pt, current_pt), he2(current_pt, next_pt); + compute_offset_edge(he1.first, he1.second, prev_pt, current_pt, distance, multiplier); + compute_offset_edge(he2.first, he2.second, current_pt, next_pt, distance, multiplier); + typename scanline_base::compute_intersection_pack pack; + if(!pack.compute_lazy_intersection(pt, he1, he2, true, true)) { + pt = he1.second; //colinear offset edges use shared point + } + } + + static void resize_poly_up(std::vector >& poly, coordinate_type distance, coordinate_type multiplier) { + point_data first_pt = poly[0]; + point_data second_pt = poly[1]; + point_data prev_pt = poly[0]; + point_data current_pt = poly[1]; + for(std::size_t i = 2; i < poly.size()-1; ++i) { + point_data next_pt = poly[i]; + modify_pt(poly[i-1], prev_pt, current_pt, next_pt, distance, multiplier); + prev_pt = current_pt; + current_pt = next_pt; + } + point_data next_pt = first_pt; + modify_pt(poly[poly.size()-2], prev_pt, current_pt, next_pt, distance, multiplier); + prev_pt = current_pt; + current_pt = next_pt; + next_pt = second_pt; + modify_pt(poly[0], prev_pt, current_pt, next_pt, distance, multiplier); + poly.back() = poly.front(); + } + static bool resize_poly_down(std::vector >& poly, coordinate_type distance, coordinate_type multiplier) { + std::vector > orig_poly(poly); + rectangle_data extents_rectangle; + set_points(extents_rectangle, poly[0], poly[0]); + point_data first_pt = poly[0]; + point_data second_pt = poly[1]; + point_data prev_pt = poly[0]; + point_data current_pt = poly[1]; + encompass(extents_rectangle, current_pt); + for(std::size_t i = 2; i < poly.size()-1; ++i) { + point_data next_pt = poly[i]; + encompass(extents_rectangle, next_pt); + modify_pt(poly[i-1], prev_pt, current_pt, next_pt, distance, multiplier); + prev_pt = current_pt; + current_pt = next_pt; + } + if(delta(extents_rectangle, HORIZONTAL) <= std::abs(2*distance)) + return false; + if(delta(extents_rectangle, VERTICAL) <= std::abs(2*distance)) + return false; + point_data next_pt = first_pt; + modify_pt(poly[poly.size()-2], prev_pt, current_pt, next_pt, distance, multiplier); + prev_pt = current_pt; + current_pt = next_pt; + next_pt = second_pt; + modify_pt(poly[0], prev_pt, current_pt, next_pt, distance, multiplier); + poly.back() = poly.front(); + //if the line segments formed between orignial and new points cross for an edge that edge inverts + //if all edges invert the polygon should be discarded + //if even one edge does not invert return true because the polygon is valid + bool non_inverting_edge = false; + for(std::size_t i = 1; i < poly.size(); ++i) { + std::pair, point_data > + he1(poly[i], orig_poly[i]), + he2(poly[i-1], orig_poly[i-1]); + if(!scanline_base::intersects(he1, he2)) { + non_inverting_edge = true; + break; + } + } + return non_inverting_edge; + } + + polygon_set_data& + bloat(typename coordinate_traits::unsigned_area_type distance) { + std::list > polys; + get(polys); + clear(); + for(typename std::list >::iterator itr = polys.begin(); + itr != polys.end(); ++itr) { + resize_poly_up((*itr).self_.coords_, (coordinate_type)distance, (coordinate_type)1); + insert_vertex_sequence((*itr).self_.begin(), (*itr).self_.end(), COUNTERCLOCKWISE, false); //inserts without holes + for(typename std::list >::iterator itrh = (*itr).holes_.begin(); + itrh != (*itr).holes_.end(); ++itrh) { + if(resize_poly_down((*itrh).coords_, (coordinate_type)distance, (coordinate_type)1)) { + insert_vertex_sequence((*itrh).coords_.begin(), (*itrh).coords_.end(), CLOCKWISE, true); + } + } + } + return *this; + } + + polygon_set_data& + shrink(typename coordinate_traits::unsigned_area_type distance) { + std::list > polys; + get(polys); + clear(); + for(typename std::list >::iterator itr = polys.begin(); + itr != polys.end(); ++itr) { + if(resize_poly_down((*itr).self_.coords_, (coordinate_type)distance, (coordinate_type)-1)) { + insert_vertex_sequence((*itr).self_.begin(), (*itr).self_.end(), COUNTERCLOCKWISE, false); //inserts without holes + for(typename std::list >::iterator itrh = (*itr).holes_.begin(); + itrh != (*itr).holes_.end(); ++itrh) { + resize_poly_up((*itrh).coords_, (coordinate_type)distance, (coordinate_type)-1); + insert_vertex_sequence((*itrh).coords_.begin(), (*itrh).coords_.end(), CLOCKWISE, true); + } + } + } + return *this; + } + // TODO:: should be private template inline polygon_set_data& @@ -481,6 +618,7 @@ namespace boost { namespace polygon { bool sizing_sign = resizing>0; bool prev_concave = true; point_data prev_point; + //int iCtr=0; //insert minkofski shapes on edges and corners @@ -494,7 +632,9 @@ namespace boost { namespace polygon { double direction = normal1.x()*normal2.y()- normal2.x()*normal1.y(); bool convex = direction>0; - bool treat_as_concave = convex ^ sizing_sign ; + bool treat_as_concave = !convex; + if(sizing_sign) + treat_as_concave = convex; point_data v; assign(v, normal1); double s2 = (v.x()*v.x()+v.y()*v.y()); @@ -533,14 +673,14 @@ namespace boost { namespace polygon { , num_circle_segments, corner_fill_arc)) { if (first_pts.size()) { - for (unsigned i=0; i - inline double compute_area(point_data& a, point_data& b, point_data& c) { +// template +// inline double compute_area(point_data& a, point_data& b, point_data& c) { - return (double)(b.x()-a.x())*(double)(c.y()-a.y())- (double)(c.x()-a.x())*(double)(b.y()-a.y()); +// return (double)(b.x()-a.x())*(double)(c.y()-a.y())- (double)(c.x()-a.x())*(double)(b.y()-a.y()); - } +// } template inline int make_resizing_vertex_list(std::vector > >& return_points, @@ -709,7 +849,7 @@ namespace boost { namespace polygon { std::pair,point_data > he1(start_offset,mid1_offset); std::pair,point_data > he2(mid2_offset ,end_offset); - typedef typename high_precision_type::type high_precision; + //typedef typename high_precision_type::type high_precision; point_data intersect; typename scanline_base::compute_intersection_pack pack; @@ -723,8 +863,8 @@ namespace boost { namespace polygon { return_points_back.push_back(start); return_points_back.push_back(curr_prev); - /*double d1= */compute_area(intersect,middle,start); - /*double d2= */compute_area(start,curr_prev,intersect); + //double d1= compute_area(intersect,middle,start); + //double d2= compute_area(start,curr_prev,intersect); curr_prev = intersect; @@ -754,7 +894,7 @@ namespace boost { namespace polygon { ps += 2.0 * our_pi; if (pe <= 0.0) pe += 2.0 * our_pi; - if (ps >= 2.0 * M_PI) + if (ps >= 2.0 * our_pi) ps -= 2.0 * our_pi; while (pe <= ps) pe += 2.0 * our_pi; @@ -771,9 +911,9 @@ namespace boost { namespace polygon { } return_points.push_back(round_down(center)); return_points.push_back(round_down(start)); - int i=0; + unsigned int i=0; double curr_angle = ps+delta_angle; - while( curr_angle < pe - 0.01 && i < 2 * (int)num_circle_segments) { + while( curr_angle < pe - 0.01 && i < 2 * num_circle_segments) { i++; double x = center.x() + r * cos( curr_angle); double y = center.y() + r * sin( curr_angle); diff --git a/include/boost/polygon/polygon_set_traits.hpp b/include/boost/polygon/polygon_set_traits.hpp index a774fedd36..f807140b4b 100644 --- a/include/boost/polygon/polygon_set_traits.hpp +++ b/include/boost/polygon/polygon_set_traits.hpp @@ -121,7 +121,7 @@ namespace boost { namespace polygon{ static inline bool clean(const polygon_set_data& polygon_set) { polygon_set.clean(); return true; } - static inline bool sorted(const polygon_set_data& polygon_set) { int untested = 0;polygon_set.sort(); return true; } + static inline bool sorted(const polygon_set_data& polygon_set) { polygon_set.sort(); return true; } }; } diff --git a/include/boost/polygon/polygon_with_holes_data.hpp b/include/boost/polygon/polygon_with_holes_data.hpp index 9c7a98f6ed..c09681ac3c 100644 --- a/include/boost/polygon/polygon_with_holes_data.hpp +++ b/include/boost/polygon/polygon_with_holes_data.hpp @@ -96,7 +96,7 @@ public: return holes_.size(); } -private: +public: polygon_data self_; std::list holes_; }; diff --git a/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp b/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp index d4c40f787d..1348661f07 100644 --- a/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp +++ b/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp @@ -131,33 +131,10 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) * so m_ZoneMinThickness is the min thickness of the filled zones areas * the main polygon is stored in polyset_zone_solid_areas */ -#if 1 - { - /* creates the main polygon (i.e. the filled area using only one outline) - * in GroupA in Bool_Engine to do a BOOL_CORRECTION operation - * to reserve a m_ZoneMinThickness/2 margin around the outlines - */ - Bool_Engine* booleng = new Bool_Engine(); - ArmBoolEng( booleng, true ); - CopyPolygonsFromFilledPolysListToBoolengine( booleng, GROUP_A ); - booleng->SetCorrectionFactor( (double) -margin ); - booleng->Do_Operation( BOOL_CORRECTION ); - /* Now copy the new outline in m_FilledPolysList */ - m_FilledPolysList.clear(); - CopyPolygonsFromBoolengineToFilledPolysList( booleng ); - delete booleng; - CopyPolygonsFromFilledPolysListTotKPolygonList( this, polyset_zone_solid_areas ); - } -#else - /* currently does not work well. - * using kbool gives reliable results - * using boost::polygone gives erroneous results - */ CopyPolygonsFromFilledPolysListTotKPolygonList( this, polyset_zone_solid_areas ); polyset_zone_solid_areas -= margin; -#endif if( polyset_zone_solid_areas.size() == 0 ) return; @@ -523,82 +500,6 @@ void AddUnconnectedThermalStubsToKPolygonList( std::vector& aCornerBuff } -/** Function CopyPolygonsFromFilledPolysListToBoolengine - * Copy (Add) polygons found in m_FilledPolysList to kbool BoolEngine - * m_FilledPolysList may have more than one polygon - * @param aBoolengine = kbool engine - * @param aGroup = group in kbool engine (GROUP_A or GROUP_B only) - * @return the corner count - */ -int ZONE_CONTAINER::CopyPolygonsFromFilledPolysListToBoolengine( - Bool_Engine* aBoolengine, GroupType aGroup ) -{ - unsigned corners_count = m_FilledPolysList.size(); - int count = 0; - unsigned ic = 0; - - while( ic < corners_count ) - { - if( aBoolengine->StartPolygonAdd( aGroup ) ) - { - for( ; ic < corners_count; ic++ ) - { - CPolyPt* corner = &m_FilledPolysList[ic]; - aBoolengine->AddPoint( corner->x, corner->y ); - count++; - if( corner->end_contour ) - { - ic++; - break; - } - } - - aBoolengine->EndPolygonAdd(); - } - } - - return count; -} - - -/** Function CopyPolygonsFromBoolengineToFilledPolysList - * Copy (Add) polygons created by kbool (after Do_Operation) to m_FilledPolysList - * @param aBoolengine = kbool engine - * @return the corner count - */ -int ZONE_CONTAINER::CopyPolygonsFromBoolengineToFilledPolysList( - Bool_Engine* aBoolengine ) -{ - int count = 0; - - while( aBoolengine->StartPolygonGet() ) - { - CPolyPt corner( 0, 0, false ); - while( aBoolengine->PolygonHasMorePoints() ) - { - corner.x = (int) aBoolengine->GetPolygonXPoint(); - corner.y = (int) aBoolengine->GetPolygonYPoint(); - corner.end_contour = false; - - // Flag this corner if starting a hole connection segment: - // This is used by draw functions to draw only useful segments (and not extra segments) - corner.utility = - (aBoolengine->GetPolygonPointEdgeType() == - KB_FALSE_EDGE) ? 1 : 0; - m_FilledPolysList.push_back( corner ); - count++; - } - - corner.end_contour = true; - m_FilledPolysList.pop_back(); - m_FilledPolysList.push_back( corner ); - aBoolengine->EndPolygonGet(); - } - - return count; -} - - void AddPolygonCornersToKPolygonList( std::vector & aCornersBuffer, KPolygonSet& aKPolyList )