diff --git a/macbuild/Resources/KLayoutDMG-Back.logoist b/macbuild/Resources/KLayoutDMG-Back.logoist index c85a5342e..8c6b6af34 100644 Binary files a/macbuild/Resources/KLayoutDMG-Back.logoist and b/macbuild/Resources/KLayoutDMG-Back.logoist differ diff --git a/macbuild/Resources/KLayoutDMG-Back.png b/macbuild/Resources/KLayoutDMG-Back.png index b2433a0fc..8db846684 100644 Binary files a/macbuild/Resources/KLayoutDMG-Back.png and b/macbuild/Resources/KLayoutDMG-Back.png differ diff --git a/macbuild/Resources/script-bundle-A.zip b/macbuild/Resources/script-bundle-A.zip index eda075de5..58e91d629 100644 Binary files a/macbuild/Resources/script-bundle-A.zip and b/macbuild/Resources/script-bundle-A.zip differ diff --git a/macbuild/Resources/script-bundle-B.zip b/macbuild/Resources/script-bundle-B.zip index 0a8dfe893..25d7a5b89 100644 Binary files a/macbuild/Resources/script-bundle-B.zip and b/macbuild/Resources/script-bundle-B.zip differ diff --git a/macbuild/Resources/script-bundle-P.zip b/macbuild/Resources/script-bundle-P.zip index 22987f14b..81f1bfef9 100644 Binary files a/macbuild/Resources/script-bundle-P.zip and b/macbuild/Resources/script-bundle-P.zip differ diff --git a/macbuild/build4mac_env.py b/macbuild/build4mac_env.py index ea3a84f22..726380184 100755 --- a/macbuild/build4mac_env.py +++ b/macbuild/build4mac_env.py @@ -121,7 +121,7 @@ CatalinaSDK = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.p RubyCatalina = { 'exe': '/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/bin/ruby', 'inc': '%s/System/Library/Frameworks/Ruby.framework/Headers' % CatalinaSDK, 'inc2': '%s/System/Library/Frameworks/Ruby.framework/Headers/ruby' % CatalinaSDK, - 'lib': '/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/libruby.dylib' + 'lib': '%s/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/libruby.tbd' % CatalinaSDK } # Bundled with Big Sur (11.0) @@ -131,7 +131,7 @@ BigSurSDK = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.p RubyBigSur = { 'exe': '/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/bin/ruby', 'inc': '%s/System/Library/Frameworks/Ruby.framework/Headers' % BigSurSDK, 'inc2': '%s/System/Library/Frameworks/Ruby.framework/Headers/ruby' % BigSurSDK, - 'lib': '/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/libruby.dylib' + 'lib': '%s/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/libruby.tbd' % BigSurSDK } # Ruby 2.7 from MacPorts (https://www.macports.org/) *+*+*+ EXPERIMENTAL *+*+*+ diff --git a/macbuild/makeDMG4mac.py b/macbuild/makeDMG4mac.py index d50ea43ed..a8b795c93 100755 --- a/macbuild/makeDMG4mac.py +++ b/macbuild/makeDMG4mac.py @@ -108,6 +108,7 @@ def SetGlobals(): if release == 20: GenOSName = "macOS" Platform = "BigSur" + LatestOS = Platform elif release == 19: GenOSName = "macOS" Platform = "Catalina" diff --git a/macbuild/nightyCatalina.py b/macbuild/nightyCatalina.py index 57ab7f9ef..3bee90bb6 100755 --- a/macbuild/nightyCatalina.py +++ b/macbuild/nightyCatalina.py @@ -37,8 +37,8 @@ def Get_Build_Options( targetDic ): buildOp = dict() for key in targetDic.keys(): target = targetDic[key] - if target == "std": # use 'Qt5Brew' that provides Qt 5.15.1 to run on "Big Sur", too - buildOp["std"] = [ '-q', 'Qt5Brew', '-r', 'sys', '-p', 'sys' ] + if target == "std": # use 'Qt5MacPorts' that provides Qt 5.15.2 to run on "Big Sur", too + buildOp["std"] = [ '-q', 'Qt5MacPorts', '-r', 'sys', '-p', 'sys' ] elif target == "ports": buildOp["ports"] = [ '-q', 'Qt5MacPorts', '-r', 'MP27', '-p', 'MP38' ] elif target == "brew": @@ -65,7 +65,7 @@ def Get_QAT_Directory( targetDic ): for key in targetDic.keys(): target = targetDic[key] if target == "std": - dirQAT["std"] = 'qt5Brew.build.macos-Catalina-release-RsysPsys.macQAT' + dirQAT["std"] = 'qt5MP.build.macos-Catalina-release-RsysPsys.macQAT' elif target == "ports": dirQAT["ports"] = 'qt5MP.build.macos-Catalina-release-Rmp27Pmp38.macQAT' elif target == "brew": @@ -99,7 +99,7 @@ def Get_Package_Options( targetDic, srlDMG, makeflag ): for key in targetDic.keys(): target = targetDic[key] if target == "std": - packOp["std"] = [ '-p', 'ST-qt5Brew.pkg.macos-Catalina-release-RsysPsys', '-s', '%d' % srlDMG, '%s' % flag ] + packOp["std"] = [ '-p', 'ST-qt5MP.pkg.macos-Catalina-release-RsysPsys', '-s', '%d' % srlDMG, '%s' % flag ] elif target == "ports": packOp["ports"] = [ '-p', 'LW-qt5MP.pkg.macos-Catalina-release-Rmp27Pmp38', '-s', '%d' % srlDMG, '%s' % flag ] elif target == "brew": diff --git a/src/db/db/db.pro b/src/db/db/db.pro index e38ea7c5d..16f9df099 100644 --- a/src/db/db/db.pro +++ b/src/db/db/db.pro @@ -82,6 +82,7 @@ SOURCES = \ dbTilingProcessor.cc \ dbTrans.cc \ dbUserObject.cc \ + dbUtils.cc \ dbVector.cc \ dbWriter.cc \ dbWriterTools.cc \ @@ -122,6 +123,7 @@ SOURCES = \ gsiDeclDbText.cc \ gsiDeclDbTilingProcessor.cc \ gsiDeclDbTrans.cc \ + gsiDeclDbUtils.cc \ gsiDeclDbVector.cc \ gsiDeclDbLayoutDiff.cc \ gsiDeclDbGlyphs.cc \ @@ -288,6 +290,7 @@ HEADERS = \ dbTrans.h \ dbTypes.h \ dbUserObject.h \ + dbUtils.h \ dbVector.h \ dbWriter.h \ dbWriterTools.h \ diff --git a/src/db/db/dbUtils.cc b/src/db/db/dbUtils.cc new file mode 100644 index 000000000..db5ef75c5 --- /dev/null +++ b/src/db/db/dbUtils.cc @@ -0,0 +1,260 @@ +/* + + KLayout Layout Viewer + Copyright (C) 2006-2021 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "dbUtils.h" +#include "dbVector.h" +#include "tlException.h" + +namespace db +{ + +/* + +Rational B-Splines (NURBS) vs. non-rational B-Splines: + https://en.wikipedia.org/wiki/Non-uniform_rational_B-spline + +De Boor algorithm for NURBS + https://github.com/caadxyz/DeBoorAlgorithmNurbs + +*/ + +static db::DPoint +b_spline_point (double x, const std::vector > &control_points, int p, const std::vector &t) +{ + int k = (int) (std::lower_bound (t.begin (), t.end (), x + 1e-6) - t.begin ()); + if (k <= p) { + return control_points.front ().first; + } else if (k > (int) control_points.size ()) { + return control_points.back ().first; + } + --k; + + std::vector d; + std::vector dw; + d.reserve(p + 1); + for (int j = 0; j <= p; ++j) { + double w = control_points[j + k - p].second; + d.push_back (control_points[j + k - p].first * w); + dw.push_back (w); + } + + for (int r = 1; r <= p; ++r) { + for (int j = p; j >= r; --j) { + double alpha = (x - t[j + k - p]) / (t[j + 1 + k - r] - t[j + k - p]); + d[j] = d[j] * alpha + (d[j - 1] - d[j - 1] * alpha); + dw[j] = dw[j] * alpha + dw[j - 1] * (1.0 - alpha); + } + } + + return d[p] * (1.0 / dw[p]); +} + +/** + * @brief Inserts new points into a sequence of points to refine the curve + * + * The idea is bisection of the segments until the desired degree of accuracy has been reached. + * + * @param control_points The control points + * @param curve_points The list of curve points which is going to be extended + * @param current_curve_point The iterator pointing to the current curve point + * @param t_start The t (curve parameter) value of the current curve point + * @param dt The current t interval + * @param degree The degree of the spline + * @param knots The knots + * @param sin_da The relative accuracy value implied by the circle resolution + * @param accu The desired absolute accuracy value + * + * New points are going to be inserted after current_curve_point and current_curve_point + 1 to achieve the + * required curvature. + */ +static void +spline_interpolate (std::list &curve_points, + typename std::list::iterator current_curve_point, + double t_start, + double dt, + const std::vector > &control_points, + int degree, + const std::vector &knots, + double sin_da, + double accu) +{ + std::list::iterator pm = current_curve_point; + ++pm; + std::list::iterator pe = pm; + ++pe; + + db::DPoint s1 = b_spline_point (t_start + 0.5 * dt, control_points, degree, knots); + db::DPoint s2 = b_spline_point (t_start + 1.5 * dt, control_points, degree, knots); + + db::DVector p1 (s1, *current_curve_point); + db::DVector p2 (*pm, s1); + double pl1 = p1.length(), pl2 = p2.length(); + + if (curve_points.size () < control_points.size () - degree - 1) { + + curve_points.insert (pm, s1); + spline_interpolate (curve_points, current_curve_point, t_start, dt * 0.5, control_points, degree, knots, sin_da, accu); + + curve_points.insert (pe, s2); + spline_interpolate (curve_points, pm, t_start + dt, dt * 0.5, control_points, degree, knots, sin_da, accu); + + } else { + + db::DVector q1 (s2, *pm); + db::DVector q2 (*pe, s2); + double ql1 = q1.length(), ql2 = q2.length(); + + db::DVector p (*pm, *current_curve_point); + db::DVector q (*pe, *pm); + double pl = p.length (), ql = q.length (); + + if (fabs (db::vprod (p, q)) > pl * ql * sin_da || + fabs (db::vprod (p1, p2)) > pl1 * pl2 * sin_da || + fabs (db::vprod (q1, q2)) > ql1 * ql2 * sin_da) { + + // angle between the segments is bigger than 2PI/n -> circle resolution is + // too small. Or: the angle between the new segments that we would introduce + // is also bigger (hence, the original segments may have a small angle but the + // curve "wiggles" when we increase the resolution) + + if (fabs (db::vprod (p1, p)) > pl * accu) { + + // In addition, the estimated accuracy is not good enough on the first segment: bisect this + // segment. + + curve_points.insert (pm, s1); + spline_interpolate (curve_points, current_curve_point, t_start, dt * 0.5, control_points, degree, knots, sin_da, accu); + + } + + if (fabs (db::vprod (q1, q)) > ql * accu) { + + // In addition, the estimated accuracy is not good enough on the first segment: bisect this + // segment. + + curve_points.insert (pe, s2); + spline_interpolate (curve_points, pm, t_start + dt, dt * 0.5, control_points, degree, knots, sin_da, accu); + + } + + } + + } +} + +static +std::list +do_spline_interpolation (const std::vector > &control_points, int degree, const std::vector &knots, double relative_accuracy, double absolute_accuracy) +{ + // TODO: this is quite inefficient + if (int (knots.size()) != int (control_points.size() + degree + 1)) { + throw tl::Exception (tl::to_string (tr ("Spline interpolation failed: mismatch between number of knots and points (#knots must be #points+degree+1)"))); + } + + if (int(knots.size ()) <= degree || control_points.empty () || degree <= 1) { + return std::list (); + } + + double t0 = knots [degree]; + double tn = knots [knots.size () - degree - 1]; + + std::list new_points; + new_points.push_back (control_points.front ().first); + + double dt = 0.5 * (tn - t0); + + for (double t = t0 + dt; t < tn + 1e-6; t += dt) { + db::DPoint s = b_spline_point (t, control_points, degree, knots); + new_points.push_back (s); + } + + spline_interpolate (new_points, new_points.begin (), t0, dt, control_points, degree, knots, relative_accuracy, absolute_accuracy); + + return new_points; +} + +template +std::list

