2
#include "delaunay_utils.h"
3
#include "natneighbors.h"
15
NaturalNeighbors::NaturalNeighbors(int npoints, int ntriangles, double *x, double *y,
16
double *centers, int *nodes, int *neighbors)
18
this->npoints = npoints;
19
this->ntriangles = ntriangles;
22
this->centers = centers;
24
this->neighbors = neighbors;
26
this->radii2 = new double[ntriangles];
27
for (int i=0; i<ntriangles; i++) {
28
double x2 = x[INDEX3(nodes,i,0)] - INDEX2(centers,i,0);
30
double y2 = y[INDEX3(nodes,i,0)] - INDEX2(centers,i,1);
32
this->radii2[i] = x2 + y2;
37
NaturalNeighbors::~NaturalNeighbors()
39
delete[] this->radii2;
42
int NaturalNeighbors::find_containing_triangle(double targetx, double targety, int start_triangle)
45
final_triangle = walking_triangles(start_triangle, targetx, targety,
46
x, y, nodes, neighbors);
47
return final_triangle;
50
double NaturalNeighbors::interpolate_one(double *z, double targetx, double targety,
51
double defvalue, int &start_triangle)
53
int t = find_containing_triangle(targetx, targety, start_triangle);
54
if (t == -1) return defvalue;
57
vector<int> circumtri;
59
circumtri.push_back(t);
65
tnew = INDEX3(this->neighbors, t, i);
71
while (!stackA.empty()) {
76
double d2 = (SQ(targetx - INDEX2(this->centers,tnew,0))
77
+ SQ(targety - INDEX2(this->centers,tnew,1)));
78
if ((this->radii2[tnew]-d2) > TOLERANCE_EPS) {
79
// tnew is a circumtriangle of the target
80
circumtri.push_back(tnew);
82
int ti = INDEX3(this->neighbors, tnew, i);
83
if ((ti != -1) && (ti != t)) {
91
vector<int>::iterator it;
94
double tA=0.0, yA=0.0, cA=0.0; // Kahan summation temps for A
95
double tf=0.0, yf=0.0, cf=0.0; // Kahan summation temps for f
101
for (it = circumtri.begin(); it != circumtri.end(); it++) {
103
double vx = INDEX2(this->centers, t, 0);
104
double vy = INDEX2(this->centers, t, 1);
106
for (int i=0; i<3; i++) {
111
this->x[INDEX3(this->nodes, t, j)],
112
this->y[INDEX3(this->nodes, t, j)],
113
this->x[INDEX3(this->nodes, t, k)],
114
this->y[INDEX3(this->nodes, t, k)],
116
INDEX2(c, i, 0), INDEX2(c, i, 1))) {
118
// bail out with the appropriate values if we're actually on a
120
if ((fabs(targetx - this->x[INDEX3(this->nodes, t, j)]) < TOLERANCE_EPS)
121
&& (fabs(targety - this->y[INDEX3(this->nodes, t, j)]) < TOLERANCE_EPS)) {
122
return z[INDEX3(this->nodes, t, j)];
123
} else if ((fabs(targetx - this->x[INDEX3(this->nodes, t, k)]) < TOLERANCE_EPS)
124
&& (fabs(targety - this->y[INDEX3(this->nodes, t, k)]) < TOLERANCE_EPS)) {
125
return z[INDEX3(this->nodes, t, k)];
126
} else if (!onedge) {
128
edge.push_back(INDEX3(this->nodes, t, j));
129
edge.push_back(INDEX3(this->nodes, t, k));
130
onhull = (INDEX3(neighbors, t, i) == -1);
134
for (int i=0; i<3; i++) {
137
int q = INDEX3(this->nodes, t, i);
140
if (!onedge || ((edge[0] != q) && edge[1] != q)) {
141
ati = signed_area(vx, vy,
142
INDEX2(c, j, 0), INDEX2(c, j, 1),
143
INDEX2(c, k, 0), INDEX2(c, k, 1));
159
// If we're on an edge, then the scheme of adding up triangles as above
160
// doesn't work so well. We'll take care of these two nodes here.
163
// If we're on the convex hull, then the other nodes don't actually
164
// contribute anything, just the nodes for the edge we're on. The
165
// Voronoi "polygons" are infinite in extent.
167
double a = (hypot(targetx-x[edge[0]], targety-y[edge[0]]) /
168
hypot(x[edge[1]]-x[edge[0]], y[edge[1]]-y[edge[0]]));
169
return (1-a) * z[edge[0]] + a*z[edge[1]];
172
set<int> T(circumtri.begin(), circumtri.end());
173
vector<int> newedges0; // the two nodes that edge[0] still connect to
174
vector<int> newedges1; // the two nodes that edge[1] still connect to
175
set<int> alltri0; // all of the circumtriangle edge[0] participates in
176
set<int> alltri1; // all of the circumtriangle edge[1] participates in
177
for (it = circumtri.begin(); it != circumtri.end(); it++) {
178
for (int i=0; i<3; i++) {
179
int ti = INDEX3(this->neighbors, *it, i);
182
int q0 = INDEX3(this->nodes, *it, j);
183
int q1 = INDEX3(this->nodes, *it, k);
185
if ((q0 == edge[0]) || (q1 == edge[0])) alltri0.insert(*it);
186
if ((q0 == edge[1]) || (q1 == edge[1])) alltri1.insert(*it);
189
// neighbor is not in the set of circumtriangles
190
if (q0 == edge[0]) newedges0.push_back(q1);
191
if (q1 == edge[0]) newedges0.push_back(q0);
192
if (q0 == edge[1]) newedges1.push_back(q1);
193
if (q1 == edge[1]) newedges1.push_back(q0);
198
set<int>::iterator sit;
204
if (edge[1] != newedges0[0]) {
205
circumcenter(this->x[edge[0]], this->y[edge[0]],
206
this->x[newedges0[0]], this->y[newedges0[0]],
211
if (edge[1] != newedges0[1]) {
212
circumcenter(this->x[edge[0]], this->y[edge[0]],
213
this->x[newedges0[1]], this->y[newedges0[1]],
219
if (edge[0] != newedges1[0]) {
220
circumcenter(this->x[edge[1]], this->y[edge[1]],
221
this->x[newedges1[0]], this->y[newedges1[0]],
226
if (edge[0] != newedges1[1]) {
227
circumcenter(this->x[edge[1]], this->y[edge[1]],
228
this->x[newedges1[1]], this->y[newedges1[1]],
234
for (sit = alltri0.begin(); sit != alltri0.end(); sit++) {
235
poly0.push(INDEX2(this->centers, *sit, 0),
236
INDEX2(this->centers, *sit, 1));
238
for (sit = alltri1.begin(); sit != alltri1.end(); sit++) {
239
poly1.push(INDEX2(this->centers, *sit, 0),
240
INDEX2(this->centers, *sit, 1));
243
double a0 = poly0.area();
244
double a1 = poly1.area();
252
// Anticlimactic, isn't it?
259
void NaturalNeighbors::interpolate_grid(double *z,
260
double x0, double x1, int xsteps,
261
double y0, double y1, int ysteps,
263
double defvalue, int start_triangle)
265
int i, ix, iy, rowtri, coltri, tri;
266
double dx, dy, targetx, targety;
268
dx = (x1 - x0) / (xsteps-1);
269
dy = (y1 - y0) / (ysteps-1);
273
for (iy=0; iy<ysteps; iy++) {
274
targety = y0 + dy*iy;
275
rowtri = find_containing_triangle(x0, targety, rowtri);
277
for (ix=0; ix<xsteps; ix++) {
278
targetx = x0 + dx*ix;
280
INDEXN(output, xsteps, iy, ix) = interpolate_one(z, targetx, targety,
282
if (coltri != -1) tri = coltri;
287
void NaturalNeighbors::interpolate_unstructured(double *z, int size,
288
double *intx, double *inty, double *output, double defvalue)
294
for (i=0; i<size; i++) {
296
output[i] = interpolate_one(z, intx[i], inty[i], defvalue, tri2);
297
if (tri2 != -1) tri1 = tri2;