int main(int argc, char* argv[]) { int nin = NPOINTSIN; int nx = NX; int nout = 0; point* pin = NULL; delaunay* d = NULL; point* pout = NULL; nnhpi* nn = NULL; int cpi = -1; /* control point index */ struct timeval tv0, tv1; struct timezone tz; int i; i = 1; while (i < argc) { switch (argv[i][1]) { case 'a': i++; nn_rule = NON_SIBSONIAN; break; case 'n': i++; if (i >= argc) nn_quit("no number of data points found after -n\n"); nin = atoi(argv[i]); i++; if (i >= argc) nn_quit("no number of ouput points per side found after -i\n"); nx = atoi(argv[i]); i++; break; case 'v': i++; nn_verbose = 1; break; case 'V': i++; nn_verbose = 2; break; default: usage(); break; } } if (nin < NMIN) nin = NMIN; if (nx < NXMIN) nx = NXMIN; printf("\nTest of Natural Neighbours hashing point interpolator:\n\n"); printf(" %d data points\n", nin); printf(" %d output points\n", nx * nx); /* * generate data */ printf(" generating data:\n"); fflush(stdout); pin = malloc(nin * sizeof(point)); for (i = 0; i < nin; ++i) { point* p = &pin[i]; p->x = (double) random() / RAND_MAX; p->y = (double) random() / RAND_MAX; p->z = franke(p->x, p->y); if (nn_verbose) printf(" (%f, %f, %f)\n", p->x, p->y, p->z); } /* * triangulate */ printf(" triangulating:\n"); fflush(stdout); d = delaunay_build(nin, pin, 0, NULL, 0, NULL); /* * generate output points */ points_generate2(-0.1, 1.1, -0.1, 1.1, nx, nx, &nout, &pout); cpi = (nx / 2) * (nx + 1); gettimeofday(&tv0, &tz); /* * create interpolator */ printf(" creating interpolator:\n"); fflush(stdout); nn = nnhpi_create(d, nout); fflush(stdout); gettimeofday(&tv1, &tz); { long dt = 1000000 * (tv1.tv_sec - tv0.tv_sec) + tv1.tv_usec - tv0.tv_usec; printf(" interpolator creation time = %ld us (%.2f us / point)\n", dt, (double) dt / nout); } /* * interpolate */ printf(" interpolating:\n"); fflush(stdout); gettimeofday(&tv1, &tz); for (i = 0; i < nout; ++i) { point* p = &pout[i]; nnhpi_interpolate(nn, p); if (nn_verbose) printf(" (%f, %f, %f)\n", p->x, p->y, p->z); } fflush(stdout); gettimeofday(&tv0, &tz); { long dt = 1000000.0 * (tv0.tv_sec - tv1.tv_sec) + tv0.tv_usec - tv1.tv_usec; printf(" interpolation time = %ld us (%.2f us / point)\n", dt, (double) dt / nout); } if (!nn_verbose) printf(" control point: (%f, %f, %f) (expected z = %f)\n", pout[cpi].x, pout[cpi].y, pout[cpi].z, franke(pout[cpi].x, pout[cpi].y)); printf(" interpolating one more time:\n"); fflush(stdout); gettimeofday(&tv0, &tz); for (i = 0; i < nout; ++i) { point* p = &pout[i]; nnhpi_interpolate(nn, p); if (nn_verbose) printf(" (%f, %f, %f)\n", p->x, p->y, p->z); } fflush(stdout); gettimeofday(&tv1, &tz); { long dt = 1000000.0 * (tv1.tv_sec - tv0.tv_sec) + tv1.tv_usec - tv0.tv_usec; printf(" interpolation time = %ld us (%.2f us / point)\n", dt, (double) dt / nout); } if (!nn_verbose) printf(" control point: (%f, %f, %f) (expected z = %f)\n", pout[cpi].x, pout[cpi].y, pout[cpi].z, franke(pout[cpi].x, pout[cpi].y)); printf(" entering new data:\n"); fflush(stdout); for (i = 0; i < nin; ++i) { point* p = &pin[i]; p->z = p->x * p->x - p->y * p->y; nnhpi_modify_data(nn, p); if (nn_verbose) printf(" (%f, %f, %f)\n", p->x, p->y, p->z); } printf(" interpolating:\n"); fflush(stdout); gettimeofday(&tv1, &tz); for (i = 0; i < nout; ++i) { point* p = &pout[i]; nnhpi_interpolate(nn, p); if (nn_verbose) printf(" (%f, %f, %f)\n", p->x, p->y, p->z); } fflush(stdout); gettimeofday(&tv0, &tz); { long dt = 1000000.0 * (tv0.tv_sec - tv1.tv_sec) + tv0.tv_usec - tv1.tv_usec; printf(" interpolation time = %ld us (%.2f us / point)\n", dt, (double) dt / nout); } if (!nn_verbose) printf(" control point: (%f, %f, %f) (expected z = %f)\n", pout[cpi].x, pout[cpi].y, pout[cpi].z, pout[cpi].x * pout[cpi].x - pout[cpi].y * pout[cpi].y); printf(" restoring data:\n"); fflush(stdout); for (i = 0; i < nin; ++i) { point* p = &pin[i]; p->z = franke(p->x, p->y); nnhpi_modify_data(nn, p); if (nn_verbose) printf(" (%f, %f, %f)\n", p->x, p->y, p->z); } printf(" interpolating:\n"); fflush(stdout); gettimeofday(&tv0, &tz); for (i = 0; i < nout; ++i) { point* p = &pout[i]; nnhpi_interpolate(nn, p); if (nn_verbose) printf(" (%f, %f, %f)\n", p->x, p->y, p->z); } fflush(stdout); gettimeofday(&tv1, &tz); { long dt = 1000000.0 * (tv1.tv_sec - tv0.tv_sec) + tv1.tv_usec - tv0.tv_usec; printf(" interpolation time = %ld us (%.2f us / point)\n", dt, (double) dt / nout); } if (!nn_verbose) printf(" control point: (%f, %f, %f) (expected z = %f)\n", pout[cpi].x, pout[cpi].y, pout[cpi].z, franke(pout[cpi].x, pout[cpi].y)); printf(" hashtable stats:\n"); fflush(stdout); { hashtable* ht = nn->ht_data; printf(" input points: %d entries, %d table elements, %d filled elements\n", ht_getnentries(ht), ht_getsize(ht), ht_getnfilled(ht)); ht = nn->ht_weights; printf(" weights: %d entries, %d table elements, %d filled elements\n", ht_getnentries(ht), ht_getsize(ht), ht_getnfilled(ht)); } printf("\n"); nnhpi_destroy(nn); free(pout); delaunay_destroy(d); free(pin); return 0; }
/* Reads array of points from a columnar file. * * @param fname File name (can be "stdin" for standard input) * @param dim Number of dimensions (must be 2 or 3) * @param n Pointer to number of points (output) * @param points Pointer to array of points [*n] (output) (to be freed) */ void points_read(char* fname, int dim, int* n, point** points) { FILE* f = NULL; int nallocated = NALLOCATED_START; char buf[BUFSIZE]; char seps[] = " ,;\t"; char* token; if (dim < 2 || dim > 3) { *n = 0; *points = NULL; return; } if (fname == NULL) f = stdin; else { if (strcmp(fname, "stdin") == 0 || strcmp(fname, "-") == 0) f = stdin; else { f = fopen(fname, "r"); if (f == NULL) nn_quit("%s: %s\n", fname, strerror(errno)); } } *points = (point *)malloc(nallocated * sizeof(point)); *n = 0; while (fgets(buf, BUFSIZE, f) != NULL) { point* p; if (*n == nallocated) { nallocated *= 2; *points = (point *)realloc(*points, nallocated * sizeof(point)); } p = &(*points)[*n]; if (buf[0] == '#') continue; if ((token = strtok(buf, seps)) == NULL) continue; if (!str2double(token, &p->x)) continue; if ((token = strtok(NULL, seps)) == NULL) continue; if (!str2double(token, &p->y)) continue; if (dim == 2) p->z = NaN; else { if ((token = strtok(NULL, seps)) == NULL) continue; if (!str2double(token, &p->z)) continue; } (*n)++; } if (*n == 0) { free(*points); *points = NULL; } else *points = (point *)realloc(*points, *n * sizeof(point)); if (f != stdin) if (fclose(f) != 0) nn_quit("%s: %s\n", fname, strerror(errno)); }
static int _nnpi_calculate_weights(nnpi* nn, point* p) { int* tids = NULL; int i; delaunay_circles_find(nn->d, p, &nn->ncircles, &tids); if (nn->ncircles == 0) return 1; /* * The algorithms of calculating weights for Sibson and non-Sibsonian * interpolations are quite different; in the first case, the weights are * calculated by processing Delaunay triangles whose tricircles contain * the interpolated point; in the second case, they are calculated by * processing triplets of natural neighbours by moving clockwise or * counterclockwise around the interpolated point. */ if (nn_rule == SIBSON) { for (i = 0; i < nn->ncircles; ++i) nnpi_triangle_process(nn, p, tids[i]); if (nn->bad != NULL) { if (ht_getnentries(nn->bad) != 0) { /* * The idea behind this hack is that if the "infinite circle" * hash table has not been cleared at the end of the weight * calculation process for a point, then this is caused by * misbehavior of some in-circle tests due to the numeric * round-up in cases when the interpolation point is close to * one of the data points. The code below effectively replaces * the interpolated value by the data value in the closest * point after detecting a non-cleared hash table. */ int vid_closest = -1; double dist_closest = DBL_MAX; for (i = 0; i < nn->nvertices; ++i) { point* pp = &nn->d->points[nn->vertices[i]]; double dist = hypot(p->x - pp->x, p->y - pp->y); if (dist < dist_closest) { vid_closest = nn->vertices[i]; dist_closest = dist; } } nnpi_add_weight(nn, vid_closest, BIGNUMBER); } } return 1; } else if (nn_rule == NON_SIBSONIAN) { int nneigh = 0; int* nids = NULL; int status; nnpi_getneighbours(nn, p, nn->ncircles, tids, &nneigh, &nids); status = nnpi_neighbours_process(nn, p, nneigh, nids); free(nids); return status; } else nn_quit("programming error"); return 0; }