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 #include "plplotP.h"
00027
00028 #ifdef WITH_CSA
00029 #include "../lib/csa/csa.h"
00030 #endif
00031 #include "../lib/csa/nan.h"
00032
00033 #ifdef PL_HAVE_QHULL
00034 #include "../lib/nn/nn.h"
00035 #include <qhull/qhull_a.h>
00036 #endif
00037
00038
00039 static void
00040 grid_nnaidw( const PLFLT *x, const PLFLT *y, const PLFLT *z, int npts,
00041 const PLFLT *xg, int nptsx, const PLFLT *yg, int nptsy,
00042 PLF2OPS zops, PLPointer zgp );
00043
00044 static void
00045 grid_nnli( const PLFLT *x, const PLFLT *y, const PLFLT *z, int npts,
00046 const PLFLT *xg, int nptsx, const PLFLT *yg, int nptsy,
00047 PLF2OPS zops, PLPointer zgp, PLFLT threshold );
00048
00049 static void
00050 grid_nnidw( const PLFLT *x, const PLFLT *y, const PLFLT *z, int npts,
00051 const PLFLT *xg, int nptsx, const PLFLT *yg, int nptsy,
00052 PLF2OPS zops, PLPointer zgp, int knn_order );
00053
00054 #ifdef WITH_CSA
00055 static void
00056 grid_csa( const PLFLT *x, const PLFLT *y, const PLFLT *z, int npts,
00057 const PLFLT *xg, int nptsx, const PLFLT *yg, int nptsy,
00058 PLF2OPS zops, PLPointer zgp );
00059 #endif
00060
00061 #ifdef PL_HAVE_QHULL
00062 static void
00063 grid_nni( const PLFLT *x, const PLFLT *y, const PLFLT *z, int npts,
00064 const PLFLT *xg, int nptsx, const PLFLT *yg, int nptsy,
00065 PLF2OPS zops, PLPointer zgp, PLFLT wmin );
00066
00067 static void
00068 grid_dtli( const PLFLT *x, const PLFLT *y, const PLFLT *z, int npts,
00069 const PLFLT *xg, int nptsx, const PLFLT *yg, int nptsy,
00070 PLF2OPS zops, PLPointer zgp );
00071 #endif
00072
00073 static void
00074 dist1( PLFLT gx, PLFLT gy, const PLFLT *x, const PLFLT *y, int npts, int knn_order );
00075 static void
00076 dist2( PLFLT gx, PLFLT gy, const PLFLT *x, const PLFLT *y, int npts );
00077
00078 #define KNN_MAX_ORDER 100
00079
00080 typedef struct pt
00081 {
00082 PLFLT dist;
00083 int item;
00084 }PT;
00085
00086 static PT items[KNN_MAX_ORDER];
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 void
00114 c_plgriddata( const PLFLT *x, const PLFLT *y, const PLFLT *z, PLINT npts,
00115 const PLFLT *xg, PLINT nptsx, const PLFLT *yg, PLINT nptsy,
00116 PLFLT **zg, PLINT type, PLFLT data )
00117 {
00118 plfgriddata( x, y, z, npts, xg, nptsx, yg, nptsy, plf2ops_c(), (PLPointer) zg, type, data );
00119 }
00120
00121 void
00122 plfgriddata( const PLFLT *x, const PLFLT *y, const PLFLT *z, PLINT npts,
00123 const PLFLT *xg, PLINT nptsx, const PLFLT *yg, PLINT nptsy,
00124 PLF2OPS zops, PLPointer zgp, PLINT type, PLFLT data )
00125 {
00126 int i, j;
00127
00128 if ( npts < 1 || nptsx < 1 || nptsy < 1 )
00129 {
00130 plabort( "plgriddata: Bad array dimensions" );
00131 return;
00132 }
00133
00134
00135
00136 for ( i = 0; i < nptsx - 1; i++ )
00137 {
00138 if ( xg[i] >= xg[i + 1] )
00139 {
00140 plabort( "plgriddata: xg array must be strictly increasing" );
00141 return;
00142 }
00143 }
00144 for ( i = 0; i < nptsy - 1; i++ )
00145 {
00146 if ( yg[i] >= yg[i + 1] )
00147 {
00148 plabort( "plgriddata: yg array must be strictly increasing" );
00149 return;
00150 }
00151 }
00152
00153
00154 for ( i = 0; i < nptsx; i++ )
00155 for ( j = 0; j < nptsy; j++ )
00156 zops->set( zgp, i, j, 0.0 );
00157
00158
00159 switch ( type )
00160 {
00161 case ( GRID_CSA ):
00162 #ifdef WITH_CSA
00163 grid_csa( x, y, z, npts, xg, nptsx, yg, nptsy, zops, zgp );
00164 #else
00165 plwarn( "plgriddata(): PLplot was configured to not use GRID_CSA.\n Reverting to GRID_NNAIDW." );
00166 grid_nnaidw( x, y, z, npts, xg, nptsx, yg, nptsy, zops, zgp );
00167 #endif
00168 break;
00169
00170 case ( GRID_NNIDW ):
00171 grid_nnidw( x, y, z, npts, xg, nptsx, yg, nptsy, zops, zgp, (int) data );
00172 break;
00173
00174 case ( GRID_NNLI ):
00175 grid_nnli( x, y, z, npts, xg, nptsx, yg, nptsy, zops, zgp, data );
00176 break;
00177
00178 case ( GRID_NNAIDW ):
00179 grid_nnaidw( x, y, z, npts, xg, nptsx, yg, nptsy, zops, zgp );
00180 break;
00181
00182 case ( GRID_DTLI ):
00183 #ifdef PL_HAVE_QHULL
00184 grid_dtli( x, y, z, npts, xg, nptsx, yg, nptsy, zops, zgp );
00185 #else
00186 plwarn( "plgriddata(): you must have the Qhull library installed to use GRID_DTLI.\n Reverting to GRID_NNAIDW." );
00187 grid_nnaidw( x, y, z, npts, xg, nptsx, yg, nptsy, zops, zgp );
00188 #endif
00189 break;
00190
00191 case ( GRID_NNI ):
00192 #ifdef PL_HAVE_QHULL
00193 grid_nni( x, y, z, npts, xg, nptsx, yg, nptsy, zops, zgp, data );
00194 #else
00195 plwarn( "plgriddata(): you must have the Qhull library installed to use GRID_NNI.\n Reverting to GRID_NNAIDW." );
00196 grid_nnaidw( x, y, z, npts, xg, nptsx, yg, nptsy, zops, zgp );
00197 #endif
00198 break;
00199
00200 default:
00201 plabort( "plgriddata: unknown algorithm type" );
00202 }
00203 }
00204
00205 #ifdef WITH_CSA
00206
00207
00208
00209
00210
00211
00212 static void
00213 grid_csa( const PLFLT *x, const PLFLT *y, const PLFLT *z, int npts,
00214 const PLFLT *xg, int nptsx, const PLFLT *yg, int nptsy,
00215 PLF2OPS zops, PLPointer zgp )
00216 {
00217 PLFLT *xt, *yt, *zt;
00218 point *pin, *pgrid, *pt;
00219 csa * a = NULL;
00220 int i, j, nptsg;
00221
00222 if ( ( pin = (point *) malloc( npts * sizeof ( point ) ) ) == NULL )
00223 {
00224 plexit( "grid_csa: Insufficient memory" );
00225 }
00226
00227 xt = (PLFLT *) x;
00228 yt = (PLFLT *) y;
00229 zt = (PLFLT *) z;
00230 pt = pin;
00231 for ( i = 0; i < npts; i++ )
00232 {
00233 pt->x = (double) *xt++;
00234 pt->y = (double) *yt++;
00235 pt->z = (double) *zt++;
00236 pt++;
00237 }
00238
00239 nptsg = nptsx * nptsy;
00240 if ( ( pgrid = (point *) malloc( nptsg * sizeof ( point ) ) ) == NULL )
00241 {
00242 plexit( "grid_csa: Insufficient memory" );
00243 }
00244
00245 yt = (PLFLT *) yg;
00246 pt = pgrid;
00247 for ( j = 0; j < nptsy; j++ )
00248 {
00249 xt = (PLFLT *) xg;
00250 for ( i = 0; i < nptsx; i++ )
00251 {
00252 pt->x = (double) *xt++;
00253 pt->y = (double) *yt;
00254 pt++;
00255 }
00256 yt++;
00257 }
00258
00259 a = csa_create();
00260 csa_addpoints( a, npts, pin );
00261 csa_calculatespline( a );
00262 csa_approximate_points( a, nptsg, pgrid );
00263
00264 for ( i = 0; i < nptsx; i++ )
00265 {
00266 for ( j = 0; j < nptsy; j++ )
00267 {
00268 pt = &pgrid[j * nptsx + i];
00269 zops->set( zgp, i, j, (PLFLT) pt->z );
00270 }
00271 }
00272
00273 csa_destroy( a );
00274 free( pin );
00275 free( pgrid );
00276 }
00277 #endif // WITH_CSA
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287 static void
00288 grid_nnidw( const PLFLT *x, const PLFLT *y, const PLFLT *z, int npts,
00289 const PLFLT *xg, int nptsx, const PLFLT *yg, int nptsy,
00290 PLF2OPS zops, PLPointer zgp, int knn_order )
00291 {
00292 int i, j, k;
00293 PLFLT wi, nt;
00294
00295 if ( knn_order > KNN_MAX_ORDER )
00296 {
00297 plabort( "plgriddata(): GRID_NNIDW: knn_order too big" );
00298 return;
00299 }
00300
00301 if ( knn_order == 0 )
00302 {
00303 plwarn( "plgriddata(): GRID_NNIDW: knn_order must be specified with 'data' arg. Using 15" );
00304 knn_order = 15;;
00305 }
00306
00307 for ( i = 0; i < nptsx; i++ )
00308 {
00309 for ( j = 0; j < nptsy; j++ )
00310 {
00311 dist1( xg[i], yg[j], x, y, npts, knn_order );
00312
00313 #ifdef GMS // alternative weight coeficients. I Don't like the results
00314
00315 md = items[0].dist;
00316 for ( k = 1; k < knn_order; k++ )
00317 if ( items[k].dist > md )
00318 md = items[k].dist;
00319 #endif
00320 zops->set( zgp, i, j, 0.0 );
00321 nt = 0.;
00322
00323 for ( k = 0; k < knn_order; k++ )
00324 {
00325 if ( items[k].item == -1 )
00326 continue;
00327 #ifdef GMS
00328 wi = ( md - items[k].dist ) / ( md * items[k].dist );
00329 wi = wi * wi;
00330 #else
00331 wi = 1. / ( items[k].dist * items[k].dist );
00332 #endif
00333 zops->add( zgp, i, j, wi * z[items[k].item] );
00334 nt += wi;
00335 }
00336 if ( nt != 0. )
00337 zops->div( zgp, i, j, nt );
00338 else
00339 zops->set( zgp, i, j, NaN );
00340 }
00341 }
00342 }
00343
00344
00345
00346
00347
00348
00349
00350 static void
00351 grid_nnli( const PLFLT *x, const PLFLT *y, const PLFLT *z, int npts,
00352 const PLFLT *xg, int nptsx, const PLFLT *yg, int nptsy,
00353 PLF2OPS zops, PLPointer zgp, PLFLT threshold )
00354 {
00355 PLFLT xx[4], yy[4], zz[4], t, A, B, C, D, d1, d2, d3, max_thick;
00356 int i, j, ii, excl, cnt, excl_item;
00357
00358 if ( threshold == 0. )
00359 {
00360 plwarn( "plgriddata(): GRID_NNLI: threshold must be specified with 'data' arg. Using 1.001" );
00361 threshold = 1.001;
00362 }
00363 else if ( threshold > 2. || threshold < 1. )
00364 {
00365 plabort( "plgriddata(): GRID_NNLI: 1. < threshold < 2." );
00366 return;
00367 }
00368
00369 for ( i = 0; i < nptsx; i++ )
00370 {
00371 for ( j = 0; j < nptsy; j++ )
00372 {
00373 dist1( xg[i], yg[j], x, y, npts, 3 );
00374
00375
00376 for ( ii = 0; ii < 3; ii++ )
00377 {
00378 xx[ii] = x[items[ii].item];
00379 yy[ii] = y[items[ii].item];
00380 zz[ii] = z[items[ii].item];
00381 }
00382
00383 d1 = sqrt( ( xx[1] - xx[0] ) * ( xx[1] - xx[0] ) + ( yy[1] - yy[0] ) * ( yy[1] - yy[0] ) );
00384 d2 = sqrt( ( xx[2] - xx[1] ) * ( xx[2] - xx[1] ) + ( yy[2] - yy[1] ) * ( yy[2] - yy[1] ) );
00385 d3 = sqrt( ( xx[0] - xx[2] ) * ( xx[0] - xx[2] ) + ( yy[0] - yy[2] ) * ( yy[0] - yy[2] ) );
00386
00387 if ( d1 == 0. || d2 == 0. || d3 == 0. )
00388 {
00389 zops->set( zgp, i, j, NaN );
00390 continue;
00391 }
00392
00393
00394 if ( d1 > d2 )
00395 {
00396 t = d1; d1 = d2; d2 = t;
00397 }
00398
00399
00400 if ( d2 > d3 )
00401 {
00402 t = d2; d2 = d3; d3 = t;
00403 }
00404
00405 if ( ( d1 + d2 ) / d3 < threshold )
00406 {
00407 zops->set( zgp, i, j, NaN );
00408 }
00409 else
00410
00411 {
00412 A = yy[0] * ( zz[1] - zz[2] ) + yy[1] * ( zz[2] - zz[0] ) + yy[2] * ( zz[0] - zz[1] );
00413 B = zz[0] * ( xx[1] - xx[2] ) + zz[1] * ( xx[2] - xx[0] ) + zz[2] * ( xx[0] - xx[1] );
00414 C = xx[0] * ( yy[1] - yy[2] ) + xx[1] * ( yy[2] - yy[0] ) + xx[2] * ( yy[0] - yy[1] );
00415 D = -A * xx[0] - B * yy[0] - C * zz[0];
00416
00417
00418 zops->set( zgp, i, j, -xg[i] * A / C - yg[j] * B / C - D / C );
00419 }
00420 }
00421 }
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432 {
00433 for ( i = 0; i < nptsx; i++ )
00434 {
00435 for ( j = 0; j < nptsy; j++ )
00436 {
00437 if ( zops->is_nan( zgp, i, j ) )
00438 {
00439 dist1( xg[i], yg[j], x, y, npts, 4 );
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453 max_thick = 0.; excl_item = -1;
00454 for ( excl = 0; excl < 4; excl++ )
00455
00456 {
00457 cnt = 0;
00458 for ( ii = 0; ii < 4; ii++ )
00459 {
00460 if ( ii != excl )
00461 {
00462 xx[cnt] = x[items[ii].item];
00463 yy[cnt] = y[items[ii].item];
00464 cnt++;
00465 }
00466 }
00467
00468 d1 = sqrt( ( xx[1] - xx[0] ) * ( xx[1] - xx[0] ) + ( yy[1] - yy[0] ) * ( yy[1] - yy[0] ) );
00469 d2 = sqrt( ( xx[2] - xx[1] ) * ( xx[2] - xx[1] ) + ( yy[2] - yy[1] ) * ( yy[2] - yy[1] ) );
00470 d3 = sqrt( ( xx[0] - xx[2] ) * ( xx[0] - xx[2] ) + ( yy[0] - yy[2] ) * ( yy[0] - yy[2] ) );
00471 if ( d1 == 0. || d2 == 0. || d3 == 0. )
00472 continue;
00473
00474
00475 if ( d1 > d2 )
00476 {
00477 t = d1; d1 = d2; d2 = t;
00478 }
00479
00480 if ( d2 > d3 )
00481 {
00482 t = d2; d2 = d3; d3 = t;
00483 }
00484
00485 t = ( d1 + d2 ) / d3;
00486 if ( t > max_thick )
00487 {
00488 max_thick = t;
00489 excl_item = excl;
00490 }
00491 }
00492
00493 if ( excl_item == -1 )
00494 continue;
00495
00496
00497 cnt = 0;
00498 for ( ii = 0; ii < 4; ii++ )
00499 {
00500 if ( ii != excl_item )
00501 {
00502 xx[cnt] = x[items[ii].item];
00503 yy[cnt] = y[items[ii].item];
00504 zz[cnt] = z[items[ii].item];
00505 cnt++;
00506 }
00507 }
00508
00509 A = yy[0] * ( zz[1] - zz[2] ) + yy[1] * ( zz[2] - zz[0] ) + yy[2] * ( zz[0] - zz[1] );
00510 B = zz[0] * ( xx[1] - xx[2] ) + zz[1] * ( xx[2] - xx[0] ) + zz[2] * ( xx[0] - xx[1] );
00511 C = xx[0] * ( yy[1] - yy[2] ) + xx[1] * ( yy[2] - yy[0] ) + xx[2] * ( yy[0] - yy[1] );
00512 D = -A * xx[0] - B * yy[0] - C * zz[0];
00513
00514
00515 zops->set( zgp, i, j, -xg[i] * A / C - yg[j] * B / C - D / C );
00516 }
00517 }
00518 }
00519 }
00520 }
00521
00522
00523
00524
00525
00526
00527
00528
00529 static void
00530 grid_nnaidw( const PLFLT *x, const PLFLT *y, const PLFLT *z, int npts,
00531 const PLFLT *xg, int nptsx, const PLFLT *yg, int nptsy, PLF2OPS zops, PLPointer zgp )
00532 {
00533 PLFLT d, nt;
00534 int i, j, k;
00535
00536 for ( i = 0; i < nptsx; i++ )
00537 {
00538 for ( j = 0; j < nptsy; j++ )
00539 {
00540 dist2( xg[i], yg[j], x, y, npts );
00541 zops->set( zgp, i, j, 0. );
00542 nt = 0.;
00543 for ( k = 0; k < 4; k++ )
00544 {
00545 if ( items[k].item != -1 )
00546 {
00547 d = 1. / ( items[k].dist * items[k].dist );
00548 zops->add( zgp, i, j, d * z[items[k].item] );
00549 nt += d;
00550 }
00551 }
00552 if ( nt == 0. )
00553 zops->set( zgp, i, j, NaN );
00554 else
00555 zops->div( zgp, i, j, nt );
00556 }
00557 }
00558 }
00559
00560 #ifdef PL_HAVE_QHULL
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572 static void
00573 grid_dtli( const PLFLT *x, const PLFLT *y, const PLFLT *z, int npts,
00574 const PLFLT *xg, int nptsx, const PLFLT *yg, int nptsy, PLF2OPS zops, PLPointer zgp )
00575 {
00576 point *pin, *pgrid, *pt;
00577 PLFLT *xt, *yt, *zt;
00578 int i, j, nptsg;
00579
00580 if ( sizeof ( realT ) != sizeof ( double ) )
00581 {
00582 plabort( "plgridata: QHull was compiled for floats instead of doubles" );
00583 return;
00584 }
00585
00586 if ( ( pin = (point *) malloc( npts * sizeof ( point ) ) ) == NULL )
00587 {
00588 plexit( "grid_dtli: Insufficient memory" );
00589 }
00590
00591 xt = (PLFLT *) x;
00592 yt = (PLFLT *) y;
00593 zt = (PLFLT *) z;
00594 pt = pin;
00595 for ( i = 0; i < npts; i++ )
00596 {
00597 pt->x = (double) *xt++;
00598 pt->y = (double) *yt++;
00599 pt->z = (double) *zt++;
00600 pt++;
00601 }
00602
00603 nptsg = nptsx * nptsy;
00604
00605 if ( ( pgrid = (point *) malloc( nptsg * sizeof ( point ) ) ) == NULL )
00606 {
00607 plexit( "grid_dtli: Insufficient memory" );
00608 }
00609
00610 yt = (PLFLT *) yg;
00611 pt = pgrid;
00612 for ( j = 0; j < nptsy; j++ )
00613 {
00614 xt = (PLFLT *) xg;
00615 for ( i = 0; i < nptsx; i++ )
00616 {
00617 pt->x = (double) *xt++;
00618 pt->y = (double) *yt;
00619 pt++;
00620 }
00621 yt++;
00622 }
00623
00624 lpi_interpolate_points( npts, pin, nptsg, pgrid );
00625 for ( i = 0; i < nptsx; i++ )
00626 {
00627 for ( j = 0; j < nptsy; j++ )
00628 {
00629 pt = &pgrid[j * nptsx + i];
00630 zops->set( zgp, i, j, (PLFLT) pt->z );
00631 }
00632 }
00633
00634 free( pin );
00635 free( pgrid );
00636 }
00637
00638
00639
00640
00641
00642
00643
00644
00645 static void
00646 grid_nni( const PLFLT *x, const PLFLT *y, const PLFLT *z, int npts,
00647 const PLFLT *xg, int nptsx, const PLFLT *yg, int nptsy, PLF2OPS zops, PLPointer zgp,
00648 PLFLT wmin )
00649 {
00650 PLFLT *xt, *yt, *zt;
00651 point *pin, *pgrid, *pt;
00652 int i, j, nptsg;
00653 nn_rule = NON_SIBSONIAN;
00654
00655 if ( sizeof ( realT ) != sizeof ( double ) )
00656 {
00657 plabort( "plgridata: QHull was compiled for floats instead of doubles" );
00658 return;
00659 }
00660
00661 if ( wmin == 0. )
00662 {
00663 plwarn( "plgriddata(): GRID_NNI: wmin must be specified with 'data' arg. Using -PLFLT_MAX" );
00664 wmin = -PLFLT_MAX;
00665 }
00666
00667 if ( ( pin = (point *) malloc( npts * sizeof ( point ) ) ) == NULL )
00668 {
00669 plexit( "plgridata: Insufficient memory" );
00670 }
00671
00672 xt = (PLFLT *) x;
00673 yt = (PLFLT *) y;
00674 zt = (PLFLT *) z;
00675 pt = pin;
00676 for ( i = 0; i < npts; i++ )
00677 {
00678 pt->x = (double) *xt++;
00679 pt->y = (double) *yt++;
00680 pt->z = (double) *zt++;
00681 pt++;
00682 }
00683
00684 nptsg = nptsx * nptsy;
00685
00686 if ( ( pgrid = (point *) malloc( nptsg * sizeof ( point ) ) ) == NULL )
00687 {
00688 plexit( "plgridata: Insufficient memory" );
00689 }
00690
00691 yt = (PLFLT *) yg;
00692 pt = pgrid;
00693 for ( j = 0; j < nptsy; j++ )
00694 {
00695 xt = (PLFLT *) xg;
00696 for ( i = 0; i < nptsx; i++ )
00697 {
00698 pt->x = (double) *xt++;
00699 pt->y = (double) *yt;
00700 pt++;
00701 }
00702 yt++;
00703 }
00704
00705 nnpi_interpolate_points( npts, pin, wmin, nptsg, pgrid );
00706 for ( i = 0; i < nptsx; i++ )
00707 {
00708 for ( j = 0; j < nptsy; j++ )
00709 {
00710 pt = &pgrid[j * nptsx + i];
00711 zops->set( zgp, i, j, (PLFLT) pt->z );
00712 }
00713 }
00714
00715 free( pin );
00716 free( pgrid );
00717 }
00718 #endif // PL_HAVE_QHULL
00719
00720
00721
00722
00723
00724
00725 static void
00726 dist1( PLFLT gx, PLFLT gy, const PLFLT *x, const PLFLT *y, int npts, int knn_order )
00727 {
00728 PLFLT d, max_dist;
00729 int max_slot, i, j;
00730
00731 max_dist = PLFLT_MAX;
00732 max_slot = 0;
00733
00734 for ( i = 0; i < knn_order; i++ )
00735 {
00736 items[i].dist = PLFLT_MAX;
00737 items[i].item = -1;
00738 }
00739
00740 for ( i = 0; i < npts; i++ )
00741 {
00742 d = ( ( gx - x[i] ) * ( gx - x[i] ) + ( gy - y[i] ) * ( gy - y[i] ) );
00743
00744 if ( d < max_dist )
00745 {
00746
00747
00748
00749
00750 items[max_slot].dist = d;
00751 items[max_slot].item = i;
00752
00753
00754 max_dist = items[0].dist;
00755 max_slot = 0;
00756 for ( j = 1; j < knn_order; j++ )
00757 {
00758 if ( items[j].dist > max_dist )
00759 {
00760 max_dist = items[j].dist;
00761 max_slot = j;
00762 }
00763 }
00764 }
00765 }
00766 for ( j = 0; j < knn_order; j++ )
00767 items[j].dist = sqrt( items[j].dist );
00768 }
00769
00770
00771
00772
00773
00774
00775 static void
00776 dist2( PLFLT gx, PLFLT gy, const PLFLT *x, const PLFLT *y, int npts )
00777 {
00778 PLFLT d;
00779 int i, quad;
00780
00781 for ( i = 0; i < 4; i++ )
00782 {
00783 items[i].dist = PLFLT_MAX;
00784 items[i].item = -1;
00785 }
00786
00787 for ( i = 0; i < npts; i++ )
00788 {
00789 d = ( ( gx - x[i] ) * ( gx - x[i] ) + ( gy - y[i] ) * ( gy - y[i] ) );
00790
00791
00792
00793
00794
00795 quad = 2 * ( x[i] > gx ) + ( y[i] < gy );
00796
00797
00798
00799
00800
00801 if ( d < items[quad].dist )
00802 {
00803 items[quad].dist = d;
00804 items[quad].item = i;
00805 }
00806 }
00807
00808 for ( i = 0; i < 4; i++ )
00809 if ( items[i].item != -1 )
00810 items[i].dist = sqrt( items[i].dist );
00811
00812 }
00813
00814 #ifdef NONN // another DTLI, based only on QHULL, not nn
00815 static void
00816 grid_adtli( const PLFLT *x, const PLFLT *y, const PLFLT *z, int npts,
00817 const PLFLT *xg, int nptsx, const PLFLT *yg, int nptsy, PLF2OPS zops, PLPointer zgp )
00818 {
00819 coordT *points;
00820 boolT ismalloc = False;
00821 char flags[250];
00822 facetT *facet;
00823 vertexT *vertex, **vertexp;
00824 facetT *neighbor, **neighborp;
00825 int curlong, totlong;
00826 FILE *outfile = NULL;
00827 FILE *errfile = stderr;
00828
00829 int exitcode;
00830 int i, j, k, l;
00831 int dim = 2;
00832 PLFLT xt[3], yt[3], zt[3];
00833 PLFLT A, B, C, D;
00834 coordT point[3];
00835 boolT isoutside;
00836 realT bestdist;
00837 int totpart = 0;
00838 int numfacets, numsimplicial, numridges;
00839 int totneighbors, numcoplanars, numtricoplanars;
00840
00841 plwarn( "plgriddata: GRID_DTLI, If you have QHull knowledge, FIXME." );
00842
00843
00844
00845 strcpy( flags, "qhull d Qbb Qt", 250 );
00846
00847 if ( ( points = (coordT *) malloc( npts * ( dim + 1 ) * sizeof ( coordT ) ) ) == NULL )
00848 {
00849 plexit( "grid_adtli: Insufficient memory" );
00850 }
00851
00852 for ( i = 0; i < npts; i++ )
00853 {
00854 points[i * dim] = x[i];
00855 points[i * dim + 1] = y[i];
00856 }
00857
00858 #if 1 // easy way
00859 exitcode = qh_new_qhull( dim, npts, points, ismalloc,
00860 flags, outfile, errfile );
00861 #else
00862 qh_init_A( stdin, stdout, stderr, 0, NULL );
00863 exitcode = setjmp( qh errexit );
00864 if ( !exitcode )
00865 {
00866 qh_initflags( flags );
00867 qh PROJECTdelaunay = True;
00868 qh_init_B( points, npts, dim, ismalloc );
00869 qh_qhull();
00870 }
00871 #endif
00872 if ( !exitcode )
00873
00874 {
00875 #if 0 // print the triangles vertices
00876 printf( "Triangles\n" );
00877 FORALLfacets {
00878 if ( !facet->upperdelaunay )
00879 {
00880 FOREACHvertex_( facet->vertices )
00881 printf( " %d", qh_pointid( vertex->point ) );
00882 printf( "\n" );
00883 }
00884 }
00885 #endif
00886
00887 #if 0 // print each triangle neighbors
00888 printf( "Neigbors\n" );
00889
00890 qh_findgood_all( qh facet_list );
00891 qh_countfacets( qh facet_list, NULL, !qh_ALL, &numfacets, &numsimplicial,
00892 &totneighbors, &numridges, &numcoplanars, &numtricoplanars );
00893
00894 FORALLfacets {
00895 if ( !facet->upperdelaunay )
00896 {
00897 FOREACHneighbor_( facet )
00898 printf( " %d", neighbor->visitid ? neighbor->visitid - 1 : -neighbor->id );
00899 printf( "\n" );
00900 }
00901 }
00902 #endif
00903
00904
00905 exitcode = setjmp( qh errexit );
00906 if ( !exitcode )
00907 {
00908 qh NOerrexit = False;
00909 for ( i = 0; i < nptsx; i++ )
00910 for ( j = 0; j < nptsy; j++ )
00911 {
00912 l = 0;
00913 point[0] = xg[i];
00914 point[1] = yg[j];
00915 qh_setdelaunay( 3, 1, point );
00916
00917
00918
00919
00920 #if 0
00921 facet = qh_findbestfacet( point, qh_ALL, &bestdist, &isoutside );
00922 #endif
00923
00924 #if 0
00925 facet = qh_findbest( point, qh facet_list, qh_ALL,
00926 !qh_ISnewfacets,
00927 qh_NOupper,
00928 &bestdist, &isoutside, &totpart );
00929 #endif
00930
00931 #if 0
00932 vertex = qh_nearvertex( facet, point, &bestdist );
00933 #endif
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948 facet = qh_findfacet_all( point, &bestdist, &isoutside, &totpart );
00949
00950 if ( facet->upperdelaunay )
00951 zops->set( zgp, i, j, NaN );
00952 else
00953 {
00954 FOREACHvertex_( facet->vertices )
00955 {
00956 k = qh_pointid( vertex->point );
00957 xt[l] = x[k];
00958 yt[l] = y[k];
00959 zt[l] = z[k];
00960 l++;
00961 }
00962
00963
00964
00965 A = yt[0] * ( zt[1] - zt[2] ) + yt[1] * ( zt[2] - zt[0] ) + yt[2] * ( zt[0] - zt[1] );
00966 B = zt[0] * ( xt[1] - xt[2] ) + zt[1] * ( xt[2] - xt[0] ) + zt[2] * ( xt[0] - xt[1] );
00967 C = xt[0] * ( yt[1] - yt[2] ) + xt[1] * ( yt[2] - yt[0] ) + xt[2] * ( yt[0] - yt[1] );
00968 D = -A * xt[0] - B * yt[0] - C * zt[0];
00969
00970
00971 zops->set( zgp, i, j, -xg[i] * A / C - yg[j] * B / C - D / C );
00972 }
00973 }
00974 }
00975 qh NOerrexit = True;
00976 }
00977
00978 free( points );
00979 qh_freeqhull( !qh_ALL );
00980 qh_memfreeshort( &curlong, &totlong );
00981 if ( curlong || totlong )
00982 fprintf( errfile,
00983 "qhull: did not free %d bytes of long memory (%d pieces)\n",
00984 totlong, curlong );
00985 }
00986 #endif // NONN