• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

nnpi.c

Go to the documentation of this file.
00001 //--------------------------------------------------------------------------
00002 //
00003 // File:           nnpi.c
00004 //
00005 // Created:        15/11/2002
00006 //
00007 // Author:         Pavel Sakov
00008 //                 CSIRO Marine Research
00009 //
00010 // Purpose:        Code for:
00011 //                 -- Natural Neighbours Point Interpolator
00012 //                 -- Natural Neighbours Point Hashing Interpolator
00013 //
00014 // Description:    `nnpi' -- "Natural Neighbours Point
00015 //                 Interpolator" -- is a structure for conducting Natural
00016 //                 Neighbours interpolation on a given data on a
00017 //                 "point-to-point" basis. Because it involves weight
00018 //                 calculation for each next output point, it is not
00019 //                 particularly suitable for consequitive interpolations on
00020 //                 the same set of observation points -- use
00021 //                 `nnhpi' or `nnai'
00022 //                 in these cases.
00023 //
00024 //                 `nnhpi' is a structure for
00025 //                 conducting consequitive Natural Neighbours interpolations
00026 //                 on a given spatial data set in a random sequence of points
00027 //                 from a set of finite size, taking advantage of repeated
00028 //                 interpolations in the same point. It allows to modify Z
00029 //                 coordinate of data in between interpolations.
00030 //
00031 //
00032 // Revisions:      01/04/2003 PS: modified nnpi_triangle_process(): for
00033 //                   Sibson interpolation, if circle_build fails(), now a
00034 //                   local copy of a point is moved slightly rather than the
00035 //                   data point itself. The later approach have found leading
00036 //                   to inconsistencies of the new point position with the
00037 //                   earlier built triangulation.
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     // work variables
00060     //
00061     int   nvertices;
00062     int   nallocated;
00063     int   * vertices;           // vertex indices
00064     double* weights;
00065     int   n;                    // number of points processed
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 // Creates Natural Neighbours point interpolator.
00084 //
00085 // @param d Delaunay triangulation
00086 // @return Natural Neighbours interpolation
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 // Destroys Natural Neighbours point interpolator.
00105 //
00106 // @param nn Structure to be destroyed
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     // find whether the vertex is already in the list
00128     //
00129     for ( i = 0; i < nn->nvertices; ++i )
00130         if ( nn->vertices[i] == vertex )
00131             break;
00132 
00133     if ( i == nn->nvertices ) // not in the list
00134     {                         //
00135         // get more memory if necessary
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         // add the vertex to the list
00146         //
00147         nn->vertices[i] = vertex;
00148         nn->weights[i]  = w;
00149         nn->nvertices++;
00150     }
00151     else                        // in the list
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 // This is a central procedure for the Natural Neighbours interpolation. It
00178 // uses the Watson's algorithm for the required areas calculation and implies
00179 // that the vertices of the delaunay triangulation are listed in uniform
00180 // (clockwise or counterclockwise) order.
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         // Sibson interpolation by using Watson's algorithm
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 // Finds Natural Neighbours-interpolated value for a point.
00286 //
00287 // @param nn NN interpolation
00288 // @param p Point to be interpolated (p->x, p->y -- input; p->z -- output)
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 // Performs Natural Neighbours interpolation for an array of points.
00356 //
00357 // @param nin Number of input points
00358 // @param pin Array of input points [pin]
00359 // @param wmin Minimal allowed weight
00360 // @param nout Number of output points
00361 // @param pout Array of output points [nout]
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 // Sets minimal allowed weight for Natural Neighbours interpolation.
00402 // @param nn Natural Neighbours point interpolator
00403 // @param wmin Minimal allowed weight
00404 //
00405 void nnpi_setwmin( nnpi* nn, double wmin )
00406 {
00407     nn->wmin = wmin;
00408 }
00409 
00410 // Sets point to interpolate in.
00411 // @param nn Natural Neighbours point interpolator
00412 // @param p Point to interpolate in
00413 //
00414 void nnpi_set_point( nnpi* nn, point* p )
00415 {
00416     nn->p = p;
00417 }
00418 
00419 // Gets number of data points involved in current interpolation.
00420 // @return Number of data points involved in current interpolation
00421 //
00422 int nnpi_get_nvertices( nnpi* nn )
00423 {
00424     return nn->nvertices;
00425 }
00426 
00427 // Gets indices of data points involved in current interpolation.
00428 // @return indices of data points involved in current interpolation
00429 //
00430 int* nnpi_get_vertices( nnpi* nn )
00431 {
00432     return nn->vertices;
00433 }
00434 
00435 // Gets weights of data points involved in current interpolation.
00436 // @return weights of data points involved in current interpolation
00437 //
00438 double* nnpi_get_weights( nnpi* nn )
00439 {
00440     return nn->weights;
00441 }
00442 
00443 //
00444 // nnhpi
00445 //
00446 
00447 struct nnhpi
00448 {
00449     nnpi     * nnpi;
00450     hashtable* ht_data;
00451     hashtable* ht_weights;
00452     int      n;                 // number of points processed
00453 };
00454 
00455 typedef struct
00456 {
00457     int   nvertices;
00458     int   * vertices;           // vertex indices [nvertices]
00459     double* weights;            // vertex weights [nvertices]
00460 } nn_weights;
00461 
00462 // Creates Natural Neighbours hashing point interpolator.
00463 //
00464 // @param d Delaunay triangulation
00465 // @param size Hash table size (should be of order of number of output points)
00466 // @return Natural Neighbours interpolation
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 // Destroys Natural Neighbours hashing point interpolation.
00495 //
00496 // @param nn Structure to be destroyed
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 // Finds Natural Neighbours-interpolated value in a point.
00507 //
00508 // @param nnhpi NN point hashing interpolator
00509 // @param p Point to be interpolated (p->x, p->y -- input; p->z -- output)
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 // Modifies interpolated data.
00606 // Finds point* pd in the underlying Delaunay triangulation such that
00607 // pd->x = p->x and pd->y = p->y, and copies p->z to pd->z. Exits with error
00608 // if the point is not found.
00609 //
00610 // @param nnhpi Natural Neighbours hashing point interpolator
00611 // @param p New data
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 // Sets minimal allowed weight for Natural Neighbours interpolation.
00622 // @param nn Natural Neighbours point hashing interpolator
00623 // @param wmin Minimal allowed weight
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; // control point index
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     // generate data
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     // triangulate
00741     //
00742     printf( "  triangulating:\n" );
00743     fflush( stdout );
00744     d = delaunay_build( nin, pin, 0, NULL, 0, NULL );
00745 
00746     //
00747     // generate output points
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     // create interpolator
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     // interpolate
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

Generated on Wed Oct 12 2011 20:42:22 for PLplot by  doxygen 1.7.1