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
...@@ -19,10 +19,10 @@ option(KICAD_MINIZIP "enable/disable building minizip (default ON)" ON) ...@@ -19,10 +19,10 @@ option(KICAD_MINIZIP "enable/disable building minizip (default ON)" ON)
option(wxUSE_UNICODE "enable/disable building unicode (default OFF)") option(wxUSE_UNICODE "enable/disable building unicode (default OFF)")
option(KICAD_GOST "enable/disable building using GOST notation for multiple gates per package (default OFF)") option(KICAD_GOST "enable/disable building using GOST notation for multiple gates per package (default OFF)")
option(USE_WX_ZOOM "Use wxDC to perform zooming (default OFF). Warning, this is experimental" ) option(USE_WX_ZOOM "Use wxDC to perform zooming (default OFF). Warning, this is experimental" )
option(USE_WX_GRAPHICS_CONTEXT option(USE_WX_GRAPHICS_CONTEXT
"Use wxGraphicsContext for rendering (default OFF). Warning, this is experimental") "Use wxGraphicsContext for rendering (default OFF). Warning, this is experimental")
option(USE_BOOST_POLYGON_LIBRARY option(USE_BOOST_POLYGON_LIBRARY
"Use boost polygon library instead of Kbool to calculate filled areas in zones (default OFF). Warning, this is experimental") "Use boost polygon library instead of Kbool to calculate filled areas in zones (default OFF). Warning, this is experimental")
......
...@@ -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 // //erase the intersection points from the queue
intersection_queue_.erase(intersection_queue_.begin(), iter); // intersection_queue_.erase(intersection_queue_.begin(), iter);
std::vector<scanline_element> insertion_edges; // std::vector<scanline_element> insertion_edges;
insertion_edges.reserve(intersecting_elements.size()); // insertion_edges.reserve(intersecting_elements.size());
std::vector<std::pair<Unit, iterator> > sloping_ends; // std::vector<std::pair<Unit, iterator> > sloping_ends;
//do all the work of updating the output of all intersecting // //do all the work of updating the output of all intersecting
for(typename std::set<iterator>::iterator inter_iter = intersecting_elements.begin(); // for(typename std::set<iterator>::iterator inter_iter = intersecting_elements.begin();
inter_iter != intersecting_elements.end(); ++inter_iter) { // inter_iter != intersecting_elements.end(); ++inter_iter) {
//if it is horizontal update it now and continue // //if it is horizontal update it now and continue
if(is_horizontal((*inter_iter).first)) { // if(is_horizontal((*inter_iter).first)) {
update_segments(intersection_points, (*inter_iter).second, Point(x_, (*inter_iter).first.get(VERTICAL))); // update_segments(intersection_points, (*inter_iter).second, Point(x_, (*inter_iter).first.get(VERTICAL)));
} else { // } else {
//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)()) {
//insert its end points into the vector of sloping ends // //insert its end points into the vector of sloping ends
const half_edge& he = (*inter_iter).first; // const half_edge& he = (*inter_iter).first;
Unit y = evalAtXforY(x_, he.first, he.second); // Unit y = evalAtXforY(x_, he.first, he.second);
Unit y2 = evalAtXforY(x_+1, 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 // 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 // else y += 1; //downward sloping round up
sloping_ends.push_back(std::make_pair(y, inter_iter)); // sloping_ends.push_back(std::make_pair(y, inter_iter));
sloping_ends.push_back(std::make_pair(y2, inter_iter)); // sloping_ends.push_back(std::make_pair(y2, inter_iter));
} // }
} // }
} // }
//merge sloping element data // //merge sloping element data
std::sort(sloping_ends.begin(), sloping_ends.end()); // std::sort(sloping_ends.begin(), sloping_ends.end());
std::map<Unit, std::set<iterator> > sloping_elements; // std::map<Unit, std::set<iterator> > sloping_elements;
std::set<iterator> merge_elements; // std::set<iterator> merge_elements;
for(typename std::vector<std::pair<Unit, iterator> >::iterator slop_iter = sloping_ends.begin(); // for(typename std::vector<std::pair<Unit, iterator> >::iterator slop_iter = sloping_ends.begin();
slop_iter = sloping_ends.end(); ++slop_iter) { // slop_iter == sloping_ends.end(); ++slop_iter) {
//merge into sloping elements // //merge into sloping elements
typename std::set<iterator>::iterator merge_iterator = merge_elements.find((*slop_iter).second); // typename std::set<iterator>::iterator merge_iterator = merge_elements.find((*slop_iter).second);
if(merge_iterator = merge_elements.end()) { // if(merge_iterator == merge_elements.end()) {
merge_elements.insert((*slop_iter).second); // merge_elements.insert((*slop_iter).second);
} else { // } else {
merge_elements.erase(merge_iterator); // merge_elements.erase(merge_iterator);
} // }
sloping_elements[(*slop_iter).first] = merge_elements; // 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();
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);
}
}
}
}
}
}
//erase and reinsert edges into scanline with check for future intersection
}
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,8 +1704,8 @@ namespace boost { namespace polygon{ ...@@ -1704,8 +1704,8 @@ namespace boost { namespace polygon{
//if half edge 1 is not vertical its slope is less than that of half edge 2 //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