/* Builds Natural Neighbours array interpolator. This includes calculation of * weights used in nnai_interpolate(). * * @param d Delaunay triangulation * @return Natural Neighbours interpolation */ nnai* nnai_build(delaunay* d, long n, double* x, double* y) { nnai* nn = (nnai *)malloc(sizeof(nnai)); nnpi* nnpi = nnpi_create(d); int* vertices; double* weights; int i; if (n <= 0) nn_quit("nnai_create(): n = %d\n", n); nn->d = d; nn->n = n; nn->x = (double *)malloc(n * sizeof(double)); memcpy(nn->x, x, n * sizeof(double)); nn->y = (double *)malloc(n * sizeof(double)); memcpy(nn->y, y, n * sizeof(double)); nn->weights = (nn_weights *)malloc(n * sizeof(nn_weights)); for (i = 0; i < n; ++i) { nn_weights* w = &nn->weights[i]; point p; p.x = x[i]; p.y = y[i]; nnpi_reset(nnpi); nnpi_set_point(nnpi, &p); nnpi_calculate_weights(nnpi); nnpi_normalize_weights(nnpi); vertices = nnpi_get_vertices(nnpi); weights = nnpi_get_weights(nnpi); w->nvertices = nnpi_get_nvertices(nnpi); w->vertices = (int *)malloc(w->nvertices * sizeof(int)); memcpy(w->vertices, vertices, w->nvertices * sizeof(int)); w->weights = (double *)malloc(w->nvertices * sizeof(double)); memcpy(w->weights, weights, w->nvertices * sizeof(double)); } nnpi_destroy(nnpi); return nn; }
/* Finds Natural Neighbours-interpolated value in a point. * * @param nnhpi NN point hashing interpolator * @param p Point to be interpolated (p->x, p->y -- input; p->z -- output) */ void nnhpi_interpolate(nnhpi* nnhpi, point* p) { nnpi* nnpi = nnhpi->nnpi; delaunay* d = nnpi->d; hashtable* ht_weights = nnhpi->ht_weights; nn_weights* weights; int i; if (ht_find(ht_weights, p) != NULL) { weights = ht_find(ht_weights, p); if (nn_verbose) fprintf(stderr, " <hashtable>\n"); } else { nnpi_calculate_weights(nnpi, p); weights = malloc(sizeof(nn_weights)); weights->vertices = malloc(sizeof(int) * nnpi->nvertices); weights->weights = malloc(sizeof(double) * nnpi->nvertices); weights->nvertices = nnpi->nvertices; for (i = 0; i < nnpi->nvertices; ++i) { weights->vertices[i] = nnpi->vertices[i]; weights->weights[i] = nnpi->weights[i]; } ht_insert(ht_weights, p, weights); if (nn_verbose) { if (nn_test_vertice == -1) { if (nnpi->n == 0) fprintf(stderr, "weights:\n"); fprintf(stderr, " %d: {", nnpi->n); for (i = 0; i < nnpi->nvertices; ++i) { fprintf(stderr, "(%d,%.5g)", nnpi->vertices[i], nnpi->weights[i]); if (i < nnpi->nvertices - 1) fprintf(stderr, ", "); } fprintf(stderr, "}\n"); } else { double w = 0.0; if (nnpi->n == 0) fprintf(stderr, "weights for vertex %d:\n", nn_test_vertice); for (i = 0; i < nnpi->nvertices; ++i) { if (nnpi->vertices[i] == nn_test_vertice) { w = nnpi->weights[i]; break; } } fprintf(stderr, "%15.7g %15.7g %15.7g\n", p->x, p->y, w); } } nnpi->n++; } nnhpi->n++; if (weights->nvertices == 0) { p->z = NaN; return; } p->z = 0.0; for (i = 0; i < weights->nvertices; ++i) { if (weights->weights[i] < nnpi->wmin) { p->z = NaN; return; } p->z += d->points[weights->vertices[i]].z * weights->weights[i]; } }
/* Performs Natural Neighbours interpolation in a point. * * @param nn NN interpolation * @param p Point to be interpolated (p->x, p->y -- input; p->z -- output) */ void nnpi_interpolate_point(nnpi* nn, point* p) { delaunay* d = nn->d; int i; nnpi_calculate_weights(nn, p); if (nn_verbose) { if (nn_test_vertice == -1) { indexedvalue* ivs = NULL; if (nn->nvertices > 0) { ivs = malloc(nn->nvertices * sizeof(indexedvalue)); for (i = 0; i < nn->nvertices; ++i) { ivs[i].i = nn->vertices[i]; ivs[i].v = &nn->weights[i]; } qsort(ivs, nn->nvertices, sizeof(indexedvalue), cmp_iv); } if (nn->n == 0) fprintf(stderr, "weights:\n"); fprintf(stderr, " %d: (%.10g, %10g)\n", nn->n, p->x, p->y); fprintf(stderr, " %4s %15s %15s %15s %15s\n", "id", "x", "y", "z", "w"); for (i = 0; i < nn->nvertices; ++i) { int ii = ivs[i].i; point* pp = &d->points[ii]; fprintf(stderr, " %5d %15.10g %15.10g %15.10g %15f\n", ii, pp->x, pp->y, pp->z, *ivs[i].v); } if (nn->nvertices > 0) free(ivs); } else { double w = 0.0; if (nn->n == 0) fprintf(stderr, "weight of vertex %d:\n", nn_test_vertice); for (i = 0; i < nn->nvertices; ++i) { if (nn->vertices[i] == nn_test_vertice) { w = nn->weights[i]; break; } } fprintf(stderr, " (%.10g, %.10g): %.7g\n", p->x, p->y, w); } } nn->n++; if (nn->nvertices == 0) { p->z = NaN; return; } p->z = 0.0; for (i = 0; i < nn->nvertices; ++i) { double weight = nn->weights[i]; if (weight < nn->wmin) { p->z = NaN; return; } p->z += d->points[nn->vertices[i]].z * weight; } }