mirror of https://github.com/KLayout/klayout.git
Implemented #2 ([Simple]Polygon#extract_rad feature for Ruby/Python)
This commit is contained in:
parent
85f048dd6d
commit
ae986d3234
|
|
@ -778,21 +778,22 @@ smooth (const db::Polygon &polygon, db::Coord d)
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// Rounding tools
|
// Rounding tools
|
||||||
|
|
||||||
bool
|
template <class C>
|
||||||
extract_rad_from_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon_contour_iterator to, double &rinner, double &router, unsigned int &n, std::vector <db::Point> *new_pts, bool fallback)
|
static bool
|
||||||
|
do_extract_rad_from_contour (typename db::polygon<C>::polygon_contour_iterator from, typename db::polygon<C>::polygon_contour_iterator to, double &rinner, double &router, unsigned int &n, std::vector <db::point<C> > *new_pts, bool fallback)
|
||||||
{
|
{
|
||||||
if (from == to) {
|
if (from == to) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
db::Polygon::polygon_contour_iterator p0 = from;
|
typename db::polygon<C>::polygon_contour_iterator p0 = from;
|
||||||
|
|
||||||
db::Polygon::polygon_contour_iterator p1 = p0;
|
typename db::polygon<C>::polygon_contour_iterator p1 = p0;
|
||||||
++p1;
|
++p1;
|
||||||
if (p1 == to) {
|
if (p1 == to) {
|
||||||
p1 = from;
|
p1 = from;
|
||||||
}
|
}
|
||||||
db::Polygon::polygon_contour_iterator p2 = p1;
|
typename db::polygon<C>::polygon_contour_iterator p2 = p1;
|
||||||
|
|
||||||
const double cos_thr = 0.8;
|
const double cos_thr = 0.8;
|
||||||
const double circle_segment_thr = 2.5;
|
const double circle_segment_thr = 2.5;
|
||||||
|
|
@ -810,8 +811,8 @@ extract_rad_from_contour (db::Polygon::polygon_contour_iterator from, db::Polygo
|
||||||
p2 = from;
|
p2 = from;
|
||||||
}
|
}
|
||||||
|
|
||||||
db::Edge ep (*p0, *p1);
|
db::edge<C> ep (*p0, *p1);
|
||||||
db::Edge e (*p1, *p2);
|
db::edge<C> e (*p1, *p2);
|
||||||
|
|
||||||
bool inner = (db::vprod_sign (ep, e) > 0);
|
bool inner = (db::vprod_sign (ep, e) > 0);
|
||||||
double &ls = inner ? ls_inner : ls_outer;
|
double &ls = inner ? ls_inner : ls_outer;
|
||||||
|
|
@ -841,7 +842,7 @@ extract_rad_from_contour (db::Polygon::polygon_contour_iterator from, db::Polygo
|
||||||
// search for the first circle segment (where cos(a) > cos_thr)
|
// search for the first circle segment (where cos(a) > cos_thr)
|
||||||
// or a long segment is followed by a short one or the curvature changes.
|
// or a long segment is followed by a short one or the curvature changes.
|
||||||
|
|
||||||
db::Polygon::polygon_contour_iterator pm1 = from;
|
typename db::polygon<C>::polygon_contour_iterator pm1 = from;
|
||||||
|
|
||||||
p0 = pm1;
|
p0 = pm1;
|
||||||
++p0;
|
++p0;
|
||||||
|
|
@ -861,7 +862,7 @@ extract_rad_from_contour (db::Polygon::polygon_contour_iterator from, db::Polygo
|
||||||
p2 = from;
|
p2 = from;
|
||||||
}
|
}
|
||||||
|
|
||||||
db::Polygon::polygon_contour_iterator p3 = p2;
|
typename db::polygon<C>::polygon_contour_iterator p3 = p2;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
|
|
@ -870,10 +871,10 @@ extract_rad_from_contour (db::Polygon::polygon_contour_iterator from, db::Polygo
|
||||||
p3 = from;
|
p3 = from;
|
||||||
}
|
}
|
||||||
|
|
||||||
db::Edge em (*pm1, *p0);
|
db::edge<C> em (*pm1, *p0);
|
||||||
db::Edge ep (*p0, *p1);
|
db::edge<C> ep (*p0, *p1);
|
||||||
db::Edge e (*p1, *p2);
|
db::edge<C> e (*p1, *p2);
|
||||||
db::Edge en (*p2, *p3);
|
db::edge<C> en (*p2, *p3);
|
||||||
|
|
||||||
bool first_or_last = fallback || (e.double_length () > circle_segment_thr * ep.double_length () || ep.double_length () > circle_segment_thr * e.double_length ())
|
bool first_or_last = fallback || (e.double_length () > circle_segment_thr * ep.double_length () || ep.double_length () > circle_segment_thr * e.double_length ())
|
||||||
|| (db::vprod_sign (em, ep) * db::vprod_sign (ep, e) < 0 || db::vprod_sign (ep, e) * db::vprod_sign (e, en) < 0);
|
|| (db::vprod_sign (em, ep) * db::vprod_sign (ep, e) < 0 || db::vprod_sign (ep, e) * db::vprod_sign (e, en) < 0);
|
||||||
|
|
@ -907,11 +908,11 @@ extract_rad_from_contour (db::Polygon::polygon_contour_iterator from, db::Polygo
|
||||||
new_pts->clear ();
|
new_pts->clear ();
|
||||||
}
|
}
|
||||||
|
|
||||||
db::Polygon::polygon_contour_iterator pfirst = p0;
|
typename db::polygon<C>::polygon_contour_iterator pfirst = p0;
|
||||||
bool in_corner = false;
|
bool in_corner = false;
|
||||||
double ls_corner = 0.0;
|
double ls_corner = 0.0;
|
||||||
db::Edge elast;
|
db::edge<C> elast;
|
||||||
db::Polygon::polygon_contour_iterator plast;
|
typename db::polygon<C>::polygon_contour_iterator plast;
|
||||||
double asum = 0.0;
|
double asum = 0.0;
|
||||||
unsigned int nseg = 0;
|
unsigned int nseg = 0;
|
||||||
|
|
||||||
|
|
@ -931,10 +932,10 @@ extract_rad_from_contour (db::Polygon::polygon_contour_iterator from, db::Polygo
|
||||||
p3 = from;
|
p3 = from;
|
||||||
}
|
}
|
||||||
|
|
||||||
db::Edge em (*pm1, *p0);
|
db::edge<C> em (*pm1, *p0);
|
||||||
db::Edge ep (*p0, *p1);
|
db::edge<C> ep (*p0, *p1);
|
||||||
db::Edge e (*p1, *p2);
|
db::edge<C> e (*p1, *p2);
|
||||||
db::Edge en (*p2, *p3);
|
db::edge<C> en (*p2, *p3);
|
||||||
|
|
||||||
// Heuristic detection of a new circle segment:
|
// Heuristic detection of a new circle segment:
|
||||||
// In fallback mode vertical or horizontal edges separate circle segments.
|
// In fallback mode vertical or horizontal edges separate circle segments.
|
||||||
|
|
@ -956,7 +957,7 @@ extract_rad_from_contour (db::Polygon::polygon_contour_iterator from, db::Polygo
|
||||||
if (! in_corner) {
|
if (! in_corner) {
|
||||||
elast = ep;
|
elast = ep;
|
||||||
plast = p1;
|
plast = p1;
|
||||||
asum = db::vprod (*p1 - db::Point (), *p2 - db::Point ());
|
asum = db::vprod (*p1 - db::point<C> (), *p2 - db::point<C> ());
|
||||||
nseg = 1;
|
nseg = 1;
|
||||||
ls_corner = ls;
|
ls_corner = ls;
|
||||||
}
|
}
|
||||||
|
|
@ -967,13 +968,13 @@ extract_rad_from_contour (db::Polygon::polygon_contour_iterator from, db::Polygo
|
||||||
|
|
||||||
if (in_corner) {
|
if (in_corner) {
|
||||||
|
|
||||||
std::pair<bool, db::Point> cp = elast.cut_point (e);
|
std::pair<bool, db::point<C> > cp = elast.cut_point (e);
|
||||||
if (! cp.first) {
|
if (! cp.first) {
|
||||||
|
|
||||||
// We have a full 180 degree bend without a stop (actually two corners).
|
// We have a full 180 degree bend without a stop (actually two corners).
|
||||||
// Use the segment in between that is perpendicular to the start and end segment as stop edge.
|
// Use the segment in between that is perpendicular to the start and end segment as stop edge.
|
||||||
db::Polygon::polygon_contour_iterator pp1 = plast;
|
typename db::polygon<C>::polygon_contour_iterator pp1 = plast;
|
||||||
db::Polygon::polygon_contour_iterator pp2 = pp1;
|
typename db::polygon<C>::polygon_contour_iterator pp2 = pp1;
|
||||||
double asum_part = 0.0;
|
double asum_part = 0.0;
|
||||||
unsigned int nseg_part = 0;
|
unsigned int nseg_part = 0;
|
||||||
|
|
||||||
|
|
@ -984,12 +985,12 @@ extract_rad_from_contour (db::Polygon::polygon_contour_iterator from, db::Polygo
|
||||||
pp2 = from;
|
pp2 = from;
|
||||||
}
|
}
|
||||||
|
|
||||||
e = db::Edge (*pp1, *pp2);
|
e = db::edge<C> (*pp1, *pp2);
|
||||||
if (db::sprod_sign (elast, e) == 0) {
|
if (db::sprod_sign (elast, e) == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
asum_part += db::vprod (*pp1 - db::Point (), *pp2 - db::Point ());
|
asum_part += db::vprod (*pp1 - db::point<C> (), *pp2 - db::point<C> ());
|
||||||
++nseg_part;
|
++nseg_part;
|
||||||
|
|
||||||
pp1 = pp2;
|
pp1 = pp2;
|
||||||
|
|
@ -1008,11 +1009,11 @@ extract_rad_from_contour (db::Polygon::polygon_contour_iterator from, db::Polygo
|
||||||
++nseg_part;
|
++nseg_part;
|
||||||
|
|
||||||
asum -= asum_part;
|
asum -= asum_part;
|
||||||
asum -= db::vprod (e.p1 () - db::Point (), e.p2 () - db::Point ());
|
asum -= db::vprod (e.p1 () - db::point<C> (), e.p2 () - db::point<C> ());
|
||||||
nseg -= nseg_part;
|
nseg -= nseg_part;
|
||||||
|
|
||||||
asum_part += db::vprod (cp.second - db::Point (), elast.p2 () - db::Point ());
|
asum_part += db::vprod (cp.second - db::point<C> (), elast.p2 () - db::point<C> ());
|
||||||
asum_part += db::vprod (*pp1 - db::Point (), cp.second - db::Point ());
|
asum_part += db::vprod (*pp1 - db::point<C> (), cp.second - db::point<C> ());
|
||||||
|
|
||||||
double sin_atot = db::vprod (elast, e);
|
double sin_atot = db::vprod (elast, e);
|
||||||
double cos_atot = db::sprod (elast, e);
|
double cos_atot = db::sprod (elast, e);
|
||||||
|
|
@ -1034,7 +1035,7 @@ extract_rad_from_contour (db::Polygon::polygon_contour_iterator from, db::Polygo
|
||||||
|
|
||||||
elast = e;
|
elast = e;
|
||||||
|
|
||||||
e = db::Edge (*p1, *p2);
|
e = db::edge<C> (*p1, *p2);
|
||||||
cp = elast.cut_point (e);
|
cp = elast.cut_point (e);
|
||||||
if (! cp.first) {
|
if (! cp.first) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1046,8 +1047,8 @@ extract_rad_from_contour (db::Polygon::polygon_contour_iterator from, db::Polygo
|
||||||
new_pts->push_back (cp.second);
|
new_pts->push_back (cp.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
asum += db::vprod (cp.second - db::Point (), elast.p2 () - db::Point ());
|
asum += db::vprod (cp.second - db::point<C> (), elast.p2 () - db::point<C> ());
|
||||||
asum += db::vprod (*p1 - db::Point (), cp.second - db::Point ());
|
asum += db::vprod (*p1 - db::point<C> (), cp.second - db::point<C> ());
|
||||||
|
|
||||||
++nseg;
|
++nseg;
|
||||||
|
|
||||||
|
|
@ -1074,7 +1075,7 @@ extract_rad_from_contour (db::Polygon::polygon_contour_iterator from, db::Polygo
|
||||||
|
|
||||||
} else if (in_corner) {
|
} else if (in_corner) {
|
||||||
|
|
||||||
asum += db::vprod (*p1 - db::Point (), *p2 - db::Point ());
|
asum += db::vprod (*p1 - db::point<C> (), *p2 - db::point<C> ());
|
||||||
++nseg;
|
++nseg;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1113,44 +1114,57 @@ extract_rad_from_contour (db::Polygon::polygon_contour_iterator from, db::Polygo
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
extract_rad (const db::Polygon &polygon, double &rinner, double &router, unsigned int &n, db::Polygon *new_polygon)
|
extract_rad_from_contour (typename db::Polygon::polygon_contour_iterator from, typename db::Polygon::polygon_contour_iterator to, double &rinner, double &router, unsigned int &n, std::vector <db::Point> *new_pts, bool fallback)
|
||||||
|
{
|
||||||
|
return do_extract_rad_from_contour (from, to, rinner, router, n, new_pts, fallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
extract_rad_from_contour (typename db::DPolygon::polygon_contour_iterator from, typename db::DPolygon::polygon_contour_iterator to, double &rinner, double &router, unsigned int &n, std::vector <db::DPoint> *new_pts, bool fallback)
|
||||||
|
{
|
||||||
|
return do_extract_rad_from_contour (from, to, rinner, router, n, new_pts, fallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class C>
|
||||||
|
static bool
|
||||||
|
do_extract_rad (const db::polygon<C> &polygon, double &rinner, double &router, unsigned int &n, db::polygon<C> *new_polygon)
|
||||||
{
|
{
|
||||||
if (new_polygon) {
|
if (new_polygon) {
|
||||||
|
|
||||||
std::vector <db::Point> new_pts;
|
std::vector <db::point<C> > new_pts;
|
||||||
|
|
||||||
if (! extract_rad_from_contour (polygon.begin_hull (), polygon.end_hull (), rinner, router, n, &new_pts) &&
|
if (! do_extract_rad_from_contour (polygon.begin_hull (), polygon.end_hull (), rinner, router, n, &new_pts, false) &&
|
||||||
! extract_rad_from_contour (polygon.begin_hull (), polygon.end_hull (), rinner, router, n, &new_pts, true)) {
|
! do_extract_rad_from_contour (polygon.begin_hull (), polygon.end_hull (), rinner, router, n, &new_pts, true)) {
|
||||||
// no radius found
|
// no radius found
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
new_polygon->assign_hull (new_pts.begin (), new_pts.end (), true /*compress*/);
|
new_polygon->assign_hull (new_pts.begin (), new_pts.end ());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int h = 0; h < polygon.holes (); ++h) {
|
for (unsigned int h = 0; h < polygon.holes (); ++h) {
|
||||||
|
|
||||||
new_pts.clear ();
|
new_pts.clear ();
|
||||||
if (! extract_rad_from_contour (polygon.begin_hole (h), polygon.end_hole (h), rinner, router, n, &new_pts) &&
|
if (! do_extract_rad_from_contour (polygon.begin_hole (h), polygon.end_hole (h), rinner, router, n, &new_pts, false) &&
|
||||||
! extract_rad_from_contour (polygon.begin_hole (h), polygon.end_hole (h), rinner, router, n, &new_pts, true)) {
|
! do_extract_rad_from_contour (polygon.begin_hole (h), polygon.end_hole (h), rinner, router, n, &new_pts, true)) {
|
||||||
// no radius found
|
// no radius found
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
new_polygon->insert_hole (new_pts.begin (), new_pts.end (), true /*compress*/);
|
new_polygon->insert_hole (new_pts.begin (), new_pts.end ());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (! extract_rad_from_contour (polygon.begin_hull (), polygon.end_hull (), rinner, router, n, 0)) {
|
if (! do_extract_rad_from_contour (polygon.begin_hull (), polygon.end_hull (), rinner, router, n, (std::vector<db::point<C> > *) 0, false)) {
|
||||||
if (! extract_rad_from_contour (polygon.begin_hull (), polygon.end_hull (), rinner, router, n, 0, true)) {
|
if (! do_extract_rad_from_contour (polygon.begin_hull (), polygon.end_hull (), rinner, router, n, (std::vector<db::point<C> > *) 0, true)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int h = 0; h < polygon.holes (); ++h) {
|
for (unsigned int h = 0; h < polygon.holes (); ++h) {
|
||||||
if (! extract_rad_from_contour (polygon.begin_hole (h), polygon.end_hole (h), rinner, router, n, 0)) {
|
if (! do_extract_rad_from_contour (polygon.begin_hole (h), polygon.end_hole (h), rinner, router, n, (std::vector<db::point<C> > *) 0, false)) {
|
||||||
if (! extract_rad_from_contour (polygon.begin_hole (h), polygon.end_hole (h), rinner, router, n, 0, true)) {
|
if (! do_extract_rad_from_contour (polygon.begin_hole (h), polygon.end_hole (h), rinner, router, n, (std::vector<db::point<C> > *) 0, true)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1162,22 +1176,36 @@ extract_rad (const db::Polygon &polygon, double &rinner, double &router, unsigne
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
compute_rounded_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon_contour_iterator to, std::vector <db::Point> &new_pts, double rinner, double router, unsigned int n)
|
extract_rad (const db::Polygon &polygon, double &rinner, double &router, unsigned int &n, db::Polygon *new_polygon)
|
||||||
{
|
{
|
||||||
std::vector<db::Point> points;
|
return do_extract_rad (polygon, rinner, router, n, new_polygon);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
extract_rad (const db::DPolygon &polygon, double &rinner, double &router, unsigned int &n, db::DPolygon *new_polygon)
|
||||||
|
{
|
||||||
|
return do_extract_rad (polygon, rinner, router, n, new_polygon);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class C>
|
||||||
|
static void
|
||||||
|
do_compute_rounded_contour (typename db::polygon<C>::polygon_contour_iterator from, typename db::polygon<C>::polygon_contour_iterator to, std::vector <db::point<C> > &new_pts, double rinner, double router, unsigned int n)
|
||||||
|
{
|
||||||
|
std::vector<db::point<C> > points;
|
||||||
|
|
||||||
// collect the points into a vector
|
// collect the points into a vector
|
||||||
|
|
||||||
if (from != to) {
|
if (from != to) {
|
||||||
|
|
||||||
db::Polygon::polygon_contour_iterator p0 = from;
|
typename db::polygon<C>::polygon_contour_iterator p0 = from;
|
||||||
db::Polygon::polygon_contour_iterator p1 = p0;
|
typename db::polygon<C>::polygon_contour_iterator p1 = p0;
|
||||||
++p1;
|
++p1;
|
||||||
if (p1 == to) {
|
if (p1 == to) {
|
||||||
p1 = from;
|
p1 = from;
|
||||||
}
|
}
|
||||||
db::Polygon::polygon_contour_iterator p2 = p1;
|
typename db::polygon<C>::polygon_contour_iterator p2 = p1;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
|
|
@ -1186,7 +1214,7 @@ compute_rounded_contour (db::Polygon::polygon_contour_iterator from, db::Polygon
|
||||||
p2 = from;
|
p2 = from;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! db::Edge (*p0, *p1).parallel (db::Edge (*p1, *p2))) {
|
if (! db::edge<C> (*p0, *p1).parallel (db::edge<C> (*p1, *p2))) {
|
||||||
points.push_back (*p1);
|
points.push_back (*p1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1204,9 +1232,9 @@ compute_rounded_contour (db::Polygon::polygon_contour_iterator from, db::Polygon
|
||||||
|
|
||||||
for (size_t i = 0; i < points.size (); ++i) {
|
for (size_t i = 0; i < points.size (); ++i) {
|
||||||
|
|
||||||
db::Point p0 = points [(i + points.size () - 1) % points.size ()];
|
db::point<C> p0 = points [(i + points.size () - 1) % points.size ()];
|
||||||
db::Point p1 = points [i];
|
db::point<C> p1 = points [i];
|
||||||
db::Point p2 = points [(i + points.size () + 1) % points.size ()];
|
db::point<C> p2 = points [(i + points.size () + 1) % points.size ()];
|
||||||
|
|
||||||
db::DVector e1 = (db::DPoint (p1) - db::DPoint (p0)) * (1.0 / p0.double_distance (p1));
|
db::DVector e1 = (db::DPoint (p1) - db::DPoint (p0)) * (1.0 / p0.double_distance (p1));
|
||||||
db::DVector e2 = (db::DPoint (p2) - db::DPoint (p1)) * (1.0 / p1.double_distance (p2));
|
db::DVector e2 = (db::DPoint (p2) - db::DPoint (p1)) * (1.0 / p1.double_distance (p2));
|
||||||
|
|
@ -1227,9 +1255,9 @@ compute_rounded_contour (db::Polygon::polygon_contour_iterator from, db::Polygon
|
||||||
|
|
||||||
for (size_t i = 0; i < points.size (); ++i) {
|
for (size_t i = 0; i < points.size (); ++i) {
|
||||||
|
|
||||||
db::Point p0 = points [(i + points.size () - 1) % points.size ()];
|
db::point<C> p0 = points [(i + points.size () - 1) % points.size ()];
|
||||||
db::Point p1 = points [i];
|
db::point<C> p1 = points [i];
|
||||||
db::Point p2 = points [(i + points.size () + 1) % points.size ()];
|
db::point<C> p2 = points [(i + points.size () + 1) % points.size ()];
|
||||||
|
|
||||||
db::DVector e1 = (db::DPoint (p1) - db::DPoint (p0)) * (1.0 / p0.double_distance (p1));
|
db::DVector e1 = (db::DPoint (p1) - db::DPoint (p0)) * (1.0 / p0.double_distance (p1));
|
||||||
db::DVector e2 = (db::DPoint (p2) - db::DPoint (p1)) * (1.0 / p1.double_distance (p2));
|
db::DVector e2 = (db::DPoint (p2) - db::DPoint (p1)) * (1.0 / p1.double_distance (p2));
|
||||||
|
|
@ -1274,7 +1302,7 @@ compute_rounded_contour (db::Polygon::polygon_contour_iterator from, db::Polygon
|
||||||
db::DPoint qm = q0 + (q1 - q0) * 0.5;
|
db::DPoint qm = q0 + (q1 - q0) * 0.5;
|
||||||
db::DPoint q = qm + (qm - pr) * (q0.sq_distance (qm) / pr.sq_distance (qm));
|
db::DPoint q = qm + (qm - pr) * (q0.sq_distance (qm) / pr.sq_distance (qm));
|
||||||
|
|
||||||
new_pts.push_back (db::Point (q));
|
new_pts.push_back (db::point<C> (q));
|
||||||
|
|
||||||
q0 = q1;
|
q0 = q1;
|
||||||
|
|
||||||
|
|
@ -1289,11 +1317,24 @@ compute_rounded_contour (db::Polygon::polygon_contour_iterator from, db::Polygon
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
db::Polygon
|
void
|
||||||
compute_rounded (const db::Polygon &polygon, double rinner, double router, unsigned int n)
|
compute_rounded_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon_contour_iterator to, std::vector <db::Point> &new_pts, double rinner, double router, unsigned int n)
|
||||||
{
|
{
|
||||||
db::Polygon new_poly;
|
do_compute_rounded_contour (from, to, new_pts, rinner, router, n);
|
||||||
std::vector <db::Point> new_pts;
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
compute_rounded_contour (db::DPolygon::polygon_contour_iterator from, db::DPolygon::polygon_contour_iterator to, std::vector <db::DPoint> &new_pts, double rinner, double router, unsigned int n)
|
||||||
|
{
|
||||||
|
do_compute_rounded_contour (from, to, new_pts, rinner, router, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class C>
|
||||||
|
static db::polygon<C>
|
||||||
|
do_compute_rounded (const db::polygon<C> &polygon, double rinner, double router, unsigned int n)
|
||||||
|
{
|
||||||
|
db::polygon<C> new_poly;
|
||||||
|
std::vector <db::point<C> > new_pts;
|
||||||
|
|
||||||
compute_rounded_contour (polygon.begin_hull (), polygon.end_hull (), new_pts, rinner, router, n);
|
compute_rounded_contour (polygon.begin_hull (), polygon.end_hull (), new_pts, rinner, router, n);
|
||||||
new_poly.assign_hull (new_pts.begin (), new_pts.end (), false /*don't compress*/);
|
new_poly.assign_hull (new_pts.begin (), new_pts.end (), false /*don't compress*/);
|
||||||
|
|
@ -1307,6 +1348,18 @@ compute_rounded (const db::Polygon &polygon, double rinner, double router, unsig
|
||||||
return new_poly;
|
return new_poly;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
db::Polygon
|
||||||
|
compute_rounded (const db::Polygon &polygon, double rinner, double router, unsigned int n)
|
||||||
|
{
|
||||||
|
return do_compute_rounded (polygon, rinner, router, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
db::DPolygon
|
||||||
|
compute_rounded (const db::DPolygon &polygon, double rinner, double router, unsigned int n)
|
||||||
|
{
|
||||||
|
return do_compute_rounded (polygon, rinner, router, n);
|
||||||
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// Implementation of AreaMap
|
// Implementation of AreaMap
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -359,6 +359,11 @@ inline bool interact (const db::DSimplePolygon &poly1, const db::DSimplePolygon
|
||||||
*/
|
*/
|
||||||
bool DB_PUBLIC extract_rad_from_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon_contour_iterator to, double &rinner, double &router, unsigned int &n, std::vector <db::Point> *new_pts = 0, bool fallback = false);
|
bool DB_PUBLIC extract_rad_from_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon_contour_iterator to, double &rinner, double &router, unsigned int &n, std::vector <db::Point> *new_pts = 0, bool fallback = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Extract a corner radius from a contour (version for double coordinates)
|
||||||
|
*/
|
||||||
|
bool DB_PUBLIC extract_rad_from_contour (db::DPolygon::polygon_contour_iterator from, db::DPolygon::polygon_contour_iterator to, double &rinner, double &router, unsigned int &n, std::vector <db::DPoint> *new_pts = 0, bool fallback = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Extract the radius (better: radii) from a polygon and if requested, compute the new polygon without the rounding
|
* @brief Extract the radius (better: radii) from a polygon and if requested, compute the new polygon without the rounding
|
||||||
*
|
*
|
||||||
|
|
@ -366,6 +371,11 @@ bool DB_PUBLIC extract_rad_from_contour (db::Polygon::polygon_contour_iterator f
|
||||||
*/
|
*/
|
||||||
bool DB_PUBLIC extract_rad (const db::Polygon &polygon, double &rinner, double &router, unsigned int &n, db::Polygon *new_polygon = 0);
|
bool DB_PUBLIC extract_rad (const db::Polygon &polygon, double &rinner, double &router, unsigned int &n, db::Polygon *new_polygon = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Extract a corner radius from a polygon (version for double coordinates)
|
||||||
|
*/
|
||||||
|
bool DB_PUBLIC extract_rad (const db::DPolygon &polygon, double &rinner, double &router, unsigned int &n, db::DPolygon *new_polygon = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Compute the rounded version of a polygon contour
|
* @brief Compute the rounded version of a polygon contour
|
||||||
*
|
*
|
||||||
|
|
@ -379,6 +389,11 @@ bool DB_PUBLIC extract_rad (const db::Polygon &polygon, double &rinner, double &
|
||||||
*/
|
*/
|
||||||
void DB_PUBLIC compute_rounded_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon_contour_iterator to, std::vector <db::Point> &new_pts, double rinner, double router, unsigned int n);
|
void DB_PUBLIC compute_rounded_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon_contour_iterator to, std::vector <db::Point> &new_pts, double rinner, double router, unsigned int n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compute the rounded version of a polygon contour (double coordinate version)
|
||||||
|
*/
|
||||||
|
void DB_PUBLIC compute_rounded_contour (db::DPolygon::polygon_contour_iterator from, db::DPolygon::polygon_contour_iterator to, std::vector <db::DPoint> &new_pts, double rinner, double router, unsigned int n);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Compute the rounded version of the polygon
|
* @brief Compute the rounded version of the polygon
|
||||||
*
|
*
|
||||||
|
|
@ -386,6 +401,11 @@ void DB_PUBLIC compute_rounded_contour (db::Polygon::polygon_contour_iterator fr
|
||||||
*/
|
*/
|
||||||
db::Polygon DB_PUBLIC compute_rounded (const db::Polygon &poly, double rinner, double router, unsigned int n);
|
db::Polygon DB_PUBLIC compute_rounded (const db::Polygon &poly, double rinner, double router, unsigned int n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compute the rounded version of the polygon (double coordinate version)
|
||||||
|
*/
|
||||||
|
db::DPolygon DB_PUBLIC compute_rounded (const db::DPolygon &poly, double rinner, double router, unsigned int n);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Smooth a contour
|
* @brief Smooth a contour
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -173,6 +173,37 @@ struct simple_polygon_defs
|
||||||
return poly->area ();
|
return poly->area ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::vector<tl::Variant> extract_rad (const C *sp)
|
||||||
|
{
|
||||||
|
db::polygon<coord_type> p, pnew;
|
||||||
|
p.assign_hull (sp->begin_hull (), sp->end_hull (), false);
|
||||||
|
double rinner = 0.0, router = 0.0;
|
||||||
|
unsigned int n = 1;
|
||||||
|
if (! db::extract_rad (p, rinner, router, n, &pnew) || pnew.holes () > 0) {
|
||||||
|
return std::vector<tl::Variant> ();
|
||||||
|
} else {
|
||||||
|
std::vector<tl::Variant> res;
|
||||||
|
C spnew;
|
||||||
|
spnew.assign_hull (pnew.begin_hull (), pnew.end_hull ());
|
||||||
|
res.push_back (tl::Variant (spnew));
|
||||||
|
res.push_back (rinner);
|
||||||
|
res.push_back (router);
|
||||||
|
res.push_back (n);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static C round_corners (const C *sp, double rinner, double router, unsigned int n)
|
||||||
|
{
|
||||||
|
db::polygon<coord_type> p;
|
||||||
|
p.assign_hull (sp->begin_hull (), sp->end_hull (), false);
|
||||||
|
p = db::compute_rounded (p, rinner, router, n);
|
||||||
|
tl_assert (p.holes () == 0);
|
||||||
|
C res;
|
||||||
|
res.assign_hull (p.begin_hull (), p.end_hull ());
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static gsi::Methods methods ()
|
static gsi::Methods methods ()
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
|
|
@ -382,6 +413,45 @@ struct simple_polygon_defs
|
||||||
method ("to_s", (std::string (C::*) () const) &C::to_string,
|
method ("to_s", (std::string (C::*) () const) &C::to_string,
|
||||||
"@brief Convert to a string\n"
|
"@brief Convert to a string\n"
|
||||||
) +
|
) +
|
||||||
|
method_ext ("round_corners", &round_corners,
|
||||||
|
"@brief Round the corners of the polygon\n"
|
||||||
|
"@args rinner, router, n\n"
|
||||||
|
"\n"
|
||||||
|
"Replaces the corners of the polygon with circle segments.\n"
|
||||||
|
"\n"
|
||||||
|
"@param rinner The circle radius of inner corners (in database units).\n"
|
||||||
|
"@param router The circle radius of outer corners (in database units).\n"
|
||||||
|
"@param n The number of points per full circle.\n"
|
||||||
|
"\n"
|
||||||
|
"@return The new polygon.\n"
|
||||||
|
"\n"
|
||||||
|
"This method was introduced in version 0.22 for integer coordinates and in 0.25 for all coordinate types.\n"
|
||||||
|
) +
|
||||||
|
method_ext ("extract_rad", &extract_rad,
|
||||||
|
"@brief Extracts the corner radii from a rounded polygon\n"
|
||||||
|
"\n"
|
||||||
|
"Attempts to extract the radii of rounded corner polygon. This is essentially the inverse of "
|
||||||
|
"the \\round_corners method. If this method succeeds, if will return an array of four elements: "
|
||||||
|
"@ul\n"
|
||||||
|
"@li The polygon with the rounded corners replaced by edgy ones @/li\n"
|
||||||
|
"@li The radius of the inner corners @/li\n"
|
||||||
|
"@li The radius of the outer corners @/li\n"
|
||||||
|
"@li The number of points per full circle @/li\n"
|
||||||
|
"@/ul\n"
|
||||||
|
"\n"
|
||||||
|
"This method is based on some assumptions and may fail. In this case, an empty array is returned.\n"
|
||||||
|
"\n"
|
||||||
|
"If successful, the following code will more or less render the original polygon and parameters\n"
|
||||||
|
"\n"
|
||||||
|
"@code\n"
|
||||||
|
"p = ... # some polygon\n"
|
||||||
|
"p.round_corners(ri, ro, n)\n"
|
||||||
|
"(p2, ri2, ro2, n2) = p.extract_rad\n"
|
||||||
|
"# -> p2 == p, ro2 == ro, ri2 == ri, n2 == n (within some limits)\n"
|
||||||
|
"@/code\n"
|
||||||
|
"\n"
|
||||||
|
"This method was introduced in version 0.25.\n"
|
||||||
|
) +
|
||||||
method_ext ("area", &area,
|
method_ext ("area", &area,
|
||||||
"@brief The area of the polygon\n"
|
"@brief The area of the polygon\n"
|
||||||
"The area is correct only if the polygon is not self-overlapping and the polygon is oriented clockwise."
|
"The area is correct only if the polygon is not self-overlapping and the polygon is oriented clockwise."
|
||||||
|
|
@ -396,13 +466,6 @@ struct simple_polygon_defs
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static db::Polygon sp_round_corners (const db::SimplePolygon *sp, double rinner, double router, unsigned int n)
|
|
||||||
{
|
|
||||||
db::Polygon p;
|
|
||||||
p.assign_hull (sp->begin_hull (), sp->end_hull (), false);
|
|
||||||
return db::compute_rounded (p, rinner, router, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
static db::Polygon sp_minkowsky_sum_pe (const db::SimplePolygon *sp, const db::Edge &e, bool rh)
|
static db::Polygon sp_minkowsky_sum_pe (const db::SimplePolygon *sp, const db::Edge &e, bool rh)
|
||||||
{
|
{
|
||||||
db::Polygon p;
|
db::Polygon p;
|
||||||
|
|
@ -474,20 +537,6 @@ Class<db::SimplePolygon> decl_SimplePolygon ("SimplePolygon",
|
||||||
"\n"
|
"\n"
|
||||||
"This method has been introduced in version 0.25."
|
"This method has been introduced in version 0.25."
|
||||||
) +
|
) +
|
||||||
method_ext ("round_corners", &sp_round_corners,
|
|
||||||
"@brief Round the corners of the polygon\n"
|
|
||||||
"@args rinner, router, n\n"
|
|
||||||
"\n"
|
|
||||||
"Replaces the corners of the polygon with circle segments.\n"
|
|
||||||
"\n"
|
|
||||||
"@param rinner The circle radius of inner corners (in database units).\n"
|
|
||||||
"@param router The circle radius of outer corners (in database units).\n"
|
|
||||||
"@param n The number of points per full circle.\n"
|
|
||||||
"\n"
|
|
||||||
"@return The new polygon.\n"
|
|
||||||
"\n"
|
|
||||||
"This method was introduced in version 0.22.\n"
|
|
||||||
) +
|
|
||||||
method_ext ("minkowsky_sum", &sp_minkowsky_sum_pe,
|
method_ext ("minkowsky_sum", &sp_minkowsky_sum_pe,
|
||||||
"@brief Compute the Minkowsky sum of a polygon and an edge\n"
|
"@brief Compute the Minkowsky sum of a polygon and an edge\n"
|
||||||
"@args a, b, resolve_holes\n"
|
"@args a, b, resolve_holes\n"
|
||||||
|
|
@ -879,6 +928,28 @@ struct polygon_defs
|
||||||
return poly->area ();
|
return poly->area ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::vector<tl::Variant> extract_rad (const C *p)
|
||||||
|
{
|
||||||
|
C pnew;
|
||||||
|
double rinner = 0.0, router = 0.0;
|
||||||
|
unsigned int n = 1;
|
||||||
|
if (! db::extract_rad (*p, rinner, router, n, &pnew)) {
|
||||||
|
return std::vector<tl::Variant> ();
|
||||||
|
} else {
|
||||||
|
std::vector<tl::Variant> res;
|
||||||
|
res.push_back (tl::Variant (pnew));
|
||||||
|
res.push_back (rinner);
|
||||||
|
res.push_back (router);
|
||||||
|
res.push_back (n);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static C round_corners (const C *p, double rinner, double router, unsigned int n)
|
||||||
|
{
|
||||||
|
return db::compute_rounded (*p, rinner, router, n);
|
||||||
|
}
|
||||||
|
|
||||||
static gsi::Methods methods ()
|
static gsi::Methods methods ()
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
|
|
@ -1259,6 +1330,45 @@ struct polygon_defs
|
||||||
method ("to_s", (std::string (C::*) () const) &C::to_string,
|
method ("to_s", (std::string (C::*) () const) &C::to_string,
|
||||||
"@brief Convert to a string\n"
|
"@brief Convert to a string\n"
|
||||||
) +
|
) +
|
||||||
|
method_ext ("round_corners", &round_corners,
|
||||||
|
"@brief Rounds the corners of the polygon\n"
|
||||||
|
"@args rinner, router, n\n"
|
||||||
|
"\n"
|
||||||
|
"Replaces the corners of the polygon with circle segments.\n"
|
||||||
|
"\n"
|
||||||
|
"@param rinner The circle radius of inner corners (in database units).\n"
|
||||||
|
"@param router The circle radius of outer corners (in database units).\n"
|
||||||
|
"@param n The number of points per full circle.\n"
|
||||||
|
"\n"
|
||||||
|
"@return The new polygon.\n"
|
||||||
|
"\n"
|
||||||
|
"This method was introduced in version 0.20 for integer coordinates and in 0.25 for all coordinate types.\n"
|
||||||
|
) +
|
||||||
|
method_ext ("extract_rad", &extract_rad,
|
||||||
|
"@brief Extracts the corner radii from a rounded polygon\n"
|
||||||
|
"\n"
|
||||||
|
"Attempts to extract the radii of rounded corner polygon. This is essentially the inverse of "
|
||||||
|
"the \\round_corners method. If this method succeeds, if will return an array of four elements: "
|
||||||
|
"@ul\n"
|
||||||
|
"@li The polygon with the rounded corners replaced by edgy ones @/li\n"
|
||||||
|
"@li The radius of the inner corners @/li\n"
|
||||||
|
"@li The radius of the outer corners @/li\n"
|
||||||
|
"@li The number of points per full circle @/li\n"
|
||||||
|
"@/ul\n"
|
||||||
|
"\n"
|
||||||
|
"This method is based on some assumptions and may fail. In this case, an empty array is returned.\n"
|
||||||
|
"\n"
|
||||||
|
"If successful, the following code will more or less render the original polygon and parameters\n"
|
||||||
|
"\n"
|
||||||
|
"@code\n"
|
||||||
|
"p = ... # some polygon\n"
|
||||||
|
"p.round_corners(ri, ro, n)\n"
|
||||||
|
"(p2, ri2, ro2, n2) = p.extract_rad\n"
|
||||||
|
"# -> p2 == p, ro2 == ro, ri2 == ri, n2 == n (within some limits)\n"
|
||||||
|
"@/code\n"
|
||||||
|
"\n"
|
||||||
|
"This method was introduced in version 0.25.\n"
|
||||||
|
) +
|
||||||
method_ext ("area", &area,
|
method_ext ("area", &area,
|
||||||
"@brief The area of the polygon\n"
|
"@brief The area of the polygon\n"
|
||||||
"The area is correct only if the polygon is not self-overlapping and the polygon is oriented clockwise."
|
"The area is correct only if the polygon is not self-overlapping and the polygon is oriented clockwise."
|
||||||
|
|
@ -1316,11 +1426,6 @@ static db::Polygon smooth (const db::Polygon *p, db::Coord d)
|
||||||
return db::smooth (*p, d);
|
return db::smooth (*p, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
static db::Polygon round_corners (const db::Polygon *p, double rinner, double router, unsigned int n)
|
|
||||||
{
|
|
||||||
return db::compute_rounded (*p, rinner, router, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
static db::Polygon minkowsky_sum_pe (const db::Polygon *p, const db::Edge &e, bool rh)
|
static db::Polygon minkowsky_sum_pe (const db::Polygon *p, const db::Edge &e, bool rh)
|
||||||
{
|
{
|
||||||
return db::minkowsky_sum (*p, e, rh);
|
return db::minkowsky_sum (*p, e, rh);
|
||||||
|
|
@ -1514,20 +1619,6 @@ Class<db::Polygon> decl_Polygon ("Polygon",
|
||||||
"\n"
|
"\n"
|
||||||
"This method was introduced in version 0.23.\n"
|
"This method was introduced in version 0.23.\n"
|
||||||
) +
|
) +
|
||||||
method_ext ("round_corners", &round_corners,
|
|
||||||
"@brief Rounds the corners of the polygon\n"
|
|
||||||
"@args rinner, router, n\n"
|
|
||||||
"\n"
|
|
||||||
"Replaces the corners of the polygon with circle segments.\n"
|
|
||||||
"\n"
|
|
||||||
"@param rinner The circle radius of inner corners (in database units).\n"
|
|
||||||
"@param router The circle radius of outer corners (in database units).\n"
|
|
||||||
"@param n The number of points per full circle.\n"
|
|
||||||
"\n"
|
|
||||||
"@return The new polygon.\n"
|
|
||||||
"\n"
|
|
||||||
"This method was introduced in version 0.20.\n"
|
|
||||||
) +
|
|
||||||
method_ext ("minkowsky_sum", &minkowsky_sum_pe,
|
method_ext ("minkowsky_sum", &minkowsky_sum_pe,
|
||||||
"@brief Computes the Minkowsky sum of the polygon and an edge\n"
|
"@brief Computes the Minkowsky sum of the polygon and an edge\n"
|
||||||
"@args e, resolve_holes\n"
|
"@args e, resolve_holes\n"
|
||||||
|
|
|
||||||
|
|
@ -472,6 +472,59 @@ class DBPolygon_TestClass < TestBase
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# polygon decomposition
|
||||||
|
def test_extractRad
|
||||||
|
|
||||||
|
ex = RBA::SimplePolygon::new.extract_rad
|
||||||
|
assert_equal(ex.inspect, "[]")
|
||||||
|
|
||||||
|
sp = RBA::SimplePolygon::from_s("(0,0;0,200000;300000,200000;300000,100000;100000,100000;100000,0)")
|
||||||
|
|
||||||
|
sp = sp.round_corners(10000, 5000, 200)
|
||||||
|
ex = sp.extract_rad
|
||||||
|
|
||||||
|
assert_equal(ex.inspect, "[(0,0;0,200000;300000,200000;300000,100000;100000,100000;100000,0), 10000.0, 5000.0, 200]")
|
||||||
|
|
||||||
|
ex = RBA::Polygon::new.extract_rad
|
||||||
|
assert_equal(ex.inspect, "[]")
|
||||||
|
|
||||||
|
sp = RBA::Polygon::from_s("(0,0;0,300000;300000,300000;300000,0/100000,100000;200000,100000;200000,200000;100000,200000)")
|
||||||
|
|
||||||
|
sp = sp.round_corners(10000, 5000, 200)
|
||||||
|
ex = sp.extract_rad
|
||||||
|
|
||||||
|
assert_equal(ex.inspect, "[(0,0;0,300000;300000,300000;300000,0/100000,100000;200000,100000;200000,200000;100000,200000), 10000.0, 5000.0, 200]")
|
||||||
|
|
||||||
|
# double coords too ...
|
||||||
|
|
||||||
|
ex = RBA::DSimplePolygon::new.extract_rad
|
||||||
|
assert_equal(ex.inspect, "[]")
|
||||||
|
|
||||||
|
sp = RBA::DSimplePolygon::from_s("(0,0;0,200000;300000,200000;300000,100000;100000,100000;100000,0)")
|
||||||
|
|
||||||
|
sp = sp.round_corners(10000, 5000, 200)
|
||||||
|
ex = sp.extract_rad
|
||||||
|
|
||||||
|
# round to integers for better comparison
|
||||||
|
|
||||||
|
ex[0] = RBA::SimplePolygon::new(ex[0])
|
||||||
|
assert_equal(ex.inspect, "[(0,0;0,200000;300000,200000;300000,100000;100000,100000;100000,0), 10000.0, 5000.0, 200]")
|
||||||
|
|
||||||
|
ex = RBA::DPolygon::new.extract_rad
|
||||||
|
assert_equal(ex.inspect, "[]")
|
||||||
|
|
||||||
|
sp = RBA::DPolygon::from_s("(0,0;0,300000;300000,300000;300000,0/100000,100000;200000,100000;200000,200000;100000,200000)")
|
||||||
|
|
||||||
|
sp = sp.round_corners(10000, 5000, 200)
|
||||||
|
ex = sp.extract_rad
|
||||||
|
|
||||||
|
# round to integers for better comparison
|
||||||
|
ex[0] = RBA::Polygon::new(ex[0])
|
||||||
|
|
||||||
|
assert_equal(ex.inspect, "[(0,0;0,300000;300000,300000;300000,0/100000,100000;200000,100000;200000,200000;100000,200000), 10000.0, 5000.0, 200]")
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
load("test_epilogue.rb")
|
load("test_epilogue.rb")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue