00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include <stdlib.h>
00042 #include <stdio.h>
00043 #include <limits.h>
00044 #include <float.h>
00045 #include <string.h>
00046 #include <assert.h>
00047 #include <math.h>
00048 #include "nn.h"
00049 #include "delaunay.h"
00050 #include "nan.h"
00051 #include "hash.h"
00052
00053 struct nnpi
00054 {
00055 delaunay* d;
00056 point * p;
00057 double wmin;
00058
00059
00060
00061 int nvertices;
00062 int nallocated;
00063 int * vertices;
00064 double* weights;
00065 int n;
00066 };
00067
00068 int circle_build( circle* c, point* p0, point* p1, point* p2 );
00069 int circle_contains( circle* c, point* p );
00070 void delaunay_circles_find( delaunay* d, point* p, int* n, int** out );
00071 int delaunay_xytoi( delaunay* d, point* p, int seed );
00072 void nn_quit( char* format, ... );
00073
00074 #define NSTART 10
00075 #define NINC 10
00076 #define EPS_SHIFT 1.0e-9
00077 #define N_SEARCH_TURNON 20
00078 #define BIGNUMBER 1.0e+100
00079
00080 #define min( x, y ) ( ( x ) < ( y ) ? ( x ) : ( y ) )
00081 #define max( x, y ) ( ( x ) > ( y ) ? ( x ) : ( y ) )
00082
00083
00084
00085
00086
00087
00088 nnpi* nnpi_create( delaunay* d )
00089 {
00090 nnpi* nn = malloc( sizeof ( nnpi ) );
00091
00092 nn->d = d;
00093 nn->wmin = -DBL_MAX;
00094 nn->vertices = calloc( NSTART, sizeof ( int ) );
00095 nn->weights = calloc( NSTART, sizeof ( double ) );
00096 nn->nvertices = 0;
00097 nn->nallocated = NSTART;
00098 nn->p = NULL;
00099 nn->n = 0;
00100
00101 return nn;
00102 }
00103
00104
00105
00106
00107
00108 void nnpi_destroy( nnpi* nn )
00109 {
00110 free( nn->weights );
00111 free( nn->vertices );
00112 free( nn );
00113 }
00114
00115 void nnpi_reset( nnpi* nn )
00116 {
00117 nn->nvertices = 0;
00118 nn->p = NULL;
00119 memset( nn->d->flags, 0, nn->d->ntriangles * sizeof ( int ) );
00120 }
00121
00122 static void nnpi_add_weight( nnpi* nn, int vertex, double w )
00123 {
00124 int i;
00125
00126
00127
00128
00129 for ( i = 0; i < nn->nvertices; ++i )
00130 if ( nn->vertices[i] == vertex )
00131 break;
00132
00133 if ( i == nn->nvertices )
00134 {
00135
00136
00137 if ( nn->nvertices == nn->nallocated )
00138 {
00139 nn->vertices = realloc( nn->vertices, ( nn->nallocated + NINC ) * sizeof ( int ) );
00140 nn->weights = realloc( nn->weights, ( nn->nallocated + NINC ) * sizeof ( double ) );
00141 nn->nallocated += NINC;
00142 }
00143
00144
00145
00146
00147 nn->vertices[i] = vertex;
00148 nn->weights[i] = w;
00149 nn->nvertices++;
00150 }
00151 else
00152
00153 {
00154 if ( nn_rule == SIBSON )
00155 nn->weights[i] += w;
00156 else if ( w > nn->weights[i] )
00157 nn->weights[i] = w;
00158 }
00159 }
00160
00161 static double triangle_scale_get( delaunay* d, triangle* t )
00162 {
00163 double x0 = d->points[t->vids[0]].x;
00164 double x1 = d->points[t->vids[1]].x;
00165 double x2 = d->points[t->vids[2]].x;
00166 double y0 = d->points[t->vids[0]].y;
00167 double y1 = d->points[t->vids[1]].y;
00168 double y2 = d->points[t->vids[2]].y;
00169 double xmin = min( min( x0, x1 ), x2 );
00170 double xmax = max( max( x0, x1 ), x2 );
00171 double ymin = min( min( y0, y1 ), y2 );
00172 double ymax = max( max( y0, y1 ), y2 );
00173
00174 return xmax - xmin + ymax - ymin;
00175 }
00176
00177
00178
00179
00180
00181
00182 static void nnpi_triangle_process( nnpi* nn, point* p, int i )
00183 {
00184 delaunay* d = nn->d;
00185 triangle* t = &d->triangles[i];
00186 circle * c = &d->circles[i];
00187 circle cs[3];
00188 int j;
00189
00190 assert( circle_contains( c, p ) );
00191
00192 if ( nn_rule == SIBSON )
00193 {
00194 point pp;
00195
00196 pp.x = p->x;
00197 pp.y = p->y;
00198
00199
00200
00201 do
00202 {
00203 for ( j = 0; j < 3; ++j )
00204 {
00205 int j1 = ( j + 1 ) % 3;
00206 int j2 = ( j + 2 ) % 3;
00207 int v1 = t->vids[j1];
00208 int v2 = t->vids[j2];
00209
00210 if ( !circle_build( &cs[j], &d->points[v1], &d->points[v2], &pp ) )
00211 {
00212 double scale = triangle_scale_get( d, t );
00213
00214 if ( d->points[v1].y == d->points[v2].y )
00215 pp.y += EPS_SHIFT * scale;
00216 else
00217 pp.x += EPS_SHIFT * scale;
00218 break;
00219 }
00220 }
00221 } while ( j != 3 );
00222
00223 for ( j = 0; j < 3; ++j )
00224 {
00225 int j1 = ( j + 1 ) % 3;
00226 int j2 = ( j + 2 ) % 3;
00227 double det = ( ( cs[j1].x - c->x ) * ( cs[j2].y - c->y ) - ( cs[j2].x - c->x ) * ( cs[j1].y - c->y ) );
00228
00229 nnpi_add_weight( nn, t->vids[j], det );
00230 }
00231 }
00232 else if ( nn_rule == NON_SIBSONIAN )
00233 {
00234 double d1 = c->r - hypot( p->x - c->x, p->y - c->y );
00235
00236 for ( i = 0; i < 3; ++i )
00237 {
00238 int vid = t->vids[i];
00239 point * pp = &d->points[vid];
00240 double d2 = hypot( p->x - pp->x, p->y - pp->y );
00241
00242 if ( d2 == 0.0 )
00243 nnpi_add_weight( nn, vid, BIGNUMBER );
00244 else
00245 nnpi_add_weight( nn, vid, d1 / d2 );
00246 }
00247 }
00248 else
00249 nn_quit( "unknown rule\n" );
00250 }
00251
00252 void nnpi_calculate_weights( nnpi* nn )
00253 {
00254 point* p = nn->p;
00255 int n = nn->d->ntriangles;
00256 int i;
00257
00258 if ( n > N_SEARCH_TURNON )
00259 {
00260 int* tids;
00261
00262 delaunay_circles_find( nn->d, p, &n, &tids );
00263 for ( i = 0; i < n; ++i )
00264 nnpi_triangle_process( nn, p, tids[i] );
00265 }
00266 else
00267 for ( i = 0; i < n; ++i )
00268 if ( circle_contains( &nn->d->circles[i], p ) )
00269 nnpi_triangle_process( nn, p, i );
00270 }
00271
00272 void nnpi_normalize_weights( nnpi* nn )
00273 {
00274 int n = nn->nvertices;
00275 double sum = 0.0;
00276 int i;
00277
00278 for ( i = 0; i < n; ++i )
00279 sum += nn->weights[i];
00280
00281 for ( i = 0; i < n; ++i )
00282 nn->weights[i] /= sum;
00283 }
00284
00285
00286
00287
00288
00289
00290 void nnpi_interpolate_point( nnpi* nn, point* p )
00291 {
00292 delaunay* d = nn->d;
00293 int i;
00294
00295 nnpi_reset( nn );
00296 nn->p = p;
00297 nnpi_calculate_weights( nn );
00298 nnpi_normalize_weights( nn );
00299
00300 if ( nn_verbose )
00301 {
00302 if ( nn_test_vertice == -1 )
00303 {
00304 if ( nn->n == 0 )
00305 fprintf( stderr, "weights:\n" );
00306 fprintf( stderr, " %d: {", nn->n );
00307 for ( i = 0; i < nn->nvertices; ++i )
00308 {
00309 fprintf( stderr, "(%d,%.5g)", nn->vertices[i], nn->weights[i] );
00310 if ( i < nn->nvertices - 1 )
00311 fprintf( stderr, ", " );
00312 }
00313 fprintf( stderr, "}\n" );
00314 }
00315 else
00316 {
00317 double w = 0.0;
00318
00319 if ( nn->n == 0 )
00320 fprintf( stderr, "weights for vertex %d:\n", nn_test_vertice );
00321 for ( i = 0; i < nn->nvertices; ++i )
00322 {
00323 if ( nn->vertices[i] == nn_test_vertice )
00324 {
00325 w = nn->weights[i];
00326 break;
00327 }
00328 }
00329 fprintf( stderr, "%15.7g %15.7g %15.7g\n", p->x, p->y, w );
00330 }
00331 }
00332
00333 nn->n++;
00334
00335 if ( nn->nvertices == 0 )
00336 {
00337 p->z = NaN;
00338 return;
00339 }
00340
00341 p->z = 0.0;
00342 for ( i = 0; i < nn->nvertices; ++i )
00343 {
00344 double weight = nn->weights[i];
00345
00346 if ( weight < nn->wmin )
00347 {
00348 p->z = NaN;
00349 return;
00350 }
00351 p->z += d->points[nn->vertices[i]].z * weight;
00352 }
00353 }
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363 void nnpi_interpolate_points( int nin, point pin[], double wmin, int nout, point pout[] )
00364 {
00365 delaunay* d = delaunay_build( nin, pin, 0, NULL, 0, NULL );
00366 nnpi * nn = nnpi_create( d );
00367 int seed = 0;
00368 int i;
00369
00370 nn->wmin = wmin;
00371
00372 if ( nn_verbose )
00373 {
00374 fprintf( stderr, "xytoi:\n" );
00375 for ( i = 0; i < nout; ++i )
00376 {
00377 point* p = &pout[i];
00378
00379 fprintf( stderr, "(%.7g,%.7g) -> %d\n", p->x, p->y, delaunay_xytoi( d, p, seed ) );
00380 }
00381 }
00382
00383 for ( i = 0; i < nout; ++i )
00384 nnpi_interpolate_point( nn, &pout[i] );
00385
00386 if ( nn_verbose )
00387 {
00388 fprintf( stderr, "output:\n" );
00389 for ( i = 0; i < nout; ++i )
00390 {
00391 point* p = &pout[i];
00392
00393 fprintf( stderr, " %d:%15.7g %15.7g %15.7g\n", i, p->x, p->y, p->z );
00394 }
00395 }
00396
00397 nnpi_destroy( nn );
00398 delaunay_destroy( d );
00399 }
00400
00401
00402
00403
00404
00405 void nnpi_setwmin( nnpi* nn, double wmin )
00406 {
00407 nn->wmin = wmin;
00408 }
00409
00410
00411
00412
00413
00414 void nnpi_set_point( nnpi* nn, point* p )
00415 {
00416 nn->p = p;
00417 }
00418
00419
00420
00421
00422 int nnpi_get_nvertices( nnpi* nn )
00423 {
00424 return nn->nvertices;
00425 }
00426
00427
00428
00429
00430 int* nnpi_get_vertices( nnpi* nn )
00431 {
00432 return nn->vertices;
00433 }
00434
00435
00436
00437
00438 double* nnpi_get_weights( nnpi* nn )
00439 {
00440 return nn->weights;
00441 }
00442
00443
00444
00445
00446
00447 struct nnhpi
00448 {
00449 nnpi * nnpi;
00450 hashtable* ht_data;
00451 hashtable* ht_weights;
00452 int n;
00453 };
00454
00455 typedef struct
00456 {
00457 int nvertices;
00458 int * vertices;
00459 double* weights;
00460 } nn_weights;
00461
00462
00463
00464
00465
00466
00467
00468 nnhpi* nnhpi_create( delaunay* d, int size )
00469 {
00470 nnhpi* nn = malloc( sizeof ( nnhpi ) );
00471 int i;
00472
00473 nn->nnpi = nnpi_create( d );
00474
00475 nn->ht_data = ht_create_d2( d->npoints );
00476 nn->ht_weights = ht_create_d2( size );
00477 nn->n = 0;
00478
00479 for ( i = 0; i < d->npoints; ++i )
00480 ht_insert( nn->ht_data, &d->points[i], &d->points[i] );
00481
00482 return nn;
00483 }
00484
00485 static void free_nn_weights( void* data )
00486 {
00487 nn_weights* weights = (nn_weights *) data;
00488
00489 free( weights->vertices );
00490 free( weights->weights );
00491 free( weights );
00492 }
00493
00494
00495
00496
00497
00498 void nnhpi_destroy( nnhpi* nn )
00499 {
00500 ht_destroy( nn->ht_data );
00501 ht_process( nn->ht_weights, free_nn_weights );
00502 ht_destroy( nn->ht_weights );
00503 nnpi_destroy( nn->nnpi );
00504 }
00505
00506
00507
00508
00509
00510
00511 void nnhpi_interpolate( nnhpi* nnhpi, point* p )
00512 {
00513 nnpi * nnpi = nnhpi->nnpi;
00514 delaunay * d = nnpi->d;
00515 hashtable * ht_weights = nnhpi->ht_weights;
00516 nn_weights* weights;
00517 int i;
00518
00519 if ( ht_find( ht_weights, p ) != NULL )
00520 {
00521 weights = ht_find( ht_weights, p );
00522 if ( nn_verbose )
00523 fprintf( stderr, " <hashtable>\n" );
00524 }
00525 else
00526 {
00527 nnpi_reset( nnpi );
00528 nnpi->p = p;
00529 nnpi_calculate_weights( nnpi );
00530 nnpi_normalize_weights( nnpi );
00531
00532 weights = malloc( sizeof ( nn_weights ) );
00533 weights->vertices = malloc( sizeof ( int ) * nnpi->nvertices );
00534 weights->weights = malloc( sizeof ( double ) * nnpi->nvertices );
00535
00536 weights->nvertices = nnpi->nvertices;
00537
00538 for ( i = 0; i < nnpi->nvertices; ++i )
00539 {
00540 weights->vertices[i] = nnpi->vertices[i];
00541 weights->weights[i] = nnpi->weights[i];
00542 }
00543
00544 ht_insert( ht_weights, p, weights );
00545
00546 if ( nn_verbose )
00547 {
00548 if ( nn_test_vertice == -1 )
00549 {
00550 if ( nnpi->n == 0 )
00551 fprintf( stderr, "weights:\n" );
00552 fprintf( stderr, " %d: {", nnpi->n );
00553
00554 for ( i = 0; i < nnpi->nvertices; ++i )
00555 {
00556 fprintf( stderr, "(%d,%.5g)", nnpi->vertices[i], nnpi->weights[i] );
00557
00558 if ( i < nnpi->nvertices - 1 )
00559 fprintf( stderr, ", " );
00560 }
00561 fprintf( stderr, "}\n" );
00562 }
00563 else
00564 {
00565 double w = 0.0;
00566
00567 if ( nnpi->n == 0 )
00568 fprintf( stderr, "weights for vertex %d:\n", nn_test_vertice );
00569 for ( i = 0; i < nnpi->nvertices; ++i )
00570 {
00571 if ( nnpi->vertices[i] == nn_test_vertice )
00572 {
00573 w = nnpi->weights[i];
00574
00575 break;
00576 }
00577 }
00578 fprintf( stderr, "%15.7g %15.7g %15.7g\n", p->x, p->y, w );
00579 }
00580 }
00581
00582 nnpi->n++;
00583 }
00584
00585 nnhpi->n++;
00586
00587 if ( weights->nvertices == 0 )
00588 {
00589 p->z = NaN;
00590 return;
00591 }
00592
00593 p->z = 0.0;
00594 for ( i = 0; i < weights->nvertices; ++i )
00595 {
00596 if ( weights->weights[i] < nnpi->wmin )
00597 {
00598 p->z = NaN;
00599 return;
00600 }
00601 p->z += d->points[weights->vertices[i]].z * weights->weights[i];
00602 }
00603 }
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613 void nnhpi_modify_data( nnhpi* nnhpi, point* p )
00614 {
00615 point* orig = ht_find( nnhpi->ht_data, p );
00616
00617 assert( orig != NULL );
00618 orig->z = p->z;
00619 }
00620
00621
00622
00623
00624
00625 void nnhpi_setwmin( nnhpi* nn, double wmin )
00626 {
00627 nn->nnpi->wmin = wmin;
00628 }
00629
00630 #if defined ( NNPHI_TEST )
00631
00632 #include <sys/time.h>
00633
00634 #define NPOINTSIN 10000
00635 #define NMIN 10
00636 #define NX 101
00637 #define NXMIN 1
00638
00639 #define SQ( x ) ( ( x ) * ( x ) )
00640
00641 static double franke( double x, double y )
00642 {
00643 x *= 9.0;
00644 y *= 9.0;
00645 return 0.75 * exp( ( -SQ( x - 2.0 ) - SQ( y - 2.0 ) ) / 4.0 )
00646 + 0.75 * exp( -SQ( x - 2.0 ) / 49.0 - ( y - 2.0 ) / 10.0 )
00647 + 0.5 * exp( ( -SQ( x - 7.0 ) - SQ( y - 3.0 ) ) / 4.0 )
00648 - 0.2 * exp( -SQ( x - 4.0 ) - SQ( y - 7.0 ) );
00649 }
00650
00651 static void usage()
00652 {
00653 printf( "Usage: nnhpi_test [-a] [-n <nin> <nxout>] [-v|-V]\n" );
00654 printf( "Options:\n" );
00655 printf( " -a -- use non-Sibsonian interpolation rule\n" );
00656 printf( " -n <nin> <nout>:\n" );
00657 printf( " <nin> -- number of input points (default = 10000)\n" );
00658 printf( " <nout> -- number of output points per side (default = 64)\n" );
00659 printf( " -v -- verbose\n" );
00660 printf( " -V -- very verbose\n" );
00661
00662 exit( 0 );
00663 }
00664
00665 int main( int argc, char* argv[] )
00666 {
00667 int nin = NPOINTSIN;
00668 int nx = NX;
00669 int nout = 0;
00670 point * pin = NULL;
00671 delaunay * d = NULL;
00672 point * pout = NULL;
00673 nnhpi * nn = NULL;
00674 int cpi = -1;
00675 struct timeval tv0, tv1;
00676 struct timezone tz;
00677 int i;
00678
00679 i = 1;
00680 while ( i < argc )
00681 {
00682 switch ( argv[i][1] )
00683 {
00684 case 'a':
00685 i++;
00686 nn_rule = NON_SIBSONIAN;
00687 break;
00688 case 'n':
00689 i++;
00690 if ( i >= argc )
00691 nn_quit( "no number of data points found after -n\n" );
00692 nin = atoi( argv[i] );
00693 i++;
00694 if ( i >= argc )
00695 nn_quit( "no number of ouput points per side found after -i\n" );
00696 nx = atoi( argv[i] );
00697 i++;
00698 break;
00699 case 'v':
00700 i++;
00701 nn_verbose = 1;
00702 break;
00703 case 'V':
00704 i++;
00705 nn_verbose = 2;
00706 break;
00707 default:
00708 usage();
00709 break;
00710 }
00711 }
00712
00713 if ( nin < NMIN )
00714 nin = NMIN;
00715 if ( nx < NXMIN )
00716 nx = NXMIN;
00717
00718 printf( "\nTest of Natural Neighbours hashing point interpolator:\n\n" );
00719 printf( " %d data points\n", nin );
00720 printf( " %d output points\n", nx * nx );
00721
00722
00723
00724
00725 printf( " generating data:\n" );
00726 fflush( stdout );
00727 pin = malloc( nin * sizeof ( point ) );
00728 for ( i = 0; i < nin; ++i )
00729 {
00730 point* p = &pin[i];
00731
00732 p->x = (double) random() / RAND_MAX;
00733 p->y = (double) random() / RAND_MAX;
00734 p->z = franke( p->x, p->y );
00735 if ( nn_verbose )
00736 printf( " (%f, %f, %f)\n", p->x, p->y, p->z );
00737 }
00738
00739
00740
00741
00742 printf( " triangulating:\n" );
00743 fflush( stdout );
00744 d = delaunay_build( nin, pin, 0, NULL, 0, NULL );
00745
00746
00747
00748
00749 points_generate2( -0.1, 1.1, -0.1, 1.1, nx, nx, &nout, &pout );
00750 cpi = ( nx / 2 ) * ( nx + 1 );
00751
00752 gettimeofday( &tv0, &tz );
00753
00754
00755
00756
00757 printf( " creating interpolator:\n" );
00758 fflush( stdout );
00759 nn = nnhpi_create( d, nout );
00760
00761 fflush( stdout );
00762 gettimeofday( &tv1, &tz );
00763 {
00764 long dt = 1000000 * ( tv1.tv_sec - tv0.tv_sec ) + tv1.tv_usec - tv0.tv_usec;
00765
00766 printf( " interpolator creation time = %ld us (%.2f us / point)\n", dt, (double) dt / nout );
00767 }
00768
00769
00770
00771
00772 printf( " interpolating:\n" );
00773 fflush( stdout );
00774 gettimeofday( &tv1, &tz );
00775 for ( i = 0; i < nout; ++i )
00776 {
00777 point* p = &pout[i];
00778
00779 nnhpi_interpolate( nn, p );
00780 if ( nn_verbose )
00781 printf( " (%f, %f, %f)\n", p->x, p->y, p->z );
00782 }
00783
00784 fflush( stdout );
00785 gettimeofday( &tv0, &tz );
00786 {
00787 long dt = 1000000.0 * ( tv0.tv_sec - tv1.tv_sec ) + tv0.tv_usec - tv1.tv_usec;
00788
00789 printf( " interpolation time = %ld us (%.2f us / point)\n", dt, (double) dt / nout );
00790 }
00791
00792 if ( !nn_verbose )
00793 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 ) );
00794
00795 printf( " interpolating one more time:\n" );
00796 fflush( stdout );
00797 gettimeofday( &tv0, &tz );
00798 for ( i = 0; i < nout; ++i )
00799 {
00800 point* p = &pout[i];
00801
00802 nnhpi_interpolate( nn, p );
00803 if ( nn_verbose )
00804 printf( " (%f, %f, %f)\n", p->x, p->y, p->z );
00805 }
00806
00807 fflush( stdout );
00808 gettimeofday( &tv1, &tz );
00809 {
00810 long dt = 1000000.0 * ( tv1.tv_sec - tv0.tv_sec ) + tv1.tv_usec - tv0.tv_usec;
00811
00812 printf( " interpolation time = %ld us (%.2f us / point)\n", dt, (double) dt / nout );
00813 }
00814
00815 if ( !nn_verbose )
00816 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 ) );
00817
00818 printf( " entering new data:\n" );
00819 fflush( stdout );
00820 for ( i = 0; i < nin; ++i )
00821 {
00822 point* p = &pin[i];
00823
00824 p->z = p->x * p->x - p->y * p->y;
00825 nnhpi_modify_data( nn, p );
00826 if ( nn_verbose )
00827 printf( " (%f, %f, %f)\n", p->x, p->y, p->z );
00828 }
00829
00830 printf( " interpolating:\n" );
00831 fflush( stdout );
00832 gettimeofday( &tv1, &tz );
00833 for ( i = 0; i < nout; ++i )
00834 {
00835 point* p = &pout[i];
00836
00837 nnhpi_interpolate( nn, p );
00838 if ( nn_verbose )
00839 printf( " (%f, %f, %f)\n", p->x, p->y, p->z );
00840 }
00841
00842 fflush( stdout );
00843 gettimeofday( &tv0, &tz );
00844 {
00845 long dt = 1000000.0 * ( tv0.tv_sec - tv1.tv_sec ) + tv0.tv_usec - tv1.tv_usec;
00846
00847 printf( " interpolation time = %ld us (%.2f us / point)\n", dt, (double) dt / nout );
00848 }
00849
00850 if ( !nn_verbose )
00851 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 );
00852
00853 printf( " restoring data:\n" );
00854 fflush( stdout );
00855 for ( i = 0; i < nin; ++i )
00856 {
00857 point* p = &pin[i];
00858
00859 p->z = franke( p->x, p->y );
00860 nnhpi_modify_data( nn, p );
00861 if ( nn_verbose )
00862 printf( " (%f, %f, %f)\n", p->x, p->y, p->z );
00863 }
00864
00865 printf( " interpolating:\n" );
00866 fflush( stdout );
00867 gettimeofday( &tv0, &tz );
00868 for ( i = 0; i < nout; ++i )
00869 {
00870 point* p = &pout[i];
00871
00872 nnhpi_interpolate( nn, p );
00873 if ( nn_verbose )
00874 printf( " (%f, %f, %f)\n", p->x, p->y, p->z );
00875 }
00876
00877 fflush( stdout );
00878 gettimeofday( &tv1, &tz );
00879 {
00880 long dt = 1000000.0 * ( tv1.tv_sec - tv0.tv_sec ) + tv1.tv_usec - tv0.tv_usec;
00881
00882 printf( " interpolation time = %ld us (%.2f us / point)\n", dt, (double) dt / nout );
00883 }
00884
00885 if ( !nn_verbose )
00886 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 ) );
00887
00888 printf( " hashtable stats:\n" );
00889 fflush( stdout );
00890 {
00891 hashtable* ht = nn->ht_data;
00892
00893 printf( " input points: %d entries, %d table elements, %d filled elements\n", ht->n, ht->size, ht->nhash );
00894 ht = nn->ht_weights;
00895 printf( " weights: %d entries, %d table elements, %d filled elements\n", ht->n, ht->size, ht->nhash );
00896 }
00897 printf( "\n" );
00898
00899 nnhpi_destroy( nn );
00900 free( pout );
00901 delaunay_destroy( d );
00902 free( pin );
00903
00904 return 0;
00905 }
00906
00907 #endif