Commit 75b5c247 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.
parent 8d777fc6
......@@ -19,10 +19,10 @@ option(KICAD_MINIZIP "enable/disable building minizip (default ON)" ON)
option(wxUSE_UNICODE "enable/disable building unicode (default OFF)")
option(KICAD_GOST "enable/disable building using GOST notation for multiple gates per package (default OFF)")
option(USE_WX_ZOOM "Use wxDC to perform zooming (default OFF). Warning, this is experimental" )
option(USE_WX_ZOOM "Use wxDC to perform zooming (default OFF). Warning, this is experimental" )
option(USE_WX_GRAPHICS_CONTEXT
"Use wxGraphicsContext for rendering (default OFF). Warning, this is experimental")
"Use wxGraphicsContext for rendering (default OFF). Warning, this is experimental")
option(USE_BOOST_POLYGON_LIBRARY
"Use boost polygon library instead of Kbool to calculate filled areas in zones (default OFF). Warning, this is experimental")
......
......@@ -29,7 +29,7 @@ private:
public:
iterator_geometry_to_set() : rectangle_(), vertex_(), corner_(4), orient_(), is_hole_() {}
iterator_geometry_to_set(const rectangle_type& rectangle, direction_1d dir,
orientation_2d orient = HORIZONTAL, bool is_hole = false) :
orientation_2d orient = HORIZONTAL, bool is_hole = false, bool = false, direction_1d = CLOCKWISE) :
rectangle_(), vertex_(), corner_(0), orient_(orient), is_hole_(is_hole) {
assign(rectangle_, rectangle);
if(dir == HIGH) corner_ = 4;
......@@ -93,7 +93,7 @@ private:
int polygon_index;
public:
iterator_geometry_to_set() : vertex_(), itrb(), itre(), last_vertex_(), is_hole_(), multiplier_(), first_pt(), second_pt(), pts(), use_wrap(), orient_(), polygon_index(-1) {}
iterator_geometry_to_set(const polygon_type& polygon, direction_1d dir, orientation_2d orient = HORIZONTAL, bool is_hole = false) :
iterator_geometry_to_set(const polygon_type& polygon, direction_1d dir, orientation_2d orient = HORIZONTAL, bool is_hole = false, bool winding_override = false, direction_1d w = CLOCKWISE) :
vertex_(), itrb(), itre(), last_vertex_(),
is_hole_(is_hole), multiplier_(), first_pt(), second_pt(), pts(), use_wrap(),
orient_(orient), polygon_index(0) {
......@@ -103,7 +103,9 @@ public:
if(itrb == itre || dir == HIGH || size(polygon) < 4) {
polygon_index = -1;
} else {
direction_1d wdir = winding(polygon);
direction_1d wdir = w;
if(!winding_override)
wdir = winding(polygon);
multiplier_ = wdir == LOW ? -1 : 1;
if(is_hole_) multiplier_ *= -1;
first_pt = pts[0] = *itrb;
......@@ -182,9 +184,7 @@ public:
vertex_.second.first =pts[1].get(orient_);
if(pts[1] == pts[2]) {
vertex_.second.second = 0;
return;
}
if(pts[0].get(HORIZONTAL) != pts[1].get(HORIZONTAL)) {
} else if(pts[0].get(HORIZONTAL) != pts[1].get(HORIZONTAL)) {
vertex_.second.second = -1;
} else if(pts[0].get(VERTICAL) != pts[1].get(VERTICAL)) {
vertex_.second.second = 1;
......@@ -214,7 +214,7 @@ private:
public:
iterator_geometry_to_set() : itrb(), itre(), itrhib(), itrhie(), itrhb(), itrhe(), orient_(), is_hole_(), started_holes() {}
iterator_geometry_to_set(const polygon_with_holes_type& polygon, direction_1d dir,
orientation_2d orient = HORIZONTAL, bool is_hole = false) :
orientation_2d orient = HORIZONTAL, bool is_hole = false, bool = false, direction_1d = CLOCKWISE) :
itrb(), itre(), itrhib(), itrhie(), itrhb(), itrhe(), orient_(orient), is_hole_(is_hole), started_holes() {
itre = iterator_geometry_to_set<polygon_90_concept, polygon_with_holes_type>(polygon, HIGH, orient, is_hole_);
itrhe = end_holes(polygon);
......
......@@ -251,12 +251,14 @@ namespace boost { namespace polygon{
return;
}
Unit firstY = (*iter).y();
Unit firstX = (*iter).x();
++iter;
if(iter == tailp_->points.end()) {
tailp_->points.push_front(point);
return;
}
if(iter->y() == point.y() && firstY == point.y()) {
if((iter->y() == point.y() && firstY == point.y()) ||
(iter->x() == point.x() && firstX == point.x())){
--iter;
*iter = point;
} else {
......@@ -274,12 +276,14 @@ namespace boost { namespace polygon{
return;
}
Unit firstY = (*iter).y();
Unit firstX = (*iter).x();
++iter;
if(iter == tailp_->points.rend()) {
tailp_->points.push_back(point);
return;
}
if(iter->y() == point.y() && firstY == point.y()) {
if((iter->y() == point.y() && firstY == point.y()) ||
(iter->x() == point.x() && firstX == point.x())){
--iter;
*iter = point;
} else {
......@@ -474,7 +478,7 @@ namespace boost { namespace polygon{
ct counts[4];
};
typedef Vertex45CountT<int> Vertex45Count;
typedef Vertex45CountT<signed char> Vertex45Count;
// inline std::ostream& operator<< (std::ostream& o, const Vertex45Count& c) {
// o << c[0] << ", " << c[1] << ", ";
......@@ -492,7 +496,8 @@ namespace boost { namespace polygon{
inline Vertex45CompactT(const Point& point, int riseIn, int countIn) : pt(point), count() {
count[riseIn+1] = countIn;
}
inline Vertex45CompactT(const Vertex45T& vertex) : pt(vertex.pt), count() {
template <typename ct2>
inline Vertex45CompactT(const typename boolean_op_45<Unit>::template Vertex45T<ct2>& vertex) : pt(vertex.pt), count() {
count[vertex.rise+1] = vertex.count;
}
inline Vertex45CompactT(const Vertex45CompactT& vertex) : pt(vertex.pt), count(vertex.count) {}
......@@ -2244,6 +2249,7 @@ namespace boost { namespace polygon{
struct geometry_concept<PolyLine45PolygonData<T> > { typedef polygon_45_with_holes_concept type; };
template <typename T>
struct geometry_concept<PolyLine45HoleData<T> > { typedef polygon_45_concept type; };
}
}
#endif
......@@ -124,13 +124,13 @@ namespace boost { namespace polygon{
};
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> >::
begin(const polygon_45_set_view<ltype, rtype, op_type>& polygon_45_set) {
return polygon_45_set.begin();
}
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> >::
end(const polygon_45_set_view<ltype, rtype, op_type>& polygon_45_set) {
return polygon_45_set.end();
......
......@@ -140,13 +140,13 @@ namespace boost { namespace polygon{
};
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> >::
begin(const polygon_90_set_view<ltype, rtype, op_type>& polygon_set) {
return polygon_set.begin();
}
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> >::
end(const polygon_90_set_view<ltype, rtype, op_type>& polygon_set) {
return polygon_set.end();
......
......@@ -42,7 +42,7 @@ namespace boost { namespace polygon{
ivlIds_.second = that.ivlIds_.second;
incremented_ = that.incremented_;
return *this;
};
}
inline bool operator==(const iterator& that) { return itr_ == that.itr_; }
inline bool operator!=(const iterator& that) { return itr_ != that.itr_; }
inline iterator& operator++() {
......
......@@ -388,7 +388,8 @@ namespace boost { namespace polygon{
struct compute_intersection_pack {
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;
static inline bool compute_lazy_intersection(Point& intersection, const half_edge& he1, const half_edge& he2, bool projected = false) {
static inline bool compute_lazy_intersection(Point& intersection, const half_edge& he1, const half_edge& he2,
bool projected = false, bool round_closest = false) {
long double y_high, dx1, dy1, dx2, dy2, x11, x21, y11, y21, x_num, y_num, x_den, y_den, x, y;
typedef rectangle_data<Unit> Rectangle;
Rectangle rect1, rect2;
......@@ -445,6 +446,10 @@ namespace boost { namespace polygon{
//std::cout << "cross2 " << dy2 << " " << dx1 << " " << dy2 * dx1 << std::endl;
//Unit exp_x = compute_x_intercept<at>(x11, x21, y11, y21, dy1, dy2, dx1, dx2);
//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 y_unit = (Unit)(y);
//truncate downward if it went up due to negative number
......@@ -463,12 +468,17 @@ namespace boost { namespace polygon{
(long double) (std::numeric_limits<Unit>::min)(),
(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;
return true;
}
inline bool compute_intersection(Point& intersection, const half_edge& he1, const half_edge& he2, bool projected = false) {
inline bool compute_intersection(Point& intersection, const half_edge& he1, const half_edge& he2,
bool projected = false, bool round_closest = false) {
if(!projected && !intersects(he1, he2))
return false;
bool lazy_success = compute_lazy_intersection(intersection, he1, he2, projected);
......@@ -536,6 +546,10 @@ namespace boost { namespace polygon{
//std::cout << "cross2 " << dy2 << " " << dx1 << " " << dy2 * dx1 << std::endl;
//Unit exp_x = compute_x_intercept<at>(x11, x21, y11, y21, dy1, dy2, dx1, dx2);
//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 y_unit = convert_high_precision_type<Unit>(y);
//truncate downward if it went up due to negative number
......@@ -549,6 +563,17 @@ namespace boost { namespace polygon{
Point result(x_unit, y_unit);
if(!contains(rect1, result, true)) return false;
if(!contains(rect2, result, true)) return false;
if(projected) {
rectangle_data<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;
return true;
}
......@@ -872,7 +897,7 @@ namespace boost { namespace polygon{
inline active_tail_arbitrary(const vertex_half_edge& vertex, active_tail_arbitrary* otherTailp = 0) : tailp_(), otherTailp_(), holesList_(), head_() {
tailp_ = new poly_line_arbitrary;
tailp_->points.push_back(vertex.pt);
bool headArray[4] = {false, true, true, true};
//bool headArray[4] = {false, true, true, true};
bool inverted = vertex.count == -1;
head_ = (!vertex.is_vertical) ^ inverted;
otherTailp_ = otherTailp;
......@@ -1172,7 +1197,7 @@ namespace boost { namespace polygon{
inline less_half_edge_count() : pt_() {}
inline less_half_edge_count(Point point) : pt_(point) {}
inline bool operator () (const std::pair<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{
Unit dx2 = elm2.first.first.first.get(HORIZONTAL) - elm2.first.first.second.get(HORIZONTAL);
Unit dy1 = elm1.first.first.first.get(VERTICAL) - elm1.first.first.second.get(VERTICAL);
Unit dy2 = elm2.first.first.first.get(VERTICAL) - elm2.first.first.second.get(VERTICAL);
return less_slope(dx1, dy1, dx2, dy2);
return scanline_base<Unit>::less_slope(dx1, dy1, dx2, dy2);
}
};
......@@ -1356,7 +1381,7 @@ namespace boost { namespace polygon{
bool have_vertical_tail_from_below = false;
if(c_size &&
is_vertical(counts_from_scanline.back().first.first)) {
scanline_base<Unit>::is_vertical(counts_from_scanline.back().first.first)) {
have_vertical_tail_from_below = true;
}
//assert size = size_less_1 + 1
......@@ -1704,7 +1729,7 @@ namespace boost { namespace polygon{
//std::cout << "checking whether ot handle hole\n";
if(currentIter == inputEnd ||
currentIter->pt.get(HORIZONTAL) != x_ ||
on_above_or_below(currentIter->pt, half_edge(iter->first.pt, iter->first.other_pt)) != -1) {
scanline_base<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_)) {
//std::cout << "handle hole here\n";
......@@ -2041,26 +2066,26 @@ namespace boost { namespace polygon{
he2.first = Point(0, 0);
he2.second = Point(10, 20);
Point result;
bool b = compute_intersection(result, he1, he2);
bool b = scanline_base<Unit>::compute_intersection(result, he1, he2);
if(!b || result != Point(0, 0)) return false;
he1.first = Point(0, 10);
b = compute_intersection(result, he1, he2);
b = scanline_base<Unit>::compute_intersection(result, he1, he2);
if(!b || result != Point(5, 10)) return false;
he1.first = Point(0, 11);
b = compute_intersection(result, he1, he2);
b = scanline_base<Unit>::compute_intersection(result, he1, he2);
if(!b || result != Point(5, 10)) return false;
he1.first = Point(0, 0);
he1.second = Point(1, 9);
he2.first = Point(0, 9);
he2.second = Point(1, 0);
b = compute_intersection(result, he1, he2);
b = scanline_base<Unit>::compute_intersection(result, he1, he2);
if(!b || result != Point(0, 4)) return false;
he1.first = Point(0, -10);
he1.second = Point(1, -1);
he2.first = Point(0, -1);
he2.second = Point(1, -10);
b = compute_intersection(result, he1, he2);
b = scanline_base<Unit>::compute_intersection(result, he1, he2);
if(!b || result != Point(0, -5)) return false;
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)());
......@@ -2068,13 +2093,13 @@ namespace boost { namespace polygon{
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)(), 0);
b = compute_intersection(result, he1, he2);
b = scanline_base<Unit>::compute_intersection(result, he1, he2);
//b is false because of overflow error
he1.first = Point(1000, 2000);
he1.second = Point(1010, 2010);
he2.first = Point(1000, 2000);
he2.second = Point(1010, 2020);
b = compute_intersection(result, he1, he2);
b = scanline_base<Unit>::compute_intersection(result, he1, he2);
if(!b || result != Point(1000, 2000)) return false;
return b;
......@@ -2301,7 +2326,7 @@ namespace boost { namespace polygon{
bool have_vertical_tail_from_below = false;
if(c_size &&
is_vertical(counts_from_scanline.back().first.first)) {
scanline_base<Unit>::is_vertical(counts_from_scanline.back().first.first)) {
have_vertical_tail_from_below = true;
}
//assert size = size_less_1 + 1
......@@ -2607,7 +2632,7 @@ namespace boost { namespace polygon{
//std::cout << "current Y " << currentY << std::endl;
//std::cout << "scanline size " << scanData_.size() << std::endl;
//print(scanData_);
iterator iter = lookUp_(currentY);
iterator iter = this->lookUp_(currentY);
//std::cout << "found element in scanline " << (iter != scanData_.end()) << std::endl;
//int counts[4] = {0, 0, 0, 0};
incoming_count counts_from_scanline;
......@@ -2634,7 +2659,7 @@ namespace boost { namespace polygon{
}
Point currentPoint(polygon_arbitrary_formation<Unit>::x_, currentY);
//std::cout << "counts_from_scanline size " << counts_from_scanline.size() << std::endl;
sort_incoming_count(counts_from_scanline, currentPoint);
this->sort_incoming_count(counts_from_scanline, currentPoint);
vertex_arbitrary_count incoming;
//std::cout << "aggregating\n";
......@@ -2646,7 +2671,7 @@ namespace boost { namespace polygon{
} while(currentIter != inputEnd && currentIter->pt.get(VERTICAL) == currentY &&
currentIter->pt.get(HORIZONTAL) == polygon_arbitrary_formation<Unit>::x_);
//print(incoming);
sort_vertex_arbitrary_count(incoming, currentPoint);
this->sort_vertex_arbitrary_count(incoming, currentPoint);
//std::cout << currentPoint.get(HORIZONTAL) << "," << currentPoint.get(VERTICAL) << std::endl;
//print(incoming);
//std::cout << "incoming counts from input size " << incoming.size() << std::endl;
......
......@@ -1721,7 +1721,7 @@ namespace polygon_formation {
unsigned int get_polygons(output_container& container, iterator_type begin, iterator_type end,
orientation_2d orient, bool fracture_holes, concept_type ) {
typedef typename output_container::value_type polygon_type;
typedef typename iterator_type::value_type::first_type coordinate_type;
typedef typename std::iterator_traits<iterator_type>::value_type::first_type coordinate_type;
polygon_type poly;
unsigned int countPolygons = 0;
typedef typename geometry_concept<polygon_type>::type polygon_concept_type;
......
......@@ -153,13 +153,13 @@ namespace boost { namespace polygon{
};
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> >::
begin(const polygon_set_view<ltype, rtype, op_type>& polygon_set) {
return polygon_set.begin();
}
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> >::
end(const polygon_set_view<ltype, rtype, op_type>& polygon_set) {
return polygon_set.end();
......
......@@ -33,38 +33,38 @@ namespace boost { namespace polygon{
typedef std::map<half_edge, std::set<segment_id>, less_half_edge> edge_scanline;
typedef typename edge_scanline::iterator iterator;
std::map<Unit, std::set<segment_id> > vertical_data_;
edge_scanline edge_scanline_;
Unit x_;
int just_before_;
segment_id segment_id_;
std::vector<std::pair<half_edge, int> > event_edges_;
std::set<Point> intersection_queue_;
// std::map<Unit, std::set<segment_id> > vertical_data_;
// edge_scanline edge_scanline_;
// Unit x_;
// int just_before_;
// segment_id segment_id_;
// std::vector<std::pair<half_edge, int> > event_edges_;
// std::set<Point> intersection_queue_;
public:
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_);
edge_scanline_ = edge_scanline(lessElm);
}
inline line_intersection(const line_intersection& that) : vertical_data_(), edge_scanline_(), x_(), just_before_(), segment_id_(), event_edges_(), intersection_queue_() { (*this) = that; }
inline line_intersection& operator=(const line_intersection& that) {
x_ = that.x_;
just_before_ = that.just_before_;
segment_id_ = that.segment_id_;
// inline line_intersection() : vertical_data_(), edge_scanline_(), x_((std::numeric_limits<Unit>::max)()), just_before_(0), segment_id_(0), event_edges_(), intersection_queue_() {
// less_half_edge lessElm(&x_, &just_before_);
// edge_scanline_ = edge_scanline(lessElm);
// }
// inline line_intersection(const line_intersection& that) : vertical_data_(), edge_scanline_(), x_(), just_before_(), segment_id_(), event_edges_(), intersection_queue_() { (*this) = that; }
// inline line_intersection& operator=(const line_intersection& that) {
// x_ = that.x_;
// just_before_ = that.just_before_;
// segment_id_ = that.segment_id_;
//I cannot simply copy that.edge_scanline_ to this edge_scanline_ becuase the functor store pointers to other members!
less_half_edge lessElm(&x_, &just_before_);
edge_scanline_ = edge_scanline(lessElm);
// //I cannot simply copy that.edge_scanline_ to this edge_scanline_ becuase the functor store pointers to other members!
// less_half_edge lessElm(&x_, &just_before_);
// edge_scanline_ = edge_scanline(lessElm);
edge_scanline_.insert(that.edge_scanline_.begin(), that.edge_scanline_.end());
return *this;
}
// edge_scanline_.insert(that.edge_scanline_.begin(), that.edge_scanline_.end());
// return *this;
// }
static inline void between(Point pt, Point pt1, Point pt2) {
less_point lp;
if(lp(pt1, pt2))
return lp(pt, pt2) && lp(pt1, pt);
return lp(pt, pt1) && lp(pt2, pt);
}
// static inline void between(Point pt, Point pt1, Point pt2) {
// less_point lp;
// if(lp(pt1, pt2))
// return lp(pt, pt2) && lp(pt1, pt);
// return lp(pt, pt1) && lp(pt2, pt);
// }
template <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) {
......@@ -216,7 +216,7 @@ namespace boost { namespace polygon{
//itr2 = pts.end();
while(lfinger != newend && (*lfinger).x() < startpt.x()) ++lfinger;
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);
}
}
......@@ -243,8 +243,8 @@ namespace boost { namespace polygon{
//edge changed orientation, invert count on edge
output_segments.back().second.second *= -1;
}
if(!is_vertical(input_segments[intermediate_segments[i].second].first) &&
is_vertical(output_segments.back().first)) {
if(!scanline_base<Unit>::is_vertical(input_segments[intermediate_segments[i].second].first) &&
scanline_base<Unit>::is_vertical(output_segments.back().first)) {
output_segments.back().second.second *= -1;
}
if(lp(output_segments.back().first.second, output_segments.back().first.first)) {
......@@ -349,7 +349,7 @@ namespace boost { namespace polygon{
segment_id id = (*iter).second;
const std::set<Point>& pts = intersection_points[id];
Point hpt(he.first.get(HORIZONTAL)+1, he.first.get(VERTICAL));
if(!is_vertical(he) && less_slope(he.first.get(HORIZONTAL), he.first.get(VERTICAL),
if(!scanline_base<Unit>::is_vertical(he) && scanline_base<Unit>::less_slope(he.first.get(HORIZONTAL), he.first.get(VERTICAL),
he.second, hpt)) {
//slope is below horizontal
std::vector<Point> tmpPts;
......@@ -365,263 +365,263 @@ namespace boost { namespace polygon{
}
}
//iT iterator over unsorted pair<Point> representing line segments of input
//output_segments is populated with fully intersected output line segment half
//edges and the index of the input segment that they are assoicated with
//duplicate output half edges with different ids will be generated in the case
//that parallel input segments intersection
//outputs are in sorted order and include both begin and end events for
//each segment
template <typename iT>
inline void scan(std::vector<std::pair<half_edge, int> >& output_segments,
iT begin, iT end) {
std::map<segment_id, std::set<Point> > intersection_points;
scan(intersection_points, begin, end);
segment_intersections(output_segments, intersection_points, begin, end);
}
//iT iterator over sorted sequence of half edge, segment id pairs representing segment begin and end points
//intersection points provides a mapping from input segment id (vector index) to the set
//of intersection points assocated with that input segment
template <typename iT>
inline void scan(std::map<segment_id, std::set<Point> >& intersection_points,
iT begin, iT end) {
for(iT iter = begin; iter != end; ++iter) {
const std::pair<half_edge, int>& elem = *iter;
const half_edge& he = elem.first;
Unit current_x = he.first.get(HORIZONTAL);
if(current_x != x_) {
process_scan_event(intersection_points);
while(!intersection_queue_.empty() &&
(*(intersection_queue_.begin()).get(HORIZONTAL) < current_x)) {
x_ = *(intersection_queue_.begin()).get(HORIZONTAL);
process_intersections_at_scan_event(intersection_points);
}
x_ = current_x;
}
event_edges_.push_back(elem);
}
process_scan_event(intersection_points);
}
inline iterator lookup(const half_edge& he) {
return edge_scanline_.find(he);
}
inline void insert_into_scanline(const half_edge& he, int id) {
edge_scanline_[he].insert(id);
}
inline void lookup_and_remove(const half_edge& he, int id) {
iterator remove_iter = lookup(he);
if(remove_iter == edge_scanline_.end()) {
//std::cout << "failed to find removal segment in scanline\n";
return;
}
std::set<segment_id>& ids = (*remove_iter).second;
std::set<segment_id>::iterator id_iter = ids.find(id);
if(id_iter == ids.end()) {
//std::cout << "failed to find removal segment id in scanline set\n";
return;
}
ids.erase(id_iter);
if(ids.empty())
edge_scanline_.erase(remove_iter);
}
static inline void update_segments(std::map<segment_id, std::set<Point> >& intersection_points,
const std::set<segment_id>& segments, Point pt) {
for(std::set<segment_id>::const_iterator itr = segments.begin(); itr != segments.end(); ++itr) {
intersection_points[*itr].insert(pt);
}
}
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
//found yet if vertical or near vertical line segments intersect more than
//once before the next x location
just_before_ = true;
std::set<iterator> intersecting_elements;
std::set<Unit> intersection_locations;
typedef typename std::set<Point>::iterator intersection_iterator;
intersection_iterator iter;
//first find all secondary intersection locations and all scanline iterators
//that are intersecting
for(iter = intersection_queue_.begin();
iter != intersection_queue_.end() && (*iter).get(HORIZONTAL) == x_; ++iter) {
Point pt = *iter;
Unit y = pt.get(VERTICAL);
intersection_locations.insert(y);
//if x_ is max there can be only end events and no sloping edges
if(x_ != (std::numeric_limits<Unit>::max)()) {
//deal with edges that project to the right of scanline
//first find the edges in the scanline adjacent to primary intersectin points
//lookup segment in scanline at pt
iterator itr = edge_scanline_.lower_bound(half_edge(pt, Point(x_+1, y)));
//look above pt in scanline until reaching end or segment that doesn't intersect
//1x1 grid upper right of pt
//look below pt in scanline until reaching begin or segment that doesn't interset
//1x1 grid upper right of pt
//second find edges in scanline on the y interval of each edge found in the previous
//step for x_ to x_ + 1
//third find overlaps in the y intervals of all found edges to find all
//secondary intersection points
}
}
//erase the intersection points from the queue
intersection_queue_.erase(intersection_queue_.begin(), iter);
std::vector<scanline_element> insertion_edges;
insertion_edges.reserve(intersecting_elements.size());
std::vector<std::pair<Unit, iterator> > sloping_ends;
//do all the work of updating the output of all intersecting
for(typename std::set<iterator>::iterator inter_iter = intersecting_elements.begin();
inter_iter != intersecting_elements.end(); ++inter_iter) {
//if it is horizontal update it now and continue
if(is_horizontal((*inter_iter).first)) {
update_segments(intersection_points, (*inter_iter).second, Point(x_, (*inter_iter).first.get(VERTICAL)));
} else {
//if x_ is max there can be only end events and no sloping edges
if(x_ != (std::numeric_limits<Unit>::max)()) {
//insert its end points into the vector of sloping ends
const half_edge& he = (*inter_iter).first;
Unit y = evalAtXforY(x_, he.first, he.second);
Unit y2 = evalAtXforY(x_+1, he.first, he.second);
if(y2 >= y) y2 +=1; //we round up, in exact case we don't worry about overbite of one
else y += 1; //downward sloping round up
sloping_ends.push_back(std::make_pair(y, inter_iter));
sloping_ends.push_back(std::make_pair(y2, inter_iter));
}
}
}
// //iT iterator over unsorted pair<Point> representing line segments of input
// //output_segments is populated with fully intersected output line segment half
// //edges and the index of the input segment that they are assoicated with
// //duplicate output half edges with different ids will be generated in the case
// //that parallel input segments intersection
// //outputs are in sorted order and include both begin and end events for
// //each segment
// template <typename iT>
// inline void scan(std::vector<std::pair<half_edge, int> >& output_segments,
// iT begin, iT end) {
// std::map<segment_id, std::set<Point> > intersection_points;
// scan(intersection_points, begin, end);
// segment_intersections(output_segments, intersection_points, begin, end);
// }
// //iT iterator over sorted sequence of half edge, segment id pairs representing segment begin and end points
// //intersection points provides a mapping from input segment id (vector index) to the set
// //of intersection points assocated with that input segment
// template <typename iT>
// inline void scan(std::map<segment_id, std::set<Point> >& intersection_points,
// iT begin, iT end) {
// for(iT iter = begin; iter != end; ++iter) {
// const std::pair<half_edge, int>& elem = *iter;
// const half_edge& he = elem.first;
// Unit current_x = he.first.get(HORIZONTAL);
// if(current_x != x_) {
// process_scan_event(intersection_points);
// while(!intersection_queue_.empty() &&
// (*(intersection_queue_.begin()).get(HORIZONTAL) < current_x)) {
// x_ = *(intersection_queue_.begin()).get(HORIZONTAL);
// process_intersections_at_scan_event(intersection_points);
// }
// x_ = current_x;
// }
// event_edges_.push_back(elem);
// }
// process_scan_event(intersection_points);
// }
// inline iterator lookup(const half_edge& he) {
// return edge_scanline_.find(he);
// }
// inline void insert_into_scanline(const half_edge& he, int id) {
// edge_scanline_[he].insert(id);
// }
// inline void lookup_and_remove(const half_edge& he, int id) {
// iterator remove_iter = lookup(he);
// if(remove_iter == edge_scanline_.end()) {
// //std::cout << "failed to find removal segment in scanline\n";
// return;
// }
// std::set<segment_id>& ids = (*remove_iter).second;
// std::set<segment_id>::iterator id_iter = ids.find(id);
// if(id_iter == ids.end()) {
// //std::cout << "failed to find removal segment id in scanline set\n";
// return;
// }
// ids.erase(id_iter);
// if(ids.empty())
// edge_scanline_.erase(remove_iter);
// }
// static inline void update_segments(std::map<segment_id, std::set<Point> >& intersection_points,
// const std::set<segment_id>& segments, Point pt) {
// for(std::set<segment_id>::const_iterator itr = segments.begin(); itr != segments.end(); ++itr) {
// intersection_points[*itr].insert(pt);
// }
// }
// 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
// //found yet if vertical or near vertical line segments intersect more than
// //once before the next x location
// just_before_ = true;
// std::set<iterator> intersecting_elements;
// std::set<Unit> intersection_locations;
// typedef typename std::set<Point>::iterator intersection_iterator;
// intersection_iterator iter;
// //first find all secondary intersection locations and all scanline iterators
// //that are intersecting
// for(iter = intersection_queue_.begin();
// iter != intersection_queue_.end() && (*iter).get(HORIZONTAL) == x_; ++iter) {
// Point pt = *iter;
// Unit y = pt.get(VERTICAL);
// intersection_locations.insert(y);
// //if x_ is max there can be only end events and no sloping edges
// if(x_ != (std::numeric_limits<Unit>::max)()) {
// //deal with edges that project to the right of scanline
// //first find the edges in the scanline adjacent to primary intersectin points
// //lookup segment in scanline at pt
// iterator itr = edge_scanline_.lower_bound(half_edge(pt, Point(x_+1, y)));
// //look above pt in scanline until reaching end or segment that doesn't intersect
// //1x1 grid upper right of pt
// //look below pt in scanline until reaching begin or segment that doesn't interset
// //1x1 grid upper right of pt
// //second find edges in scanline on the y interval of each edge found in the previous
// //step for x_ to x_ + 1
// //third find overlaps in the y intervals of all found edges to find all
// //secondary intersection points
// }
// }
// //erase the intersection points from the queue
// intersection_queue_.erase(intersection_queue_.begin(), iter);
// std::vector<scanline_element> insertion_edges;
// insertion_edges.reserve(intersecting_elements.size());
// std::vector<std::pair<Unit, iterator> > sloping_ends;
// //do all the work of updating the output of all intersecting
// for(typename std::set<iterator>::iterator inter_iter = intersecting_elements.begin();
// inter_iter != intersecting_elements.end(); ++inter_iter) {
// //if it is horizontal update it now and continue
// if(is_horizontal((*inter_iter).first)) {
// update_segments(intersection_points, (*inter_iter).second, Point(x_, (*inter_iter).first.get(VERTICAL)));
// } else {
// //if x_ is max there can be only end events and no sloping edges
// if(x_ != (std::numeric_limits<Unit>::max)()) {
// //insert its end points into the vector of sloping ends
// const half_edge& he = (*inter_iter).first;
// Unit y = evalAtXforY(x_, he.first, he.second);
// Unit y2 = evalAtXforY(x_+1, he.first, he.second);
// if(y2 >= y) y2 +=1; //we round up, in exact case we don't worry about overbite of one
// else y += 1; //downward sloping round up
// sloping_ends.push_back(std::make_pair(y, inter_iter));
// sloping_ends.push_back(std::make_pair(y2, inter_iter));
// }
// }
// }
//merge sloping element data
std::sort(sloping_ends.begin(), sloping_ends.end());
std::map<Unit, std::set<iterator> > sloping_elements;
std::set<iterator> merge_elements;
for(typename std::vector<std::pair<Unit, iterator> >::iterator slop_iter = sloping_ends.begin();
slop_iter = sloping_ends.end(); ++slop_iter) {
//merge into sloping elements
typename std::set<iterator>::iterator merge_iterator = merge_elements.find((*slop_iter).second);
if(merge_iterator = merge_elements.end()) {
merge_elements.insert((*slop_iter).second);
} else {
merge_elements.erase(merge_iterator);
}
sloping_elements[(*slop_iter).first] = merge_elements;
}
//scan intersection points
typename std::map<Unit, std::set<segment_id> >::iterator vertical_iter = vertical_data_.begin();
typename std::map<Unit, std::set<iterator> >::iterator sloping_iter = sloping_elements.begin();
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
}
// //merge sloping element data
// std::sort(sloping_ends.begin(), sloping_ends.end());
// std::map<Unit, std::set<iterator> > sloping_elements;
// std::set<iterator> merge_elements;
// for(typename std::vector<std::pair<Unit, iterator> >::iterator slop_iter = sloping_ends.begin();
// slop_iter == sloping_ends.end(); ++slop_iter) {
// //merge into sloping elements
// typename std::set<iterator>::iterator merge_iterator = merge_elements.find((*slop_iter).second);
// if(merge_iterator == merge_elements.end()) {
// merge_elements.insert((*slop_iter).second);
// } else {
// merge_elements.erase(merge_iterator);
// }
// sloping_elements[(*slop_iter).first] = merge_elements;
// }
inline void process_scan_event(std::map<segment_id, std::set<Point> >& intersection_points) {
just_before_ = true;
// //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);
// }
// }
// }
// }
// }
// }
//process end events by removing those segments from the scanline
//and insert vertices of all events into intersection queue
Point prev_point((std::numeric_limits<Unit>::min)(), (std::numeric_limits<Unit>::min)());
less_point lp;
std::set<segment_id> vertical_ids;
vertical_data_.clear();
for(std::size_t i = 0; i < event_edges_.size(); ++i) {
segment_id id = event_edges_[i].second;
const half_edge& he = event_edges_[i].first;
//vertical half edges are handled during intersection processing because
//they cannot be inserted into the scanline
if(!is_vertical(he)) {
if(lp(he.second, he.first)) {
//half edge is end event
lookup_and_remove(he, id);
} else {
//half edge is begin event
insert_into_scanline(he, id);
//note that they will be immediately removed and reinserted after
//handling their intersection (vertex)
//an optimization would allow them to be processed specially to avoid the redundant
//removal and reinsertion
}
} else {
//common case if you are lucky
//update the map of y to set of segment id
if(lp(he.second, he.first)) {
//half edge is end event
std::set<segment_id>::iterator itr = vertical_ids.find(id);
if(itr == vertical_ids.end()) {
//std::cout << "Failed to find end event id in vertical ids\n";
} else {
vertical_ids.erase(itr);
vertical_data_[he.first.get(HORIZONTAL)] = vertical_ids;
}
} else {
//half edge is a begin event
vertical_ids.insert(id);
vertical_data_[he.first.get(HORIZONTAL)] = vertical_ids;
}
}
//prevent repeated insertion of same vertex into intersection queue
if(prev_point != he.first)
intersection_queue_.insert(he.first);
else
prev_point = he.first;
// process intersections at scan event
process_intersections_at_scan_event(intersection_points);
}
event_edges_.clear();
}
// //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) {
// just_before_ = true;
// //process end events by removing those segments from the scanline
// //and insert vertices of all events into intersection queue
// Point prev_point((std::numeric_limits<Unit>::min)(), (std::numeric_limits<Unit>::min)());
// less_point lp;
// std::set<segment_id> vertical_ids;
// vertical_data_.clear();
// for(std::size_t i = 0; i < event_edges_.size(); ++i) {
// segment_id id = event_edges_[i].second;
// const half_edge& he = event_edges_[i].first;
// //vertical half edges are handled during intersection processing because
// //they cannot be inserted into the scanline
// if(!is_vertical(he)) {
// if(lp(he.second, he.first)) {
// //half edge is end event
// lookup_and_remove(he, id);
// } else {
// //half edge is begin event
// insert_into_scanline(he, id);
// //note that they will be immediately removed and reinserted after
// //handling their intersection (vertex)
// //an optimization would allow them to be processed specially to avoid the redundant
// //removal and reinsertion
// }
// } else {
// //common case if you are lucky
// //update the map of y to set of segment id
// if(lp(he.second, he.first)) {
// //half edge is end event
// std::set<segment_id>::iterator itr = vertical_ids.find(id);
// if(itr == vertical_ids.end()) {
// //std::cout << "Failed to find end event id in vertical ids\n";
// } else {
// vertical_ids.erase(itr);
// vertical_data_[he.first.get(HORIZONTAL)] = vertical_ids;
// }
// } else {
// //half edge is a begin event
// vertical_ids.insert(id);
// vertical_data_[he.first.get(HORIZONTAL)] = vertical_ids;
// }
// }
// //prevent repeated insertion of same vertex into intersection queue
// if(prev_point != he.first)
// intersection_queue_.insert(he.first);
// else
// prev_point = he.first;
// // process intersections at scan event
// process_intersections_at_scan_event(intersection_points);
// }
// event_edges_.clear();
// }
public:
template <typename stream_type>
......@@ -892,23 +892,23 @@ namespace boost { namespace polygon{
return false;
}
edges.pop_back();
edges.push_back(std::make_pair(half_edge(Point(1, 0), Point(11, 11)), edges.size()));
edges.push_back(std::make_pair(half_edge(Point(1, 0), Point(11, 11)), (segment_id)edges.size()));
if(!verify_scan(result, edges.begin(), edges.end())) {
stdcout << "fail3\n";
return false;
}
edges.push_back(std::make_pair(half_edge(Point(1, 0), Point(10, 11)), edges.size()));
edges.push_back(std::make_pair(half_edge(Point(1, 0), Point(10, 11)), (segment_id)edges.size()));
if(verify_scan(result, edges.begin(), edges.end())) {
stdcout << "fail4\n";
return false;
}
edges.pop_back();
edges.push_back(std::make_pair(half_edge(Point(1, 2), Point(11, 11)), edges.size()));
edges.push_back(std::make_pair(half_edge(Point(1, 2), Point(11, 11)), (segment_id)edges.size()));
if(!verify_scan(result, edges.begin(), edges.end())) {
stdcout << "fail5 " << result.first << " " << result.second << "\n";
return false;
}
edges.push_back(std::make_pair(half_edge(Point(0, 5), Point(0, 11)), edges.size()));
edges.push_back(std::make_pair(half_edge(Point(0, 5), Point(0, 11)), (segment_id)edges.size()));
if(verify_scan(result, edges.begin(), edges.end())) {
stdcout << "fail6 " << result.first << " " << result.second << "\n";
return false;
......@@ -1048,7 +1048,7 @@ namespace boost { namespace polygon{
if(current_iter != scan_data_.end()) {
//make sure we are looking at element in scanline just below y
//if(evalAtXforY(x_, (*current_iter).first.first, (*current_iter).first.second) != y) {
if(on_above_or_below(Point(x_, y), (*current_iter).first) != 0) {
if(scanline_base<Unit>::on_above_or_below(Point(x_, y), (*current_iter).first) != 0) {
Point e2(pt);
if(e2.get(VERTICAL) != (std::numeric_limits<Unit>::max)())
e2.set(VERTICAL, e2.get(VERTICAL) + 1);
......@@ -1060,12 +1060,12 @@ namespace boost { namespace polygon{
if(current_iter != scan_data_.end()) {
//get the bottom iterator for elements at this point
//while(evalAtXforY(x_, (*current_iter).first.first, (*current_iter).first.second) >= (high_precision)y &&
while(on_above_or_below(Point(x_, y), (*current_iter).first) != 1 &&
while(scanline_base<Unit>::on_above_or_below(Point(x_, y), (*current_iter).first) != 1 &&
current_iter != scan_data_.begin()) {
--current_iter;
}
//if(evalAtXforY(x_, (*current_iter).first.first, (*current_iter).first.second) >= (high_precision)y) {
if(on_above_or_below(Point(x_, y), (*current_iter).first) != 1) {
if(scanline_base<Unit>::on_above_or_below(Point(x_, y), (*current_iter).first) != 1) {
properties_below.clear();
} else {
properties_below = (*current_iter).second;
......@@ -1078,7 +1078,7 @@ namespace boost { namespace polygon{
while(current_iter != scan_data_.end() &&
//can only be true if y is integer
//evalAtXforY(x_, (*current_iter).first.first, (*current_iter).first.second) == y) {
on_above_or_below(Point(x_, y), (*current_iter).first) == 0) {
scanline_base<Unit>::on_above_or_below(Point(x_, y), (*current_iter).first) == 0) {
//removal_set_.push_back(current_iter);
++current_iter;
}
......@@ -1129,7 +1129,7 @@ namespace boost { namespace polygon{
y = vertical_edge_below.second.get(VERTICAL);
continue;
}
if(is_vertical(he)) {
if(scanline_base<Unit>::is_vertical(he)) {
update_property_map(vertical_properties_above, vp.second);
vertical_edge_above = he;
} else {
......@@ -1556,7 +1556,7 @@ namespace boost { namespace polygon{
sl.scan(result, mof, pmd.begin(), pmd.end());
}
inline bool verify() {
inline bool verify1() {
std::pair<int, int> offenders;
std::vector<std::pair<half_edge, int> > lines;
int count = 0;
......@@ -1704,8 +1704,8 @@ namespace boost { namespace polygon{
//if half edge 1 is not vertical its slope is less than that of half edge 2
return get(pt1, HORIZONTAL) != get(pt2, HORIZONTAL);
}
return less_slope(get(pt_, HORIZONTAL),
get(pt_, VERTICAL), pt1, pt2);
return scanline_base<Unit>::less_slope(get(pt_, HORIZONTAL),
get(pt_, VERTICAL), pt1, pt2);
}
};
......@@ -2154,7 +2154,7 @@ pts.push_back(Point(12344171, 6695983 )); pts.push_back(Point(12287208, 6672388
si.insert(poly, 444);
result.clear();
si.merge(result);
si.verify();
si.verify1();
print(stdcout, si.pmd) << std::endl;
if(!result.empty()) {
psd = (*(result.begin())).second;
......@@ -2534,7 +2534,7 @@ pts.push_back(Point(12344171, 6695983 )); pts.push_back(Point(12287208, 6672388
elem.first = edge;
elem.second = 1;
if(edge.second < edge.first) elem.second *= -1;
if(is_vertical(edge)) elem.second *= -1;
if(scanline_base<Unit>::is_vertical(edge)) elem.second *= -1;
#ifdef BOOST_POLYGON_MSVC
#pragma warning (disable: 4127)
#endif
......
......@@ -34,17 +34,29 @@ namespace boost { namespace polygon{
#endif
{ (*this) = that; }
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) {
coords_[0] = that.coords_[0]; coords_[1] = that.coords_[1]; return *this;
}
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_[VERTICAL] = (coordinate_type)y;
}
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_[VERTICAL] = (coordinate_type)(rvalue.y());
}
......
......@@ -62,7 +62,7 @@ public:
inline std::size_t size() const { return coords_.size(); }
private:
public:
std::vector<point_data<coordinate_type> > coords_;
};
......
......@@ -1541,11 +1541,11 @@ namespace boost { namespace polygon{
polygon_90_set_data<Unit> l90sd(VERTICAL), r90sd(VERTICAL), output(VERTICAL);
for(typename value_type::const_iterator itr = data_.begin(); itr != data_.end(); ++itr) {
if((*itr).count[3] == 0) continue; //skip all non vertical edges
l90sd.insert(std::make_pair((*itr).pt.x(), std::make_pair((*itr).pt.y(), (*itr).count[3])), false, VERTICAL);
l90sd.insert(std::make_pair((*itr).pt.x(), std::make_pair<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) {
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();
r90sd.sort();
......@@ -1673,7 +1673,7 @@ namespace boost { namespace polygon{
polygon_90_set_data<Unit> l90sd(VERTICAL);
for(typename value_type::const_iterator itr = data_.begin(); itr != data_.end(); ++itr) {
if((*itr).count[3] == 0) continue; //skip all non vertical edges
l90sd.insert(std::make_pair((*itr).pt.x(), std::make_pair((*itr).pt.y(), (*itr).count[3])), false, VERTICAL);
l90sd.insert(std::make_pair((*itr).pt.x(), std::make_pair<Unit, int>((*itr).pt.y(), (*itr).count[3])), false, VERTICAL);
}
l90sd.sort();
#ifdef BOOST_POLYGON_MSVC
......
......@@ -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 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:
return holes_.size();
}
private:
public:
polygon_45_data<coordinate_type> self_;
std::list<hole_type> holes_;
};
}
}
#endif
......
......@@ -244,6 +244,38 @@ namespace boost { namespace polygon{
// get the scanline orientation of the polygon set
inline orientation_2d orient() const { return orient_; }
polygon_90_set_data<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 {
sort();
if(dirty_) {
......@@ -297,7 +329,7 @@ namespace boost { namespace polygon{
}
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 south_bloating,
typename coordinate_traits<coordinate_type>::unsigned_area_type north_bloating) {
......@@ -318,11 +350,257 @@ namespace boost { namespace polygon{
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&
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 south_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;
if(!extents(externalBoundary)) return *this;
::boost::polygon::bloat(externalBoundary, 10); //bloat by diferential ammount
......@@ -352,6 +630,30 @@ namespace boost { namespace polygon{
return *this;
}
polygon_90_set_data&
shrink(direction_2d dir, typename coordinate_traits<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&
resize(coordinate_type west, coordinate_type east, coordinate_type south, coordinate_type north);
......
......@@ -60,7 +60,7 @@ public:
inline std::size_t size() const { return coords_.size(); }
private:
public:
std::vector<point_data<coordinate_type> > coords_;
};
......
......@@ -120,38 +120,7 @@ namespace boost { namespace polygon {
template <typename polygon_type>
inline void insert(const polygon_type& polygon_object, bool is_hole, polygon_concept ) {
bool first_iteration = true;
point_type first_point;
point_type previous_point;
point_type current_point;
direction_1d winding_dir = winding(polygon_object);
int multiplier = winding_dir == COUNTERCLOCKWISE ? 1 : -1;
if(is_hole) multiplier *= -1;
for(typename polygon_traits<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;
}
insert_vertex_sequence(begin_points(polygon_object), end_points(polygon_object), winding(polygon_object), is_hole);
}
inline void insert(const polygon_set_data& ps, bool is_hole = false) {
......@@ -229,9 +198,37 @@ namespace boost { namespace polygon {
template <class iT>
inline void insert_vertex_sequence(iT begin_vertex, iT end_vertex, direction_1d winding, bool is_hole) {
polygon_data<coordinate_type> poly;
poly.set(begin_vertex, end_vertex);
insert(poly, is_hole);
bool first_iteration = true;
point_type first_point;
point_type previous_point;
point_type current_point;
direction_1d winding_dir = winding;
int multiplier = winding_dir == COUNTERCLOCKWISE ? 1 : -1;
if(is_hole) multiplier *= -1;
for( ; begin_vertex != end_vertex; ++begin_vertex) {
assign(current_point, *begin_vertex);
if(first_iteration) {
first_iteration = false;
first_point = previous_point = current_point;
} else {
if(previous_point != current_point) {
element_type elem(edge_type(previous_point, current_point),
( previous_point.get(HORIZONTAL) == current_point.get(HORIZONTAL) ? -1 : 1) * multiplier);
insert_clean(elem);
}
}
previous_point = current_point;
}
current_point = first_point;
if(!first_iteration) {
if(previous_point != current_point) {
element_type elem(edge_type(previous_point, current_point),
( previous_point.get(HORIZONTAL) == current_point.get(HORIZONTAL) ? -1 : 1) * multiplier);
insert_clean(elem);
}
dirty_ = true;
unsorted_ = true;
}
}
template <typename output_container>
......@@ -363,6 +360,13 @@ namespace boost { namespace polygon {
inline polygon_set_data&
resize(coordinate_type resizing, bool corner_fill_arc = false, unsigned int num_circle_segments=0) {
if(!corner_fill_arc) {
if(resizing < 0)
return shrink(-resizing);
if(resizing > 0)
return bloat(-resizing);
return *this;
}
if(resizing == 0) return *this;
std::list<polygon_with_holes_data<coordinate_type> > pl;
get(pl);
......@@ -421,6 +425,139 @@ namespace boost { namespace polygon {
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
template <typename geometry_type>
inline polygon_set_data&
......@@ -481,6 +618,7 @@ namespace boost { namespace polygon {
bool sizing_sign = resizing>0;
bool prev_concave = true;
point_data<T> prev_point;
//int iCtr=0;
//insert minkofski shapes on edges and corners
......@@ -494,7 +632,9 @@ namespace boost { namespace polygon {
double direction = normal1.x()*normal2.y()- normal2.x()*normal1.y();
bool convex = direction>0;
bool treat_as_concave = convex ^ sizing_sign ;
bool treat_as_concave = !convex;
if(sizing_sign)
treat_as_concave = convex;
point_data<double> v;
assign(v, normal1);
double s2 = (v.x()*v.x()+v.y()*v.y());
......@@ -533,14 +673,14 @@ namespace boost { namespace polygon {
, num_circle_segments, corner_fill_arc))
{
if (first_pts.size()) {
for (unsigned i=0; i<pts.size(); i++) {
for (unsigned int i=0; i<pts.size(); i++) {
sizingSet.insert_vertex_sequence(pts[i].begin(),pts[i].end(),winding,false);
}
} else {
first_pts = pts[0];
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);
}
}
......@@ -573,7 +713,7 @@ namespace boost { namespace polygon {
//insert original shape
tmp.insert(poly, false, polygon_concept());
if( ((resizing < 0) ^ hole) ) tmp -= sizingSet;
if((resizing < 0) ^ hole) tmp -= sizingSet;
else tmp += sizingSet;
//tmp.clean();
insert(tmp, hole);
......@@ -662,13 +802,13 @@ namespace boost { namespace polygon {
typedef polygon_set_concept type;
};
template <typename T>
inline double compute_area(point_data<T>& a, point_data<T>& b, point_data<T>& c) {
// template <typename T>
// 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>
inline int make_resizing_vertex_list(std::vector<std::vector<point_data< T> > >& return_points,
......@@ -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> > 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;
typename scanline_base<T>::compute_intersection_pack pack;
......@@ -723,8 +863,8 @@ namespace boost { namespace polygon {
return_points_back.push_back(start);
return_points_back.push_back(curr_prev);
/*double d1= */compute_area(intersect,middle,start);
/*double d2= */compute_area(start,curr_prev,intersect);
//double d1= compute_area(intersect,middle,start);
//double d2= compute_area(start,curr_prev,intersect);
curr_prev = intersect;
......@@ -754,7 +894,7 @@ namespace boost { namespace polygon {
ps += 2.0 * our_pi;
if (pe <= 0.0)
pe += 2.0 * our_pi;
if (ps >= 2.0 * M_PI)
if (ps >= 2.0 * our_pi)
ps -= 2.0 * our_pi;
while (pe <= ps)
pe += 2.0 * our_pi;
......@@ -771,9 +911,9 @@ namespace boost { namespace polygon {
}
return_points.push_back(round_down<T>(center));
return_points.push_back(round_down<T>(start));
int i=0;
unsigned int i=0;
double curr_angle = ps+delta_angle;
while( curr_angle < pe - 0.01 && i < 2 * (int)num_circle_segments) {
while( curr_angle < pe - 0.01 && i < 2 * num_circle_segments) {
i++;
double x = center.x() + r * cos( curr_angle);
double y = center.y() + r * sin( curr_angle);
......
......@@ -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 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:
return holes_.size();
}
private:
public:
polygon_data<coordinate_type> self_;
std::list<hole_type> holes_;
};
......
......@@ -131,33 +131,10 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
* so m_ZoneMinThickness is the min thickness of the filled zones areas
* the main polygon is stored in polyset_zone_solid_areas
*/
#if 1
{
/* creates the main polygon (i.e. the filled area using only one outline)
* in GroupA in Bool_Engine to do a BOOL_CORRECTION operation
* to reserve a m_ZoneMinThickness/2 margin around the outlines
*/
Bool_Engine* booleng = new Bool_Engine();
ArmBoolEng( booleng, true );
CopyPolygonsFromFilledPolysListToBoolengine( booleng, GROUP_A );
booleng->SetCorrectionFactor( (double) -margin );
booleng->Do_Operation( BOOL_CORRECTION );
/* Now copy the new outline in m_FilledPolysList */
m_FilledPolysList.clear();
CopyPolygonsFromBoolengineToFilledPolysList( booleng );
delete booleng;
CopyPolygonsFromFilledPolysListTotKPolygonList( this, polyset_zone_solid_areas );
}
#else
/* currently does not work well.
* using kbool gives reliable results
* using boost::polygone gives erroneous results
*/
CopyPolygonsFromFilledPolysListTotKPolygonList( this,
polyset_zone_solid_areas );
polyset_zone_solid_areas -= margin;
#endif
if( polyset_zone_solid_areas.size() == 0 )
return;
......@@ -523,82 +500,6 @@ void AddUnconnectedThermalStubsToKPolygonList( std::vector<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>&
aCornersBuffer,
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