2 WARNING - Do not remove this header.
4 This code is a templated version of the 'magic-software' spherical
5 interpolation code by Dave Eberly. The original (un-hacked) code can be
6 obtained from here: http://www.magic-software.com/gr_appr.htm
7 This code is derived from linintp2.h/cpp and sphrintp.h/cpp.
9 Dave Eberly says that the conditions for use are:
11 * You may distribute the original source code to others at no charge.
13 * You may modify the original source code and distribute it to others at
14 no charge. The modified code must be documented to indicate that it is
15 not part of the original package.
17 * You may use this code for non-commercial purposes. You may also
18 incorporate this code into commercial packages. However, you may not
19 sell any of your source code which contains my original and/or modified
20 source code. In such a case, you need to factor out my code and freely
23 * The original code comes with absolutely no warranty and no guarantee is
24 made that the code is bug-free.
26 This does not seem incompatible with GPL - so this modified version
27 is hereby placed under GPL along with the rest of FlightGear.
37 //---------------------------------------------------------------------------
39 mgcLinInterp2D<T>::mgcLinInterp2D (int _numPoints, double* x, double* y,
42 if ( (numPoints = _numPoints) < 3 )
51 cout << "[ 20%] allocating memory \r";
53 point = new double*[numPoints];
54 tmppoint = new double*[numPoints+3];
57 for (i = 0; i < numPoints; i++)
58 point[i] = new double[2];
59 for (i = 0; i < numPoints+3; i++)
60 tmppoint[i] = new double[2];
61 for (i = 0; i < numPoints; i++)
63 point[i][0] = tmppoint[i][0] = x[i];
64 point[i][1] = tmppoint[i][1] = y[i];
69 cout << "[ 30%] creating delaunay diagram \r";
73 //---------------------------------------------------------------------------
75 mgcLinInterp2D<T>::~mgcLinInterp2D ()
84 for (i = 0; i < numPoints; i++)
90 for (i = 0; i < numPoints+3; i++)
99 //---------------------------------------------------------------------------
101 void mgcLinInterp2D<T>::ComputeBarycenter (Vertex& v0, Vertex& v1, Vertex& v2,
102 Vertex& ver, double c[3])
104 double A0 = v0.x-v2.x, B0 = v0.y-v2.y;
105 double A1 = v1.x-v2.x, B1 = v1.y-v2.y;
106 double A2 = ver.x-v2.x, B2 = ver.y-v2.y;
108 double m00 = A0*A0+B0*B0, m01 = A0*A1+B0*B1, m11 = A1*A1+B1*B1;
109 double r0 = A2*A0+B2*B0, r1 = A2*A1+B2*B1;
110 double det = m00*m11-m01*m01;
112 c[0] = (m11*r0-m01*r1)/det;
113 c[1] = (m00*r1-m01*r0)/det;
116 //---------------------------------------------------------------------------
118 int mgcLinInterp2D<T>::InTriangle (Vertex& v0, Vertex& v1, Vertex& v2,
121 const double eps = 1e-08;
122 double tx, ty, nx, ny;
124 // test against normal to first edge
129 if ( tx*nx + ty*ny < -eps )
132 // test against normal to second edge
137 if ( tx*nx + ty*ny < -eps )
140 // test against normal to third edge
145 if ( tx*nx + ty*ny < -eps )
150 //---------------------------------------------------------------------------
152 int mgcLinInterp2D<T>::Evaluate (double x, double y, T& F)
154 Vertex ver = { x, y };
155 // determine which triangle contains the target point
159 for (i = 0; i < numTriangles; i++)
161 Triangle& t = triangle[i];
162 v0.x = point[t.vertex[0]][0];
163 v0.y = point[t.vertex[0]][1];
164 v1.x = point[t.vertex[1]][0];
165 v1.y = point[t.vertex[1]][1];
166 v2.x = point[t.vertex[2]][0];
167 v2.y = point[t.vertex[2]][1];
169 if ( InTriangle(v0,v1,v2,ver) )
173 if ( i == numTriangles ) // point is outside interpolation region
178 Triangle& t = triangle[i]; // (x,y) is in this triangle
180 // compute barycentric coordinates with respect to subtriangle
182 ComputeBarycenter(v0,v1,v2,ver,bary);
184 // compute barycentric combination of function values at vertices
185 F = bary[0]*f[t.vertex[0]]+bary[1]*f[t.vertex[1]]+bary[2]*f[t.vertex[2]];
189 //---------------------------------------------------------------------------
191 int mgcLinInterp2D<T>::Delaunay2D ()
195 const double EPSILON = 1e-12;
196 const int TSIZE = 75;
197 const double RANGE = 10.0;
199 xmin = tmppoint[0][0];
201 ymin = tmppoint[0][1];
205 for (i = 0; i < numPoints; i++)
207 double value = tmppoint[i][0];
213 value = tmppoint[i][1];
220 double xrange = xmax-xmin, yrange = ymax-ymin;
221 double maxrange = xrange;
222 if ( maxrange < yrange )
225 // need to scale the data later to do a correct triangle count
226 double maxrange2 = maxrange*maxrange;
228 // tweak the points by very small random numbers
229 double bgs = EPSILON*maxrange;
231 for (i = 0; i < numPoints; i++)
233 tmppoint[i][0] += bgs*(0.5 - rand()/double(RAND_MAX));
234 tmppoint[i][1] += bgs*(0.5 - rand()/double(RAND_MAX));
239 { 5*RANGE, -RANGE, -RANGE },
240 { -RANGE, 5*RANGE, -RANGE }
242 for (i = 0; i < 3; i++)
244 tmppoint[numPoints+i][0] = xmin+xrange*wrk[0][i];
245 tmppoint[numPoints+i][1] = ymin+yrange*wrk[1][i];
248 int i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i11;
253 int** tmp = new int*[tsz+1];
254 tmp[0] = new int[2*(tsz+1)];
255 for (i0 = 1; i0 < tsz+1; i0++)
256 tmp[i0] = tmp[0] + 2*i0;
257 i1 = 2*(numPoints + 2);
259 int* id = new int[i1];
260 for (i0 = 0; i0 < i1; i0++)
263 int** a3s = new int*[i1];
264 a3s[0] = new int[3*i1];
265 for (i0 = 1; i0 < i1; i0++)
266 a3s[i0] = a3s[0] + 3*i0;
267 a3s[0][0] = numPoints;
268 a3s[0][1] = numPoints+1;
269 a3s[0][2] = numPoints+2;
271 double** ccr = new double*[i1]; // circumscribed centers and radii
272 ccr[0] = new double[3*i1];
273 for (i0 = 1; i0 < i1; i0++)
274 ccr[i0] = ccr[0] + 3*i0;
279 nts = 1; // number of triangles
282 cout << "[ 40%] create triangulation \r";
284 // compute triangulation
285 for (i0 = 0; i0 < numPoints; i0++)
289 for (i11 = 0; i11 < nts; i11++)
292 while ( a3s[i1][0] < 0 )
295 for (i2 = 0; i2 < 2; i2++)
297 double z = tmppoint[i0][i2]-ccr[i1][i2];
305 for (i2 = 0; i2 < 3; i2++)
310 for (i3 = 1; i3 < 2; i3++)
312 ii[i3] = ii[i3-1] + 1;
319 for (i3 = 0; i3 <= i8; i3++)
321 for (i5 = 0; i5 < 2; i5++)
322 if ( a3s[i1][ii[i5]] != tmp[i3][i5] )
324 for (i6 = 0; i6 < 2; i6++)
325 tmp[i3][i6] = tmp[i8][i6];
333 // temporary storage exceeded, increase TSIZE
337 for (i3 = 0; i3 < 2; i3++)
338 tmp[i7][i3] = a3s[i1][ii[i3]];
345 for (i1 = 0; i1 <= i7; i1++)
347 for (i2 = 0; i2 < 2; i2++)
348 for (wrk[i2][2] = 0, i3 = 0; i3 < 2; i3++)
350 wrk[i2][i3] = tmppoint[tmp[i1][i2]][i3]-tmppoint[i0][i3];
352 0.5*wrk[i2][i3]*(tmppoint[tmp[i1][i2]][i3]+
356 xx = wrk[0][0]*wrk[1][1]-wrk[1][0]*wrk[0][1];
357 ccr[id[i4]][0] = (wrk[0][2]*wrk[1][1]-wrk[1][2]*wrk[0][1])/xx;
358 ccr[id[i4]][1] = (wrk[0][0]*wrk[1][2]-wrk[1][0]*wrk[0][2])/xx;
360 for (ccr[id[i4]][2] = 0, i2 = 0; i2 < 2; i2++)
362 double z = tmppoint[i0][i2]-ccr[id[i4]][i2];
363 ccr[id[i4]][2] += z*z;
364 a3s[id[i4]][i2] = tmp[i1][i2];
374 // count the number of triangles
375 cout << "[ 50%] count the number of triangles \r";
379 for (i11 = 0; i11 < nts; i11++)
382 while ( a3s[i0][0] < 0 )
384 if ( a3s[i0][0] < numPoints )
386 for (i1 = 0; i1 < 2; i1++)
387 for (i2 = 0; i2 < 2; i2++)
389 tmppoint[a3s[i0][i1]][i2]-tmppoint[a3s[i0][2]][i2];
391 if ( fabs(wrk[0][0]*wrk[1][1]-wrk[0][1]*wrk[1][0]) > EPSILON*maxrange2 )
396 // create the triangles
397 cout << "[ 60%] create the triangles \r";
399 triangle = new Triangle[numTriangles];
403 for (i11 = 0; i11 < nts; i11++)
406 while ( a3s[i0][0] < 0 )
408 if ( a3s[i0][0] < numPoints )
410 for (i1 = 0; i1 < 2; i1++)
411 for (i2 = 0; i2 < 2; i2++)
413 tmppoint[a3s[i0][i1]][i2]-tmppoint[a3s[i0][2]][i2];
414 xx = wrk[0][0]*wrk[1][1]-wrk[0][1]*wrk[1][0];
415 if ( fabs(xx) > EPSILON*maxrange2 )
417 int delta = xx < 0 ? 1 : 0;
418 Triangle& tri = triangle[numTriangles];
419 tri.vertex[0] = a3s[i0][0];
420 tri.vertex[1] = a3s[i0][1+delta];
421 tri.vertex[2] = a3s[i0][2-delta];
431 cout << "[ 70%] build the edge table \r";
434 edge = new Edge[3*numTriangles];
437 for (i = 0; i < numTriangles; i++)
440 cout << "[ 7" << 10*i/numTriangles << "%] build the edge table \r";
442 Triangle& t = triangle[i];
444 for (j0 = 0, j1 = 1; j0 < 3; j0++, j1 = (j1+1)%3)
446 for (j = 0; j < numEdges; j++)
449 if ( (t.vertex[j0] == e.vertex[0]
450 && t.vertex[j1] == e.vertex[1])
451 || (t.vertex[j0] == e.vertex[1]
452 && t.vertex[j1] == e.vertex[0]) )
455 if ( j == numEdges ) // add edge to table
457 edge[j].vertex[0] = t.vertex[j0];
458 edge[j].vertex[1] = t.vertex[j1];
459 edge[j].triangle[0] = i;
460 edge[j].index[0] = j0;
461 edge[j].triangle[1] = -1;
464 else // edge already exists, add triangle to table
466 edge[j].triangle[1] = i;
467 edge[j].index[1] = j0;
472 // establish links between adjacent triangles
473 cout << "[ 80%] establishing links between adjacent triangles \r";
475 for (i = 0; i < numEdges; i++)
477 if ( edge[i].triangle[1] != -1 )
479 j0 = edge[i].triangle[0];
480 j1 = edge[i].triangle[1];
481 triangle[j0].adj[edge[i].index[0]] = j1;
482 triangle[j1].adj[edge[i].index[1]] = j0;
497 cout << "[ 90%] finsishes delauney triangulation \r";
501 //---------------------------------------------------------------------------
503 void mgcLinInterp2D<T>::GetPoint (int i, double& x, double& y)
505 // assumes i is valid [can use PointCount() before passing i]
509 //---------------------------------------------------------------------------
511 void mgcLinInterp2D<T>::GetEdge (int i, double& x0, double& y0, double& x1,
514 // assumes i is valid [can use EdgeCount() before passing i]
515 int v0 = edge[i].vertex[0], v1 = edge[i].vertex[1];
522 //---------------------------------------------------------------------------
524 void mgcLinInterp2D<T>::GetTriangle (int i, double& x0, double& y0, double& x1,
525 double& y1, double& x2, double& y2)
527 // assumes i is valid [can use TriangleCount() before passing i]
528 int v0 = triangle[i].vertex[0];
529 int v1 = triangle[i].vertex[1];
530 int v2 = triangle[i].vertex[2];
539 //---------------------------------------------------------------------------