+spline_interpolation (const std::vector > &control_points, int degree, const std::vector &knots, double relative_accuracy, double absolute_accuracy) +{ + std::vector > cp; + cp.reserve (control_points.size ()); + + for (size_t i = 0; i < control_points.size (); ++i) { + cp.push_back (std::make_pair (db::DPoint (control_points [i].first), control_points [i].second)); + } + + std::list result = do_spline_interpolation (cp, degree, knots, relative_accuracy, absolute_accuracy); + + std::list

ret; + for (std::list::const_iterator i = result.begin (); i != result.end (); ++i) { + ret.push_back (P (*i)); + } + return ret; +} + +template <> +std::list +spline_interpolation (const std::vector > &control_points, int degree, const std::vector &knots, double relative_accuracy, double absolute_accuracy) +{ + return do_spline_interpolation (control_points, degree, knots, relative_accuracy, absolute_accuracy); +} + +template +std::list

+spline_interpolation (const std::vector

&control_points, const std::vector &weights, int degree, const std::vector &knots, double relative_accuracy, double absolute_accuracy) +{ + std::vector > cp; + cp.reserve (control_points.size ()); + + for (size_t i = 0; i < control_points.size (); ++i) { + if (i >= weights.size ()) { + cp.push_back (std::make_pair (control_points [i], 1.0)); + } else { + cp.push_back (std::make_pair (control_points [i], weights [i])); + } + } + + return spline_interpolation (cp, degree, knots, relative_accuracy, absolute_accuracy); +} + +template +std::list

