merge from testing
This commit is contained in:
commit
d48f6e0023
|
@ -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 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);
|
||||
}
|
||||
// //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 iterator lookup(const half_edge& he) {
|
||||
// return edge_scanline_.find(he);
|
||||
// }
|
||||
|
||||
inline void insert_into_scanline(const half_edge& he, int id) {
|
||||
edge_scanline_[he].insert(id);
|
||||
}
|
||||
// inline void insert_into_scanline(const half_edge& he, int id) {
|
||||
// edge_scanline_[he].insert(id);
|
||||
// }
|
||||
|
||||
inline void lookup_and_remove(const half_edge& he, int id) {
|
||||
iterator remove_iter = lookup(he);
|
||||
if(remove_iter == edge_scanline_.end()) {
|
||||
//std::cout << "failed to find removal segment in scanline\n";
|
||||
return;
|
||||
}
|
||||
std::set<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);
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
// 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
|
||||
// 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
|
||||
// //second find edges in scanline on the y interval of each edge found in the previous
|
||||
// //step for x_ to x_ + 1
|
||||
|
||||
//third find overlaps in the y intervals of all found edges to find all
|
||||
//secondary intersection points
|
||||
// //third find overlaps in the y intervals of all found edges to find all
|
||||
// //secondary intersection points
|
||||
|
||||
}
|
||||
}
|
||||
//erase the intersection points from the queue
|
||||
intersection_queue_.erase(intersection_queue_.begin(), iter);
|
||||
std::vector<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));
|
||||
}
|
||||
}
|
||||
}
|
||||
// }
|
||||
// }
|
||||
// //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;
|
||||
}
|
||||
// //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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// //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
|
||||
}
|
||||
// //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;
|
||||
// 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();
|
||||
}
|
||||
// //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 )
|
||||
|
|
Loading…
Reference in New Issue