Commit e2d4b16b authored by jean-pierre charras's avatar jean-pierre charras

Updated boost::polygon from http://svn.boost.org/svn/boost/trunk/boost/polygon...

Updated boost::polygon from http://svn.boost.org/svn/boost/trunk/boost/polygon (boost 1.44) Seems fix some issues.
parents 8d777fc6 75b5c247
...@@ -29,7 +29,7 @@ private: ...@@ -29,7 +29,7 @@ private:
public: public:
iterator_geometry_to_set() : rectangle_(), vertex_(), corner_(4), orient_(), is_hole_() {} iterator_geometry_to_set() : rectangle_(), vertex_(), corner_(4), orient_(), is_hole_() {}
iterator_geometry_to_set(const rectangle_type& rectangle, direction_1d dir, 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) { rectangle_(), vertex_(), corner_(0), orient_(orient), is_hole_(is_hole) {
assign(rectangle_, rectangle); assign(rectangle_, rectangle);
if(dir == HIGH) corner_ = 4; if(dir == HIGH) corner_ = 4;
...@@ -93,7 +93,7 @@ private: ...@@ -93,7 +93,7 @@ private:
int polygon_index; int polygon_index;
public: 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() : 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_(), vertex_(), itrb(), itre(), last_vertex_(),
is_hole_(is_hole), multiplier_(), first_pt(), second_pt(), pts(), use_wrap(), is_hole_(is_hole), multiplier_(), first_pt(), second_pt(), pts(), use_wrap(),
orient_(orient), polygon_index(0) { orient_(orient), polygon_index(0) {
...@@ -103,7 +103,9 @@ public: ...@@ -103,7 +103,9 @@ public:
if(itrb == itre || dir == HIGH || size(polygon) < 4) { if(itrb == itre || dir == HIGH || size(polygon) < 4) {
polygon_index = -1; polygon_index = -1;
} else { } else {
direction_1d wdir = winding(polygon); direction_1d wdir = w;
if(!winding_override)
wdir = winding(polygon);
multiplier_ = wdir == LOW ? -1 : 1; multiplier_ = wdir == LOW ? -1 : 1;
if(is_hole_) multiplier_ *= -1; if(is_hole_) multiplier_ *= -1;
first_pt = pts[0] = *itrb; first_pt = pts[0] = *itrb;
...@@ -182,9 +184,7 @@ public: ...@@ -182,9 +184,7 @@ public:
vertex_.second.first =pts[1].get(orient_); vertex_.second.first =pts[1].get(orient_);
if(pts[1] == pts[2]) { if(pts[1] == pts[2]) {
vertex_.second.second = 0; vertex_.second.second = 0;
return; } else if(pts[0].get(HORIZONTAL) != pts[1].get(HORIZONTAL)) {
}
if(pts[0].get(HORIZONTAL) != pts[1].get(HORIZONTAL)) {
vertex_.second.second = -1; vertex_.second.second = -1;
} else if(pts[0].get(VERTICAL) != pts[1].get(VERTICAL)) { } else if(pts[0].get(VERTICAL) != pts[1].get(VERTICAL)) {
vertex_.second.second = 1; vertex_.second.second = 1;
...@@ -214,7 +214,7 @@ private: ...@@ -214,7 +214,7 @@ private:
public: public:
iterator_geometry_to_set() : itrb(), itre(), itrhib(), itrhie(), itrhb(), itrhe(), orient_(), is_hole_(), started_holes() {} 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, 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() { itrb(), itre(), itrhib(), itrhie(), itrhb(), itrhe(), orient_(orient), is_hole_(is_hole), started_holes() {
itre = iterator_geometry_to_set<polygon_90_concept, polygon_with_holes_type>(polygon, HIGH, orient, is_hole_); itre = iterator_geometry_to_set<polygon_90_concept, polygon_with_holes_type>(polygon, HIGH, orient, is_hole_);
itrhe = end_holes(polygon); itrhe = end_holes(polygon);
......
...@@ -251,12 +251,14 @@ namespace boost { namespace polygon{ ...@@ -251,12 +251,14 @@ namespace boost { namespace polygon{
return; return;
} }
Unit firstY = (*iter).y(); Unit firstY = (*iter).y();
Unit firstX = (*iter).x();
++iter; ++iter;
if(iter == tailp_->points.end()) { if(iter == tailp_->points.end()) {
tailp_->points.push_front(point); tailp_->points.push_front(point);
return; 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;
*iter = point; *iter = point;
} else { } else {
...@@ -274,12 +276,14 @@ namespace boost { namespace polygon{ ...@@ -274,12 +276,14 @@ namespace boost { namespace polygon{
return; return;
} }
Unit firstY = (*iter).y(); Unit firstY = (*iter).y();
Unit firstX = (*iter).x();
++iter; ++iter;
if(iter == tailp_->points.rend()) { if(iter == tailp_->points.rend()) {
tailp_->points.push_back(point); tailp_->points.push_back(point);
return; 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;
*iter = point; *iter = point;
} else { } else {
...@@ -474,7 +478,7 @@ namespace boost { namespace polygon{ ...@@ -474,7 +478,7 @@ namespace boost { namespace polygon{
ct counts[4]; ct counts[4];
}; };
typedef Vertex45CountT<int> Vertex45Count; typedef Vertex45CountT<signed char> Vertex45Count;
// inline std::ostream& operator<< (std::ostream& o, const Vertex45Count& c) { // inline std::ostream& operator<< (std::ostream& o, const Vertex45Count& c) {
// o << c[0] << ", " << c[1] << ", "; // o << c[0] << ", " << c[1] << ", ";
...@@ -492,7 +496,8 @@ namespace boost { namespace polygon{ ...@@ -492,7 +496,8 @@ namespace boost { namespace polygon{
inline Vertex45CompactT(const Point& point, int riseIn, int countIn) : pt(point), count() { inline Vertex45CompactT(const Point& point, int riseIn, int countIn) : pt(point), count() {
count[riseIn+1] = countIn; count[riseIn+1] = countIn;
} }
inline Vertex45CompactT(const Vertex45T& vertex) : pt(vertex.pt), count() { template <typename ct2>
inline Vertex45CompactT(const typename boolean_op_45<Unit>::template Vertex45T<ct2>& vertex) : pt(vertex.pt), count() {
count[vertex.rise+1] = vertex.count; count[vertex.rise+1] = vertex.count;
} }
inline Vertex45CompactT(const Vertex45CompactT& vertex) : pt(vertex.pt), count(vertex.count) {} inline Vertex45CompactT(const Vertex45CompactT& vertex) : pt(vertex.pt), count(vertex.count) {}
...@@ -2244,6 +2249,7 @@ namespace boost { namespace polygon{ ...@@ -2244,6 +2249,7 @@ namespace boost { namespace polygon{
struct geometry_concept<PolyLine45PolygonData<T> > { typedef polygon_45_with_holes_concept type; }; struct geometry_concept<PolyLine45PolygonData<T> > { typedef polygon_45_with_holes_concept type; };
template <typename T> template <typename T>
struct geometry_concept<PolyLine45HoleData<T> > { typedef polygon_45_concept type; }; struct geometry_concept<PolyLine45HoleData<T> > { typedef polygon_45_concept type; };
} }
} }
#endif #endif
...@@ -124,13 +124,13 @@ namespace boost { namespace polygon{ ...@@ -124,13 +124,13 @@ namespace boost { namespace polygon{
}; };
template <typename ltype, typename rtype, int op_type> template <typename ltype, typename rtype, int op_type>
typename polygon_45_set_view<ltype, rtype, op_type>::iterator_type typename polygon_45_set_traits<polygon_45_set_view<ltype, rtype, op_type> >::iterator_type
polygon_45_set_traits<polygon_45_set_view<ltype, rtype, op_type> >:: polygon_45_set_traits<polygon_45_set_view<ltype, rtype, op_type> >::
begin(const polygon_45_set_view<ltype, rtype, op_type>& polygon_45_set) { begin(const polygon_45_set_view<ltype, rtype, op_type>& polygon_45_set) {
return polygon_45_set.begin(); return polygon_45_set.begin();
} }
template <typename ltype, typename rtype, int op_type> template <typename ltype, typename rtype, int op_type>
typename polygon_45_set_view<ltype, rtype, op_type>::iterator_type typename polygon_45_set_traits<polygon_45_set_view<ltype, rtype, op_type> >::iterator_type
polygon_45_set_traits<polygon_45_set_view<ltype, rtype, op_type> >:: polygon_45_set_traits<polygon_45_set_view<ltype, rtype, op_type> >::
end(const polygon_45_set_view<ltype, rtype, op_type>& polygon_45_set) { end(const polygon_45_set_view<ltype, rtype, op_type>& polygon_45_set) {
return polygon_45_set.end(); return polygon_45_set.end();
......
...@@ -140,13 +140,13 @@ namespace boost { namespace polygon{ ...@@ -140,13 +140,13 @@ namespace boost { namespace polygon{
}; };
template <typename ltype, typename rtype, typename op_type> template <typename ltype, typename rtype, typename op_type>
typename polygon_90_set_view<ltype, rtype, op_type>::iterator_type typename polygon_90_set_traits<polygon_90_set_view<ltype, rtype, op_type> >::iterator_type
polygon_90_set_traits<polygon_90_set_view<ltype, rtype, op_type> >:: polygon_90_set_traits<polygon_90_set_view<ltype, rtype, op_type> >::
begin(const polygon_90_set_view<ltype, rtype, op_type>& polygon_set) { begin(const polygon_90_set_view<ltype, rtype, op_type>& polygon_set) {
return polygon_set.begin(); return polygon_set.begin();
} }
template <typename ltype, typename rtype, typename op_type> template <typename ltype, typename rtype, typename op_type>
typename polygon_90_set_view<ltype, rtype, op_type>::iterator_type typename polygon_90_set_traits<polygon_90_set_view<ltype, rtype, op_type> >::iterator_type
polygon_90_set_traits<polygon_90_set_view<ltype, rtype, op_type> >:: polygon_90_set_traits<polygon_90_set_view<ltype, rtype, op_type> >::
end(const polygon_90_set_view<ltype, rtype, op_type>& polygon_set) { end(const polygon_90_set_view<ltype, rtype, op_type>& polygon_set) {
return polygon_set.end(); return polygon_set.end();
......
...@@ -42,7 +42,7 @@ namespace boost { namespace polygon{ ...@@ -42,7 +42,7 @@ namespace boost { namespace polygon{
ivlIds_.second = that.ivlIds_.second; ivlIds_.second = that.ivlIds_.second;
incremented_ = that.incremented_; incremented_ = that.incremented_;
return *this; return *this;
}; }
inline bool operator==(const iterator& that) { return itr_ == that.itr_; } inline bool operator==(const iterator& that) { return itr_ == that.itr_; }
inline bool operator!=(const iterator& that) { return itr_ != that.itr_; } inline bool operator!=(const iterator& that) { return itr_ != that.itr_; }
inline iterator& operator++() { inline iterator& operator++() {
......
...@@ -388,7 +388,8 @@ namespace boost { namespace polygon{ ...@@ -388,7 +388,8 @@ namespace boost { namespace polygon{
struct compute_intersection_pack { struct compute_intersection_pack {
typedef typename high_precision_type<Unit>::type high_precision; typedef typename high_precision_type<Unit>::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; 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; 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<Unit> Rectangle; typedef rectangle_data<Unit> Rectangle;
Rectangle rect1, rect2; Rectangle rect1, rect2;
...@@ -445,6 +446,10 @@ namespace boost { namespace polygon{ ...@@ -445,6 +446,10 @@ namespace boost { namespace polygon{
//std::cout << "cross2 " << dy2 << " " << dx1 << " " << dy2 * dx1 << std::endl; //std::cout << "cross2 " << dy2 << " " << dx1 << " " << dy2 * dx1 << std::endl;
//Unit exp_x = compute_x_intercept<at>(x11, x21, y11, y21, dy1, dy2, dx1, dx2); //Unit exp_x = compute_x_intercept<at>(x11, x21, y11, y21, dy1, dy2, dx1, dx2);
//Unit exp_y = compute_x_intercept<at>(y11, y21, x11, x21, dx1, dx2, dy1, dy2); //Unit exp_y = compute_x_intercept<at>(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 x_unit = (Unit)(x);
Unit y_unit = (Unit)(y); Unit y_unit = (Unit)(y);
//truncate downward if it went up due to negative number //truncate downward if it went up due to negative number
...@@ -463,12 +468,17 @@ namespace boost { namespace polygon{ ...@@ -463,12 +468,17 @@ namespace boost { namespace polygon{
(long double) (std::numeric_limits<Unit>::min)(), (long double) (std::numeric_limits<Unit>::min)(),
(long double)(std::numeric_limits<Unit>::max)(), (long double)(std::numeric_limits<Unit>::max)(),
(long double) (std::numeric_limits<Unit>::max)() ); (long double) (std::numeric_limits<Unit>::max)() );
return contains(inf_rect, intersection, true); if(contains(inf_rect, intersection, true)) {
intersection = result;
return true;
} else
return false;
} }
intersection = result; intersection = result;
return true; 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)) if(!projected && !intersects(he1, he2))
return false; return false;
bool lazy_success = compute_lazy_intersection(intersection, he1, he2, projected); bool lazy_success = compute_lazy_intersection(intersection, he1, he2, projected);
...@@ -536,6 +546,10 @@ namespace boost { namespace polygon{ ...@@ -536,6 +546,10 @@ namespace boost { namespace polygon{
//std::cout << "cross2 " << dy2 << " " << dx1 << " " << dy2 * dx1 << std::endl; //std::cout << "cross2 " << dy2 << " " << dx1 << " " << dy2 * dx1 << std::endl;
//Unit exp_x = compute_x_intercept<at>(x11, x21, y11, y21, dy1, dy2, dx1, dx2); //Unit exp_x = compute_x_intercept<at>(x11, x21, y11, y21, dy1, dy2, dx1, dx2);
//Unit exp_y = compute_x_intercept<at>(y11, y21, x11, x21, dx1, dx2, dy1, dy2); //Unit exp_y = compute_x_intercept<at>(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<Unit>(x); Unit x_unit = convert_high_precision_type<Unit>(x);
Unit y_unit = convert_high_precision_type<Unit>(y); Unit y_unit = convert_high_precision_type<Unit>(y);
//truncate downward if it went up due to negative number //truncate downward if it went up due to negative number
...@@ -549,6 +563,17 @@ namespace boost { namespace polygon{ ...@@ -549,6 +563,17 @@ namespace boost { namespace polygon{
Point result(x_unit, y_unit); Point result(x_unit, y_unit);
if(!contains(rect1, result, true)) return false; if(!contains(rect1, result, true)) return false;
if(!contains(rect2, result, true)) return false; if(!contains(rect2, result, true)) return false;
if(projected) {
rectangle_data<long double> inf_rect((long double)(std::numeric_limits<Unit>::min)(),
(long double) (std::numeric_limits<Unit>::min)(),
(long double)(std::numeric_limits<Unit>::max)(),
(long double) (std::numeric_limits<Unit>::max)() );
if(contains(inf_rect, intersection, true)) {
intersection = result;
return true;
} else
return false;
}
intersection = result; intersection = result;
return true; return true;
} }
...@@ -872,7 +897,7 @@ namespace boost { namespace polygon{ ...@@ -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_() { inline active_tail_arbitrary(const vertex_half_edge& vertex, active_tail_arbitrary* otherTailp = 0) : tailp_(), otherTailp_(), holesList_(), head_() {
tailp_ = new poly_line_arbitrary; tailp_ = new poly_line_arbitrary;
tailp_->points.push_back(vertex.pt); 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; bool inverted = vertex.count == -1;
head_ = (!vertex.is_vertical) ^ inverted; head_ = (!vertex.is_vertical) ^ inverted;
otherTailp_ = otherTailp; otherTailp_ = otherTailp;
...@@ -1172,7 +1197,7 @@ namespace boost { namespace polygon{ ...@@ -1172,7 +1197,7 @@ namespace boost { namespace polygon{
inline less_half_edge_count() : pt_() {} inline less_half_edge_count() : pt_() {}
inline less_half_edge_count(Point point) : pt_(point) {} inline less_half_edge_count(Point point) : pt_(point) {}
inline bool operator () (const std::pair<Point, int>& elm1, const std::pair<Point, int>& elm2) const { inline bool operator () (const std::pair<Point, int>& elm1, const std::pair<Point, int>& elm2) const {
return less_slope(pt_.get(HORIZONTAL), pt_.get(VERTICAL), elm1.first, elm2.first); return scanline_base<Unit>::less_slope(pt_.get(HORIZONTAL), pt_.get(VERTICAL), elm1.first, elm2.first);
} }
}; };
...@@ -1196,7 +1221,7 @@ namespace boost { namespace polygon{ ...@@ -1196,7 +1221,7 @@ namespace boost { namespace polygon{
Unit dx2 = elm2.first.first.first.get(HORIZONTAL) - elm2.first.first.second.get(HORIZONTAL); 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 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); Unit dy2 = elm2.first.first.first.get(VERTICAL) - elm2.first.first.second.get(VERTICAL);
return less_slope(dx1, dy1, dx2, dy2); return scanline_base<Unit>::less_slope(dx1, dy1, dx2, dy2);
} }
}; };
...@@ -1356,7 +1381,7 @@ namespace boost { namespace polygon{ ...@@ -1356,7 +1381,7 @@ namespace boost { namespace polygon{
bool have_vertical_tail_from_below = false; bool have_vertical_tail_from_below = false;
if(c_size && if(c_size &&
is_vertical(counts_from_scanline.back().first.first)) { scanline_base<Unit>::is_vertical(counts_from_scanline.back().first.first)) {
have_vertical_tail_from_below = true; have_vertical_tail_from_below = true;
} }
//assert size = size_less_1 + 1 //assert size = size_less_1 + 1
...@@ -1704,7 +1729,7 @@ namespace boost { namespace polygon{ ...@@ -1704,7 +1729,7 @@ namespace boost { namespace polygon{
//std::cout << "checking whether ot handle hole\n"; //std::cout << "checking whether ot handle hole\n";
if(currentIter == inputEnd || if(currentIter == inputEnd ||
currentIter->pt.get(HORIZONTAL) != x_ || currentIter->pt.get(HORIZONTAL) != x_ ||
on_above_or_below(currentIter->pt, half_edge(iter->first.pt, iter->first.other_pt)) != -1) { scanline_base<Unit>::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_)) { //(high_precision)(currentIter->pt.get(VERTICAL)) >= iter->first.evalAtX(x_)) {
//std::cout << "handle hole here\n"; //std::cout << "handle hole here\n";
...@@ -2041,26 +2066,26 @@ namespace boost { namespace polygon{ ...@@ -2041,26 +2066,26 @@ namespace boost { namespace polygon{
he2.first = Point(0, 0); he2.first = Point(0, 0);
he2.second = Point(10, 20); he2.second = Point(10, 20);
Point result; Point result;
bool b = compute_intersection(result, he1, he2); bool b = scanline_base<Unit>::compute_intersection(result, he1, he2);
if(!b || result != Point(0, 0)) return false; if(!b || result != Point(0, 0)) return false;
he1.first = Point(0, 10); he1.first = Point(0, 10);
b = compute_intersection(result, he1, he2); b = scanline_base<Unit>::compute_intersection(result, he1, he2);
if(!b || result != Point(5, 10)) return false; if(!b || result != Point(5, 10)) return false;
he1.first = Point(0, 11); he1.first = Point(0, 11);
b = compute_intersection(result, he1, he2); b = scanline_base<Unit>::compute_intersection(result, he1, he2);
if(!b || result != Point(5, 10)) return false; if(!b || result != Point(5, 10)) return false;
he1.first = Point(0, 0); he1.first = Point(0, 0);
he1.second = Point(1, 9); he1.second = Point(1, 9);
he2.first = Point(0, 9); he2.first = Point(0, 9);
he2.second = Point(1, 0); he2.second = Point(1, 0);
b = compute_intersection(result, he1, he2); b = scanline_base<Unit>::compute_intersection(result, he1, he2);
if(!b || result != Point(0, 4)) return false; if(!b || result != Point(0, 4)) return false;
he1.first = Point(0, -10); he1.first = Point(0, -10);
he1.second = Point(1, -1); he1.second = Point(1, -1);
he2.first = Point(0, -1); he2.first = Point(0, -1);
he2.second = Point(1, -10); he2.second = Point(1, -10);
b = compute_intersection(result, he1, he2); b = scanline_base<Unit>::compute_intersection(result, he1, he2);
if(!b || result != Point(0, -5)) return false; if(!b || result != Point(0, -5)) return false;
he1.first = Point((std::numeric_limits<int>::max)(), (std::numeric_limits<int>::max)()-1); he1.first = Point((std::numeric_limits<int>::max)(), (std::numeric_limits<int>::max)()-1);
he1.second = Point((std::numeric_limits<int>::min)(), (std::numeric_limits<int>::max)()); he1.second = Point((std::numeric_limits<int>::min)(), (std::numeric_limits<int>::max)());
...@@ -2068,13 +2093,13 @@ namespace boost { namespace polygon{ ...@@ -2068,13 +2093,13 @@ namespace boost { namespace polygon{
he2.first = Point((std::numeric_limits<int>::max)()-1, (std::numeric_limits<int>::max)()); he2.first = Point((std::numeric_limits<int>::max)()-1, (std::numeric_limits<int>::max)());
he2.second = Point((std::numeric_limits<int>::max)(), (std::numeric_limits<int>::min)()); he2.second = Point((std::numeric_limits<int>::max)(), (std::numeric_limits<int>::min)());
//he2.second = Point((std::numeric_limits<int>::max)(), 0); //he2.second = Point((std::numeric_limits<int>::max)(), 0);
b = compute_intersection(result, he1, he2); b = scanline_base<Unit>::compute_intersection(result, he1, he2);
//b is false because of overflow error //b is false because of overflow error
he1.first = Point(1000, 2000); he1.first = Point(1000, 2000);
he1.second = Point(1010, 2010); he1.second = Point(1010, 2010);
he2.first = Point(1000, 2000); he2.first = Point(1000, 2000);
he2.second = Point(1010, 2020); he2.second = Point(1010, 2020);
b = compute_intersection(result, he1, he2); b = scanline_base<Unit>::compute_intersection(result, he1, he2);
if(!b || result != Point(1000, 2000)) return false; if(!b || result != Point(1000, 2000)) return false;
return b; return b;
...@@ -2301,7 +2326,7 @@ namespace boost { namespace polygon{ ...@@ -2301,7 +2326,7 @@ namespace boost { namespace polygon{
bool have_vertical_tail_from_below = false; bool have_vertical_tail_from_below = false;
if(c_size && if(c_size &&
is_vertical(counts_from_scanline.back().first.first)) { scanline_base<Unit>::is_vertical(counts_from_scanline.back().first.first)) {
have_vertical_tail_from_below = true; have_vertical_tail_from_below = true;
} }
//assert size = size_less_1 + 1 //assert size = size_less_1 + 1
...@@ -2607,7 +2632,7 @@ namespace boost { namespace polygon{ ...@@ -2607,7 +2632,7 @@ namespace boost { namespace polygon{
//std::cout << "current Y " << currentY << std::endl; //std::cout << "current Y " << currentY << std::endl;
//std::cout << "scanline size " << scanData_.size() << std::endl; //std::cout << "scanline size " << scanData_.size() << std::endl;
//print(scanData_); //print(scanData_);
iterator iter = lookUp_(currentY); iterator iter = this->lookUp_(currentY);
//std::cout << "found element in scanline " << (iter != scanData_.end()) << std::endl; //std::cout << "found element in scanline " << (iter != scanData_.end()) << std::endl;
//int counts[4] = {0, 0, 0, 0}; //int counts[4] = {0, 0, 0, 0};
incoming_count counts_from_scanline; incoming_count counts_from_scanline;
...@@ -2634,7 +2659,7 @@ namespace boost { namespace polygon{ ...@@ -2634,7 +2659,7 @@ namespace boost { namespace polygon{
} }
Point currentPoint(polygon_arbitrary_formation<Unit>::x_, currentY); Point currentPoint(polygon_arbitrary_formation<Unit>::x_, currentY);
//std::cout << "counts_from_scanline size " << counts_from_scanline.size() << std::endl; //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; vertex_arbitrary_count incoming;
//std::cout << "aggregating\n"; //std::cout << "aggregating\n";
...@@ -2646,7 +2671,7 @@ namespace boost { namespace polygon{ ...@@ -2646,7 +2671,7 @@ namespace boost { namespace polygon{
} while(currentIter != inputEnd && currentIter->pt.get(VERTICAL) == currentY && } while(currentIter != inputEnd && currentIter->pt.get(VERTICAL) == currentY &&
currentIter->pt.get(HORIZONTAL) == polygon_arbitrary_formation<Unit>::x_); currentIter->pt.get(HORIZONTAL) == polygon_arbitrary_formation<Unit>::x_);
//print(incoming); //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; //std::cout << currentPoint.get(HORIZONTAL) << "," << currentPoint.get(VERTICAL) << std::endl;
//print(incoming); //print(incoming);
//std::cout << "incoming counts from input size " << incoming.size() << std::endl; //std::cout << "incoming counts from input size " << incoming.size() << std::endl;
......
...@@ -1721,7 +1721,7 @@ namespace polygon_formation { ...@@ -1721,7 +1721,7 @@ namespace polygon_formation {
unsigned int get_polygons(output_container& container, iterator_type begin, iterator_type end, unsigned int get_polygons(output_container& container, iterator_type begin, iterator_type end,
orientation_2d orient, bool fracture_holes, concept_type ) { orientation_2d orient, bool fracture_holes, concept_type ) {
typedef typename output_container::value_type polygon_type; typedef typename output_container::value_type polygon_type;
typedef typename iterator_type::value_type::first_type coordinate_type; typedef typename std::iterator_traits<iterator_type>::value_type::first_type coordinate_type;
polygon_type poly; polygon_type poly;
unsigned int countPolygons = 0; unsigned int countPolygons = 0;
typedef typename geometry_concept<polygon_type>::type polygon_concept_type; typedef typename geometry_concept<polygon_type>::type polygon_concept_type;
......
...@@ -153,13 +153,13 @@ namespace boost { namespace polygon{ ...@@ -153,13 +153,13 @@ namespace boost { namespace polygon{
}; };
template <typename ltype, typename rtype, int op_type> template <typename ltype, typename rtype, int op_type>
typename polygon_set_view<ltype, rtype, op_type>::iterator_type typename polygon_set_traits<polygon_set_view<ltype, rtype, op_type> >::iterator_type
polygon_set_traits<polygon_set_view<ltype, rtype, op_type> >:: polygon_set_traits<polygon_set_view<ltype, rtype, op_type> >::
begin(const polygon_set_view<ltype, rtype, op_type>& polygon_set) { begin(const polygon_set_view<ltype, rtype, op_type>& polygon_set) {
return polygon_set.begin(); return polygon_set.begin();
} }
template <typename ltype, typename rtype, int op_type> template <typename ltype, typename rtype, int op_type>
typename polygon_set_view<ltype, rtype, op_type>::iterator_type typename polygon_set_traits<polygon_set_view<ltype, rtype, op_type> >::iterator_type
polygon_set_traits<polygon_set_view<ltype, rtype, op_type> >:: polygon_set_traits<polygon_set_view<ltype, rtype, op_type> >::
end(const polygon_set_view<ltype, rtype, op_type>& polygon_set) { end(const polygon_set_view<ltype, rtype, op_type>& polygon_set) {
return polygon_set.end(); return polygon_set.end();
......
...@@ -33,38 +33,38 @@ namespace boost { namespace polygon{ ...@@ -33,38 +33,38 @@ namespace boost { namespace polygon{
typedef std::map<half_edge, std::set<segment_id>, less_half_edge> edge_scanline; typedef std::map<half_edge, std::set<segment_id>, less_half_edge> edge_scanline;
typedef typename edge_scanline::iterator iterator; typedef typename edge_scanline::iterator iterator;
std::map<Unit, std::set<segment_id> > vertical_data_; // std::map<Unit, std::set<segment_id> > vertical_data_;
edge_scanline edge_scanline_; // edge_scanline edge_scanline_;
Unit x_; // Unit x_;
int just_before_; // int just_before_;
segment_id segment_id_; // segment_id segment_id_;
std::vector<std::pair<half_edge, int> > event_edges_; // std::vector<std::pair<half_edge, int> > event_edges_;
std::set<Point> intersection_queue_; // std::set<Point> intersection_queue_;
public: public:
inline line_intersection() : vertical_data_(), edge_scanline_(), x_((std::numeric_limits<Unit>::max)()), just_before_(0), segment_id_(0), event_edges_(), intersection_queue_() { // inline line_intersection() : vertical_data_(), edge_scanline_(), x_((std::numeric_limits<Unit>::max)()), just_before_(0), segment_id_(0), event_edges_(), intersection_queue_() {
less_half_edge lessElm(&x_, &just_before_); // less_half_edge lessElm(&x_, &just_before_);
edge_scanline_ = edge_scanline(lessElm); // 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(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) { // inline line_intersection& operator=(const line_intersection& that) {
x_ = that.x_; // x_ = that.x_;
just_before_ = that.just_before_; // just_before_ = that.just_before_;
segment_id_ = that.segment_id_; // segment_id_ = that.segment_id_;
//I cannot simply copy that.edge_scanline_ to this edge_scanline_ becuase the functor store pointers to other members! // //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_); // less_half_edge lessElm(&x_, &just_before_);
edge_scanline_ = edge_scanline(lessElm); // edge_scanline_ = edge_scanline(lessElm);
edge_scanline_.insert(that.edge_scanline_.begin(), that.edge_scanline_.end()); // edge_scanline_.insert(that.edge_scanline_.begin(), that.edge_scanline_.end());
return *this; // return *this;
} // }
static inline void between(Point pt, Point pt1, Point pt2) { // static inline void between(Point pt, Point pt1, Point pt2) {
less_point lp; // less_point lp;
if(lp(pt1, pt2)) // if(lp(pt1, pt2))
return lp(pt, pt2) && lp(pt1, pt); // return lp(pt, pt2) && lp(pt1, pt);
return lp(pt, pt1) && lp(pt2, pt); // return lp(pt, pt1) && lp(pt2, pt);
} // }
template <typename iT> template <typename iT>
static inline void compute_histogram_in_y(iT begin, iT end, std::size_t size, std::vector<std::pair<Unit, std::pair<std::size_t, std::size_t> > >& histogram) { static inline void compute_histogram_in_y(iT begin, iT end, std::size_t size, std::vector<std::pair<Unit, std::pair<std::size_t, std::size_t> > >& histogram) {
...@@ -216,7 +216,7 @@ namespace boost { namespace polygon{ ...@@ -216,7 +216,7 @@ namespace boost { namespace polygon{
//itr2 = pts.end(); //itr2 = pts.end();
while(lfinger != newend && (*lfinger).x() < startpt.x()) ++lfinger; while(lfinger != newend && (*lfinger).x() < startpt.x()) ++lfinger;
for(typename std::vector<Point>::iterator itr = lfinger ; itr != newend && (*itr).x() <= stoppt.x(); ++itr) { for(typename std::vector<Point>::iterator itr = lfinger ; itr != newend && (*itr).x() <= stoppt.x(); ++itr) {
if(intersects_grid(*itr, he1)) if(scanline_base<Unit>::intersects_grid(*itr, he1))
intersection_points[id1].insert(*itr); intersection_points[id1].insert(*itr);
} }
} }
...@@ -243,8 +243,8 @@ namespace boost { namespace polygon{ ...@@ -243,8 +243,8 @@ namespace boost { namespace polygon{
//edge changed orientation, invert count on edge //edge changed orientation, invert count on edge
output_segments.back().second.second *= -1; output_segments.back().second.second *= -1;
} }
if(!is_vertical(input_segments[intermediate_segments[i].second].first) && if(!scanline_base<Unit>::is_vertical(input_segments[intermediate_segments[i].second].first) &&
is_vertical(output_segments.back().first)) { scanline_base<Unit>::is_vertical(output_segments.back().first)) {
output_segments.back().second.second *= -1; output_segments.back().second.second *= -1;
} }
if(lp(output_segments.back().first.second, output_segments.back().first.first)) { if(lp(output_segments.back().first.second, output_segments.back().first.first)) {
...@@ -349,7 +349,7 @@ namespace boost { namespace polygon{ ...@@ -349,7 +349,7 @@ namespace boost { namespace polygon{
segment_id id = (*iter).second; segment_id id = (*iter).second;
const std::set<Point>& pts = intersection_points[id]; const std::set<Point>& pts = intersection_points[id];
Point hpt(he.first.get(HORIZONTAL)+1, he.first.get(VERTICAL)); 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<Unit>::is_vertical(he) && scanline_base<Unit>::less_slope(he.first.get(HORIZONTAL), he.first.get(VERTICAL),
he.second, hpt)) { he.second, hpt)) {
//slope is below horizontal //slope is below horizontal
std::vector<Point> tmpPts; std::vector<Point> tmpPts;
...@@ -365,263 +365,263 @@ namespace boost { namespace polygon{ ...@@ -365,263 +365,263 @@ namespace boost { namespace polygon{
} }
} }
//iT iterator over unsorted pair<Point> representing line segments of input // //iT iterator over unsorted pair<Point> representing line segments of input
//output_segments is populated with fully intersected output line segment half // //output_segments is populated with fully intersected output line segment half
//edges and the index of the input segment that they are assoicated with // //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 // //duplicate output half edges with different ids will be generated in the case
//that parallel input segments intersection // //that parallel input segments intersection
//outputs are in sorted order and include both begin and end events for // //outputs are in sorted order and include both begin and end events for
//each segment // //each segment
template <typename iT> // template <typename iT>
inline void scan(std::vector<std::pair<half_edge, int> >& output_segments, // inline void scan(std::vector<std::pair<half_edge, int> >& output_segments,
iT begin, iT end) { // iT begin, iT end) {
std::map<segment_id, std::set<Point> > intersection_points; // std::map<segment_id, std::set<Point> > intersection_points;
scan(intersection_points, begin, end); // scan(intersection_points, begin, end);
segment_intersections(output_segments, 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 // //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 // //intersection points provides a mapping from input segment id (vector index) to the set
//of intersection points assocated with that input segment // //of intersection points assocated with that input segment
template <typename iT> // template <typename iT>
inline void scan(std::map<segment_id, std::set<Point> >& intersection_points, // inline void scan(std::map<segment_id, std::set<Point> >& intersection_points,
iT begin, iT end) { // iT begin, iT end) {
for(iT iter = begin; iter != end; ++iter) { // for(iT iter = begin; iter != end; ++iter) {
const std::pair<half_edge, int>& elem = *iter; // const std::pair<half_edge, int>& elem = *iter;
const half_edge& he = elem.first; // const half_edge& he = elem.first;
Unit current_x = he.first.get(HORIZONTAL); // Unit current_x = he.first.get(HORIZONTAL);
if(current_x != x_) { // if(current_x != x_) {
process_scan_event(intersection_points); // process_scan_event(intersection_points);
while(!intersection_queue_.empty() && // while(!intersection_queue_.empty() &&
(*(intersection_queue_.begin()).get(HORIZONTAL) < current_x)) { // (*(intersection_queue_.begin()).get(HORIZONTAL) < current_x)) {
x_ = *(intersection_queue_.begin()).get(HORIZONTAL); // x_ = *(intersection_queue_.begin()).get(HORIZONTAL);
process_intersections_at_scan_event(intersection_points); // process_intersections_at_scan_event(intersection_points);
} // }
x_ = current_x; // x_ = current_x;
} // }
event_edges_.push_back(elem); // event_edges_.push_back(elem);
} // }
process_scan_event(intersection_points); // process_scan_event(intersection_points);
} // }
inline iterator lookup(const half_edge& he) { // inline iterator lookup(const half_edge& he) {
return edge_scanline_.find(he); // return edge_scanline_.find(he);
} // }
inline void insert_into_scanline(const half_edge& he, int id) { // inline void insert_into_scanline(const half_edge& he, int id) {
edge_scanline_[he].insert(id); // edge_scanline_[he].insert(id);
} // }
inline void lookup_and_remove(const half_edge& he, int id) { // inline void lookup_and_remove(const half_edge& he, int id) {
iterator remove_iter = lookup(he); // iterator remove_iter = lookup(he);
if(remove_iter == edge_scanline_.end()) { // if(remove_iter == edge_scanline_.end()) {
//std::cout << "failed to find removal segment in scanline\n"; // //std::cout << "failed to find removal segment in scanline\n";
return; // return;
} // }
std::set<segment_id>& ids = (*remove_iter).second; // std::set<segment_id>& ids = (*remove_iter).second;
std::set<segment_id>::iterator id_iter = ids.find(id); // std::set<segment_id>::iterator id_iter = ids.find(id);
if(id_iter == ids.end()) { // if(id_iter == ids.end()) {
//std::cout << "failed to find removal segment id in scanline set\n"; // //std::cout << "failed to find removal segment id in scanline set\n";
return; // return;
} // }
ids.erase(id_iter); // ids.erase(id_iter);
if(ids.empty()) // if(ids.empty())
edge_scanline_.erase(remove_iter); // edge_scanline_.erase(remove_iter);
} // }
static inline void update_segments(std::map<segment_id, std::set<Point> >& intersection_points, // static inline void update_segments(std::map<segment_id, std::set<Point> >& intersection_points,
const std::set<segment_id>& segments, Point pt) { // const std::set<segment_id>& segments, Point pt) {
for(std::set<segment_id>::const_iterator itr = segments.begin(); itr != segments.end(); ++itr) { // for(std::set<segment_id>::const_iterator itr = segments.begin(); itr != segments.end(); ++itr) {
intersection_points[*itr].insert(pt); // intersection_points[*itr].insert(pt);
} // }
} // }
inline void process_intersections_at_scan_event(std::map<segment_id, std::set<Point> >& intersection_points) { // inline void process_intersections_at_scan_event(std::map<segment_id, std::set<Point> >& intersection_points) {
//there may be additional intersection points at this x location that haven't been // //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 // //found yet if vertical or near vertical line segments intersect more than
//once before the next x location // //once before the next x location
just_before_ = true; // just_before_ = true;
std::set<iterator> intersecting_elements; // std::set<iterator> intersecting_elements;
std::set<Unit> intersection_locations; // std::set<Unit> intersection_locations;
typedef typename std::set<Point>::iterator intersection_iterator; // typedef typename std::set<Point>::iterator intersection_iterator;
intersection_iterator iter; // intersection_iterator iter;
//first find all secondary intersection locations and all scanline iterators // //first find all secondary intersection locations and all scanline iterators
//that are intersecting // //that are intersecting
for(iter = intersection_queue_.begin(); // for(iter = intersection_queue_.begin();
iter != intersection_queue_.end() && (*iter).get(HORIZONTAL) == x_; ++iter) { // iter != intersection_queue_.end() && (*iter).get(HORIZONTAL) == x_; ++iter) {
Point pt = *iter; // Point pt = *iter;
Unit y = pt.get(VERTICAL); // Unit y = pt.get(VERTICAL);
intersection_locations.insert(y); // intersection_locations.insert(y);
//if x_ is max there can be only end events and no sloping edges // //if x_ is max there can be only end events and no sloping edges
if(x_ != (std::numeric_limits<Unit>::max)()) { // if(x_ != (std::numeric_limits<Unit>::max)()) {
//deal with edges that project to the right of scanline // //deal with edges that project to the right of scanline
//first find the edges in the scanline adjacent to primary intersectin points // //first find the edges in the scanline adjacent to primary intersectin points
//lookup segment in scanline at pt // //lookup segment in scanline at pt
iterator itr = edge_scanline_.lower_bound(half_edge(pt, Point(x_+1, y))); // 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 // //look above pt in scanline until reaching end or segment that doesn't intersect
//1x1 grid upper right of pt // //1x1 grid upper right of pt
//look below pt in scanline until reaching begin or segment that doesn't interset // //look below pt in scanline until reaching begin or segment that doesn't interset
//1x1 grid upper right of pt // //1x1 grid upper right of pt
//second find edges in scanline on the y interval of each edge found in the previous // //second find edges in scanline on the y interval of each edge found in the previous
//step for x_ to x_ + 1 // //step for x_ to x_ + 1
//third find overlaps in the y intervals of all found edges to find all // //third find overlaps in the y intervals of all found edges to find all
//secondary intersection points // //secondary intersection points
}
}
//erase the intersection points from the queue
intersection_queue_.erase(intersection_queue_.begin(), iter);
std::vector<scanline_element> insertion_edges;
insertion_edges.reserve(intersecting_elements.size());
std::vector<std::pair<Unit, iterator> > sloping_ends;
//do all the work of updating the output of all intersecting
for(typename std::set<iterator>::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<Unit>::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<Unit, std::set<iterator> > sloping_elements;
std::set<iterator> merge_elements;
for(typename std::vector<std::pair<Unit, iterator> >::iterator slop_iter = sloping_ends.begin();
slop_iter = sloping_ends.end(); ++slop_iter) {
//merge into sloping elements
typename std::set<iterator>::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<Unit, std::set<segment_id> >::iterator vertical_iter = vertical_data_.begin(); // }
typename std::map<Unit, std::set<iterator> >::iterator sloping_iter = sloping_elements.begin(); // //erase the intersection points from the queue
for(typename std::set<Unit>::iterator position_iter = intersection_locations.begin(); // intersection_queue_.erase(intersection_queue_.begin(), iter);
position_iter = intersection_locations.end(); ++position_iter) { // std::vector<scanline_element> insertion_edges;
//look for vertical segments that intersect this point and update them // insertion_edges.reserve(intersecting_elements.size());
Unit y = *position_iter; // std::vector<std::pair<Unit, iterator> > sloping_ends;
Point pt(x_, y); // //do all the work of updating the output of all intersecting
//handle vertical segments // for(typename std::set<iterator>::iterator inter_iter = intersecting_elements.begin();
if(vertical_iter != vertical_data_.end()) { // inter_iter != intersecting_elements.end(); ++inter_iter) {
typename std::map<Unit, std::set<segment_id> >::iterator next_vertical = vertical_iter; // //if it is horizontal update it now and continue
for(++next_vertical; next_vertical != vertical_data_.end() && // if(is_horizontal((*inter_iter).first)) {
(*next_vertical).first < y; ++next_vertical) { // update_segments(intersection_points, (*inter_iter).second, Point(x_, (*inter_iter).first.get(VERTICAL)));
vertical_iter = next_vertical; // } else {
} // //if x_ is max there can be only end events and no sloping edges
if((*vertical_iter).first < y && !(*vertical_iter).second.empty()) { // if(x_ != (std::numeric_limits<Unit>::max)()) {
update_segments(intersection_points, (*vertical_iter).second, pt); // //insert its end points into the vector of sloping ends
++vertical_iter; // const half_edge& he = (*inter_iter).first;
if(vertical_iter != vertical_data_.end() && (*vertical_iter).first == y) // Unit y = evalAtXforY(x_, he.first, he.second);
update_segments(intersection_points, (*vertical_iter).second, pt); // 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
//handle sloping segments // sloping_ends.push_back(std::make_pair(y, inter_iter));
if(sloping_iter != sloping_elements.end()) { // sloping_ends.push_back(std::make_pair(y2, inter_iter));
typename std::map<Unit, std::set<iterator> >::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>::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>::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 // //merge sloping element data
} // std::sort(sloping_ends.begin(), sloping_ends.end());
// std::map<Unit, std::set<iterator> > sloping_elements;
// std::set<iterator> merge_elements;
// for(typename std::vector<std::pair<Unit, iterator> >::iterator slop_iter = sloping_ends.begin();
// slop_iter == sloping_ends.end(); ++slop_iter) {
// //merge into sloping elements
// typename std::set<iterator>::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;
// }
inline void process_scan_event(std::map<segment_id, std::set<Point> >& intersection_points) { // //scan intersection points
just_before_ = true; // typename std::map<Unit, std::set<segment_id> >::iterator vertical_iter = vertical_data_.begin();
// typename std::map<Unit, std::set<iterator> >::iterator sloping_iter = sloping_elements.begin();
// for(typename std::set<Unit>::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<Unit, std::set<segment_id> >::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<Unit, std::set<iterator> >::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>::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>::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);
// }
// }
// }
// }
// }
// }
//process end events by removing those segments from the scanline // //erase and reinsert edges into scanline with check for future intersection
//and insert vertices of all events into intersection queue // }
Point prev_point((std::numeric_limits<Unit>::min)(), (std::numeric_limits<Unit>::min)());
less_point lp; // inline void process_scan_event(std::map<segment_id, std::set<Point> >& intersection_points) {
std::set<segment_id> vertical_ids; // just_before_ = true;
vertical_data_.clear();
for(std::size_t i = 0; i < event_edges_.size(); ++i) { // //process end events by removing those segments from the scanline
segment_id id = event_edges_[i].second; // //and insert vertices of all events into intersection queue
const half_edge& he = event_edges_[i].first; // Point prev_point((std::numeric_limits<Unit>::min)(), (std::numeric_limits<Unit>::min)());
//vertical half edges are handled during intersection processing because // less_point lp;
//they cannot be inserted into the scanline // std::set<segment_id> vertical_ids;
if(!is_vertical(he)) { // vertical_data_.clear();
if(lp(he.second, he.first)) { // for(std::size_t i = 0; i < event_edges_.size(); ++i) {
//half edge is end event // segment_id id = event_edges_[i].second;
lookup_and_remove(he, id); // const half_edge& he = event_edges_[i].first;
} else { // //vertical half edges are handled during intersection processing because
//half edge is begin event // //they cannot be inserted into the scanline
insert_into_scanline(he, id); // if(!is_vertical(he)) {
//note that they will be immediately removed and reinserted after // if(lp(he.second, he.first)) {
//handling their intersection (vertex) // //half edge is end event
//an optimization would allow them to be processed specially to avoid the redundant // lookup_and_remove(he, id);
//removal and reinsertion // } else {
} // //half edge is begin event
} else { // insert_into_scanline(he, id);
//common case if you are lucky // //note that they will be immediately removed and reinserted after
//update the map of y to set of segment id // //handling their intersection (vertex)
if(lp(he.second, he.first)) { // //an optimization would allow them to be processed specially to avoid the redundant
//half edge is end event // //removal and reinsertion
std::set<segment_id>::iterator itr = vertical_ids.find(id); // }
if(itr == vertical_ids.end()) { // } else {
//std::cout << "Failed to find end event id in vertical ids\n"; // //common case if you are lucky
} else { // //update the map of y to set of segment id
vertical_ids.erase(itr); // if(lp(he.second, he.first)) {
vertical_data_[he.first.get(HORIZONTAL)] = vertical_ids; // //half edge is end event
} // std::set<segment_id>::iterator itr = vertical_ids.find(id);
} else { // if(itr == vertical_ids.end()) {
//half edge is a begin event // //std::cout << "Failed to find end event id in vertical ids\n";
vertical_ids.insert(id); // } else {
vertical_data_[he.first.get(HORIZONTAL)] = vertical_ids; // vertical_ids.erase(itr);
} // vertical_data_[he.first.get(HORIZONTAL)] = vertical_ids;
} // }
//prevent repeated insertion of same vertex into intersection queue // } else {
if(prev_point != he.first) // //half edge is a begin event
intersection_queue_.insert(he.first); // vertical_ids.insert(id);
else // vertical_data_[he.first.get(HORIZONTAL)] = vertical_ids;
prev_point = he.first; // }
// process intersections at scan event // }
process_intersections_at_scan_event(intersection_points); // //prevent repeated insertion of same vertex into intersection queue
} // if(prev_point != he.first)
event_edges_.clear(); // 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: public:
template <typename stream_type> template <typename stream_type>
...@@ -892,23 +892,23 @@ namespace boost { namespace polygon{ ...@@ -892,23 +892,23 @@ namespace boost { namespace polygon{
return false; return false;
} }
edges.pop_back(); 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())) { if(!verify_scan(result, edges.begin(), edges.end())) {
stdcout << "fail3\n"; stdcout << "fail3\n";
return false; 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())) { if(verify_scan(result, edges.begin(), edges.end())) {
stdcout << "fail4\n"; stdcout << "fail4\n";
return false; return false;
} }
edges.pop_back(); 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())) { if(!verify_scan(result, edges.begin(), edges.end())) {
stdcout << "fail5 " << result.first << " " << result.second << "\n"; stdcout << "fail5 " << result.first << " " << result.second << "\n";
return false; 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())) { if(verify_scan(result, edges.begin(), edges.end())) {
stdcout << "fail6 " << result.first << " " << result.second << "\n"; stdcout << "fail6 " << result.first << " " << result.second << "\n";
return false; return false;
...@@ -1048,7 +1048,7 @@ namespace boost { namespace polygon{ ...@@ -1048,7 +1048,7 @@ namespace boost { namespace polygon{
if(current_iter != scan_data_.end()) { if(current_iter != scan_data_.end()) {
//make sure we are looking at element in scanline just below y //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(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<Unit>::on_above_or_below(Point(x_, y), (*current_iter).first) != 0) {
Point e2(pt); Point e2(pt);
if(e2.get(VERTICAL) != (std::numeric_limits<Unit>::max)()) if(e2.get(VERTICAL) != (std::numeric_limits<Unit>::max)())
e2.set(VERTICAL, e2.get(VERTICAL) + 1); e2.set(VERTICAL, e2.get(VERTICAL) + 1);
...@@ -1060,12 +1060,12 @@ namespace boost { namespace polygon{ ...@@ -1060,12 +1060,12 @@ namespace boost { namespace polygon{
if(current_iter != scan_data_.end()) { if(current_iter != scan_data_.end()) {
//get the bottom iterator for elements at this point //get the bottom iterator for elements at this point
//while(evalAtXforY(x_, (*current_iter).first.first, (*current_iter).first.second) >= (high_precision)y && //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<Unit>::on_above_or_below(Point(x_, y), (*current_iter).first) != 1 &&
current_iter != scan_data_.begin()) { current_iter != scan_data_.begin()) {
--current_iter; --current_iter;
} }
//if(evalAtXforY(x_, (*current_iter).first.first, (*current_iter).first.second) >= (high_precision)y) { //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<Unit>::on_above_or_below(Point(x_, y), (*current_iter).first) != 1) {
properties_below.clear(); properties_below.clear();
} else { } else {
properties_below = (*current_iter).second; properties_below = (*current_iter).second;
...@@ -1078,7 +1078,7 @@ namespace boost { namespace polygon{ ...@@ -1078,7 +1078,7 @@ namespace boost { namespace polygon{
while(current_iter != scan_data_.end() && while(current_iter != scan_data_.end() &&
//can only be true if y is integer //can only be true if y is integer
//evalAtXforY(x_, (*current_iter).first.first, (*current_iter).first.second) == y) { //evalAtXforY(x_, (*current_iter).first.first, (*current_iter).first.second) == y) {
on_above_or_below(Point(x_, y), (*current_iter).first) == 0) { scanline_base<Unit>::on_above_or_below(Point(x_, y), (*current_iter).first) == 0) {
//removal_set_.push_back(current_iter); //removal_set_.push_back(current_iter);
++current_iter; ++current_iter;
} }
...@@ -1129,7 +1129,7 @@ namespace boost { namespace polygon{ ...@@ -1129,7 +1129,7 @@ namespace boost { namespace polygon{
y = vertical_edge_below.second.get(VERTICAL); y = vertical_edge_below.second.get(VERTICAL);
continue; continue;
} }
if(is_vertical(he)) { if(scanline_base<Unit>::is_vertical(he)) {
update_property_map(vertical_properties_above, vp.second); update_property_map(vertical_properties_above, vp.second);
vertical_edge_above = he; vertical_edge_above = he;
} else { } else {
...@@ -1556,7 +1556,7 @@ namespace boost { namespace polygon{ ...@@ -1556,7 +1556,7 @@ namespace boost { namespace polygon{
sl.scan(result, mof, pmd.begin(), pmd.end()); sl.scan(result, mof, pmd.begin(), pmd.end());
} }
inline bool verify() { inline bool verify1() {
std::pair<int, int> offenders; std::pair<int, int> offenders;
std::vector<std::pair<half_edge, int> > lines; std::vector<std::pair<half_edge, int> > lines;
int count = 0; int count = 0;
...@@ -1704,7 +1704,7 @@ namespace boost { namespace polygon{ ...@@ -1704,7 +1704,7 @@ namespace boost { namespace polygon{
//if half edge 1 is not vertical its slope is less than that of half edge 2 //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 get(pt1, HORIZONTAL) != get(pt2, HORIZONTAL);
} }
return less_slope(get(pt_, HORIZONTAL), return scanline_base<Unit>::less_slope(get(pt_, HORIZONTAL),
get(pt_, VERTICAL), pt1, pt2); get(pt_, VERTICAL), pt1, pt2);
} }
}; };
...@@ -2154,7 +2154,7 @@ pts.push_back(Point(12344171, 6695983 )); pts.push_back(Point(12287208, 6672388 ...@@ -2154,7 +2154,7 @@ pts.push_back(Point(12344171, 6695983 )); pts.push_back(Point(12287208, 6672388
si.insert(poly, 444); si.insert(poly, 444);
result.clear(); result.clear();
si.merge(result); si.merge(result);
si.verify(); si.verify1();
print(stdcout, si.pmd) << std::endl; print(stdcout, si.pmd) << std::endl;
if(!result.empty()) { if(!result.empty()) {
psd = (*(result.begin())).second; psd = (*(result.begin())).second;
...@@ -2534,7 +2534,7 @@ pts.push_back(Point(12344171, 6695983 )); pts.push_back(Point(12287208, 6672388 ...@@ -2534,7 +2534,7 @@ pts.push_back(Point(12344171, 6695983 )); pts.push_back(Point(12287208, 6672388
elem.first = edge; elem.first = edge;
elem.second = 1; elem.second = 1;
if(edge.second < edge.first) elem.second *= -1; if(edge.second < edge.first) elem.second *= -1;
if(is_vertical(edge)) elem.second *= -1; if(scanline_base<Unit>::is_vertical(edge)) elem.second *= -1;
#ifdef BOOST_POLYGON_MSVC #ifdef BOOST_POLYGON_MSVC
#pragma warning (disable: 4127) #pragma warning (disable: 4127)
#endif #endif
......
...@@ -34,17 +34,29 @@ namespace boost { namespace polygon{ ...@@ -34,17 +34,29 @@ namespace boost { namespace polygon{
#endif #endif
{ (*this) = that; } { (*this) = that; }
template <typename other> template <typename other>
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) { inline point_data& operator=(const point_data& that) {
coords_[0] = that.coords_[0]; coords_[1] = that.coords_[1]; return *this; coords_[0] = that.coords_[0]; coords_[1] = that.coords_[1]; return *this;
} }
template<typename T1, typename T2> template<typename T1, typename T2>
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_[HORIZONTAL] = (coordinate_type)x;
coords_[VERTICAL] = (coordinate_type)y; coords_[VERTICAL] = (coordinate_type)y;
} }
template <typename T2> template <typename T2>
inline point_data(const point_data<T2>& rvalue):coords_() { inline point_data(const point_data<T2>& rvalue)
#ifndef BOOST_POLYGON_MSVC
:coords_()
#endif
{
coords_[HORIZONTAL] = (coordinate_type)(rvalue.x()); coords_[HORIZONTAL] = (coordinate_type)(rvalue.x());
coords_[VERTICAL] = (coordinate_type)(rvalue.y()); coords_[VERTICAL] = (coordinate_type)(rvalue.y());
} }
......
...@@ -62,7 +62,7 @@ public: ...@@ -62,7 +62,7 @@ public:
inline std::size_t size() const { return coords_.size(); } inline std::size_t size() const { return coords_.size(); }
private: public:
std::vector<point_data<coordinate_type> > coords_; std::vector<point_data<coordinate_type> > coords_;
}; };
......
...@@ -1541,11 +1541,11 @@ namespace boost { namespace polygon{ ...@@ -1541,11 +1541,11 @@ namespace boost { namespace polygon{
polygon_90_set_data<Unit> l90sd(VERTICAL), r90sd(VERTICAL), output(VERTICAL); polygon_90_set_data<Unit> l90sd(VERTICAL), r90sd(VERTICAL), output(VERTICAL);
for(typename value_type::const_iterator itr = data_.begin(); itr != data_.end(); ++itr) { for(typename value_type::const_iterator itr = data_.begin(); itr != data_.end(); ++itr) {
if((*itr).count[3] == 0) continue; //skip all non vertical edges 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<Unit, int>((*itr).pt.y(), (*itr).count[3])), false, VERTICAL);
} }
for(typename value_type::const_iterator itr = rvalue.data_.begin(); itr != rvalue.data_.end(); ++itr) { 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 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<Unit, int>((*itr).pt.y(), (*itr).count[3])), false, VERTICAL);
} }
l90sd.sort(); l90sd.sort();
r90sd.sort(); r90sd.sort();
...@@ -1673,7 +1673,7 @@ namespace boost { namespace polygon{ ...@@ -1673,7 +1673,7 @@ namespace boost { namespace polygon{
polygon_90_set_data<Unit> l90sd(VERTICAL); polygon_90_set_data<Unit> l90sd(VERTICAL);
for(typename value_type::const_iterator itr = data_.begin(); itr != data_.end(); ++itr) { for(typename value_type::const_iterator itr = data_.begin(); itr != data_.end(); ++itr) {
if((*itr).count[3] == 0) continue; //skip all non vertical edges 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<Unit, int>((*itr).pt.y(), (*itr).count[3])), false, VERTICAL);
} }
l90sd.sort(); l90sd.sort();
#ifdef BOOST_POLYGON_MSVC #ifdef BOOST_POLYGON_MSVC
......
...@@ -137,7 +137,7 @@ namespace boost { namespace polygon{ ...@@ -137,7 +137,7 @@ namespace boost { namespace polygon{
static inline bool clean(const polygon_45_set_data<T>& polygon_set) { polygon_set.clean(); return true; } static inline bool clean(const polygon_45_set_data<T>& polygon_set) { polygon_set.clean(); return true; }
static inline bool sorted(const polygon_45_set_data<T>& polygon_set) { int untested = 0;polygon_set.sort(); return true; } static inline bool sorted(const polygon_45_set_data<T>& polygon_set) { polygon_set.sort(); return true; }
}; };
} }
......
...@@ -96,10 +96,12 @@ public: ...@@ -96,10 +96,12 @@ public:
return holes_.size(); return holes_.size();
} }
private: public:
polygon_45_data<coordinate_type> self_; polygon_45_data<coordinate_type> self_;
std::list<hole_type> holes_; std::list<hole_type> holes_;
}; };
} }
} }
#endif #endif
......
...@@ -244,6 +244,38 @@ namespace boost { namespace polygon{ ...@@ -244,6 +244,38 @@ namespace boost { namespace polygon{
// get the scanline orientation of the polygon set // get the scanline orientation of the polygon set
inline orientation_2d orient() const { return orient_; } inline orientation_2d orient() const { return orient_; }
polygon_90_set_data<coordinate_type>& 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<boolean_op::BinaryNot>());
return *this;
}
polygon_90_set_data<coordinate_type>& 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<boolean_op::BinaryXor>());
return *this;
}
polygon_90_set_data<coordinate_type>& 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<boolean_op::BinaryAnd>());
return *this;
}
polygon_90_set_data<coordinate_type>& operator|=(const polygon_90_set_data& that) {
insert(that);
return *this;
}
void clean() const { void clean() const {
sort(); sort();
if(dirty_) { if(dirty_) {
...@@ -297,7 +329,7 @@ namespace boost { namespace polygon{ ...@@ -297,7 +329,7 @@ namespace boost { namespace polygon{
} }
polygon_90_set_data& polygon_90_set_data&
bloat(typename coordinate_traits<coordinate_type>::unsigned_area_type west_bloating, bloat2(typename coordinate_traits<coordinate_type>::unsigned_area_type west_bloating,
typename coordinate_traits<coordinate_type>::unsigned_area_type east_bloating, typename coordinate_traits<coordinate_type>::unsigned_area_type east_bloating,
typename coordinate_traits<coordinate_type>::unsigned_area_type south_bloating, typename coordinate_traits<coordinate_type>::unsigned_area_type south_bloating,
typename coordinate_traits<coordinate_type>::unsigned_area_type north_bloating) { typename coordinate_traits<coordinate_type>::unsigned_area_type north_bloating) {
...@@ -318,11 +350,257 @@ namespace boost { namespace polygon{ ...@@ -318,11 +350,257 @@ namespace boost { namespace polygon{
return *this; return *this;
} }
static void modify_pt(point_data<coordinate_type>& pt, const point_data<coordinate_type>& prev_pt,
const point_data<coordinate_type>& current_pt, const point_data<coordinate_type>& 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<point_data<coordinate_type> >& poly,
coordinate_type west_bloating,
coordinate_type east_bloating,
coordinate_type south_bloating,
coordinate_type north_bloating) {
point_data<coordinate_type> first_pt = poly[0];
point_data<coordinate_type> second_pt = poly[1];
point_data<coordinate_type> prev_pt = poly[0];
point_data<coordinate_type> current_pt = poly[1];
for(std::size_t i = 2; i < poly.size(); ++i) {
point_data<coordinate_type> 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<coordinate_type> 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<point_data<coordinate_type> >& poly,
coordinate_type west_shrinking,
coordinate_type east_shrinking,
coordinate_type south_shrinking,
coordinate_type north_shrinking) {
rectangle_data<coordinate_type> extents_rectangle;
set_points(extents_rectangle, poly[0], poly[0]);
point_data<coordinate_type> first_pt = poly[0];
point_data<coordinate_type> second_pt = poly[1];
point_data<coordinate_type> prev_pt = poly[0];
point_data<coordinate_type> current_pt = poly[1];
encompass(extents_rectangle, current_pt);
for(int i = 2; i < poly.size(); ++i) {
point_data<coordinate_type> 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<coordinate_type> 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<point_data<coordinate_type> >& poly) {
bool found_colinear = true;
while(found_colinear) {
found_colinear = false;
typename std::vector<point_data<coordinate_type> >::iterator itr = poly.begin();
itr += poly.size() - 1; //get last element position
typename std::vector<point_data<coordinate_type> >::iterator itr2 = poly.begin();
typename std::vector<point_data<coordinate_type> >::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<coordinate_type>::unsigned_area_type west_bloating,
typename coordinate_traits<coordinate_type>::unsigned_area_type east_bloating,
typename coordinate_traits<coordinate_type>::unsigned_area_type south_bloating,
typename coordinate_traits<coordinate_type>::unsigned_area_type north_bloating) {
std::list<polygon_45_with_holes_data<coordinate_type> > polys;
get(polys);
clear();
for(typename std::list<polygon_45_with_holes_data<coordinate_type> >::iterator itr = polys.begin();
itr != polys.end(); ++itr) {
//polygon_90_set_data<coordinate_type> psref;
//psref.insert(view_as<polygon_90_concept>((*itr).self_));
//rectangle_data<coordinate_type> prerect;
//psref.extents(prerect);
resize_poly_up((*itr).self_.coords_, west_bloating, east_bloating, south_bloating, north_bloating);
iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > >
begin_input(view_as<polygon_90_concept>((*itr).self_), LOW, orient_, false, true, COUNTERCLOCKWISE),
end_input(view_as<polygon_90_concept>((*itr).self_), HIGH, orient_, false, true, COUNTERCLOCKWISE);
insert(begin_input, end_input, orient_);
//polygon_90_set_data<coordinate_type> pstest;
//pstest.insert(view_as<polygon_90_concept>((*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<polygon_45_data<coordinate_type> >::iterator itrh = (*itr).holes_.begin();
itrh != (*itr).holes_.end(); ++itrh) {
//rectangle_data<coordinate_type> rect;
//psref.extents(rect);
//polygon_90_set_data<coordinate_type> psrefhole;
//psrefhole.insert(prerect);
//psrefhole.insert(view_as<polygon_90_concept>(*itrh), true);
//polygon_45_data<coordinate_type> testpoly(*itrh);
if(resize_poly_down((*itrh).coords_, west_bloating, east_bloating, south_bloating, north_bloating)) {
iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > >
begin_input(view_as<polygon_90_concept>(*itrh), LOW, orient_, true, true),
end_input(view_as<polygon_90_concept>(*itrh), HIGH, orient_, true, true);
insert(begin_input, end_input, orient_);
//polygon_90_set_data<coordinate_type> pstesthole;
//pstesthole.insert(rect);
//iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > >
// begin_input2(view_as<polygon_90_concept>(*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<coordinate_type> c(psrefhole);
// c.clean();
// polygon_90_set_data<coordinate_type> a(pstesthole);
// polygon_90_set_data<coordinate_type> b(pstesthole);
// a.sort();
// b.clean();
// std::cout << "test hole failed\n";
// //std::cout << testpoly << std::endl;
//}
}
}
}
return *this;
}
polygon_90_set_data& polygon_90_set_data&
shrink(typename coordinate_traits<coordinate_type>::unsigned_area_type west_shrinking, shrink(typename coordinate_traits<coordinate_type>::unsigned_area_type west_shrinking,
typename coordinate_traits<coordinate_type>::unsigned_area_type east_shrinking, typename coordinate_traits<coordinate_type>::unsigned_area_type east_shrinking,
typename coordinate_traits<coordinate_type>::unsigned_area_type south_shrinking, typename coordinate_traits<coordinate_type>::unsigned_area_type south_shrinking,
typename coordinate_traits<coordinate_type>::unsigned_area_type north_shrinking) { typename coordinate_traits<coordinate_type>::unsigned_area_type north_shrinking) {
std::list<polygon_45_with_holes_data<coordinate_type> > polys;
get(polys);
clear();
for(typename std::list<polygon_45_with_holes_data<coordinate_type> >::iterator itr = polys.begin();
itr != polys.end(); ++itr) {
//polygon_90_set_data<coordinate_type> psref;
//psref.insert(view_as<polygon_90_concept>((*itr).self_));
//rectangle_data<coordinate_type> prerect;
//psref.extents(prerect);
//polygon_45_data<coordinate_type> testpoly((*itr).self_);
if(resize_poly_down((*itr).self_.coords_, -west_shrinking, -east_shrinking, -south_shrinking, -north_shrinking)) {
iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > >
begin_input(view_as<polygon_90_concept>((*itr).self_), LOW, orient_, false, true, COUNTERCLOCKWISE),
end_input(view_as<polygon_90_concept>((*itr).self_), HIGH, orient_, false, true, COUNTERCLOCKWISE);
insert(begin_input, end_input, orient_);
//iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > >
// begin_input2(view_as<polygon_90_concept>((*itr).self_), LOW, orient_, false, true, COUNTERCLOCKWISE);
//polygon_90_set_data<coordinate_type> 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<polygon_45_data<coordinate_type> >::iterator itrh = (*itr).holes_.begin();
itrh != (*itr).holes_.end(); ++itrh) {
//rectangle_data<coordinate_type> rect;
//psref.extents(rect);
//polygon_90_set_data<coordinate_type> psrefhole;
//psrefhole.insert(prerect);
//psrefhole.insert(view_as<polygon_90_concept>(*itrh), true);
//polygon_45_data<coordinate_type> testpoly(*itrh);
resize_poly_up((*itrh).coords_, -west_shrinking, -east_shrinking, -south_shrinking, -north_shrinking);
iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > >
begin_input(view_as<polygon_90_concept>(*itrh), LOW, orient_, true, true),
end_input(view_as<polygon_90_concept>(*itrh), HIGH, orient_, true, true);
insert(begin_input, end_input, orient_);
//polygon_90_set_data<coordinate_type> pstesthole;
//pstesthole.insert(rect);
//iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > >
// begin_input2(view_as<polygon_90_concept>(*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<coordinate_type> c(psrefhole);
// c.clean();
// polygon_90_set_data<coordinate_type> a(pstesthole);
// polygon_90_set_data<coordinate_type> 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<coordinate_type>::unsigned_area_type west_shrinking,
typename coordinate_traits<coordinate_type>::unsigned_area_type east_shrinking,
typename coordinate_traits<coordinate_type>::unsigned_area_type south_shrinking,
typename coordinate_traits<coordinate_type>::unsigned_area_type north_shrinking) {
rectangle_data<coordinate_type> externalBoundary; rectangle_data<coordinate_type> externalBoundary;
if(!extents(externalBoundary)) return *this; if(!extents(externalBoundary)) return *this;
::boost::polygon::bloat(externalBoundary, 10); //bloat by diferential ammount ::boost::polygon::bloat(externalBoundary, 10); //bloat by diferential ammount
...@@ -352,6 +630,30 @@ namespace boost { namespace polygon{ ...@@ -352,6 +630,30 @@ namespace boost { namespace polygon{
return *this; return *this;
} }
polygon_90_set_data&
shrink(direction_2d dir, typename coordinate_traits<coordinate_type>::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<coordinate_type>::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& polygon_90_set_data&
resize(coordinate_type west, coordinate_type east, coordinate_type south, coordinate_type north); resize(coordinate_type west, coordinate_type east, coordinate_type south, coordinate_type north);
......
...@@ -60,7 +60,7 @@ public: ...@@ -60,7 +60,7 @@ public:
inline std::size_t size() const { return coords_.size(); } inline std::size_t size() const { return coords_.size(); }
private: public:
std::vector<point_data<coordinate_type> > coords_; std::vector<point_data<coordinate_type> > coords_;
}; };
......
...@@ -120,38 +120,7 @@ namespace boost { namespace polygon { ...@@ -120,38 +120,7 @@ namespace boost { namespace polygon {
template <typename polygon_type> template <typename polygon_type>
inline void insert(const polygon_type& polygon_object, bool is_hole, polygon_concept ) { inline void insert(const polygon_type& polygon_object, bool is_hole, polygon_concept ) {
bool first_iteration = true; insert_vertex_sequence(begin_points(polygon_object), end_points(polygon_object), winding(polygon_object), is_hole);
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<polygon_type>::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;
}
} }
inline void insert(const polygon_set_data& ps, bool is_hole = false) { inline void insert(const polygon_set_data& ps, bool is_hole = false) {
...@@ -229,9 +198,37 @@ namespace boost { namespace polygon { ...@@ -229,9 +198,37 @@ namespace boost { namespace polygon {
template <class iT> template <class iT>
inline void insert_vertex_sequence(iT begin_vertex, iT end_vertex, direction_1d winding, bool is_hole) { inline void insert_vertex_sequence(iT begin_vertex, iT end_vertex, direction_1d winding, bool is_hole) {
polygon_data<coordinate_type> poly; bool first_iteration = true;
poly.set(begin_vertex, end_vertex); point_type first_point;
insert(poly, is_hole); 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 <typename output_container> template <typename output_container>
...@@ -363,6 +360,13 @@ namespace boost { namespace polygon { ...@@ -363,6 +360,13 @@ namespace boost { namespace polygon {
inline polygon_set_data& inline polygon_set_data&
resize(coordinate_type resizing, bool corner_fill_arc = false, unsigned int num_circle_segments=0) { 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; if(resizing == 0) return *this;
std::list<polygon_with_holes_data<coordinate_type> > pl; std::list<polygon_with_holes_data<coordinate_type> > pl;
get(pl); get(pl);
...@@ -421,6 +425,139 @@ namespace boost { namespace polygon { ...@@ -421,6 +425,139 @@ namespace boost { namespace polygon {
return *this; return *this;
} }
static inline void compute_offset_edge(point_data<coordinate_type>& pt1, point_data<coordinate_type>& pt2,
const point_data<coordinate_type>& prev_pt,
const point_data<coordinate_type>& 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<coordinate_type>& pt, const point_data<coordinate_type>& prev_pt,
const point_data<coordinate_type>& current_pt, const point_data<coordinate_type>& next_pt,
coordinate_type distance, coordinate_type multiplier) {
std::pair<point_data<coordinate_type>, point_data<coordinate_type> > 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<coordinate_type>::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<point_data<coordinate_type> >& poly, coordinate_type distance, coordinate_type multiplier) {
point_data<coordinate_type> first_pt = poly[0];
point_data<coordinate_type> second_pt = poly[1];
point_data<coordinate_type> prev_pt = poly[0];
point_data<coordinate_type> current_pt = poly[1];
for(std::size_t i = 2; i < poly.size()-1; ++i) {
point_data<coordinate_type> 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<coordinate_type> 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<point_data<coordinate_type> >& poly, coordinate_type distance, coordinate_type multiplier) {
std::vector<point_data<coordinate_type> > orig_poly(poly);
rectangle_data<coordinate_type> extents_rectangle;
set_points(extents_rectangle, poly[0], poly[0]);
point_data<coordinate_type> first_pt = poly[0];
point_data<coordinate_type> second_pt = poly[1];
point_data<coordinate_type> prev_pt = poly[0];
point_data<coordinate_type> current_pt = poly[1];
encompass(extents_rectangle, current_pt);
for(std::size_t i = 2; i < poly.size()-1; ++i) {
point_data<coordinate_type> 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<coordinate_type> 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<coordinate_type>, point_data<coordinate_type> >
he1(poly[i], orig_poly[i]),
he2(poly[i-1], orig_poly[i-1]);
if(!scanline_base<coordinate_type>::intersects(he1, he2)) {
non_inverting_edge = true;
break;
}
}
return non_inverting_edge;
}
polygon_set_data&
bloat(typename coordinate_traits<coordinate_type>::unsigned_area_type distance) {
std::list<polygon_with_holes_data<coordinate_type> > polys;
get(polys);
clear();
for(typename std::list<polygon_with_holes_data<coordinate_type> >::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<polygon_data<coordinate_type> >::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<coordinate_type>::unsigned_area_type distance) {
std::list<polygon_with_holes_data<coordinate_type> > polys;
get(polys);
clear();
for(typename std::list<polygon_with_holes_data<coordinate_type> >::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<polygon_data<coordinate_type> >::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 // TODO:: should be private
template <typename geometry_type> template <typename geometry_type>
inline polygon_set_data& inline polygon_set_data&
...@@ -481,6 +618,7 @@ namespace boost { namespace polygon { ...@@ -481,6 +618,7 @@ namespace boost { namespace polygon {
bool sizing_sign = resizing>0; bool sizing_sign = resizing>0;
bool prev_concave = true; bool prev_concave = true;
point_data<T> prev_point; point_data<T> prev_point;
//int iCtr=0;
//insert minkofski shapes on edges and corners //insert minkofski shapes on edges and corners
...@@ -494,7 +632,9 @@ namespace boost { namespace polygon { ...@@ -494,7 +632,9 @@ namespace boost { namespace polygon {
double direction = normal1.x()*normal2.y()- normal2.x()*normal1.y(); double direction = normal1.x()*normal2.y()- normal2.x()*normal1.y();
bool convex = direction>0; 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<double> v; point_data<double> v;
assign(v, normal1); assign(v, normal1);
double s2 = (v.x()*v.x()+v.y()*v.y()); double s2 = (v.x()*v.x()+v.y()*v.y());
...@@ -533,14 +673,14 @@ namespace boost { namespace polygon { ...@@ -533,14 +673,14 @@ namespace boost { namespace polygon {
, num_circle_segments, corner_fill_arc)) , num_circle_segments, corner_fill_arc))
{ {
if (first_pts.size()) { if (first_pts.size()) {
for (unsigned i=0; i<pts.size(); i++) { for (unsigned int i=0; i<pts.size(); i++) {
sizingSet.insert_vertex_sequence(pts[i].begin(),pts[i].end(),winding,false); sizingSet.insert_vertex_sequence(pts[i].begin(),pts[i].end(),winding,false);
} }
} else { } else {
first_pts = pts[0]; first_pts = pts[0];
first_wdir = resize_wdir; first_wdir = resize_wdir;
for (unsigned i=1; i<pts.size(); i++) { for (unsigned int i=1; i<pts.size(); i++) {
sizingSet.insert_vertex_sequence(pts[i].begin(),pts[i].end(),winding,false); sizingSet.insert_vertex_sequence(pts[i].begin(),pts[i].end(),winding,false);
} }
} }
...@@ -573,7 +713,7 @@ namespace boost { namespace polygon { ...@@ -573,7 +713,7 @@ namespace boost { namespace polygon {
//insert original shape //insert original shape
tmp.insert(poly, false, polygon_concept()); tmp.insert(poly, false, polygon_concept());
if( ((resizing < 0) ^ hole) ) tmp -= sizingSet; if((resizing < 0) ^ hole) tmp -= sizingSet;
else tmp += sizingSet; else tmp += sizingSet;
//tmp.clean(); //tmp.clean();
insert(tmp, hole); insert(tmp, hole);
...@@ -662,13 +802,13 @@ namespace boost { namespace polygon { ...@@ -662,13 +802,13 @@ namespace boost { namespace polygon {
typedef polygon_set_concept type; typedef polygon_set_concept type;
}; };
template <typename T> // template <typename T>
inline double compute_area(point_data<T>& a, point_data<T>& b, point_data<T>& c) { // inline double compute_area(point_data<T>& a, point_data<T>& b, point_data<T>& 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 <typename T> template <typename T>
inline int make_resizing_vertex_list(std::vector<std::vector<point_data< T> > >& return_points, inline int make_resizing_vertex_list(std::vector<std::vector<point_data< T> > >& return_points,
...@@ -709,7 +849,7 @@ namespace boost { namespace polygon { ...@@ -709,7 +849,7 @@ namespace boost { namespace polygon {
std::pair<point_data<double>,point_data<double> > he1(start_offset,mid1_offset); std::pair<point_data<double>,point_data<double> > he1(start_offset,mid1_offset);
std::pair<point_data<double>,point_data<double> > he2(mid2_offset ,end_offset); std::pair<point_data<double>,point_data<double> > he2(mid2_offset ,end_offset);
typedef typename high_precision_type<double>::type high_precision; //typedef typename high_precision_type<double>::type high_precision;
point_data<T> intersect; point_data<T> intersect;
typename scanline_base<T>::compute_intersection_pack pack; typename scanline_base<T>::compute_intersection_pack pack;
...@@ -723,8 +863,8 @@ namespace boost { namespace polygon { ...@@ -723,8 +863,8 @@ namespace boost { namespace polygon {
return_points_back.push_back(start); return_points_back.push_back(start);
return_points_back.push_back(curr_prev); return_points_back.push_back(curr_prev);
/*double d1= */compute_area(intersect,middle,start); //double d1= compute_area(intersect,middle,start);
/*double d2= */compute_area(start,curr_prev,intersect); //double d2= compute_area(start,curr_prev,intersect);
curr_prev = intersect; curr_prev = intersect;
...@@ -754,7 +894,7 @@ namespace boost { namespace polygon { ...@@ -754,7 +894,7 @@ namespace boost { namespace polygon {
ps += 2.0 * our_pi; ps += 2.0 * our_pi;
if (pe <= 0.0) if (pe <= 0.0)
pe += 2.0 * our_pi; pe += 2.0 * our_pi;
if (ps >= 2.0 * M_PI) if (ps >= 2.0 * our_pi)
ps -= 2.0 * our_pi; ps -= 2.0 * our_pi;
while (pe <= ps) while (pe <= ps)
pe += 2.0 * our_pi; pe += 2.0 * our_pi;
...@@ -771,9 +911,9 @@ namespace boost { namespace polygon { ...@@ -771,9 +911,9 @@ namespace boost { namespace polygon {
} }
return_points.push_back(round_down<T>(center)); return_points.push_back(round_down<T>(center));
return_points.push_back(round_down<T>(start)); return_points.push_back(round_down<T>(start));
int i=0; unsigned int i=0;
double curr_angle = ps+delta_angle; 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++; i++;
double x = center.x() + r * cos( curr_angle); double x = center.x() + r * cos( curr_angle);
double y = center.y() + r * sin( curr_angle); double y = center.y() + r * sin( curr_angle);
......
...@@ -121,7 +121,7 @@ namespace boost { namespace polygon{ ...@@ -121,7 +121,7 @@ namespace boost { namespace polygon{
static inline bool clean(const polygon_set_data<T>& polygon_set) { polygon_set.clean(); return true; } static inline bool clean(const polygon_set_data<T>& polygon_set) { polygon_set.clean(); return true; }
static inline bool sorted(const polygon_set_data<T>& polygon_set) { int untested = 0;polygon_set.sort(); return true; } static inline bool sorted(const polygon_set_data<T>& polygon_set) { polygon_set.sort(); return true; }
}; };
} }
......
...@@ -96,7 +96,7 @@ public: ...@@ -96,7 +96,7 @@ public:
return holes_.size(); return holes_.size();
} }
private: public:
polygon_data<coordinate_type> self_; polygon_data<coordinate_type> self_;
std::list<hole_type> holes_; std::list<hole_type> holes_;
}; };
......
...@@ -131,33 +131,10 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) ...@@ -131,33 +131,10 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
* so m_ZoneMinThickness is the min thickness of the filled zones areas * so m_ZoneMinThickness is the min thickness of the filled zones areas
* the main polygon is stored in polyset_zone_solid_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, CopyPolygonsFromFilledPolysListTotKPolygonList( this,
polyset_zone_solid_areas ); polyset_zone_solid_areas );
polyset_zone_solid_areas -= margin; polyset_zone_solid_areas -= margin;
#endif
if( polyset_zone_solid_areas.size() == 0 ) if( polyset_zone_solid_areas.size() == 0 )
return; return;
...@@ -523,82 +500,6 @@ void AddUnconnectedThermalStubsToKPolygonList( std::vector<CPolyPt>& aCornerBuff ...@@ -523,82 +500,6 @@ void AddUnconnectedThermalStubsToKPolygonList( std::vector<CPolyPt>& 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 <CPolyPt>& void AddPolygonCornersToKPolygonList( std::vector <CPolyPt>&
aCornersBuffer, aCornersBuffer,
KPolygonSet& aKPolyList ) KPolygonSet& aKPolyList )
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment