Pcbnew: fix a serious bug in ZONE_CONTAINER::HitTestFilledArea( ) which could break connectivity calculations relative to copper areas.

Fix also very minor issues relative to copper zones.
Update boost::polygon from Boost svn repository.
This commit is contained in:
jean-pierre charras 2010-11-13 20:21:16 +01:00
parent 3dbae0b84c
commit 746dea5ae3
15 changed files with 387 additions and 216 deletions

View File

@ -253,8 +253,13 @@ public:
typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, HIGH, orient_, !is_hole_); typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, HIGH, orient_, !is_hole_);
++itrhb; ++itrhb;
} else { } else {
itrhib = itrhie = iterator_geometry_to_set<polygon_90_concept, //in this case we have no holes so we just need the iterhib == itrhie, which
typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(); //is always true if they were default initialized in the initial case or
//both point to end of the previous hole processed
//no need to explicitly reset them, and it causes an stl debug assertion to use
//the default constructed iterator this way
//itrhib = itrhie = iterator_geometry_to_set<polygon_90_concept,
// typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>();
} }
} else { } else {
++itrhib; ++itrhib;
@ -266,8 +271,9 @@ public:
typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, HIGH, orient_, !is_hole_); typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, HIGH, orient_, !is_hole_);
++itrhb; ++itrhb;
} else { } else {
itrhib = itrhie = iterator_geometry_to_set<polygon_90_concept, //this is the same case as above
typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(); //itrhib = itrhie = iterator_geometry_to_set<polygon_90_concept,
// typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>();
} }
} }
} }

View File

@ -0,0 +1,125 @@
namespace boost { namespace polygon { namespace detail {
template <typename coordinate_type>
struct minkowski_offset {
typedef point_data<coordinate_type> point;
typedef polygon_set_data<coordinate_type> polygon_set;
typedef polygon_with_holes_data<coordinate_type> polygon;
typedef std::pair<point, point> edge;
static void convolve_two_segments(std::vector<point>& figure, const edge& a, const edge& b) {
figure.clear();
figure.push_back(point(a.first));
figure.push_back(point(a.first));
figure.push_back(point(a.second));
figure.push_back(point(a.second));
convolve(figure[0], b.second);
convolve(figure[1], b.first);
convolve(figure[2], b.first);
convolve(figure[3], b.second);
}
template <typename itrT1, typename itrT2>
static void convolve_two_point_sequences(polygon_set& result, itrT1 ab, itrT1 ae, itrT2 bb, itrT2 be) {
if(ab == ae || bb == be)
return;
point first_a = *ab;
point prev_a = *ab;
std::vector<point> vec;
polygon poly;
++ab;
for( ; ab != ae; ++ab) {
point first_b = *bb;
point prev_b = *bb;
itrT2 tmpb = bb;
++tmpb;
for( ; tmpb != be; ++tmpb) {
convolve_two_segments(vec, std::make_pair(prev_b, *tmpb), std::make_pair(prev_a, *ab));
set_points(poly, vec.begin(), vec.end());
result.insert(poly);
prev_b = *tmpb;
}
prev_a = *ab;
}
}
template <typename itrT>
static void convolve_point_sequence_with_polygons(polygon_set& result, itrT b, itrT e, const std::vector<polygon>& polygons) {
for(std::size_t i = 0; i < polygons.size(); ++i) {
convolve_two_point_sequences(result, b, e, begin_points(polygons[i]), end_points(polygons[i]));
for(typename polygon_with_holes_traits<polygon>::iterator_holes_type itrh = begin_holes(polygons[i]);
itrh != end_holes(polygons[i]); ++itrh) {
convolve_two_point_sequences(result, b, e, begin_points(*itrh), end_points(*itrh));
}
}
}
static void convolve_two_polygon_sets(polygon_set& result, const polygon_set& a, const polygon_set& b) {
result.clear();
std::vector<polygon> a_polygons;
std::vector<polygon> b_polygons;
a.get(a_polygons);
b.get(b_polygons);
for(std::size_t ai = 0; ai < a_polygons.size(); ++ai) {
convolve_point_sequence_with_polygons(result, begin_points(a_polygons[ai]),
end_points(a_polygons[ai]), b_polygons);
for(typename polygon_with_holes_traits<polygon>::iterator_holes_type itrh = begin_holes(a_polygons[ai]);
itrh != end_holes(a_polygons[ai]); ++itrh) {
convolve_point_sequence_with_polygons(result, begin_points(*itrh),
end_points(*itrh), b_polygons);
}
for(std::size_t bi = 0; bi < b_polygons.size(); ++bi) {
polygon tmp_poly = a_polygons[ai];
result.insert(convolve(tmp_poly, *(begin_points(b_polygons[bi]))));
tmp_poly = b_polygons[bi];
result.insert(convolve(tmp_poly, *(begin_points(a_polygons[ai]))));
}
}
}
};
}
template<typename T>
inline polygon_set_data<T>&
polygon_set_data<T>::resize(coordinate_type resizing, bool corner_fill_arc, unsigned int num_circle_segments) {
using namespace ::boost::polygon::operators;
if(!corner_fill_arc) {
if(resizing < 0)
return shrink(-resizing);
if(resizing > 0)
return bloat(resizing);
return *this;
}
if(resizing == 0) return *this;
if(empty()) return *this;
if(num_circle_segments < 3) num_circle_segments = 4;
rectangle_data<coordinate_type> rect;
extents(rect);
if(resizing < 0) {
::boost::polygon::bloat(rect, 10);
(*this) = rect - (*this); //invert
}
//make_arc(std::vector<point_data< T> >& return_points,
//point_data< double> start, point_data< double> end,
//point_data< double> center, double r, unsigned int num_circle_segments)
std::vector<point_data<coordinate_type> > circle;
point_data<double> center(0.0, 0.0), start(0.0, (double)resizing);
make_arc(circle, start, start, center, std::abs((double)resizing),
num_circle_segments);
polygon_data<coordinate_type> poly;
set_points(poly, circle.begin(), circle.end());
polygon_set_data<coordinate_type> offset_set;
offset_set += poly;
polygon_set_data<coordinate_type> result;
detail::minkowski_offset<coordinate_type>::convolve_two_polygon_sets
(result, *this, offset_set);
if(resizing < 0) {
result = result & rect;//eliminate overhang
result = result ^ rect;//invert
}
*this = result;
return *this;
}
}}

View File

@ -478,7 +478,7 @@ namespace boost { namespace polygon{
ct counts[4]; ct counts[4];
}; };
typedef Vertex45CountT<signed char> Vertex45Count; typedef Vertex45CountT<int> Vertex45Count;
// inline std::ostream& operator<< (std::ostream& o, const Vertex45Count& c) { // inline std::ostream& operator<< (std::ostream& o, const Vertex45Count& c) {
// o << c[0] << ", " << c[1] << ", "; // o << c[0] << ", " << c[1] << ", ";

View File

