diff --git a/src/db/dbPolygonTools.cc b/src/db/dbPolygonTools.cc index 94249c34f..762540dc2 100644 --- a/src/db/dbPolygonTools.cc +++ b/src/db/dbPolygonTools.cc @@ -778,21 +778,22 @@ smooth (const db::Polygon &polygon, db::Coord d) // ------------------------------------------------------------------------- // Rounding tools -bool -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 *new_pts, bool fallback) +template +static bool +do_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 > *new_pts, bool fallback) { if (from == to) { return false; } - db::Polygon::polygon_contour_iterator p0 = from; + typename db::polygon::polygon_contour_iterator p0 = from; - db::Polygon::polygon_contour_iterator p1 = p0; + typename db::polygon::polygon_contour_iterator p1 = p0; ++p1; if (p1 == to) { p1 = from; } - db::Polygon::polygon_contour_iterator p2 = p1; + typename db::polygon::polygon_contour_iterator p2 = p1; const double cos_thr = 0.8; 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; } - db::Edge ep (*p0, *p1); - db::Edge e (*p1, *p2); + db::edge ep (*p0, *p1); + db::edge e (*p1, *p2); bool inner = (db::vprod_sign (ep, e) > 0); 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) // or a long segment is followed by a short one or the curvature changes. - db::Polygon::polygon_contour_iterator pm1 = from; + typename db::polygon::polygon_contour_iterator pm1 = from; p0 = pm1; ++p0; @@ -861,7 +862,7 @@ extract_rad_from_contour (db::Polygon::polygon_contour_iterator from, db::Polygo p2 = from; } - db::Polygon::polygon_contour_iterator p3 = p2; + typename db::polygon::polygon_contour_iterator p3 = p2; do { @@ -870,10 +871,10 @@ extract_rad_from_contour (db::Polygon::polygon_contour_iterator from, db::Polygo p3 = from; } - db::Edge em (*pm1, *p0); - db::Edge ep (*p0, *p1); - db::Edge e (*p1, *p2); - db::Edge en (*p2, *p3); + db::edge em (*pm1, *p0); + db::edge ep (*p0, *p1); + db::edge e (*p1, *p2); + db::edge 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 ()) || (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 (); } - db::Polygon::polygon_contour_iterator pfirst = p0; + typename db::polygon::polygon_contour_iterator pfirst = p0; bool in_corner = false; double ls_corner = 0.0; - db::Edge elast; - db::Polygon::polygon_contour_iterator plast; + db::edge elast; + typename db::polygon::polygon_contour_iterator plast; double asum = 0.0; unsigned int nseg = 0; @@ -931,10 +932,10 @@ extract_rad_from_contour (db::Polygon::polygon_contour_iterator from, db::Polygo p3 = from; } - db::Edge em (*pm1, *p0); - db::Edge ep (*p0, *p1); - db::Edge e (*p1, *p2); - db::Edge en (*p2, *p3); + db::edge em (*pm1, *p0); + db::edge ep (*p0, *p1); + db::edge e (*p1, *p2); + db::edge en (*p2, *p3); // Heuristic detection of a new circle segment: // 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) { elast = ep; plast = p1; - asum = db::vprod (*p1 - db::Point (), *p2 - db::Point ()); + asum = db::vprod (*p1 - db::point (), *p2 - db::point ()); nseg = 1; ls_corner = ls; } @@ -967,13 +968,13 @@ extract_rad_from_contour (db::Polygon::polygon_contour_iterator from, db::Polygo if (in_corner) { - std::pair cp = elast.cut_point (e); + std::pair > cp = elast.cut_point (e); if (! cp.first) { // 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. - db::Polygon::polygon_contour_iterator pp1 = plast; - db::Polygon::polygon_contour_iterator pp2 = pp1; + typename db::polygon::polygon_contour_iterator pp1 = plast; + typename db::polygon::polygon_contour_iterator pp2 = pp1; double asum_part = 0.0; unsigned int nseg_part = 0; @@ -984,12 +985,12 @@ extract_rad_from_contour (db::Polygon::polygon_contour_iterator from, db::Polygo pp2 = from; } - e = db::Edge (*pp1, *pp2); + e = db::edge (*pp1, *pp2); if (db::sprod_sign (elast, e) == 0) { break; } - asum_part += db::vprod (*pp1 - db::Point (), *pp2 - db::Point ()); + asum_part += db::vprod (*pp1 - db::point (), *pp2 - db::point ()); ++nseg_part; pp1 = pp2; @@ -1008,11 +1009,11 @@ extract_rad_from_contour (db::Polygon::polygon_contour_iterator from, db::Polygo ++nseg_part; asum -= asum_part; - asum -= db::vprod (e.p1 () - db::Point (), e.p2 () - db::Point ()); + asum -= db::vprod (e.p1 () - db::point (), e.p2 () - db::point ()); nseg -= nseg_part; - asum_part += db::vprod (cp.second - db::Point (), elast.p2 () - db::Point ()); - asum_part += db::vprod (*pp1 - db::Point (), cp.second - db::Point ()); + asum_part += db::vprod (cp.second - db::point (), elast.p2 () - db::point ()); + asum_part += db::vprod (*pp1 - db::point (), cp.second - db::point ()); double sin_atot = db::vprod (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; - e = db::Edge (*p1, *p2); + e = db::edge (*p1, *p2); cp = elast.cut_point (e); if (! cp.first) { return false; @@ -1046,8 +1047,8 @@ extract_rad_from_contour (db::Polygon::polygon_contour_iterator from, db::Polygo new_pts->push_back (cp.second); } - asum += db::vprod (cp.second - db::Point (), elast.p2 () - db::Point ()); - asum += db::vprod (*p1 - db::Point (), cp.second - db::Point ()); + asum += db::vprod (cp.second - db::point (), elast.p2 () - db::point ()); + asum += db::vprod (*p1 - db::point (), cp.second - db::point ()); ++nseg; @@ -1074,7 +1075,7 @@ extract_rad_from_contour (db::Polygon::polygon_contour_iterator from, db::Polygo } else if (in_corner) { - asum += db::vprod (*p1 - db::Point (), *p2 - db::Point ()); + asum += db::vprod (*p1 - db::point (), *p2 - db::point ()); ++nseg; } else { @@ -1112,45 +1113,58 @@ extract_rad_from_contour (db::Polygon::polygon_contour_iterator from, db::Polygo } } -bool -extract_rad (const db::Polygon &polygon, double &rinner, double &router, unsigned int &n, db::Polygon *new_polygon) +bool +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 *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 *new_pts, bool fallback) +{ + return do_extract_rad_from_contour (from, to, rinner, router, n, new_pts, fallback); +} + +template +static bool +do_extract_rad (const db::polygon &polygon, double &rinner, double &router, unsigned int &n, db::polygon *new_polygon) { if (new_polygon) { - std::vector new_pts; + std::vector > new_pts; - if (! extract_rad_from_contour (polygon.begin_hull (), polygon.end_hull (), rinner, router, n, &new_pts) && - ! extract_rad_from_contour (polygon.begin_hull (), polygon.end_hull (), rinner, router, n, &new_pts, true)) { + if (! do_extract_rad_from_contour (polygon.begin_hull (), polygon.end_hull (), rinner, router, n, &new_pts, false) && + ! do_extract_rad_from_contour (polygon.begin_hull (), polygon.end_hull (), rinner, router, n, &new_pts, true)) { // no radius found return false; } 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) { new_pts.clear (); - if (! extract_rad_from_contour (polygon.begin_hole (h), polygon.end_hole (h), rinner, router, n, &new_pts) && - ! extract_rad_from_contour (polygon.begin_hole (h), polygon.end_hole (h), rinner, router, n, &new_pts, true)) { + if (! do_extract_rad_from_contour (polygon.begin_hole (h), polygon.end_hole (h), rinner, router, n, &new_pts, false) && + ! do_extract_rad_from_contour (polygon.begin_hole (h), polygon.end_hole (h), rinner, router, n, &new_pts, true)) { // no radius found return false; } else { - new_polygon->insert_hole (new_pts.begin (), new_pts.end (), true /*compress*/); + new_polygon->insert_hole (new_pts.begin (), new_pts.end ()); } } } else { - if (! extract_rad_from_contour (polygon.begin_hull (), polygon.end_hull (), rinner, router, n, 0)) { - 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 > *) 0, false)) { + if (! do_extract_rad_from_contour (polygon.begin_hull (), polygon.end_hull (), rinner, router, n, (std::vector > *) 0, true)) { return false; } } 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 (! 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 > *) 0, false)) { + if (! do_extract_rad_from_contour (polygon.begin_hole (h), polygon.end_hole (h), rinner, router, n, (std::vector > *) 0, true)) { return false; } } @@ -1162,22 +1176,36 @@ extract_rad (const db::Polygon &polygon, double &rinner, double &router, unsigne } -void -compute_rounded_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon_contour_iterator to, std::vector &new_pts, double rinner, double router, unsigned int n) +bool +extract_rad (const db::Polygon &polygon, double &rinner, double &router, unsigned int &n, db::Polygon *new_polygon) { - std::vector 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 +static void +do_compute_rounded_contour (typename db::polygon::polygon_contour_iterator from, typename db::polygon::polygon_contour_iterator to, std::vector > &new_pts, double rinner, double router, unsigned int n) +{ + std::vector > points; // collect the points into a vector if (from != to) { - db::Polygon::polygon_contour_iterator p0 = from; - db::Polygon::polygon_contour_iterator p1 = p0; + typename db::polygon::polygon_contour_iterator p0 = from; + typename db::polygon::polygon_contour_iterator p1 = p0; ++p1; if (p1 == to) { p1 = from; } - db::Polygon::polygon_contour_iterator p2 = p1; + typename db::polygon::polygon_contour_iterator p2 = p1; do { @@ -1186,7 +1214,7 @@ compute_rounded_contour (db::Polygon::polygon_contour_iterator from, db::Polygon p2 = from; } - if (! db::Edge (*p0, *p1).parallel (db::Edge (*p1, *p2))) { + if (! db::edge (*p0, *p1).parallel (db::edge (*p1, *p2))) { 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) { - db::Point p0 = points [(i + points.size () - 1) % points.size ()]; - db::Point p1 = points [i]; - db::Point p2 = points [(i + points.size () + 1) % points.size ()]; + db::point p0 = points [(i + points.size () - 1) % points.size ()]; + db::point p1 = points [i]; + db::point 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 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) { - db::Point p0 = points [(i + points.size () - 1) % points.size ()]; - db::Point p1 = points [i]; - db::Point p2 = points [(i + points.size () + 1) % points.size ()]; + db::point p0 = points [(i + points.size () - 1) % points.size ()]; + db::point p1 = points [i]; + db::point 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 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 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 (q)); q0 = q1; @@ -1289,11 +1317,24 @@ compute_rounded_contour (db::Polygon::polygon_contour_iterator from, db::Polygon } } -db::Polygon -compute_rounded (const db::Polygon &polygon, double rinner, double router, unsigned int n) +void +compute_rounded_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon_contour_iterator to, std::vector &new_pts, double rinner, double router, unsigned int n) { - db::Polygon new_poly; - std::vector new_pts; + do_compute_rounded_contour (from, to, new_pts, rinner, router, n); +} + +void +compute_rounded_contour (db::DPolygon::polygon_contour_iterator from, db::DPolygon::polygon_contour_iterator to, std::vector &new_pts, double rinner, double router, unsigned int n) +{ + do_compute_rounded_contour (from, to, new_pts, rinner, router, n); +} + +template +static db::polygon +do_compute_rounded (const db::polygon &polygon, double rinner, double router, unsigned int n) +{ + db::polygon new_poly; + std::vector > new_pts; 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*/); @@ -1307,6 +1348,18 @@ compute_rounded (const db::Polygon &polygon, double rinner, double router, unsig 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 diff --git a/src/db/dbPolygonTools.h b/src/db/dbPolygonTools.h index 643255ae1..17bc5421d 100644 --- a/src/db/dbPolygonTools.h +++ b/src/db/dbPolygonTools.h @@ -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 *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 *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 * @@ -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); +/** + * @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 * @@ -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 &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 &new_pts, double rinner, double router, unsigned int n); + /** * @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); +/** + * @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 * diff --git a/src/db/gsiDeclDbPolygon.cc b/src/db/gsiDeclDbPolygon.cc index 57d2837b7..7aa0123e5 100644 --- a/src/db/gsiDeclDbPolygon.cc +++ b/src/db/gsiDeclDbPolygon.cc @@ -173,6 +173,37 @@ struct simple_polygon_defs return poly->area (); } + static std::vector extract_rad (const C *sp) + { + db::polygon 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 (); + } else { + std::vector 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 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 () { return @@ -382,6 +413,45 @@ struct simple_polygon_defs method ("to_s", (std::string (C::*) () const) &C::to_string, "@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, "@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." @@ -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) { db::Polygon p; @@ -474,20 +537,6 @@ Class decl_SimplePolygon ("SimplePolygon", "\n" "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, "@brief Compute the Minkowsky sum of a polygon and an edge\n" "@args a, b, resolve_holes\n" @@ -879,6 +928,28 @@ struct polygon_defs return poly->area (); } + static std::vector 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 (); + } else { + std::vector 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 () { return @@ -1259,6 +1330,45 @@ struct polygon_defs method ("to_s", (std::string (C::*) () const) &C::to_string, "@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, "@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." @@ -1316,11 +1426,6 @@ static db::Polygon smooth (const db::Polygon *p, db::Coord 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) { return db::minkowsky_sum (*p, e, rh); @@ -1514,20 +1619,6 @@ Class decl_Polygon ("Polygon", "\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, "@brief Computes the Minkowsky sum of the polygon and an edge\n" "@args e, resolve_holes\n" diff --git a/testdata/ruby/dbPolygonTest.rb b/testdata/ruby/dbPolygonTest.rb index d9224ca01..748bb15f4 100644 --- a/testdata/ruby/dbPolygonTest.rb +++ b/testdata/ruby/dbPolygonTest.rb @@ -472,6 +472,59 @@ class DBPolygon_TestClass < TestBase 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 load("test_epilogue.rb")