File indexing completed on 2024-05-05 03:48:44
0001 /* 0002 File : NSLGeomTest.cpp 0003 Project : LabPlot 0004 Description : NSL Tests for geometric functions 0005 -------------------------------------------------------------------- 0006 SPDX-FileCopyrightText: 2019 Stefan Gerlach <stefan.gerlach@uni.kn> 0007 0008 SPDX-License-Identifier: GPL-2.0-or-later 0009 */ 0010 0011 #include "NSLGeomTest.h" 0012 0013 extern "C" { 0014 #include "backend/nsl/nsl_geom.h" 0015 #include "backend/nsl/nsl_geom_linesim.h" 0016 } 0017 0018 void NSLGeomTest::initTestCase() { 0019 const QString currentDir = QLatin1String(__FILE__); 0020 m_dataDir = currentDir.left(currentDir.lastIndexOf(QDir::separator())) + QDir::separator() + QLatin1String("data") + QDir::separator(); 0021 } 0022 0023 // ############################################################################## 0024 // ################# line sim test 0025 // ############################################################################## 0026 0027 void NSLGeomTest::testDist() { 0028 double dist = nsl_geom_point_point_dist(0, 0, 1, 1); 0029 QCOMPARE(dist, M_SQRT2); 0030 dist = nsl_geom_point_point_dist(1, 2, 2, 1); 0031 QCOMPARE(dist, M_SQRT2); 0032 dist = nsl_geom_point_point_dist(-1, -2, 2, 2); 0033 QCOMPARE(dist, 5.); 0034 0035 dist = nsl_geom_point_line_dist(0, 0, 1, 0, .5, 1); 0036 QCOMPARE(dist, 1.); 0037 dist = nsl_geom_point_line_dist(0, 0, 1, 0, 0, 1); 0038 QCOMPARE(dist, 1.); 0039 dist = nsl_geom_point_line_dist(0, 0, 1, 0, 1, 1); 0040 QCOMPARE(dist, 1.); 0041 dist = nsl_geom_point_line_dist(0, 0, 1, 1, 0, 1); 0042 QCOMPARE(dist, M_SQRT1_2); 0043 dist = nsl_geom_point_line_dist(0, 0, 1, 1, 1, 0); 0044 QCOMPARE(dist, M_SQRT1_2); 0045 0046 // TODO: nsl_geom_point_line_dist_y 0047 // TODO: nsl_geom_three_point_area 0048 0049 dist = nsl_geom_point_point_dist3(0, 0, 0, 1, 1, 1); 0050 QCOMPARE(dist, M_SQRT3); 0051 dist = nsl_geom_point_point_dist3(-1, -1, 1, 1, 1, 1); 0052 QCOMPARE(dist, 2. * M_SQRT2); 0053 } 0054 0055 void NSLGeomTest::testLineSim() { 0056 const double xdata[] = {1, 2, 2.5, 3, 4, 7, 9, 11, 13, 14}; 0057 const double ydata[] = {1, 1, 1, 3, 4, 7, 8, 12, 13, 13}; 0058 const size_t n = 10; 0059 0060 double atol = nsl_geom_linesim_clip_diag_perpoint(xdata, ydata, n); 0061 printf("automatic tol clip_diag_perpoint = %.15g\n", atol); 0062 QCOMPARE(atol, 1.76918060129541); 0063 atol = nsl_geom_linesim_clip_area_perpoint(xdata, ydata, n); 0064 printf("automatic tol clip_area_perpoint = %.15g\n", atol); 0065 QCOMPARE(atol, 15.6); 0066 atol = nsl_geom_linesim_avg_dist_perpoint(xdata, ydata, n); 0067 printf("automatic tol avg_dist = %.15g\n", atol); 0068 QCOMPARE(atol, 1.91626789723004); 0069 0070 size_t index[n], i; 0071 const double tol = 0.6; 0072 const size_t result[] = {0, 2, 3, 6, 7, 9}; 0073 printf("* Simplification (Douglas Peucker)\n"); 0074 size_t nout = nsl_geom_linesim_douglas_peucker(xdata, ydata, n, tol, index); 0075 double perr = nsl_geom_linesim_positional_squared_error(xdata, ydata, n, index); 0076 double aerr = nsl_geom_linesim_area_error(xdata, ydata, n, index); 0077 printf("pos. error = %.15g, area error = %.15g\n", perr, aerr); 0078 QCOMPARE(nout, 6uL); 0079 QCOMPARE(perr, 0.0378688524590164); 0080 QCOMPARE(aerr, 0.25); 0081 0082 for (i = 0; i < nout; ++i) 0083 QCOMPARE(index[i], result[i]); 0084 0085 const size_t no = 6; 0086 printf("* Simplification (Douglas Peucker variant) nout = %zu\n", no); 0087 double tolout = nsl_geom_linesim_douglas_peucker_variant(xdata, ydata, n, no, index); 0088 perr = nsl_geom_linesim_positional_squared_error(xdata, ydata, n, index); 0089 aerr = nsl_geom_linesim_area_error(xdata, ydata, n, index); 0090 printf("tolout = %.15g, pos. error = %.15g, area error = %.15g)\n", tolout, perr, aerr); 0091 QCOMPARE(tolout, 0.994505452921406); 0092 QCOMPARE(perr, 0.0378688524590164); 0093 QCOMPARE(aerr, 0.25); 0094 0095 for (i = 0; i < no; ++i) 0096 QCOMPARE(index[i], result[i]); 0097 0098 const size_t np = 2; 0099 const size_t result2[] = {0, 2, 4, 6, 8, 9}; 0100 printf("* N-th point\n"); 0101 nout = nsl_geom_linesim_nthpoint(n, np, index); 0102 perr = nsl_geom_linesim_positional_squared_error(xdata, ydata, n, index); 0103 aerr = nsl_geom_linesim_area_error(xdata, ydata, n, index); 0104 printf("pos. error = %.15g, area error = %.15g\n", perr, aerr); 0105 QCOMPARE(nout, 6uL); 0106 QCOMPARE(perr, 0.129756097560976); 0107 QCOMPARE(aerr, 0.525); 0108 0109 for (i = 0; i < nout; ++i) 0110 QCOMPARE(index[i], result2[i]); 0111 0112 const double tol2 = 1.5; 0113 const size_t result3[] = {0, 3, 5, 6, 7, 9}; 0114 printf("* Radial distance (tol = %g)\n", tol2); 0115 nout = nsl_geom_linesim_raddist(xdata, ydata, n, tol2, index); 0116 perr = nsl_geom_linesim_positional_squared_error(xdata, ydata, n, index); 0117 aerr = nsl_geom_linesim_area_error(xdata, ydata, n, index); 0118 printf("pos. error = %.15g, area error = %.15g\n", perr, aerr); 0119 QCOMPARE(nout, 6uL); 0120 QCOMPARE(perr, 0.1725); 0121 QCOMPARE(aerr, 0.2); 0122 0123 for (i = 0; i < nout; ++i) 0124 QCOMPARE(index[i], result3[i]); 0125 0126 const double tol3 = 0.5; 0127 const size_t repeat = 3; 0128 const size_t result4[] = {0, 2, 4, 6, 7, 9}; 0129 printf("* Perpendicular distance (repeat = %zu)\n", repeat); 0130 nout = nsl_geom_linesim_perpdist_repeat(xdata, ydata, n, tol3, repeat, index); 0131 perr = nsl_geom_linesim_positional_squared_error(xdata, ydata, n, index); 0132 aerr = nsl_geom_linesim_area_error(xdata, ydata, n, index); 0133 printf("pos. error = %.15g, area error = %.15g\n", perr, aerr); 0134 QCOMPARE(nout, 6uL); 0135 QCOMPARE(perr, 0.0519512195121951); 0136 QCOMPARE(aerr, 0.275); 0137 0138 for (i = 0; i < nout; ++i) 0139 QCOMPARE(index[i], result4[i]); 0140 0141 const double tol4 = 0.7; 0142 printf("* Y distance (interpolation)\n"); 0143 nout = nsl_geom_linesim_interp(xdata, ydata, n, tol4, index); 0144 perr = nsl_geom_linesim_positional_squared_error(xdata, ydata, n, index); 0145 aerr = nsl_geom_linesim_area_error(xdata, ydata, n, index); 0146 printf("pos. error = %.15g, area error = %.15g\n", perr, aerr); 0147 QCOMPARE(nout, 6uL); 0148 QCOMPARE(perr, 0.0378688524590164); 0149 QCOMPARE(aerr, 0.25); 0150 0151 for (i = 0; i < nout; ++i) 0152 QCOMPARE(index[i], result[i]); 0153 0154 const double tol5 = 1.6; 0155 printf("* minimum area (Visvalingam-Whyatt)\n"); 0156 nout = nsl_geom_linesim_visvalingam_whyatt(xdata, ydata, n, tol5, index); 0157 perr = nsl_geom_linesim_positional_squared_error(xdata, ydata, n, index); 0158 aerr = nsl_geom_linesim_area_error(xdata, ydata, n, index); 0159 printf("pos. error = %.15g, area error = %.15g\n", perr, aerr); 0160 QCOMPARE(nout, 6uL); 0161 QCOMPARE(perr, 0.1725); 0162 QCOMPARE(aerr, 0.2); 0163 0164 // nout can be up to 10 when third arg of nsl_geom_linesim_visvalingam_whyatt() is 10 0165 for (i = 0; i < std::min(nout, (size_t)6uL); ++i) 0166 QCOMPARE(index[i], result3[i]); 0167 0168 const size_t result5[] = {0, 2, 3, 5, 6, 7, 9}; 0169 printf("* Perp. distance (Reumann-Witkam)\n"); 0170 nout = nsl_geom_linesim_reumann_witkam(xdata, ydata, n, tol3, index); 0171 perr = nsl_geom_linesim_positional_squared_error(xdata, ydata, n, index); 0172 aerr = nsl_geom_linesim_area_error(xdata, ydata, n, index); 0173 printf("pos. error = %.15g, area error = %.15g\n", perr, aerr); 0174 QCOMPARE(nout, 7uL); 0175 QCOMPARE(perr, 0.01); 0176 QCOMPARE(aerr, 0.05); 0177 0178 for (i = 0; i < nout; ++i) 0179 QCOMPARE(index[i], result5[i]); 0180 0181 const double mintol = 2.0; 0182 const double maxtol = 7.0; 0183 printf("* Perp. distance (Opheim)\n"); 0184 nout = nsl_geom_linesim_opheim(xdata, ydata, n, mintol, maxtol, index); 0185 perr = nsl_geom_linesim_positional_squared_error(xdata, ydata, n, index); 0186 aerr = nsl_geom_linesim_area_error(xdata, ydata, n, index); 0187 printf("pos. error = %.15g, area error = %.15g\n", perr, aerr); 0188 QCOMPARE(nout, 6uL); 0189 QCOMPARE(perr, 0.129756097560976); 0190 QCOMPARE(aerr, 0.525); 0191 0192 for (i = 0; i < nout; ++i) 0193 QCOMPARE(index[i], result2[i]); 0194 0195 const size_t region = 5; 0196 printf("* Simplification (Lang)\n"); 0197 nout = nsl_geom_linesim_lang(xdata, ydata, n, tol3, region, index); 0198 perr = nsl_geom_linesim_positional_squared_error(xdata, ydata, n, index); 0199 aerr = nsl_geom_linesim_area_error(xdata, ydata, n, index); 0200 printf("pos. error = %.15g, area error = %.15g\n", perr, aerr); 0201 QCOMPARE(nout, 6uL); 0202 QCOMPARE(perr, 0.0519512195121951); 0203 QCOMPARE(aerr, 0.275); 0204 0205 for (i = 0; i < nout; ++i) 0206 QCOMPARE(index[i], result4[i]); 0207 } 0208 0209 #ifdef _MSC_VER // crashes on Windows 0210 void NSLGeomTest::testLineSimMorse() { 0211 } 0212 #else 0213 void NSLGeomTest::testLineSimMorse() { 0214 printf("NSLGeomTest::testLineSimMorse()\n"); 0215 0216 const QString fileName = m_dataDir + QStringLiteral("morse_code.dat"); 0217 FILE* file; 0218 if ((file = fopen(fileName.toLocal8Bit().constData(), "r")) == nullptr) { 0219 printf("ERROR reading %s. Giving up.\n", fileName.toLocal8Bit().constData()); 0220 return; 0221 } 0222 0223 const int N = 152000; 0224 const int NOUT = 15200; 0225 0226 printf("NSLGeomTest::testLineSimMorse(): allocating space for reading data\n"); 0227 QScopedArrayPointer<double> xdata(new double[N]); 0228 QScopedArrayPointer<double> ydata(new double[N]); 0229 0230 printf("NSLGeomTest::testLineSimMorse(): reading data from file\n"); 0231 size_t i; 0232 for (i = 0; i < N; i++) { 0233 int num = fscanf(file, "%lf %lf", &xdata[i], &ydata[i]); 0234 if (num != 2) { // failed to read two values 0235 printf("ERROR reading data\n"); 0236 fclose(file); 0237 return; 0238 } 0239 } 0240 fclose(file); 0241 0242 double atol = nsl_geom_linesim_clip_diag_perpoint(xdata.data(), ydata.data(), N); 0243 printf("automatic tol clip_diag_perpoint = %.15g\n", atol); 0244 QCOMPARE(atol, 0.999993446759985); 0245 atol = nsl_geom_linesim_clip_area_perpoint(xdata.data(), ydata.data(), N); 0246 printf("automatic tol clip_area_perpoint = %.15g\n", atol); 0247 QCOMPARE(atol, 34.4653732526316); 0248 atol = nsl_geom_linesim_avg_dist_perpoint(xdata.data(), ydata.data(), N); 0249 printf("automatic tol avg_dist = %.15g\n", atol); 0250 QCOMPARE(atol, 4.72091524721907); 0251 0252 printf("* Simplification (Douglas Peucker variant) nout = %d\n", NOUT); 0253 0254 double tolout; 0255 size_t index[N]; 0256 QBENCHMARK { 0257 tolout = nsl_geom_linesim_douglas_peucker_variant(xdata.data(), ydata.data(), N, NOUT, index); 0258 QCOMPARE(tolout, 11.5280857733246); 0259 } 0260 0261 double perr = nsl_geom_linesim_positional_squared_error(xdata.data(), ydata.data(), N, index); 0262 double aerr = nsl_geom_linesim_area_error(xdata.data(), ydata.data(), N, index); 0263 printf("maxtol = %.15g (pos. error = %.15g, area error = %.15g)\n", tolout, perr, aerr); 0264 QCOMPARE(perr, 11.9586266895937); 0265 QCOMPARE(aerr, 17.558046450762); 0266 } 0267 #endif 0268 0269 // ############################################################################## 0270 // ################# performance 0271 // ############################################################################## 0272 0273 QTEST_MAIN(NSLGeomTest)