File indexing completed on 2024-12-22 04:10:13
0001 /* 0002 * SPDX-FileCopyrightText: 2014 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kis_bsplines_test.h" 0008 0009 #include <simpletest.h> 0010 0011 #include <cmath> 0012 0013 #include <bsplines/kis_bspline_1d.h> 0014 #include <bsplines/kis_bspline_2d.h> 0015 #include <bsplines/kis_nu_bspline_2d.h> 0016 #include <kis_debug.h> 0017 #include <kis_global.h> 0018 0019 #include <boost/accumulators/accumulators.hpp> 0020 #include <boost/accumulators/statistics/stats.hpp> 0021 #include <boost/accumulators/statistics/variance.hpp> 0022 #include <boost/accumulators/statistics/min.hpp> 0023 #include <boost/accumulators/statistics/max.hpp> 0024 0025 using namespace boost::accumulators; 0026 using namespace KisBSplines; 0027 0028 struct FunctionOp { 0029 float operator() (qreal x) { 0030 return std::sqrt(x); 0031 } 0032 0033 float operator() (qreal x, qreal y) const { 0034 return std::sqrt(x) + y - pow2(x + y); 0035 } 0036 }; 0037 0038 void KisBSplinesTest::test1D() 0039 { 0040 const qreal start = 1.0; 0041 const qreal end = 11.0; 0042 0043 KisBSpline1D spline(start, end, 10, Natural); 0044 spline.initializeSpline<FunctionOp>(); 0045 0046 accumulator_set<qreal, stats<tag::variance, tag::max, tag::min> > accum; 0047 0048 FunctionOp op; 0049 for (qreal x = start; x < end; x += 0.01) { 0050 qreal value = op(x); 0051 qreal relError = (spline.value(x) - value) / value; 0052 0053 accum(relError); 0054 0055 if (relError > 0.10) { 0056 dbgKrita << ppVar(x) << ppVar(op(x)) << ppVar(spline.value(x)) << ppVar(relError); 0057 } 0058 } 0059 0060 dbgKrita << ppVar(count(accum)); 0061 dbgKrita << ppVar(mean(accum)); 0062 dbgKrita << ppVar(variance(accum)); 0063 dbgKrita << ppVar((min)(accum)); 0064 dbgKrita << ppVar((max)(accum)); 0065 0066 qreal maxError = qMax(qAbs((min)(accum)), qAbs((max)(accum))); 0067 QVERIFY(maxError < 0.10); // Error is less than 10% 0068 0069 } 0070 0071 void KisBSplinesTest::testEmpty1D() 0072 { 0073 const qreal start = 1.0; 0074 const qreal end = 11.0; 0075 KisBSpline1D spline(start, end, 10, Natural); 0076 // just let it be destructed uninitialized 0077 } 0078 0079 template <class Spline, class Op> 0080 bool test2DSpline(const Spline &spline, const Op &op, qreal start, qreal end) 0081 { 0082 accumulator_set<qreal, stats<tag::variance, tag::max, tag::min> > accum; 0083 0084 for (qreal y = start; y < end; y += 0.01) { 0085 for (qreal x = start; x < end; x += 0.01) { 0086 qreal value = op(x, y); 0087 qreal relError = (spline.value(x, y) - value) / value; 0088 0089 accum(relError); 0090 0091 if (relError > 0.10) { 0092 dbgKrita << ppVar(x) << ppVar(y) << ppVar(op(x, y)) << ppVar(spline.value(x, y)) << ppVar(relError); 0093 } 0094 } 0095 } 0096 0097 dbgKrita << ppVar(count(accum)); 0098 dbgKrita << ppVar(mean(accum)); 0099 dbgKrita << ppVar(variance(accum)); 0100 dbgKrita << ppVar((min)(accum)); 0101 dbgKrita << ppVar((max)(accum)); 0102 0103 qreal maxError = qMax(qAbs((min)(accum)), qAbs((max)(accum))); 0104 return maxError < 0.10; // Error is less than 10% 0105 } 0106 0107 void KisBSplinesTest::test2D() 0108 { 0109 const qreal start = 1.0; 0110 const qreal end = 11.0; 0111 0112 KisBSpline2D spline(start, end, 10, Natural, 0113 start, end, 10, Natural); 0114 0115 FunctionOp op; 0116 spline.initializeSpline(op); 0117 0118 QVERIFY(test2DSpline(spline, op, start, end)); 0119 0120 dbgKrita << "Resampled"; 0121 0122 QScopedPointer<KisBSpline2D> resampledSpline( 0123 KisBSpline2D::createResampledSpline(spline, 7, 7)); 0124 0125 QVERIFY(test2DSpline(*resampledSpline.data(), op, start, end)); 0126 } 0127 0128 void KisBSplinesTest::testEmpty2D() 0129 { 0130 const qreal start = 1.0; 0131 const qreal end = 11.0; 0132 KisBSpline2D spline(start, end, 10, Natural, 0133 start, end, 10, Natural); 0134 // just let it be destructed uninitialized 0135 } 0136 0137 void KisBSplinesTest::testNU2D() 0138 { 0139 const qreal start = 1.0; 0140 const qreal end = 11.0; 0141 0142 QVector<double> samples; 0143 0144 double v = start; 0145 int i = 1; 0146 do { 0147 samples << v; 0148 v += (0.1 * i++); 0149 } while (v < end); 0150 0151 samples << end; 0152 0153 KisNUBSpline2D spline(samples, Natural, 0154 samples, Natural); 0155 FunctionOp op; 0156 spline.initializeSpline(op); 0157 0158 QVERIFY(test2DSpline(spline, op, start, end)); 0159 0160 dbgKrita << "Resampled"; 0161 0162 QScopedPointer<KisBSpline2D> resampledSpline( 0163 KisBSpline2D::createResampledSpline(spline, 7, 7)); 0164 0165 QVERIFY(test2DSpline(*resampledSpline.data(), op, start, end)); 0166 0167 } 0168 0169 SIMPLE_TEST_MAIN(KisBSplinesTest)