File indexing completed on 2024-05-12 03:47:52
0001 /* 0002 File : nsl_geom_linesim.c 0003 Project : LabPlot 0004 Description : NSL geometry line simplification functions 0005 -------------------------------------------------------------------- 0006 SPDX-FileCopyrightText: 2016-2019 Stefan Gerlach <stefan.gerlach@uni.kn> 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 #include "nsl_geom_linesim.h" 0011 #include "nsl_common.h" 0012 #include "nsl_geom.h" 0013 #include "nsl_sort.h" 0014 #include "nsl_stats.h" 0015 0016 const char* nsl_geom_linesim_type_name[] = {i18n("Douglas-Peucker (Number)"), 0017 i18n("Douglas-Peucker (Tolerance)"), 0018 i18n("Visvalingam-Whyatt"), 0019 i18n("Reumann-Witkam"), 0020 i18n("Perpendicular Distance"), 0021 i18n("n-th Point"), 0022 i18n("Radial Distance"), 0023 i18n("Interpolation"), 0024 i18n("Opheim"), 0025 i18n("Lang")}; 0026 0027 /*********** error calculation functions *********/ 0028 0029 double nsl_geom_linesim_positional_error(const double xdata[], const double ydata[], const size_t n, const size_t index[]) { 0030 double dist = 0; 0031 size_t i = 0, j; /* i: index of index[] */ 0032 do { 0033 /*for every point not in index[] calculate distance to line*/ 0034 /*printf("i=%d (index[i]-index[i+1]=%d-%d)\n", i , index[i], index[i+1]);*/ 0035 for (j = 1; j < index[i + 1] - index[i]; j++) { 0036 /*printf("i=%d: j=%d\n", i, j);*/ 0037 dist += 0038 nsl_geom_point_line_dist(xdata[index[i]], ydata[index[i]], xdata[index[i + 1]], ydata[index[i + 1]], xdata[index[i] + j], ydata[index[i] + j]); 0039 /*printf("dist = %g\n", dist);*/ 0040 } 0041 i++; 0042 } while (index[i] != n - 1); 0043 0044 return dist / (double)n; 0045 } 0046 0047 double nsl_geom_linesim_positional_squared_error(const double xdata[], const double ydata[], const size_t n, const size_t index[]) { 0048 double dist = 0; 0049 size_t i = 0, j; /* i: index of index[] */ 0050 do { 0051 /*for every point not in index[] calculate distance to line*/ 0052 /*printf("i=%d (index[i]-index[i+1]=%d-%d)\n", i , index[i], index[i+1]);*/ 0053 for (j = 1; j < index[i + 1] - index[i]; j++) { 0054 /*printf("i=%d: j=%d\n", i, j);*/ 0055 dist += pow( 0056 nsl_geom_point_line_dist(xdata[index[i]], ydata[index[i]], xdata[index[i + 1]], ydata[index[i + 1]], xdata[index[i] + j], ydata[index[i] + j]), 0057 2); 0058 /*printf("dist = %g\n", dist);*/ 0059 } 0060 i++; 0061 } while (index[i] != n - 1); 0062 0063 return dist / (double)n; 0064 } 0065 0066 double nsl_geom_linesim_area_error(const double xdata[], const double ydata[], const size_t n, const size_t index[]) { 0067 double area = 0; 0068 0069 size_t i = 0, j; /* i: index of index[] */ 0070 do { 0071 /* for every point not in index[] calculate area */ 0072 /*printf("i=%d (index[i]-index[i+1]=%d-%d)\n", i , index[i], index[i+1]);*/ 0073 for (j = 1; j < index[i + 1] - index[i]; j++) { 0074 /*printf("j=%d: area between %d %d %d\n", j, index[i]+j-1, index[i]+j, index[i+1]);*/ 0075 area += nsl_geom_three_point_area(xdata[index[i] + j - 1], 0076 ydata[index[i] + j - 1], 0077 xdata[index[i] + j], 0078 ydata[index[i] + j], 0079 xdata[index[i + 1]], 0080 ydata[index[i + 1]]); 0081 /*printf("area = %g\n", area);*/ 0082 } 0083 i++; 0084 } while (index[i] != n - 1); 0085 0086 return area / (double)n; 0087 } 0088 0089 double nsl_geom_linesim_clip_diag_perpoint(const double xdata[], const double ydata[], const size_t n) { 0090 double dx = nsl_stats_maximum(xdata, n, NULL) - nsl_stats_minimum(xdata, n, NULL); 0091 double dy = nsl_stats_maximum(ydata, n, NULL) - nsl_stats_minimum(ydata, n, NULL); 0092 double d = sqrt(dx * dx + dy * dy); 0093 0094 return d / (double)n; /* per point */ 0095 } 0096 0097 double nsl_geom_linesim_clip_area_perpoint(const double xdata[], const double ydata[], const size_t n) { 0098 double dx = nsl_stats_maximum(xdata, n, NULL) - nsl_stats_minimum(xdata, n, NULL); 0099 double dy = nsl_stats_maximum(ydata, n, NULL) - nsl_stats_minimum(ydata, n, NULL); 0100 double A = dx * dy; 0101 0102 return A / (double)n; /* per point */ 0103 } 0104 0105 double nsl_geom_linesim_avg_dist_perpoint(const double xdata[], const double ydata[], const size_t n) { 0106 double dist = 0; 0107 size_t i; 0108 for (i = 0; i < n - 1; i++) { 0109 double dx = xdata[i + 1] - xdata[i]; 0110 double dy = ydata[i + 1] - ydata[i]; 0111 dist += sqrt(dx * dx + dy * dy); 0112 } 0113 dist /= (double)n; 0114 0115 return dist; 0116 } 0117 0118 /*********** simplification algorithms *********/ 0119 0120 void nsl_geom_linesim_douglas_peucker_step(const double xdata[], 0121 const double ydata[], 0122 const size_t start, 0123 const size_t end, 0124 size_t* nout, 0125 const double tol, 0126 size_t index[]) { 0127 /*printf("DP: %d - %d\n", start, end);*/ 0128 0129 size_t i, nkey = start; 0130 double maxdist = 0; 0131 /* search for key (biggest perp. distance) */ 0132 for (i = start + 1; i < end; i++) { 0133 double dist = nsl_geom_point_line_dist(xdata[start], ydata[start], xdata[end], ydata[end], xdata[i], ydata[i]); 0134 if (dist > maxdist) { 0135 maxdist = dist; 0136 nkey = i; 0137 } 0138 } 0139 /*printf("maxdist = %g @ i = %zu\n", maxdist, nkey);*/ 0140 0141 if (maxdist > tol) { 0142 /*printf("take %d\n", nkey);*/ 0143 index[(*nout)++] = nkey; 0144 if (nkey - start > 1) 0145 nsl_geom_linesim_douglas_peucker_step(xdata, ydata, start, nkey, nout, tol, index); 0146 if (end - nkey > 1) 0147 nsl_geom_linesim_douglas_peucker_step(xdata, ydata, nkey, end, nout, tol, index); 0148 } 0149 0150 /*printf("nout=%d\n", *nout);*/ 0151 } 0152 0153 size_t nsl_geom_linesim_douglas_peucker(const double xdata[], const double ydata[], const size_t n, const double tol, size_t index[]) { 0154 size_t nout = 0; 0155 0156 /*first point*/ 0157 index[nout++] = 0; 0158 0159 nsl_geom_linesim_douglas_peucker_step(xdata, ydata, 0, n - 1, &nout, tol, index); 0160 0161 /* last point */ 0162 if (index[nout - 1] != n - 1) 0163 index[nout++] = n - 1; 0164 0165 /* sort array index */ 0166 nsl_sort_size_t(index, nout); 0167 0168 return nout; 0169 } 0170 size_t nsl_geom_linesim_douglas_peucker_auto(const double xdata[], const double ydata[], const size_t n, size_t index[]) { 0171 double tol = nsl_geom_linesim_clip_diag_perpoint(xdata, ydata, n); 0172 return nsl_geom_linesim_douglas_peucker(xdata, ydata, n, tol, index); 0173 } 0174 0175 /* 0176 * Douglas-Peucker variant: 0177 * The key of all egdes of the current simplified line is calculated and only the 0178 * largest is added. This is repeated until nout is reached. 0179 * */ 0180 double nsl_geom_linesim_douglas_peucker_variant(const double xdata[], const double ydata[], const size_t n, const size_t nout, size_t index[]) { 0181 size_t i; 0182 if (nout >= n) { /* use all points */ 0183 for (i = 0; i < n; i++) 0184 index[i] = i; 0185 return 0; 0186 } 0187 0188 /* set first and last point in index (other indizes not initialized) */ 0189 size_t ncount = 0; 0190 index[ncount++] = 0; 0191 index[ncount++] = n - 1; 0192 0193 if (nout <= 2) /* use only first and last point (perp. dist is zero) */ 0194 return 0.0; 0195 0196 double* dist = (double*)malloc(n * sizeof(double)); 0197 if (dist == NULL) { 0198 /* printf("nsl_geom_linesim_douglas_peucker_variant(): ERROR allocating memory for 'dist'!\n"); */ 0199 return DBL_MAX; 0200 } 0201 0202 double* maxdist = (double*)malloc(nout * sizeof(double)); /* max dist per edge */ 0203 if (maxdist == NULL) { 0204 /* printf("nsl_geom_linesim_douglas_peucker_variant(): ERROR allocating memory for 'maxdist'!\n"); */ 0205 free(dist); 0206 return DBL_MAX; 0207 } 0208 0209 for (i = 0; i < n; i++) { /* initialize dist */ 0210 dist[i] = nsl_geom_point_line_dist(xdata[0], ydata[0], xdata[n - 1], ydata[n - 1], xdata[i], ydata[i]); 0211 /* printf("nsl_geom_linesim_douglas_peucker_variant(): %zu dist = %g\n", i, dist[i]); */ 0212 } 0213 for (i = 0; i < nout; i++) 0214 maxdist[i] = 0; 0215 0216 double newmaxdist = 0; 0217 do { 0218 /* printf("nsl_geom_linesim_douglas_peucker_variant(): NEXT ITERATION\n"); */ 0219 size_t key = 0; 0220 0221 /* find edge of maximum */ 0222 size_t maxindex; 0223 nsl_stats_maximum(maxdist, ncount, &maxindex); 0224 /* printf("nsl_geom_linesim_douglas_peucker_variant(): found edge with max dist at index %zu\n", maxindex); */ 0225 /*newmaxdist = nsl_stats_maximum(dist, n, &key);*/ 0226 newmaxdist = 0; 0227 for (i = index[maxindex] + 1; i < index[maxindex + 1]; i++) { 0228 /* printf("nsl_geom_linesim_douglas_peucker_variant(): iterate i=%zu\n", i); */ 0229 if (dist[i] > newmaxdist) { 0230 newmaxdist = dist[i]; 0231 key = i; 0232 } 0233 } 0234 0235 /* printf("nsl_geom_linesim_douglas_peucker_variant(): found key %zu (dist = %g)\n", key, newmaxdist); */ 0236 ncount++; 0237 dist[key] = 0; 0238 0239 /* find index of previous key */ 0240 size_t previndex = 0; 0241 while (index[previndex + 1] < key) 0242 previndex++; 0243 /* printf("nsl_geom_linesim_douglas_peucker_variant(): previndex = %zu (update keys %zu - %zu)\n", previndex, index[previndex], index[previndex+1]); */ 0244 0245 size_t v; 0246 /* printf("nsl_geom_linesim_douglas_peucker_variant(): ncount = %zu, previndex = %zu\n", ncount, previndex); */ 0247 /* update dist[]. no update on last key */ 0248 if (ncount < nout) { 0249 /* shift maxdist */ 0250 for (v = ncount; v > previndex; v--) 0251 maxdist[v] = maxdist[v - 1]; 0252 0253 double tmpmax = 0; 0254 for (v = index[previndex] + 1; v < key; v++) { 0255 /* printf("nsl_geom_linesim_douglas_peucker_variant(): %zu in %zu - %zu", v, index[previndex], key); */ 0256 dist[v] = nsl_geom_point_line_dist(xdata[index[previndex]], ydata[index[previndex]], xdata[key], ydata[key], xdata[v], ydata[v]); 0257 if (dist[v] > tmpmax) 0258 tmpmax = dist[v]; 0259 0260 /* printf(" dist = %g\n", dist[v]); */ 0261 } 0262 maxdist[previndex] = tmpmax; 0263 0264 tmpmax = 0; 0265 for (v = key + 1; v < index[previndex + 1]; v++) { 0266 /* printf("nsl_geom_linesim_douglas_peucker_variant(): %zu in %zu - %zu", v, key, index[previndex+1]); */ 0267 dist[v] = nsl_geom_point_line_dist(xdata[key], ydata[key], xdata[index[previndex + 1]], ydata[index[previndex + 1]], xdata[v], ydata[v]); 0268 if (dist[v] > tmpmax) 0269 tmpmax = dist[v]; 0270 /* printf(" dist = %g\n", dist[v]); */ 0271 } 0272 maxdist[previndex + 1] = tmpmax; 0273 } 0274 0275 /* put into index array */ 0276 for (v = ncount; v > previndex + 1; v--) 0277 index[v] = index[v - 1]; 0278 index[previndex + 1] = key; 0279 } while (ncount < nout); 0280 0281 free(maxdist); 0282 free(dist); 0283 0284 return newmaxdist; 0285 } 0286 0287 size_t nsl_geom_linesim_nthpoint(const size_t n, const int step, size_t index[]) { 0288 if (step < 1) { 0289 printf("step size must be > 0 (given: %d)\n", step); 0290 return 0; 0291 } 0292 0293 size_t i, nout = 0; 0294 0295 /*first point*/ 0296 index[nout++] = 0; 0297 0298 for (i = 1; i < n - 1; i++) 0299 if (i % step == 0) 0300 index[nout++] = i; 0301 0302 /* last point */ 0303 index[nout++] = n - 1; 0304 0305 return nout; 0306 } 0307 0308 size_t nsl_geom_linesim_raddist(const double xdata[], const double ydata[], const size_t n, const double tol, size_t index[]) { 0309 size_t i, nout = 0, key = 0; 0310 0311 /*first point*/ 0312 index[nout++] = 0; 0313 0314 for (i = 1; i < n - 1; i++) { 0315 /* distance to key point */ 0316 double dist = nsl_geom_point_point_dist(xdata[i], ydata[i], xdata[key], ydata[key]); 0317 /* distance to last point */ 0318 double lastdist = nsl_geom_point_point_dist(xdata[i], ydata[i], xdata[n - 1], ydata[n - 1]); 0319 /*printf("%d: %g %g\n", i, dist, lastdist);*/ 0320 0321 if (dist > tol && lastdist > tol) { 0322 index[nout++] = i; 0323 key = i; 0324 } 0325 } 0326 0327 /* last point */ 0328 index[nout++] = n - 1; 0329 0330 return nout; 0331 } 0332 size_t nsl_geom_linesim_raddist_auto(const double xdata[], const double ydata[], const size_t n, size_t index[]) { 0333 double tol = 10. * nsl_geom_linesim_clip_diag_perpoint(xdata, ydata, n); 0334 return nsl_geom_linesim_raddist(xdata, ydata, n, tol, index); 0335 } 0336 0337 size_t nsl_geom_linesim_perpdist(const double xdata[], const double ydata[], const size_t n, const double tol, size_t index[]) { 0338 size_t nout = 0, key = 0, i; 0339 0340 /*first point*/ 0341 index[nout++] = 0; 0342 0343 for (i = 1; i < n - 1; i++) { 0344 /* distance of point i to line key -- i+1 */ 0345 double dist = nsl_geom_point_line_dist(xdata[key], ydata[key], xdata[i + 1], ydata[i + 1], xdata[i], ydata[i]); 0346 /*printf("%d: %g\n", i, dist);*/ 0347 0348 if (dist > tol) { /* take it */ 0349 index[nout++] = i; 0350 key = i; 0351 /*printf("%d: take it (key = %d)\n", i, key);*/ 0352 } else { /* ignore it */ 0353 if (i + 1 < n - 1) /* last point is taken anyway */ 0354 index[nout++] = i + 1; /* take next point in any case */ 0355 /*printf("%d: ignore it (key = %d)\n", i, i+1);*/ 0356 key = ++i; 0357 } 0358 } 0359 0360 /* last point */ 0361 index[nout++] = n - 1; 0362 0363 return nout; 0364 } 0365 size_t nsl_geom_linesim_perpdist_auto(const double xdata[], const double ydata[], const size_t n, size_t index[]) { 0366 double tol = nsl_geom_linesim_clip_diag_perpoint(xdata, ydata, n); 0367 return nsl_geom_linesim_perpdist(xdata, ydata, n, tol, index); 0368 } 0369 0370 size_t nsl_geom_linesim_perpdist_repeat(const double xdata[], const double ydata[], const size_t n, const double tol, const size_t repeat, size_t index[]) { 0371 size_t i, j, nout; 0372 double* xtmp = (double*)malloc(n * sizeof(double)); 0373 if (xtmp == NULL) { 0374 printf("nsl_geom_linesim_perpdist_repeat(): ERROR allocating memory for 'xtmp'!\n"); 0375 return 0; 0376 } 0377 0378 double* ytmp = (double*)malloc(n * sizeof(double)); 0379 if (ytmp == NULL) { 0380 printf("nsl_geom_linesim_perpdist_repeat(): ERROR allocating memory for 'ytmp'!\n"); 0381 free(xtmp); 0382 return 0; 0383 } 0384 0385 size_t* tmpindex = (size_t*)malloc(n * sizeof(size_t)); 0386 if (tmpindex == NULL) { 0387 printf("nsl_geom_linesim_perpdist_repeat(): ERROR allocating memory for 'tmpindex'!\n"); 0388 free(xtmp); 0389 free(ytmp); 0390 return 0; 0391 } 0392 0393 /* first round */ 0394 nout = nsl_geom_linesim_perpdist(xdata, ydata, n, tol, index); 0395 /* repeats */ 0396 for (i = 0; i < repeat - 1; i++) { 0397 for (j = 0; j < nout; j++) { 0398 xtmp[j] = xdata[index[j]]; 0399 ytmp[j] = ydata[index[j]]; 0400 tmpindex[j] = index[j]; 0401 /*printf("%g %g\n", xtmp[j], ytmp[j]);*/ 0402 } 0403 size_t tmpnout = nsl_geom_linesim_perpdist(xtmp, ytmp, nout, tol, tmpindex); 0404 for (j = 0; j < tmpnout; j++) { 0405 index[j] = index[tmpindex[j]]; 0406 /*printf("tmpindex[%d]: %d\n", j, tmpindex[j]);*/ 0407 } 0408 0409 if (tmpnout == nout) /* return if nout does not change anymore */ 0410 break; 0411 else 0412 nout = tmpnout; 0413 } 0414 0415 free(tmpindex); 0416 free(xtmp); 0417 free(ytmp); 0418 0419 return nout; 0420 } 0421 0422 size_t nsl_geom_linesim_interp(const double xdata[], const double ydata[], const size_t n, const double tol, size_t index[]) { 0423 size_t i, nout = 0; 0424 0425 /*first point*/ 0426 index[nout++] = 0; 0427 0428 size_t key = 0; 0429 for (i = 1; i < n - 1; i++) { 0430 /*printf("%d: %d-%d\n", i, key, i+1);*/ 0431 double dist = nsl_geom_point_line_dist_y(xdata[key], ydata[key], xdata[i + 1], ydata[i + 1], xdata[i], ydata[i]); 0432 /*printf("%d: dist = %g\n", i, dist);*/ 0433 if (dist > tol) { 0434 /*printf("take it %d\n", i);*/ 0435 index[nout++] = key = i; 0436 } 0437 } 0438 0439 /* last point */ 0440 index[nout++] = n - 1; 0441 0442 return nout; 0443 } 0444 size_t nsl_geom_linesim_interp_auto(const double xdata[], const double ydata[], const size_t n, size_t index[]) { 0445 double tol = nsl_geom_linesim_clip_diag_perpoint(xdata, ydata, n); 0446 return nsl_geom_linesim_interp(xdata, ydata, n, tol, index); 0447 } 0448 0449 size_t nsl_geom_linesim_visvalingam_whyatt(const double xdata[], const double ydata[], const size_t n, const double tol, size_t index[]) { 0450 if (n < 3) /* we need at least three points */ 0451 return 0; 0452 0453 size_t i, nout = n; 0454 double* area = (double*)malloc((n - 2) * sizeof(double)); /* area associated with every point */ 0455 if (area == NULL) { 0456 printf("nsl_geom_linesim_visvalingam_whyatt(): ERROR allocating memory!\n"); 0457 return 0; 0458 } 0459 for (i = 0; i < n; i++) 0460 index[i] = i; 0461 for (i = 1; i < n - 1; i++) 0462 area[i - 1] = nsl_geom_three_point_area(xdata[i - 1], ydata[i - 1], xdata[i], ydata[i], xdata[i + 1], ydata[i + 1]); 0463 0464 size_t minindex; 0465 while (nsl_stats_minimum(area, n - 2, &minindex) < tol && nout > 2) { 0466 /* double minarea; 0467 while ( (minarea = nsl_stats_minimum(area, n-2, &minindex)) < tol && nout > 2) { */ 0468 /*for (i=0; i < n-2; i++) 0469 if (area[i]<DBL_MAX) 0470 printf("area[%zu] = %g\n", i, area[i]); 0471 */ 0472 /* remove point minindex */ 0473 /*printf("removing point %zu (minindex = %zu, minarea = %g) nout=%zu\n", minindex+1, minindex, minarea, nout-1);*/ 0474 index[minindex + 1] = 0; 0475 area[minindex] = DBL_MAX; 0476 double tmparea; 0477 /* update area of neigbor points */ 0478 size_t before = minindex, after = minindex + 2; /* find index before and after */ 0479 while (index[before] == 0 && before > 0) 0480 before--; 0481 while (after < n + 1 && index[after] == 0) 0482 after++; 0483 if (minindex > 0) { /*before */ 0484 if (before > 0) { 0485 size_t beforebefore = before - 1; 0486 while (index[beforebefore] == 0 && beforebefore > 0) 0487 beforebefore--; 0488 /*printf("recalculate area[%zu] from %zu %zu %zu\n", before-1, beforebefore, before, after);*/ 0489 tmparea = nsl_geom_three_point_area(xdata[beforebefore], ydata[beforebefore], xdata[before], ydata[before], xdata[after], ydata[after]); 0490 if (tmparea > area[before - 1]) /* take largest value of new and old area */ 0491 area[before - 1] = tmparea; 0492 } 0493 } 0494 if (minindex < n - 3) { /* after */ 0495 if (after < n - 1) { 0496 size_t afterafter = after + 1; 0497 while (afterafter < n - 1 && index[afterafter] == 0) 0498 afterafter++; 0499 /*printf("recalculate area[%zu] from %zu %zu %zu\n",after-1, before, after, afterafter);*/ 0500 tmparea = nsl_geom_three_point_area(xdata[before], ydata[before], xdata[after], ydata[after], xdata[afterafter], ydata[afterafter]); 0501 if (tmparea > area[after - 1]) /* take largest value of new and old area */ 0502 area[after - 1] = tmparea; 0503 } 0504 } 0505 nout--; 0506 }; 0507 0508 /*for(i=0;i<n;i++) 0509 printf("INDEX = %d\n", index[i]); 0510 */ 0511 0512 /* condens index */ 0513 i = 1; 0514 size_t newi = 1; 0515 while (newi < n - 1) { 0516 while (index[newi] == 0) 0517 newi++; 0518 index[i++] = index[newi++]; 0519 }; 0520 0521 /*for(i=0;i<nout;i++) 0522 printf("INDEX2 = %d\n", index[i]); 0523 */ 0524 0525 free(area); 0526 return nout; 0527 } 0528 size_t nsl_geom_linesim_visvalingam_whyatt_auto(const double xdata[], const double ydata[], const size_t n, size_t index[]) { 0529 double tol = nsl_geom_linesim_clip_area_perpoint(xdata, ydata, n); 0530 0531 return nsl_geom_linesim_visvalingam_whyatt(xdata, ydata, n, tol, index); 0532 } 0533 0534 size_t nsl_geom_linesim_reumann_witkam(const double xdata[], const double ydata[], const size_t n, const double tol, size_t index[]) { 0535 size_t i, nout = 0, key = 0, key2 = 1; 0536 0537 /*first point*/ 0538 index[nout++] = 0; 0539 0540 for (i = 2; i < n - 1; i++) { 0541 /* distance to line key -- key2 */ 0542 double dist = nsl_geom_point_line_dist(xdata[key], ydata[key], xdata[key2], ydata[key2], xdata[i], ydata[i]); 0543 /*printf("%d: %g\n", i, dist);*/ 0544 0545 if (dist > tol) { /* take it */ 0546 /*printf("%d: take it\n", i);*/ 0547 key = i - 1; 0548 key2 = i; 0549 index[nout++] = i - 1; 0550 } 0551 } 0552 0553 /* last point */ 0554 index[nout++] = n - 1; 0555 0556 return nout; 0557 } 0558 size_t nsl_geom_linesim_reumann_witkam_auto(const double xdata[], const double ydata[], const size_t n, size_t index[]) { 0559 double tol = nsl_geom_linesim_clip_diag_perpoint(xdata, ydata, n); 0560 return nsl_geom_linesim_reumann_witkam(xdata, ydata, n, tol, index); 0561 } 0562 0563 size_t nsl_geom_linesim_opheim(const double xdata[], const double ydata[], const size_t n, const double mintol, const double maxtol, size_t index[]) { 0564 size_t i, nout = 0, key = 0, key2; 0565 0566 /*first point*/ 0567 index[nout++] = 0; 0568 0569 for (i = 1; i < n - 1; i++) { 0570 double dist, perpdist; 0571 do { /* find key2 */ 0572 dist = nsl_geom_point_point_dist(xdata[key], ydata[key], xdata[i], ydata[i]); 0573 /*printf("dist = %g: %d-%d\n", dist, key, i);*/ 0574 i++; 0575 } while (dist < mintol); 0576 i--; 0577 if (key == i - 1) /*i+1 outside mintol */ 0578 key2 = i; 0579 else 0580 key2 = i - 1; /* last point inside */ 0581 /*printf("found key2 @%d\n", key2);*/ 0582 0583 do { /* find next key */ 0584 dist = nsl_geom_point_point_dist(xdata[key], ydata[key], xdata[i], ydata[i]); 0585 perpdist = nsl_geom_point_line_dist(xdata[key], ydata[key], xdata[key2], ydata[key2], xdata[i], ydata[i]); 0586 /*printf("dist = %g, perpdist=%g: %d\n", dist, perpdist, i);*/ 0587 i++; 0588 } while (dist < maxtol && perpdist < mintol); 0589 i--; 0590 if (key == i - 1) /*i+1 outside */ 0591 key = i; 0592 else { 0593 key = i - 1; 0594 i--; 0595 } 0596 /*printf("new key: %d\n", key);*/ 0597 index[nout++] = key; 0598 } 0599 0600 /* last point */ 0601 if (index[nout - 1] != n - 1) 0602 index[nout++] = n - 1; 0603 0604 return nout; 0605 } 0606 size_t nsl_geom_linesim_opheim_auto(const double xdata[], const double ydata[], const size_t n, size_t index[]) { 0607 double mintol = 10. * nsl_geom_linesim_clip_diag_perpoint(xdata, ydata, n); 0608 /* TODO: calculate max tolerance ? */ 0609 double maxtol = 5. * mintol; 0610 0611 return nsl_geom_linesim_opheim(xdata, ydata, n, mintol, maxtol, index); 0612 } 0613 0614 size_t nsl_geom_linesim_lang(const double xdata[], const double ydata[], const size_t n, const double tol, const size_t region, size_t index[]) { 0615 size_t i, j, nout = 0, key = 0; 0616 0617 /*first point*/ 0618 index[nout++] = 0; 0619 0620 double dist, maxdist; 0621 for (i = 1; i < n - 1; i++) { 0622 size_t tmpregion = region; 0623 if (key + tmpregion > n - 1) /* end of data set */ 0624 tmpregion = n - 1 - key; 0625 0626 do { 0627 maxdist = 0; 0628 for (j = 1; j < tmpregion; j++) { 0629 dist = nsl_geom_point_line_dist(xdata[key], ydata[key], xdata[key + tmpregion], ydata[key + tmpregion], xdata[key + j], ydata[key + j]); 0630 /*printf("%d: dist (%d to %d-%d) = %g\n", j, key+j, key, key+tmpregion, dist);*/ 0631 if (dist > maxdist) 0632 maxdist = dist; 0633 } 0634 /*printf("tol = %g maxdist = %g\n", tol, maxdist);*/ 0635 tmpregion--; 0636 /*printf("region = %d\n", tmpregion);*/ 0637 } while (maxdist > tol && tmpregion > 0); 0638 i += tmpregion; 0639 index[nout++] = key = i; 0640 /*printf("take it (%d) key=%d\n", i, key);*/ 0641 } 0642 0643 /* last point */ 0644 if (index[nout - 1] != n - 1) 0645 index[nout++] = n - 1; 0646 0647 return nout; 0648 } 0649 size_t nsl_geom_linesim_lang_auto(const double xdata[], const double ydata[], const size_t n, size_t index[]) { 0650 double tol = nsl_geom_linesim_clip_diag_perpoint(xdata, ydata, n); 0651 /* TODO: calculate search region */ 0652 size_t region = 0; 0653 printf("nsl_geom_linesim_lang_auto(): Not implemented yet\n"); 0654 0655 return nsl_geom_linesim_lang(xdata, ydata, n, tol, region, index); 0656 }