/* 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; }
void nnpi_calculate_weights(nnpi* nn, point* p) { point pp; int nvertices = 0; int* vertices = NULL; double* weights = NULL; int i; nnpi_reset(nn); if (_nnpi_calculate_weights(nn, p)) { nnpi_normalize_weights(nn); return; } nnpi_reset(nn); pp.x = p->x + nn->dx; pp.y = p->y + nn->dy; /* * If the triangles are extremely thin, then making a small step in * perpendicular direction may turn out between another pair of data * points. A very rare event. Take care of this. */ while (!_nnpi_calculate_weights(nn, &pp)) { pp.x = p->x + nn->dx * RANDOM; pp.y = p->y + nn->dy * RANDOM; } nnpi_normalize_weights(nn); nvertices = nn->nvertices; if (nvertices > 0) { vertices = malloc(nvertices * sizeof(int)); memcpy(vertices, nn->vertices, nvertices * sizeof(int)); weights = malloc(nvertices * sizeof(double)); memcpy(weights, nn->weights, nvertices * sizeof(double)); } nnpi_reset(nn); pp.x = p->x - nn->dx; pp.y = p->y - nn->dy; while (!_nnpi_calculate_weights(nn, &pp)) { pp.x = p->x - nn->dx * RANDOM; pp.y = p->y - nn->dy * RANDOM; } nnpi_normalize_weights(nn); for (i = 0; i < nn->nvertices; ++i) nn->weights[i] /= 2.0; for (i = 0; i < nvertices; ++i) nnpi_add_weight(nn, vertices[i], weights[i] / 2.0); if (nvertices > 0) { free(vertices); free(weights); } }
void nnpi_calculate_weights(nnpi* nn, point* p) { point pp; int nvertices = 0; int* vertices = NULL; double* weights = NULL; int i; nnpi_reset(nn); if (_nnpi_calculate_weights(nn, p)) { nnpi_normalize_weights(nn); return; } nnpi_reset(nn); nn->dx = (nn->d->xmax - nn->d->xmin) * EPS_SHIFT; nn->dy = (nn->d->ymax - nn->d->ymin) * EPS_SHIFT; pp.x = p->x + nn->dx; pp.y = p->y + nn->dy; while (!_nnpi_calculate_weights(nn, &pp)) { nnpi_reset(nn); pp.x = p->x + nn->dx * RANDOM; pp.y = p->y + nn->dy * RANDOM; } nnpi_normalize_weights(nn); nvertices = nn->nvertices; if (nvertices > 0) { vertices = malloc(nvertices * sizeof(int)); memcpy(vertices, nn->vertices, nvertices * sizeof(int)); weights = malloc(nvertices * sizeof(double)); memcpy(weights, nn->weights, nvertices * sizeof(double)); } nnpi_reset(nn); pp.x = 2.0 * p->x - pp.x; pp.y = 2.0 * p->y - pp.y; while (!_nnpi_calculate_weights(nn, &pp) || nn->nvertices == 0) { nnpi_reset(nn); pp.x = p->x + nn->dx * RANDOM; pp.y = p->y + nn->dy * RANDOM; } nnpi_normalize_weights(nn); if (nvertices > 0) for (i = 0; i < nn->nvertices; ++i) nn->weights[i] /= 2.0; for (i = 0; i < nvertices; ++i) nnpi_add_weight(nn, vertices[i], weights[i] / 2.0); if (nvertices > 0) { free(vertices); free(weights); } }