@ -455,6 +455,10 @@ namespace boost { namespace polygon{
//truncate downward if it went up due to negative number //truncate downward if it went up due to negative number
if(x < x_unit) --x_unit; if(x < x_unit) --x_unit;
if(y < y_unit) --y_unit; if(y < y_unit) --y_unit;
if(is_horizontal(he1))
y_unit = he1.first.y();
if(is_horizontal(he2))
y_unit = he2.first.y();
//if(x != exp_x || y != exp_y) //if(x != exp_x || y != exp_y)
// std::cout << exp_x << " " << exp_y << " " << x << " " << y << std::endl; // std::cout << exp_x << " " << exp_y << " " << x << " " << y << std::endl;
//Unit y1 = evalAtXforY(exp_x, he1.first, he1.second); //Unit y1 = evalAtXforY(exp_x, he1.first, he1.second);
@ -464,11 +468,11 @@ namespace boost { namespace polygon{
if(!projected && !contains(rect1, result, true)) return false; if(!projected && !contains(rect1, result, true)) return false;
if(!projected && !contains(rect2, result, true)) return false; if(!projected && !contains(rect2, result, true)) return false;
if(projected) { if(projected) {
rectangle_data<long double> inf_rect((long double)(std::numeric_limits<Unit>::min)(), rectangle_data<long double> inf_rect(-(long double)(std::numeric_limits<Unit>::max)(),
(long double) (std::numeric_limits<Unit>::min)(), -(long double) (std::numeric_limits<Unit>::max)(),
(long double)(std::numeric_limits<Unit>::max)(), (long double)(std::numeric_limits<Unit>::max)(),
(long double) (std::numeric_limits<Unit>::max)() ); (long double) (std::numeric_limits<Unit>::max)() );
if(contains(inf_rect, intersection, true)) { if(contains(inf_rect, point_data<long double>(x, y), true)) {
intersection = result; intersection = result;
return true; return true;
} else } else
@ -477,6 +481,7 @@ namespace boost { namespace polygon{
intersection = result; intersection = result;
return true; return true;
} }
inline bool compute_intersection(Point& intersection, const half_edge& he1, const half_edge& he2, inline bool compute_intersection(Point& intersection, const half_edge& he1, const half_edge& he2,
bool projected = false, bool round_closest = false) { bool projected = false, bool round_closest = false) {
if(!projected && !intersects(he1, he2)) if(!projected && !intersects(he1, he2))
@ -491,6 +496,13 @@ namespace boost { namespace polygon{
} else { } else {
return lazy_success; return lazy_success;
} }
return compute_exact_intersection(intersection, he1, he2, projected, round_closest);
}
inline bool compute_exact_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;
typedef rectangle_data<Unit> Rectangle; typedef rectangle_data<Unit> Rectangle;
Rectangle rect1, rect2; Rectangle rect1, rect2;
set_points(rect1, he1.first, he1.second); set_points(rect1, he1.first, he1.second);
@ -542,6 +554,7 @@ namespace boost { namespace polygon{
y_den = (dx1 * dy2 - dx2 * dy1); y_den = (dx1 * dy2 - dx2 * dy1);
x = x_num / x_den; x = x_num / x_den;
y = y_num / y_den; y = y_num / y_den;
//std::cout << x << " " << y << std::endl;
//std::cout << "cross1 " << dy1 << " " << dx2 << " " << dy1 * dx2 << std::endl; //std::cout << "cross1 " << dy1 << " " << dx2 << " " << dy1 * dx2 << std::endl;
//std::cout << "cross2 " << dy2 << " " << dx1 << " " << dy2 * dx1 << std::endl; //std::cout << "cross2 " << dy2 << " " << dx1 << " " << dy2 * dx1 << std::endl;
//Unit exp_x = compute_x_intercept<at>(x11, x21, y11, y21, dy1, dy2, dx1, dx2); //Unit exp_x = compute_x_intercept<at>(x11, x21, y11, y21, dy1, dy2, dx1, dx2);
@ -555,6 +568,10 @@ namespace boost { namespace polygon{
//truncate downward if it went up due to negative number //truncate downward if it went up due to negative number
if(x < (high_precision)x_unit) --x_unit; if(x < (high_precision)x_unit) --x_unit;
if(y < (high_precision)y_unit) --y_unit; if(y < (high_precision)y_unit) --y_unit;
if(is_horizontal(he1))
y_unit = he1.first.y();
if(is_horizontal(he2))
y_unit = he2.first.y();
//if(x != exp_x || y != exp_y) //if(x != exp_x || y != exp_y)
// std::cout << exp_x << " " << exp_y << " " << x << " " << y << std::endl; // std::cout << exp_x << " " << exp_y << " " << x << " " << y << std::endl;
//Unit y1 = evalAtXforY(exp_x, he1.first, he1.second); //Unit y1 = evalAtXforY(exp_x, he1.first, he1.second);
@ -564,14 +581,9 @@ namespace boost { namespace polygon{
if(!contains(rect1, result, true)) return false; if(!contains(rect1, result, true)) return false;
if(!contains(rect2, result, true)) return false; if(!contains(rect2, result, true)) return false;
if(projected) { if(projected) {
rectangle_data<long double> inf_rect((long double)(std::numeric_limits<Unit>::min)(), high_precision b1 = (high_precision) (std::numeric_limits<Unit>::min)();
(long double) (std::numeric_limits<Unit>::min)(), high_precision b2 = (high_precision) (std::numeric_limits<Unit>::max)();
(long double)(std::numeric_limits<Unit>::max)(), if(x > b2 || y > b2 || x < b1 || y < b1)
(long double) (std::numeric_limits<Unit>::max)() );
if(contains(inf_rect, intersection, true)) {
intersection = result;
return true;
} else
return false; return false;
} }
intersection = result; intersection = result;
@ -641,6 +653,10 @@ namespace boost { namespace polygon{
//truncate downward if it went up due to negative number //truncate downward if it went up due to negative number
if(x < (high_precision)x_unit) --x_unit; if(x < (high_precision)x_unit) --x_unit;
if(y < (high_precision)y_unit) --y_unit; if(y < (high_precision)y_unit) --y_unit;
if(is_horizontal(he1))
y_unit = he1.first.y();
if(is_horizontal(he2))
y_unit = he2.first.y();
//if(x != exp_x || y != exp_y) //if(x != exp_x || y != exp_y)
// std::cout << exp_x << " " << exp_y << " " << x << " " << y << std::endl; // std::cout << exp_x << " " << exp_y << " " << x << " " << y << std::endl;
//Unit y1 = evalAtXforY(exp_x, he1.first, he1.second); //Unit y1 = evalAtXforY(exp_x, he1.first, he1.second);

View File

@ -125,5 +125,5 @@ namespace boost { namespace polygon {
} }
} }
//==
#endif #endif

View File

@ -198,6 +198,16 @@ namespace boost { namespace polygon{
typedef double coordinate_distance; typedef double coordinate_distance;
}; };
template <>
struct coordinate_traits<long double> {
typedef long double coordinate_type;
typedef long double area_type;
typedef long double manhattan_area_type;
typedef long double unsigned_area_type;
typedef long double coordinate_difference;
typedef long double coordinate_distance;
};
template <typename T> template <typename T>
struct scaling_policy { struct scaling_policy {
template <typename T2> template <typename T2>
@ -222,6 +232,8 @@ namespace boost { namespace polygon{
struct geometry_concept<float> { typedef coordinate_concept type; }; struct geometry_concept<float> { typedef coordinate_concept type; };
template <> template <>
struct geometry_concept<double> { typedef coordinate_concept type; }; struct geometry_concept<double> { typedef coordinate_concept type; };
template <>
struct geometry_concept<long double> { typedef coordinate_concept type; };
#ifndef BOOST_POLYGON_NO_DEPS #ifndef BOOST_POLYGON_NO_DEPS
struct gtl_no : mpl::bool_<false> {}; struct gtl_no : mpl::bool_<false> {};

View File

@ -244,37 +244,47 @@ namespace boost { namespace polygon{
// get the scanline orientation of the polygon set // get the scanline orientation of the polygon set
inline orientation_2d orient() const { return orient_; } inline orientation_2d orient() const { return orient_; }
polygon_90_set_data<coordinate_type>& operator-=(const polygon_90_set_data& that) { // Start BM
sort(); // The problem: If we have two polygon sets with two different scanline orientations:
that.sort(); // I tried changing the orientation of one to coincide with other (If not, resulting boolean operation
value_type data; // produces spurious results).
std::swap(data, data_); // First I tried copying polygon data from one of the sets into another set with corrected orientation
applyBooleanBinaryOp(data.begin(), data.end(), // using one of the copy constructor that takes in orientation (see somewhere above in this file) --> copy constructor throws error
that.begin(), that.end(), boolean_op::BinaryCount<boolean_op::BinaryNot>()); // Then I tried another approach:(see below). This approach also fails to produce the desired results when test case is run.
return *this; // Here is the part that beats me: If I comment out the whole section, I can do all the operations (^=, -=, &= )these commented out
} // operations perform. So then why do we need them?. Hence, I commented out this whole section.
polygon_90_set_data<coordinate_type>& operator^=(const polygon_90_set_data& that) { // End BM
sort(); // polygon_90_set_data<coordinate_type>& operator-=(const polygon_90_set_data& that) {
that.sort(); // sort();
value_type data; // that.sort();
std::swap(data, data_); // value_type data;
applyBooleanBinaryOp(data.begin(), data.end(), // std::swap(data, data_);
that.begin(), that.end(), boolean_op::BinaryCount<boolean_op::BinaryXor>()); // applyBooleanBinaryOp(data.begin(), data.end(),
return *this; // 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(); // polygon_90_set_data<coordinate_type>& operator^=(const polygon_90_set_data& that) {
that.sort(); // sort();
value_type data; // that.sort();
std::swap(data, data_); // value_type data;
applyBooleanBinaryOp(data.begin(), data.end(), // std::swap(data, data_);
that.begin(), that.end(), boolean_op::BinaryCount<boolean_op::BinaryAnd>()); // applyBooleanBinaryOp(data.begin(), data.end(),
return *this; // 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) { // }
insert(that); // polygon_90_set_data<coordinate_type>& operator&=(const polygon_90_set_data& that) {
return *this; // sort();
} // that.sort();
// value_type data;
// std::swap(data, data_);
// applyBooleanBinaryOp(data.begin(), data.end(),
// that.begin(), that.end(), boolean_op::BinaryCount<boolean_op::BinaryAnd>());
// return *this;
// }
// polygon_90_set_data<coordinate_type>& operator|=(const polygon_90_set_data& that) {
// insert(that);
// return *this;
// }
void clean() const { void clean() const {
sort(); sort();
@ -439,7 +449,7 @@ namespace boost { namespace polygon{
static bool remove_colinear_pts(std::vector<point_data<coordinate_type> >& poly) { static bool remove_colinear_pts(std::vector<point_data<coordinate_type> >& poly) {
bool found_colinear = true; bool found_colinear = true;
while(found_colinear) { while(found_colinear && poly.size() >= 4) {
found_colinear = false; found_colinear = false;
typename std::vector<point_data<coordinate_type> >::iterator itr = poly.begin(); typename std::vector<point_data<coordinate_type> >::iterator itr = poly.begin();
itr += poly.size() - 1; //get last element position itr += poly.size() - 1; //get last element position
@ -504,9 +514,9 @@ namespace boost { namespace polygon{
//polygon_45_data<coordinate_type> testpoly(*itrh); //polygon_45_data<coordinate_type> testpoly(*itrh);
if(resize_poly_down((*itrh).coords_, west_bloating, east_bloating, south_bloating, north_bloating)) { 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> > > 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), begin_input2(view_as<polygon_90_concept>(*itrh), LOW, orient_, true, true),
end_input(view_as<polygon_90_concept>(*itrh), HIGH, orient_, true, true); end_input2(view_as<polygon_90_concept>(*itrh), HIGH, orient_, true, true);
insert(begin_input, end_input, orient_); insert(begin_input2, end_input2, orient_);
//polygon_90_set_data<coordinate_type> pstesthole; //polygon_90_set_data<coordinate_type> pstesthole;
//pstesthole.insert(rect); //pstesthole.insert(rect);
//iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > > //iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > >
@ -569,9 +579,9 @@ namespace boost { namespace polygon{
//polygon_45_data<coordinate_type> testpoly(*itrh); //polygon_45_data<coordinate_type> testpoly(*itrh);
resize_poly_up((*itrh).coords_, -west_shrinking, -east_shrinking, -south_shrinking, -north_shrinking); 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> > > 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), begin_input2(view_as<polygon_90_concept>(*itrh), LOW, orient_, true, true),
end_input(view_as<polygon_90_concept>(*itrh), HIGH, orient_, true, true); end_input2(view_as<polygon_90_concept>(*itrh), HIGH, orient_, true, true);
insert(begin_input, end_input, orient_); insert(begin_input2, end_input2, orient_);
//polygon_90_set_data<coordinate_type> pstesthole; //polygon_90_set_data<coordinate_type> pstesthole;
//pstesthole.insert(rect); //pstesthole.insert(rect);
//iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > > //iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > >
@ -638,8 +648,7 @@ namespace boost { namespace polygon{
return shrink(0, shrinking, 0, 0); return shrink(0, shrinking, 0, 0);
if(dir == SOUTH) if(dir == SOUTH)
return shrink(0, 0, shrinking, 0); return shrink(0, 0, shrinking, 0);
if(dir == NORTH) return shrink(0, 0, 0, shrinking);
return shrink(0, 0, 0, shrinking);
} }
polygon_90_set_data& polygon_90_set_data&
@ -650,8 +659,7 @@ namespace boost { namespace polygon{
return bloat(0, shrinking, 0, 0); return bloat(0, shrinking, 0, 0);
if(dir == SOUTH) if(dir == SOUTH)
return bloat(0, 0, shrinking, 0); return bloat(0, 0, shrinking, 0);
if(dir == NORTH) return bloat(0, 0, 0, shrinking);
return bloat(0, 0, 0, shrinking);
} }
polygon_90_set_data& polygon_90_set_data&

View File

@ -1,6 +1,6 @@
/* /*
Copyright 2008 Intel Corporation Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License, Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt). http://www.boost.org/LICENSE_1_0.txt).
@ -22,7 +22,7 @@ namespace boost { namespace polygon {
template <typename T> template <typename T>
static inline T round_down(double val) { static inline T round_down(double val) {
T rounded_val = (T)(val); T rounded_val = (T)(val);
if(val < (double)rounded_val) if(val < (double)rounded_val)
--rounded_val; --rounded_val;
return rounded_val; return rounded_val;
} }
@ -57,11 +57,11 @@ namespace boost { namespace polygon {
} }
// copy constructor // copy constructor
inline polygon_set_data(const polygon_set_data& that) : inline polygon_set_data(const polygon_set_data& that) :
data_(that.data_), dirty_(that.dirty_), unsorted_(that.unsorted_), is_45_(that.is_45_) {} data_(that.data_), dirty_(that.dirty_), unsorted_(that.unsorted_), is_45_(that.is_45_) {}
// copy constructor // copy constructor
template <typename ltype, typename rtype, int op_type> template <typename ltype, typename rtype, int op_type>
inline polygon_set_data(const polygon_set_view<ltype, rtype, op_type>& that); inline polygon_set_data(const polygon_set_view<ltype, rtype, op_type>& that);
// destructor // destructor
@ -150,10 +150,10 @@ namespace boost { namespace polygon {
insert(polygon_object, is_hole, polygon_concept()); } insert(polygon_object, is_hole, polygon_concept()); }
template <typename polygon_with_holes_type> template <typename polygon_with_holes_type>
inline void insert(const polygon_with_holes_type& polygon_with_holes_object, bool is_hole, inline void insert(const polygon_with_holes_type& polygon_with_holes_object, bool is_hole,
polygon_with_holes_concept ) { polygon_with_holes_concept ) {
insert(polygon_with_holes_object, is_hole, polygon_concept()); insert(polygon_with_holes_object, is_hole, polygon_concept());
for(typename polygon_with_holes_traits<polygon_with_holes_type>::iterator_holes_type itr = for(typename polygon_with_holes_traits<polygon_with_holes_type>::iterator_holes_type itr =
begin_holes(polygon_with_holes_object); begin_holes(polygon_with_holes_object);
itr != end_holes(polygon_with_holes_object); ++itr) { itr != end_holes(polygon_with_holes_object); ++itr) {
insert(*itr, !is_hole, polygon_concept()); insert(*itr, !is_hole, polygon_concept());
@ -161,12 +161,12 @@ namespace boost { namespace polygon {
} }
template <typename polygon_with_holes_type> template <typename polygon_with_holes_type>
inline void insert(const polygon_with_holes_type& polygon_with_holes_object, bool is_hole, inline void insert(const polygon_with_holes_type& polygon_with_holes_object, bool is_hole,
polygon_45_with_holes_concept ) { polygon_45_with_holes_concept ) {
insert(polygon_with_holes_object, is_hole, polygon_with_holes_concept()); } insert(polygon_with_holes_object, is_hole, polygon_with_holes_concept()); }
template <typename polygon_with_holes_type> template <typename polygon_with_holes_type>
inline void insert(const polygon_with_holes_type& polygon_with_holes_object, bool is_hole, inline void insert(const polygon_with_holes_type& polygon_with_holes_object, bool is_hole,
polygon_90_with_holes_concept ) { polygon_90_with_holes_concept ) {
insert(polygon_with_holes_object, is_hole, polygon_with_holes_concept()); } insert(polygon_with_holes_object, is_hole, polygon_with_holes_concept()); }
@ -212,7 +212,7 @@ namespace boost { namespace polygon {
first_point = previous_point = current_point; first_point = previous_point = current_point;
} else { } else {
if(previous_point != current_point) { if(previous_point != current_point) {
element_type elem(edge_type(previous_point, current_point), element_type elem(edge_type(previous_point, current_point),
( previous_point.get(HORIZONTAL) == current_point.get(HORIZONTAL) ? -1 : 1) * multiplier); ( previous_point.get(HORIZONTAL) == current_point.get(HORIZONTAL) ? -1 : 1) * multiplier);
insert_clean(elem); insert_clean(elem);
} }
@ -222,7 +222,7 @@ namespace boost { namespace polygon {
current_point = first_point; current_point = first_point;
if(!first_iteration) { if(!first_iteration) {
if(previous_point != current_point) { if(previous_point != current_point) {
element_type elem(edge_type(previous_point, current_point), element_type elem(edge_type(previous_point, current_point),
( previous_point.get(HORIZONTAL) == current_point.get(HORIZONTAL) ? -1 : 1) * multiplier); ( previous_point.get(HORIZONTAL) == current_point.get(HORIZONTAL) ? -1 : 1) * multiplier);
insert_clean(elem); insert_clean(elem);
} }
@ -270,14 +270,14 @@ namespace boost { namespace polygon {
} }
} }
// equivalence operator // equivalence operator
inline bool operator==(const polygon_set_data& p) const { inline bool operator==(const polygon_set_data& p) const {
clean(); clean();
p.clean(); p.clean();
return data_ == p.data_; return data_ == p.data_;
} }
// inequivalence operator // inequivalence operator
inline bool operator!=(const polygon_set_data& p) const { inline bool operator!=(const polygon_set_data& p) const {
return !((*this) == p); return !((*this) == p);
} }
@ -335,7 +335,7 @@ namespace boost { namespace polygon {
} }
void set(const value_type& value) { void set(const value_type& value) {
data_ = value; data_ = value;
dirty_ = true; dirty_ = true;
unsorted_ = true; unsorted_ = true;
} }
@ -359,27 +359,10 @@ namespace boost { namespace polygon {
} }
inline polygon_set_data& inline polygon_set_data&
resize(coordinate_type resizing, bool corner_fill_arc = false, unsigned int num_circle_segments=0) { resize(coordinate_type resizing, bool corner_fill_arc = false, unsigned int num_circle_segments=0);
if(!corner_fill_arc) {
if(resizing < 0)
return shrink(-resizing);
if(resizing > 0)
return bloat(resizing);
return *this;
}
if(resizing == 0) return *this;
std::list<polygon_with_holes_data<coordinate_type> > pl;
get(pl);
clear();
for(typename std::list<polygon_with_holes_data<coordinate_type> >::iterator itr = pl.begin(); itr != pl.end(); ++itr) {
insert_with_resize(*itr, resizing, corner_fill_arc, num_circle_segments);
}
clean();
return *this;
}
template <typename transform_type> template <typename transform_type>
inline polygon_set_data& inline polygon_set_data&
transform(const transform_type& tr) { transform(const transform_type& tr) {
std::vector<polygon_with_holes_data<T> > polys; std::vector<polygon_with_holes_data<T> > polys;
get(polys); get(polys);
@ -393,7 +376,7 @@ namespace boost { namespace polygon {
return *this; return *this;
} }
inline polygon_set_data& inline polygon_set_data&
scale_up(typename coordinate_traits<coordinate_type>::unsigned_area_type factor) { scale_up(typename coordinate_traits<coordinate_type>::unsigned_area_type factor) {
for(typename value_type::iterator itr = data_.begin(); itr != data_.end(); ++itr) { for(typename value_type::iterator itr = data_.begin(); itr != data_.end(); ++itr) {
::boost::polygon::scale_up((*itr).first.first, factor); ::boost::polygon::scale_up((*itr).first.first, factor);
@ -401,8 +384,8 @@ namespace boost { namespace polygon {
} }
return *this; return *this;
} }
inline polygon_set_data& inline polygon_set_data&
scale_down(typename coordinate_traits<coordinate_type>::unsigned_area_type factor) { scale_down(typename coordinate_traits<coordinate_type>::unsigned_area_type factor) {
for(typename value_type::iterator itr = data_.begin(); itr != data_.end(); ++itr) { for(typename value_type::iterator itr = data_.begin(); itr != data_.end(); ++itr) {
::boost::polygon::scale_down((*itr).first.first, factor); ::boost::polygon::scale_down((*itr).first.first, factor);
@ -412,9 +395,9 @@ namespace boost { namespace polygon {
dirty_ = true; dirty_ = true;
return *this; return *this;
} }
template <typename scaling_type> template <typename scaling_type>
inline polygon_set_data& scale(polygon_set_data& polygon_set, inline polygon_set_data& scale(polygon_set_data& polygon_set,
const scaling_type& scaling) { const scaling_type& scaling) {
for(typename value_type::iterator itr = begin(); itr != end(); ++itr) { for(typename value_type::iterator itr = begin(); itr != end(); ++itr) {
::boost::polygon::scale((*itr).first.first, scaling); ::boost::polygon::scale((*itr).first.first, scaling);
@ -425,37 +408,53 @@ namespace boost { namespace polygon {
return *this; return *this;
} }
static inline void compute_offset_edge(point_data<coordinate_type>& pt1, point_data<coordinate_type>& pt2, static inline void compute_offset_edge(point_data<long double>& pt1, point_data<long double>& pt2,
const point_data<coordinate_type>& prev_pt, const point_data<long double>& prev_pt,
const point_data<coordinate_type>& current_pt, const point_data<long double>& current_pt,
coordinate_type distance, int multiplier) { long double distance, int multiplier) {
coordinate_type dx = current_pt.x() - prev_pt.x(); long double dx = current_pt.x() - prev_pt.x();
coordinate_type dy = current_pt.y() - prev_pt.y(); long double dy = current_pt.y() - prev_pt.y();
double ddx = (double)dx; long double edge_length = std::sqrt(dx*dx + dy*dy);
double ddy = (double)dy; long double dnx = dy;
double edge_length = std::sqrt(ddx*ddx + ddy*ddy); long double dny = -dx;
double dnx = dy; dnx = dnx * (long double)distance / edge_length;
double dny = -dx; dny = dny * (long double)distance / edge_length;
dnx = dnx * (double)distance / edge_length; pt1.x(prev_pt.x() + (long double)dnx * (long double)multiplier);
dny = dny * (double)distance / edge_length; pt2.x(current_pt.x() + (long double)dnx * (long double)multiplier);
dnx = std::floor(dnx+0.5); pt1.y(prev_pt.y() + (long double)dny * (long double)multiplier);
dny = std::floor(dny+0.5); pt2.y(current_pt.y() + (long double)dny * (long double)multiplier);
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, 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, const point_data<coordinate_type>& current_pt, const point_data<coordinate_type>& next_pt,
coordinate_type distance, coordinate_type multiplier) { 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); std::pair<point_data<long double>, point_data<long double> > he1, he2;
he1.first.x((long double)(prev_pt.x()));
he1.first.y((long double)(prev_pt.y()));
he1.second.x((long double)(current_pt.x()));
he1.second.y((long double)(current_pt.y()));
he2.first.x((long double)(current_pt.x()));
he2.first.y((long double)(current_pt.y()));
he2.second.x((long double)(next_pt.x()));
he2.second.y((long double)(next_pt.y()));
compute_offset_edge(he1.first, he1.second, prev_pt, current_pt, distance, multiplier); 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); compute_offset_edge(he2.first, he2.second, current_pt, next_pt, distance, multiplier);
typename scanline_base<coordinate_type>::compute_intersection_pack pack; typename scanline_base<long double>::compute_intersection_pack pack;
if(!pack.compute_lazy_intersection(pt, he1, he2, true, true)) { point_data<long double> rpt;
pt = he1.second; //colinear offset edges use shared point point_data<long double> bisectorpt((he1.second.x()+he2.first.x())/2,
(he1.second.y()+he2.first.y())/2);
point_data<long double> orig_pt((long double)pt.x(), (long double)pt.y());
if(euclidean_distance(bisectorpt, orig_pt) < distance/2) {
if(!pack.compute_lazy_intersection(rpt, he1, he2, true, false)) {
rpt = he1.second; //colinear offset edges use shared point
}
} else {
if(!pack.compute_lazy_intersection(rpt, he1, std::pair<point_data<long double>, point_data<long double> >(orig_pt, bisectorpt), true, false)) {
rpt = he1.second; //colinear offset edges use shared point
}
} }
pt.x((coordinate_type)(std::floor(rpt.x()+0.5)));
pt.y((coordinate_type)(std::floor(rpt.y()+0.5)));
} }
static void resize_poly_up(std::vector<point_data<coordinate_type> >& poly, coordinate_type distance, coordinate_type multiplier) { static void resize_poly_up(std::vector<point_data<coordinate_type> >& poly, coordinate_type distance, coordinate_type multiplier) {
@ -566,8 +565,8 @@ namespace boost { namespace polygon {
} }
template <typename geometry_type> template <typename geometry_type>
inline polygon_set_data& inline polygon_set_data&
insert_with_resize_dispatch(const geometry_type& poly, coordinate_type resizing, bool corner_fill_arc, unsigned int num_circle_segments, bool hole, insert_with_resize_dispatch(const geometry_type& poly, coordinate_type resizing, bool corner_fill_arc, unsigned int num_circle_segments, bool hole,
polygon_with_holes_concept tag) { polygon_with_holes_concept tag) {
insert_with_resize_dispatch(poly, resizing, corner_fill_arc, num_circle_segments, hole, polygon_concept()); insert_with_resize_dispatch(poly, resizing, corner_fill_arc, num_circle_segments, hole, polygon_concept());
for(typename polygon_with_holes_traits<geometry_type>::iterator_holes_type itr = for(typename polygon_with_holes_traits<geometry_type>::iterator_holes_type itr =
@ -579,14 +578,14 @@ namespace boost { namespace polygon {
} }
template <typename geometry_type> template <typename geometry_type>
inline polygon_set_data& inline polygon_set_data&
insert_with_resize_dispatch(const geometry_type& poly, coordinate_type resizing, bool corner_fill_arc, unsigned int num_circle_segments, bool hole, insert_with_resize_dispatch(const geometry_type& poly, coordinate_type resizing, bool corner_fill_arc, unsigned int num_circle_segments, bool hole,
polygon_concept tag) { polygon_concept tag) {
if (resizing==0) if (resizing==0)
return *this; return *this;
// one dimensional used to store CCW/CW flag // one dimensional used to store CCW/CW flag
//direction_1d wdir = winding(poly); //direction_1d wdir = winding(poly);
// LOW==CLOCKWISE just faster to type // LOW==CLOCKWISE just faster to type
@ -615,7 +614,7 @@ namespace boost { namespace polygon {
// for all corners // for all corners
polygon_set_data<T> sizingSet; polygon_set_data<T> sizingSet;
bool sizing_sign = resizing>0; bool sizing_sign = resizing<0;
bool prev_concave = true; bool prev_concave = true;
point_data<T> prev_point; point_data<T> prev_point;
//int iCtr=0; //int iCtr=0;
@ -631,7 +630,7 @@ namespace boost { namespace polygon {
point_data<coordinate_type> normal2( third->y()-second->y(), second->x()-third->x()); point_data<coordinate_type> normal2( third->y()-second->y(), second->x()-third->x());
double direction = normal1.x()*normal2.y()- normal2.x()*normal1.y(); double direction = normal1.x()*normal2.y()- normal2.x()*normal1.y();
bool convex = direction>0; bool convex = direction>0;
bool treat_as_concave = !convex; bool treat_as_concave = !convex;
if(sizing_sign) if(sizing_sign)
treat_as_concave = convex; treat_as_concave = convex;
@ -644,12 +643,12 @@ namespace boost { namespace polygon {
if (prev_concave) if (prev_concave)
//TODO missing round_down() //TODO missing round_down()
curr_prev = point_data<T>(first->x()+v.x(),first->y()+v.y()); curr_prev = point_data<T>(first->x()+v.x(),first->y()+v.y());
else else
curr_prev = prev_point; curr_prev = prev_point;
// around concave corners - insert rectangle // around concave corners - insert rectangle
// if previous corner is concave it's point info may be ignored // if previous corner is concave it's point info may be ignored
if ( treat_as_concave) { if ( treat_as_concave) {
std::vector<point_data<T> > pts; std::vector<point_data<T> > pts;
pts.push_back(point_data<T>(second->x()+v.x(),second->y()+v.y())); pts.push_back(point_data<T>(second->x()+v.x(),second->y()+v.y()));
@ -670,13 +669,13 @@ namespace boost { namespace polygon {
direction_1d winding; direction_1d winding;
winding = convex?COUNTERCLOCKWISE:CLOCKWISE; winding = convex?COUNTERCLOCKWISE:CLOCKWISE;
if (make_resizing_vertex_list(pts, curr_prev, prev_concave, *first, *second, *third, resizing if (make_resizing_vertex_list(pts, curr_prev, prev_concave, *first, *second, *third, resizing
, num_circle_segments, corner_fill_arc)) , num_circle_segments, corner_fill_arc))
{ {
if (first_pts.size()) { if (first_pts.size()) {
for (unsigned int i=0; i<pts.size(); i++) { for (unsigned int i=0; i<pts.size(); i++) {
sizingSet.insert_vertex_sequence(pts[i].begin(),pts[i].end(),winding,false); sizingSet.insert_vertex_sequence(pts[i].begin(),pts[i].end(),winding,false);
} }
} else { } else {
first_pts = pts[0]; first_pts = pts[0];
first_wdir = resize_wdir; first_wdir = resize_wdir;
@ -685,7 +684,7 @@ namespace boost { namespace polygon {
} }
} }
prev_point = curr_prev; prev_point = curr_prev;
} else { } else {
treat_as_concave = true; treat_as_concave = true;
} }
@ -708,7 +707,7 @@ namespace boost { namespace polygon {
first_pts[first_pts.size()-1]=prev_point; first_pts[first_pts.size()-1]=prev_point;
} }
sizingSet.insert_vertex_sequence(first_pts.begin(),first_pts.end(),first_wdir,false); sizingSet.insert_vertex_sequence(first_pts.begin(),first_pts.end(),first_wdir,false);
polygon_set_data<coordinate_type> tmp; polygon_set_data<coordinate_type> tmp;
//insert original shape //insert original shape
@ -722,7 +721,7 @@ namespace boost { namespace polygon {
inline polygon_set_data& inline polygon_set_data&
interact(const polygon_set_data& that); interact(const polygon_set_data& that);
inline bool downcast(polygon_45_set_data<coordinate_type>& result) const { inline bool downcast(polygon_45_set_data<coordinate_type>& result) const {
if(!is_45_) return false; if(!is_45_) return false;
@ -811,7 +810,7 @@ namespace boost { namespace polygon {
// } // }
template <typename T> template <typename T>
inline int make_resizing_vertex_list(std::vector<std::vector<point_data< T> > >& return_points, inline int make_resizing_vertex_list(std::vector<std::vector<point_data< T> > >& return_points,
point_data<T>& curr_prev, bool ignore_prev_point, point_data<T>& curr_prev, bool ignore_prev_point,
point_data< T> start, point_data<T> middle, point_data< T> end, point_data< T> start, point_data<T> middle, point_data< T> end,
double sizing_distance, unsigned int num_circle_segments, bool corner_fill_arc) { double sizing_distance, unsigned int num_circle_segments, bool corner_fill_arc) {
@ -844,7 +843,7 @@ namespace boost { namespace polygon {
int num = make_arc(return_points[return_points.size()-1],mid1_offset,mid2_offset,dmid,sizing_distance,num_circle_segments); int num = make_arc(return_points[return_points.size()-1],mid1_offset,mid2_offset,dmid,sizing_distance,num_circle_segments);
curr_prev = round_down<T>(mid2_offset); curr_prev = round_down<T>(mid2_offset);
return num; return num;
} }
std::pair<point_data<double>,point_data<double> > he1(start_offset,mid1_offset); std::pair<point_data<double>,point_data<double> > he1(start_offset,mid1_offset);
@ -882,21 +881,21 @@ namespace boost { namespace polygon {
// returnPoints will start with the first point after start // returnPoints will start with the first point after start
// returnPoints vector may be empty // returnPoints vector may be empty
template <typename T> template <typename T>
inline int make_arc(std::vector<point_data< T> >& return_points, inline int make_arc(std::vector<point_data< T> >& return_points,
point_data< double> start, point_data< double> end, point_data< double> start, point_data< double> end,
point_data< double> center, double r, unsigned int num_circle_segments) { point_data< double> center, double r, unsigned int num_circle_segments) {
const double our_pi=3.1415926535897932384626433832795028841971; const double our_pi=3.1415926535897932384626433832795028841971;
// derive start and end angles // derive start and end angles
double ps = atan2(start.y()-center.y(), start.x()-center.x()); double ps = atan2(start.y()-center.y(), start.x()-center.x());
double pe = atan2(end.y()-center.y(), end.x()-center.x()); double pe = atan2(end.y()-center.y(), end.x()-center.x());
if (ps < 0.0) if (ps < 0.0)
ps += 2.0 * our_pi; ps += 2.0 * our_pi;
if (pe <= 0.0) if (pe <= 0.0)
pe += 2.0 * our_pi; pe += 2.0 * our_pi;
if (ps >= 2.0 * our_pi) if (ps >= 2.0 * our_pi)
ps -= 2.0 * our_pi; ps -= 2.0 * our_pi;
while (pe <= ps) while (pe <= ps)
pe += 2.0 * our_pi; pe += 2.0 * our_pi;
double delta_angle = (2.0 * our_pi) / (double)num_circle_segments; double delta_angle = (2.0 * our_pi) / (double)num_circle_segments;
if ( start==end) // full circle? if ( start==end) // full circle?
@ -942,12 +941,12 @@ namespace boost { namespace polygon {
inline connectivity_extraction() : ce_(), nodeCount_(0) {} inline connectivity_extraction() : ce_(), nodeCount_(0) {}
inline connectivity_extraction(const connectivity_extraction& that) : ce_(that.ce_), inline connectivity_extraction(const connectivity_extraction& that) : ce_(that.ce_),
nodeCount_(that.nodeCount_) {} nodeCount_(that.nodeCount_) {}
inline connectivity_extraction& operator=(const connectivity_extraction& that) { inline connectivity_extraction& operator=(const connectivity_extraction& that) {
ce_ = that.ce_; ce_ = that.ce_;
nodeCount_ = that.nodeCount_; {} nodeCount_ = that.nodeCount_; {}
return *this; return *this;
} }
//insert a polygon set graph node, the value returned is the id of the graph node //insert a polygon set graph node, the value returned is the id of the graph node
inline unsigned int insert(const polygon_set_data<coordinate_type>& ps) { inline unsigned int insert(const polygon_set_data<coordinate_type>& ps) {
ps.clean(); ps.clean();
@ -960,7 +959,7 @@ namespace boost { namespace polygon {
ps.insert(geoObj); ps.insert(geoObj);
return insert(ps); return insert(ps);
} }
//extract connectivity and store the edges in the graph //extract connectivity and store the edges in the graph
//graph must be indexable by graph node id and the indexed value must be a std::set of //graph must be indexable by graph node id and the indexed value must be a std::set of
//graph node id //graph node id
@ -996,5 +995,6 @@ namespace boost { namespace polygon {
#include "detail/polygon_set_view.hpp" #include "detail/polygon_set_view.hpp"
#include "polygon_set_concept.hpp" #include "polygon_set_concept.hpp"
#include "detail/minkowski.hpp"
#endif #endif

View File

@ -29,6 +29,7 @@ ZONE_CONTAINER::ZONE_CONTAINER( BOARD* parent ) :
m_NetCode = -1; // Net number for fast comparisons m_NetCode = -1; // Net number for fast comparisons
m_CornerSelection = -1; m_CornerSelection = -1;
m_IsFilled = false; // fill status : true when the zone is filled m_IsFilled = false; // fill status : true when the zone is filled
m_FillMode = 0; // How to fill areas: 0 = use filled polygons, != 0 fill with segments
utility = 0; // flags used in polygon calculations utility = 0; // flags used in polygon calculations
utility2 = 0; // flags used in polygon calculations utility2 = 0; // flags used in polygon calculations
m_Poly = new CPolyLine(); // Outlines m_Poly = new CPolyLine(); // Outlines
@ -903,6 +904,8 @@ bool ZONE_CONTAINER::HitTestFilledArea( const wxPoint& aRefPos )
inside = true; inside = true;
break; break;
} }
// Prepare test of next area which starts after the current indexend (if exists)
indexstart = indexend+1;
} }
} }
return inside; return inside;

View File

@ -41,7 +41,7 @@ public:
int m_CornerSelection; // For corner moving, corner index to drag, or -1 if no selection int m_CornerSelection; // For corner moving, corner index to drag, or -1 if no selection
int m_ZoneClearance; // clearance value int m_ZoneClearance; // clearance value
int m_ZoneMinThickness; // Min thickness value in filled areas int m_ZoneMinThickness; // Min thickness value in filled areas
int m_FillMode; // How to fillingareas: 0 = use polygonal areas , != 0 fill with segments int m_FillMode; // How to fill areas: 0 = use filled polygons, != 0 fill with segments
int m_ArcToSegmentsCount; // number of segments to convert a circle to a polygon int m_ArcToSegmentsCount; // number of segments to convert a circle to a polygon
// (uses ARC_APPROX_SEGMENTS_COUNT_LOW_DEF or ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF) // (uses ARC_APPROX_SEGMENTS_COUNT_LOW_DEF or ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF)
int m_PadOption; // int m_PadOption; //

View File

@ -24,7 +24,7 @@
ZONE_SETTING::ZONE_SETTING( void ) ZONE_SETTING::ZONE_SETTING( void )
{ {
m_FillMode = 1; // Mode for filling zone : 1 use segments, 0 use polygons m_FillMode = 0; // Mode for filling zone : 1 use segments, 0 use polygons
m_ZoneClearance = 200; // Clearance value m_ZoneClearance = 200; // Clearance value
m_ZoneMinThickness = 100; // Min thickness value in filled areas m_ZoneMinThickness = 100; // Min thickness value in filled areas
m_NetcodeSelection = 0; // Net code selection for the current zone m_NetcodeSelection = 0; // Net code selection for the current zone

View File

@ -19,9 +19,10 @@
#include "dialog_copper_zones.h" #include "dialog_copper_zones.h"
wxString dialog_copper_zone::m_netNameShowFilter( wxT( "*" ) ); /* the filter to show nets (default * "*"). /* the filter to show nets (default * "*").
* static to keep this pattern for an entire pcbnew session * static to keep this pattern for an entire pcbnew session
*/ */
wxString dialog_copper_zone::m_netNameShowFilter( wxT( "*" ) );
/************************************************************************************************/ /************************************************************************************************/
dialog_copper_zone::dialog_copper_zone( WinEDA_PcbFrame* parent, ZONE_SETTING* zone_setting ) : dialog_copper_zone::dialog_copper_zone( WinEDA_PcbFrame* parent, ZONE_SETTING* zone_setting ) :
@ -31,8 +32,10 @@ dialog_copper_zone::dialog_copper_zone( WinEDA_PcbFrame* parent, ZONE_SETTING* z
m_Parent = parent; m_Parent = parent;
m_Config = wxGetApp().m_EDA_Config; m_Config = wxGetApp().m_EDA_Config;
m_Zone_Setting = zone_setting; m_Zone_Setting = zone_setting;
m_NetSorting = 1; // 0 = alphabetic sort, 1 = pad count sort, and filtering net names m_NetSortingByPadCount = true; /* false = alphabetic sort.
m_OnExitCode = ZONE_ABORT; * true = pad count sort.
*/
m_OnExitCode = ZONE_ABORT;
SetReturnCode( ZONE_ABORT ); // Will be changed on buttons click SetReturnCode( ZONE_ABORT ); // Will be changed on buttons click
@ -156,7 +159,7 @@ void dialog_copper_zone::initDialog()
else else
m_NetDisplayOption->SetSelection( 1 ); m_NetDisplayOption->SetSelection( 1 );
m_ShowNetNameFilter->SetValue(m_netNameShowFilter); m_ShowNetNameFilter->SetValue( m_netNameShowFilter );
initListNetsParams(); initListNetsParams();
// Build list of nets: // Build list of nets:
@ -392,7 +395,7 @@ void dialog_copper_zone::OnPadsInZoneClick( wxCommandEvent& event )
} }
/** init m_NetSorting and m_NetFiltering values /** init m_NetSortingByPadCount and m_NetFiltering values
* according to m_NetDisplayOption selection * according to m_NetDisplayOption selection
*/ */
void dialog_copper_zone::initListNetsParams() void dialog_copper_zone::initListNetsParams()
@ -400,22 +403,22 @@ void dialog_copper_zone::initListNetsParams()
switch( m_NetDisplayOption->GetSelection() ) switch( m_NetDisplayOption->GetSelection() )
{ {
case 0: case 0:
m_NetSorting = true; m_NetSortingByPadCount = false;
m_NetFiltering = false; m_NetFiltering = false;
break; break;
case 1: case 1:
m_NetSorting = false; m_NetSortingByPadCount = true;
m_NetFiltering = false; m_NetFiltering = false;
break; break;
case 2: case 2:
m_NetSorting = true; m_NetSortingByPadCount = false;
m_NetFiltering = true; m_NetFiltering = true;
break; break;
case 3: case 3:
m_NetSorting = false; m_NetSortingByPadCount = true;
m_NetFiltering = true; m_NetFiltering = true;
break; break;
} }
@ -429,6 +432,7 @@ void dialog_copper_zone::initListNetsParams()
void dialog_copper_zone::OnRunFiltersButtonClick( wxCommandEvent& event ) void dialog_copper_zone::OnRunFiltersButtonClick( wxCommandEvent& event )
{ {
m_netNameShowFilter = m_ShowNetNameFilter->GetValue(); m_netNameShowFilter = m_ShowNetNameFilter->GetValue();
// Ensure filtered option for nets: // Ensure filtered option for nets:
if( m_NetDisplayOption->GetSelection() == 0 ) if( m_NetDisplayOption->GetSelection() == 0 )
m_NetDisplayOption->SetSelection( 2 ); m_NetDisplayOption->SetSelection( 2 );
@ -443,8 +447,7 @@ void dialog_copper_zone::buildAvailableListOfNets()
{ {
wxArrayString listNetName; wxArrayString listNetName;
m_Parent->GetBoard()->ReturnSortedNetnamesList( m_Parent->GetBoard()->ReturnSortedNetnamesList( listNetName, m_NetSortingByPadCount );
listNetName, m_NetSorting == 0 ? false : true );
if( m_NetFiltering ) if( m_NetFiltering )
{ {

View File

@ -18,7 +18,9 @@ private:
*/ */
ZONE_SETTING* m_Zone_Setting; ZONE_SETTING* m_Zone_Setting;
long m_NetSorting; bool m_NetSortingByPadCount; /* false = alphabetic sort.
* true = pad count sort.
*/
long m_NetFiltering; long m_NetFiltering;
int m_LayerId[LAYER_COUNT]; // Handle the real layer number from layer name position in m_LayerSelectionCtrl int m_LayerId[LAYER_COUNT]; // Handle the real layer number from layer name position in m_LayerSelectionCtrl
static wxString m_netNameShowFilter; /* the filter to show nets (default * "*"). static wxString m_netNameShowFilter; /* the filter to show nets (default * "*").

View File

@ -486,7 +486,6 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
booleng = new Bool_Engine(); booleng = new Bool_Engine();
ArmBoolEng( booleng, true ); ArmBoolEng( booleng, true );
cornerBufferPolysToSubstract.clear(); cornerBufferPolysToSubstract.clear();
// Test thermal stubs connections and add polygons to remove unconnected stubs. // Test thermal stubs connections and add polygons to remove unconnected stubs.
for( MODULE* module = aPcb->m_Modules; module; module = module->Next() ) for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
{ {
@ -535,62 +534,60 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
// translate point // translate point
ptTest[i] += pad->ReturnShapePos(); ptTest[i] += pad->ReturnShapePos();
bool inside = HitTestFilledArea( ptTest[i] ); if( HitTestFilledArea( ptTest[i] ) )
continue;
if( inside == false ) // polygon buffer
std::vector<wxPoint> corners_buffer;
// polygons are rectangles with width of copper bridge value
// contour line width has to be taken into calculation to avoid "thermal stub bleed"
const int iDTRC =
( m_ThermalReliefCopperBridgeValue - m_ZoneMinThickness ) / 2;
switch( i )
{ {
// polygon buffer case 0:
std::vector<wxPoint> corners_buffer; corners_buffer.push_back( wxPoint( -iDTRC, dy ) );
corners_buffer.push_back( wxPoint( +iDTRC, dy ) );
corners_buffer.push_back( wxPoint( +iDTRC, iDTRC ) );
corners_buffer.push_back( wxPoint( -iDTRC, iDTRC ) );
break;
// polygons are rectangles with width of copper bridge value case 1:
// contour line width has to be taken into calculation to avoid "thermal stub bleed" corners_buffer.push_back( wxPoint( -iDTRC, -dy ) );
const int iDTRC = corners_buffer.push_back( wxPoint( +iDTRC, -dy ) );
( m_ThermalReliefCopperBridgeValue - m_ZoneMinThickness ) / 2; corners_buffer.push_back( wxPoint( +iDTRC, -iDTRC ) );
corners_buffer.push_back( wxPoint( -iDTRC, -iDTRC ) );
break;
switch( i ) case 2:
{ corners_buffer.push_back( wxPoint( dx, -iDTRC ) );
case 0: corners_buffer.push_back( wxPoint( dx, iDTRC ) );
corners_buffer.push_back( wxPoint( -iDTRC, dy ) ); corners_buffer.push_back( wxPoint( +iDTRC, iDTRC ) );
corners_buffer.push_back( wxPoint( +iDTRC, dy ) ); corners_buffer.push_back( wxPoint( +iDTRC, -iDTRC ) );
corners_buffer.push_back( wxPoint( +iDTRC, iDTRC ) ); break;
corners_buffer.push_back( wxPoint( -iDTRC, iDTRC ) );
break;
case 1: case 3:
corners_buffer.push_back( wxPoint( -iDTRC, -dy ) ); corners_buffer.push_back( wxPoint( -dx, -iDTRC ) );
corners_buffer.push_back( wxPoint( +iDTRC, -dy ) ); corners_buffer.push_back( wxPoint( -dx, iDTRC ) );
corners_buffer.push_back( wxPoint( +iDTRC, -iDTRC ) ); corners_buffer.push_back( wxPoint( -iDTRC, iDTRC ) );
corners_buffer.push_back( wxPoint( -iDTRC, -iDTRC ) ); corners_buffer.push_back( wxPoint( -iDTRC, -iDTRC ) );
break; break;
}
case 2:
corners_buffer.push_back( wxPoint( dx, -iDTRC ) );
corners_buffer.push_back( wxPoint( dx, iDTRC ) );
corners_buffer.push_back( wxPoint( +iDTRC, iDTRC ) );
corners_buffer.push_back( wxPoint( +iDTRC, -iDTRC ) );
break;
case 3:
corners_buffer.push_back( wxPoint( -dx, -iDTRC ) );
corners_buffer.push_back( wxPoint( -dx, iDTRC ) );
corners_buffer.push_back( wxPoint( -iDTRC, iDTRC ) );
corners_buffer.push_back( wxPoint( -iDTRC, -iDTRC ) );
break;
}
// add computed polygon to list // add computed polygon to list
for( unsigned ic = 0; ic < corners_buffer.size(); ic++ ) for( unsigned ic = 0; ic < corners_buffer.size(); ic++ )
{ {
wxPoint cpos = corners_buffer[ic]; wxPoint cpos = corners_buffer[ic];
RotatePoint( &cpos, fAngle ); // Rotate according to module orientation RotatePoint( &cpos, fAngle ); // Rotate according to module orientation
cpos += pad->ReturnShapePos(); // Shift origin to position cpos += pad->ReturnShapePos(); // Shift origin to position
CPolyPt corner; CPolyPt corner;
corner.x = cpos.x; corner.x = cpos.x;
corner.y = cpos.y; corner.y = cpos.y;
corner.end_contour = ( ic < (corners_buffer.size() - 1) ) ? 0 : 1; corner.end_contour = ( ic < (corners_buffer.size() - 1) ) ? 0 : 1;
cornerBufferPolysToSubstract.push_back( corner ); cornerBufferPolysToSubstract.push_back( corner );
}
} }
} }
} }

View File

@ -83,8 +83,8 @@ bool TestPointInsidePolygon( std::vector <CPolyPt> aPolysList,
// with the horizontal line at the new refy position // with the horizontal line at the new refy position
// the line slope = seg_endY/seg_endX; // the line slope = seg_endY/seg_endX;
// and the x pos relative to the new origin is intersec_x = refy/slope // and the x pos relative to the new origin is intersec_x = refy/slope
// Note: because horizontal segments are skipped, 1/slope exists (seg_end_y never == O) // Note: because horizontal segments are skipped, 1/slope exists (seg_endY never == O)
double intersec_x = newrefy * seg_endX / seg_endY; double intersec_x = (newrefy * seg_endX) / seg_endY;
if( newrefx < intersec_x ) // Intersection found with the semi-infinite line from refx to infinite if( newrefx < intersec_x ) // Intersection found with the semi-infinite line from refx to infinite
count++; count++;
} }
@ -101,7 +101,6 @@ bool TestPointInsidePolygon( wxPoint *aPolysList, int aCount,wxPoint aRefPoint )
// count intersection points to right of (refx,refy). If odd number, point (refx,refy) is inside polyline // count intersection points to right of (refx,refy). If odd number, point (refx,refy) is inside polyline
int ics, ice; int ics, ice;
int count = 0; int count = 0;
// find all intersection points of line with polyline sides // find all intersection points of line with polyline sides
for( ics = 0, ice = aCount-1; ics < aCount; ice = ics++ ) for( ics = 0, ice = aCount-1; ics < aCount; ice = ics++ )
{ {
@ -138,8 +137,8 @@ bool TestPointInsidePolygon( wxPoint *aPolysList, int aCount,wxPoint aRefPoint )
// with the horizontal line at the new refy position // with the horizontal line at the new refy position
// the line slope = seg_endY/seg_endX; // the line slope = seg_endY/seg_endX;
// and the x pos relative to the new origin is intersec_x = refy/slope // and the x pos relative to the new origin is intersec_x = refy/slope
// Note: because horizontal segments are skipped, 1/slope exists (seg_end_y never == O) // Note: because horizontal segments are skipped, 1/slope exists (seg_endY never == O)
double intersec_x = newrefy * seg_endX / seg_endY; double intersec_x = (newrefy * seg_endX) / seg_endY;
if( newrefx < intersec_x ) // Intersection found with the semi-infinite line from refx to infinite if( newrefx < intersec_x ) // Intersection found with the semi-infinite line from refx to infinite
count++; count++;
} }