+spline_interpolation (const std::vector

&control_points, int degree, const std::vector &knots, double relative_accuracy, double absolute_accuracy) +{ + std::vector > cp; + cp.reserve (control_points.size ()); + + for (size_t i = 0; i < control_points.size (); ++i) { + cp.push_back (std::make_pair (control_points [i], 1.0)); + } + + return spline_interpolation (cp, degree, knots, relative_accuracy, absolute_accuracy); +} + +template std::list spline_interpolation (const std::vector &, int, const std::vector &, double, double); +template std::list spline_interpolation (const std::vector &, const std::vector &, int, const std::vector &, double, double); +template std::list spline_interpolation (const std::vector > &, int, const std::vector &, double, double); + +template std::list spline_interpolation (const std::vector &, int, const std::vector &, double, double); +template std::list spline_interpolation (const std::vector &, const std::vector &, int, const std::vector &, double, double); + +} diff --git a/src/db/db/dbUtils.h b/src/db/db/dbUtils.h new file mode 100644 index 000000000..30b6b4d03 --- /dev/null +++ b/src/db/db/dbUtils.h @@ -0,0 +1,84 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2021 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#ifndef HDR_dbUtils +#define HDR_dbUtils + +#include "dbCommon.h" +#include "dbPoint.h" + +#include +#include + +namespace db +{ + +/** + * @brief Provides a Spline curve with adjustable accuracy + * + * This function computes the Spline curve for a given set of control points (point, weight), degree and knots. + * + * The knot vector needs to be padded and it's size must fulfill the condition: + * + * @code + * knots.size == control_points.size + degree + 1 + * @/code + * + * The accuracy parameters allow tuing the resolution of the curve to target a specific approximation quality. + * "relative_accuracy" gives the accuracy relative to the local curvature radius, "absolute" accuracy gives the + * absolute accuracy. "accuracy" is the allowed deviation of polygon approximation from the ideal curve. + * The computed curve should meet at least one of the accurcay criteria. Setting both limits to a very small + * value will result in long run times and a large number of points returned. + * + * This function supports both rational splines (NURBS) and non-rational splines. The latter use weights of + * 1.0 for each point. + * + * The return value is a list of points forming a path which approximates the spline curve. + */ +template +DB_PUBLIC std::list

+spline_interpolation (const std::vector > &control_points, int degree, const std::vector &knots, double relative_accuracy, double absolute_accuracy); + +/** + * @brief A convencience version of the previous function + * + * This version takes separate vectors for point and weights for the control points. + */ +template +DB_PUBLIC std::list

+spline_interpolation (const std::vector

&control_points, const std::vector &weights, int degree, const std::vector &knots, double relative_accuracy, double absolute_accuracy); + +/** + * @brief A convencience version of the previous function + * + * This version provides non-rational splines and does not take a weight vector. + */ +template +DB_PUBLIC std::list

+spline_interpolation (const std::vector

&control_points, int degree, const std::vector &knots, double relative_accuracy, double absolute_accuracy); + +} + +#endif + + diff --git a/src/db/db/gsiDeclDbUtils.cc b/src/db/db/gsiDeclDbUtils.cc new file mode 100644 index 000000000..97b2fa359 --- /dev/null +++ b/src/db/db/gsiDeclDbUtils.cc @@ -0,0 +1,102 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2021 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#include "gsiDecl.h" +#include "dbUtils.h" + +namespace db +{ + +/** + * @brief A dummy class providing the namespace. + */ +struct UtilsDummy +{ + static std::list spi1 (const std::vector &control_points, const std::vector &weight, int degree, const std::vector &knots, double relative_accuracy, double absolute_accuracy) + { + return db::spline_interpolation (control_points, weight, degree, knots, relative_accuracy, absolute_accuracy); + } + + static std::list spi2 (const std::vector &control_points, const std::vector &weight, int degree, const std::vector &knots, double relative_accuracy, double absolute_accuracy) + { + return db::spline_interpolation (control_points, weight, degree, knots, relative_accuracy, absolute_accuracy); + } + + static std::list spi3 (const std::vector &control_points, int degree, const std::vector &knots, double relative_accuracy, double absolute_accuracy) + { + return db::spline_interpolation (control_points, degree, knots, relative_accuracy, absolute_accuracy); + } + + static std::list spi4 (const std::vector &control_points, int degree, const std::vector &knots, double relative_accuracy, double absolute_accuracy) + { + return db::spline_interpolation (control_points, degree, knots, relative_accuracy, absolute_accuracy); + } +}; + +} + +namespace gsi +{ + + Class decl_dbUtils ("db", "Utils", + gsi::method ("spline_interpolation", &db::UtilsDummy::spi1, gsi::arg ("control_points"), gsi::arg ("weights"), gsi::arg ("degree"), gsi::arg ("knots"), gsi::arg ("relative_accuracy"), gsi::arg ("absolute_accuracy"), + "@brief This function computes the Spline curve for a given set of control points (point, weight), degree and knots.\n" + "\n" + "The knot vector needs to be padded and it's size must fulfill the condition:\n" + "\n" + "@code\n" + " knots.size == control_points.size + degree + 1\n" + "@/code\n" + "\n" + "The accuracy parameters allow tuing the resolution of the curve to target a specific approximation quality.\n" + "\"relative_accuracy\" gives the accuracy relative to the local curvature radius, \"absolute\" accuracy gives the\n" + "absolute accuracy. \"accuracy\" is the allowed deviation of polygon approximation from the ideal curve.\n" + "The computed curve should meet at least one of the accurcay criteria. Setting both limits to a very small\n" + "value will result in long run times and a large number of points returned.\n" + "\n" + "This function supports both rational splines (NURBS) and non-rational splines. The latter use weights of\n" + "1.0 for each point.\n" + "\n" + "The return value is a list of points forming a path which approximates the spline curve.\n" + ) + + gsi::method ("spline_interpolation", &db::UtilsDummy::spi2, gsi::arg ("control_points"), gsi::arg ("weights"), gsi::arg ("degree"), gsi::arg ("knots"), gsi::arg ("relative_accuracy"), gsi::arg ("absolute_accuracy"), + "@brief This function computes the Spline curve for a given set of control points (point, weight), degree and knots.\n" + "\n" + "This is the version for integer-coordinate points." + ) + + gsi::method ("spline_interpolation", &db::UtilsDummy::spi3, gsi::arg ("control_points"), gsi::arg ("degree"), gsi::arg ("knots"), gsi::arg ("relative_accuracy"), gsi::arg ("absolute_accuracy"), + "@brief This function computes the Spline curve for a given set of control points (point, weight), degree and knots.\n" + "\n" + "This is the version for non-rational splines. It lacks the weight vector." + ) + + gsi::method ("spline_interpolation", &db::UtilsDummy::spi4, gsi::arg ("control_points"), gsi::arg ("degree"), gsi::arg ("knots"), gsi::arg ("relative_accuracy"), gsi::arg ("absolute_accuracy"), + "@brief This function computes the Spline curve for a given set of control points (point, weight), degree and knots.\n" + "\n" + "This is the version for integer-coordinate points for non-rational splines." + ), + "@brief This namespace provides a collection of utility functions\n" + "\n" + "This class has been introduced in version 0.27." + ); + +} diff --git a/src/db/unit_tests/dbRegionUtilsTests.cc b/src/db/unit_tests/dbRegionUtilsTests.cc index 5e161b272..c27a41e3d 100644 --- a/src/db/unit_tests/dbRegionUtilsTests.cc +++ b/src/db/unit_tests/dbRegionUtilsTests.cc @@ -23,46 +23,10 @@ #include "tlUnitTest.h" -#include "tlString.h" +#include "tlStringEx.h" #include "dbRegionUtils.h" -namespace tl -{ - -template -std::string to_string (Iter b, Iter e) -{ - std::string res; - for (Iter i = b; i != e; ++i) { - if (i != b) { - res += ","; - } - res += tl::to_string (*i); - } - return res; -} - -template -std::string to_string (const std::vector &v) -{ - return to_string (v.begin (), v.end ()); -} - -template -std::string to_string (const std::list &v) -{ - return to_string (v.begin (), v.end ()); -} - -template -std::string to_string (const std::set &v) -{ - return to_string (v.begin (), v.end ()); -} - -} - TEST(1_SimpleLShape) { std::set ep; diff --git a/src/db/unit_tests/dbUtilsTests.cc b/src/db/unit_tests/dbUtilsTests.cc new file mode 100644 index 000000000..8392775c6 --- /dev/null +++ b/src/db/unit_tests/dbUtilsTests.cc @@ -0,0 +1,143 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2021 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#include "dbUtils.h" +#include "tlUnitTest.h" +#include "tlStringEx.h" + +#include + +TEST(1) +{ + std::list pts; + + std::vector > cp; + cp.push_back (std::make_pair (db::DPoint (-1, 0), 1)); + cp.push_back (std::make_pair (db::DPoint (-1, 1), sqrt (0.5))); + cp.push_back (std::make_pair (db::DPoint (0, 1), 1)); + + std::vector k; + k.push_back (0.0); + k.push_back (0.0); + k.push_back (0.0); + k.push_back (1.0); + k.push_back (1.0); + k.push_back (1.0); + + pts = db::spline_interpolation (cp, 2, k, 0.01, 0.01); + + EXPECT_EQ (tl::to_string (pts), + "-1,0," + "-0.983305368417,0.181963052412," + "-0.929788301062,0.368094709562," + "-0.836995511219,0.547209753385," + "-0.707106781187,0.707106781187," + "-0.547209753385,0.836995511219," + "-0.368094709562,0.929788301062," + "-0.181963052412,0.983305368417," + "0,1" + ); + + for (std::list::iterator i = pts.begin (); i != pts.end (); ++i) { + EXPECT_EQ (fabs (i->double_distance () - 1.0) < 1e-10, true); + } + + pts = db::spline_interpolation (cp, 2, k, 0.001, 0.001); + + EXPECT_EQ (pts.size (), size_t (33)); + + for (std::list::iterator i = pts.begin (); i != pts.end (); ++i) { + EXPECT_EQ (fabs (i->double_distance () - 1.0) < 1e-10, true); + } +} + +TEST(2) +{ + std::list pts; + + std::vector cp; + cp.push_back (db::DPoint (-1, 0)); + cp.push_back (db::DPoint (-1, 1)); + cp.push_back (db::DPoint (0, 1)); + + std::vector w; + w.push_back (1); + w.push_back (sqrt (0.5)); + w.push_back (1); + + std::vector k; + k.push_back (0.0); + k.push_back (0.0); + k.push_back (0.0); + k.push_back (1.0); + k.push_back (1.0); + k.push_back (1.0); + + pts = db::spline_interpolation (cp, w, 2, k, 0.01, 0.01); + + EXPECT_EQ (tl::to_string (pts), + "-1,0," + "-0.983305368417,0.181963052412," + "-0.929788301062,0.368094709562," + "-0.836995511219,0.547209753385," + "-0.707106781187,0.707106781187," + "-0.547209753385,0.836995511219," + "-0.368094709562,0.929788301062," + "-0.181963052412,0.983305368417," + "0,1" + ); +} + +TEST(3) +{ + std::list pts; + + std::vector cp; + cp.push_back (db::DPoint (-1, 0)); + cp.push_back (db::DPoint (-1, 1)); + cp.push_back (db::DPoint (0, 1)); + + std::vector k; + k.push_back (0.0); + k.push_back (0.0); + k.push_back (0.0); + k.push_back (1.0); + k.push_back (1.0); + k.push_back (1.0); + + // non-rational spline + pts = db::spline_interpolation (cp, 2, k, 0.01, 0.01); + + EXPECT_EQ (tl::to_string (pts), + "-1,0," + "-0.984375,0.234375," + "-0.9375,0.4375," + "-0.859375,0.609375," + "-0.75,0.75," + "-0.609375,0.859375," + "-0.4375,0.9375," + "-0.234375,0.984375," + "0,1" + ); +} + diff --git a/src/db/unit_tests/unit_tests.pro b/src/db/unit_tests/unit_tests.pro index 5ff79a744..ee48d7549 100644 --- a/src/db/unit_tests/unit_tests.pro +++ b/src/db/unit_tests/unit_tests.pro @@ -9,6 +9,7 @@ include($$PWD/../../lib_ut.pri) SOURCES = \ dbCompoundOperationTests.cc \ dbRegionUtilsTests.cc \ + dbUtilsTests.cc \ dbWriterTools.cc \ dbLoadLayoutOptionsTests.cc \ dbSaveLayoutOptionsTests.cc \ diff --git a/src/rba/unit_tests/rbaTests.cc b/src/rba/unit_tests/rbaTests.cc index c9b83a6f9..9ac96cbf9 100644 --- a/src/rba/unit_tests/rbaTests.cc +++ b/src/rba/unit_tests/rbaTests.cc @@ -132,6 +132,7 @@ RUBYTEST (dbTextsTest, "dbTextsTest.rb") RUBYTEST (dbTilingProcessorTest, "dbTilingProcessorTest.rb") RUBYTEST (dbTransTest, "dbTransTest.rb") RUBYTEST (dbVectorTest, "dbVectorTest.rb") +RUBYTEST (dbUtilsTests, "dbUtilsTests.rb") RUBYTEST (edtTest, "edtTest.rb") RUBYTEST (extNetTracer, "extNetTracer.rb") RUBYTEST (imgObject, "imgObject.rb") diff --git a/src/tl/tl/tlStringEx.h b/src/tl/tl/tlStringEx.h new file mode 100644 index 000000000..8c325ddfb --- /dev/null +++ b/src/tl/tl/tlStringEx.h @@ -0,0 +1,95 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2021 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef HDR_tlStringEx +#define HDR_tlStringEx + +#include "tlString.h" + +#include +#include +#include +#include +#include +#include + +namespace tl +{ + +template +std::string to_string (Iter b, Iter e) +{ + std::string res; + for (Iter i = b; i != e; ++i) { + if (i != b) { + res += ","; + } + res += tl::to_string (*i); + } + return res; +} + +template +std::string to_string (const std::pair &p) +{ + return to_string (p.first) + "," + to_string (p.second); +} + +template +std::string to_string (const std::vector &v) +{ + return to_string (v.begin (), v.end ()); +} + +template +std::string to_string (const std::list &v) +{ + return to_string (v.begin (), v.end ()); +} + +template +std::string to_string (const std::set &v) +{ + return to_string (v.begin (), v.end ()); +} + +template +std::string to_string (const std::map &v) +{ + return to_string (v.begin (), v.end ()); +} + +template +std::string to_string (const std::unordered_set &v) +{ + return to_string (v.begin (), v.end ()); +} + +template +std::string to_string (const std::unordered_map &v) +{ + return to_string (v.begin (), v.end ()); +} + +} + +#endif diff --git a/src/tl/tl/tlVariant.cc b/src/tl/tl/tlVariant.cc index 61cbbea95..a2b71ac90 100644 --- a/src/tl/tl/tlVariant.cc +++ b/src/tl/tl/tlVariant.cc @@ -1599,13 +1599,15 @@ Variant::to_qstring () const std::vector Variant::to_bytearray () const { - if (m_type == t_qbytearray) { - return std::vector (m_var.m_qbytearray->constBegin (), m_var.m_qbytearray->constEnd ()); - } else if (m_type == t_bytearray) { + if (m_type == t_bytearray) { return *m_var.m_bytearray; +#if defined(HAVE_QT) } else if (m_type == t_qstring) { QByteArray ba = m_var.m_qstring->toUtf8 (); return std::vector (ba.constBegin (), ba.constEnd ()); + } else if (m_type == t_qbytearray) { + return std::vector (m_var.m_qbytearray->constBegin (), m_var.m_qbytearray->constEnd ()); +#endif } else if (m_type == t_stdstring) { return std::vector (m_var.m_stdstring->begin (), m_var.m_stdstring->end ()); } else { diff --git a/testdata/ruby/dbUtilsTests.rb b/testdata/ruby/dbUtilsTests.rb new file mode 100644 index 000000000..4ad4838cf --- /dev/null +++ b/testdata/ruby/dbUtilsTests.rb @@ -0,0 +1,79 @@ +# encoding: UTF-8 + +# KLayout Layout Viewer +# Copyright (C) 2006-2021 Matthias Koefferlein +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +if !$:.member?(File::dirname($0)) + $:.push(File::dirname($0)) +end + +load("test_prologue.rb") + +class DBUtils_TestClass < TestBase + + def test_1 + + pts = [ RBA::DPoint::new(-1, 0), RBA::DPoint::new(-1, 1), RBA::DPoint::new(0, 1) ] + weights = [ 1, Math::sqrt(0.5), 1 ] + k = [ 0, 0, 0, 1, 1, 1 ] + + pts = RBA::Utils::spline_interpolation(pts, weights, 2, k, 0.01, 0.01) + + assert_equal(pts.collect(&:to_s).join(","), "-1,0,-0.983305368417,0.181963052412,-0.929788301062,0.368094709562,-0.836995511219,0.547209753385,-0.707106781187,0.707106781187,-0.547209753385,0.836995511219,-0.368094709562,0.929788301062,-0.181963052412,0.983305368417,0,1") + assert_equal(pts.collect(&:abs).collect { |d| "%.12g" % d }.join(","), "1,1,1,1,1,1,1,1,1") + + end + + def test_2 + + pts = [ RBA::Point::new(-1000, 0), RBA::Point::new(-1000, 1000), RBA::Point::new(0, 1000) ] + weights = [ 1, Math::sqrt(0.5), 1] + k = [ 0, 0, 0, 1, 1, 1 ] + + pts = RBA::Utils::spline_interpolation(pts, weights, 2, k, 0.01, 10) + + assert_equal(pts.collect(&:to_s).join(","), "-1000,0,-983,182,-930,368,-837,547,-707,707,-547,837,-368,930,-182,983,0,1000") + assert_equal(pts.collect(&:abs).collect { |d| "%.0f" % d }.join(","), "1000,1000,1000,1000,1000,1000,1000,1000,1000") + + end + + def test_3 + + pts = [ RBA::DPoint::new(-1, 0), RBA::DPoint::new(-1, 1), RBA::DPoint::new(0, 1) ] + k = [ 0, 0, 0, 1, 1, 1 ] + + pts = RBA::Utils::spline_interpolation(pts, 2, k, 0.01, 0.01) + + assert_equal(pts.collect(&:to_s).join(","), "-1,0,-0.984375,0.234375,-0.9375,0.4375,-0.859375,0.609375,-0.75,0.75,-0.609375,0.859375,-0.4375,0.9375,-0.234375,0.984375,0,1") + + end + + def test_4 + + pts = [ RBA::Point::new(-1000, 0), RBA::Point::new(-1000, 1000), RBA::Point::new(0, 1000) ] + k = [ 0, 0, 0, 1, 1, 1 ] + + pts = RBA::Utils::spline_interpolation(pts, 2, k, 0.01, 10) + + assert_equal(pts.collect(&:to_s).join(","), "-1000,0,-984,234,-938,438,-859,609,-750,750,-609,859,-438,938,-234,984,0,1000") + assert_equal(pts.collect(&:abs).collect { |d| "%.0f" % d }.join(","), "1000,1011,1035,1053,1061,1053,1035,1011,1000") + + end + +end + +load("test_epilogue.rb")