27 #include "../lib/csa/csa.h"
29 #include "../lib/csa/nan.h"
32 #include "../lib/nn/nn.h"
33 #include <qhull/qhull_a.h>
76 #define KNN_MAX_ORDER 100
116 plfgriddata( x, y, z, npts, xg, nptsx, yg, nptsy,
plf2ops_c(), (
PLPointer) zg, type, data );
126 if ( npts < 1 || nptsx < 1 || nptsy < 1 )
128 plabort(
"plgriddata: Bad array dimensions" );
134 for ( i = 0; i < nptsx - 1; i++ )
136 if ( xg[i] >= xg[i + 1] )
138 plabort(
"plgriddata: xg array must be strictly increasing" );
142 for ( i = 0; i < nptsy - 1; i++ )
144 if ( yg[i] >= yg[i + 1] )
146 plabort(
"plgriddata: yg array must be strictly increasing" );
152 for ( i = 0; i < nptsx; i++ )
153 for ( j = 0; j < nptsy; j++ )
154 zops->
set( zgp, i, j, 0.0 );
161 grid_csa( x, y, z, npts, xg, nptsx, yg, nptsy, zops, zgp );
163 plwarn(
"plgriddata(): PLplot was configured to not use GRID_CSA.\n Reverting to GRID_NNAIDW." );
164 grid_nnaidw( x, y, z, npts, xg, nptsx, yg, nptsy, zops, zgp );
169 grid_nnidw( x, y, z, npts, xg, nptsx, yg, nptsy, zops, zgp, (
int) data );
173 grid_nnli( x, y, z, npts, xg, nptsx, yg, nptsy, zops, zgp, data );
177 grid_nnaidw( x, y, z, npts, xg, nptsx, yg, nptsy, zops, zgp );
182 grid_dtli( x, y, z, npts, xg, nptsx, yg, nptsy, zops, zgp );
184 plwarn(
"plgriddata(): you must have the Qhull library installed to use GRID_DTLI.\n Reverting to GRID_NNAIDW." );
185 grid_nnaidw( x, y, z, npts, xg, nptsx, yg, nptsy, zops, zgp );
191 grid_nni( x, y, z, npts, xg, nptsx, yg, nptsy, zops, zgp, data );
193 plwarn(
"plgriddata(): you must have the Qhull library installed to use GRID_NNI.\n Reverting to GRID_NNAIDW." );
194 grid_nnaidw( x, y, z, npts, xg, nptsx, yg, nptsy, zops, zgp );
199 plabort(
"plgriddata: unknown algorithm type" );
215 const PLFLT *xt, *yt, *zt;
220 if ( ( pin = (
point *) malloc( (
size_t) npts *
sizeof (
point ) ) ) == NULL )
222 plexit(
"grid_csa: Insufficient memory" );
229 for ( i = 0; i < npts; i++ )
231 pt->
x = (double) *xt++;
232 pt->
y = (double) *yt++;
233 pt->
z = (double) *zt++;
237 nptsg = nptsx * nptsy;
238 if ( ( pgrid = (
point *) malloc( (
size_t) nptsg *
sizeof (
point ) ) ) == NULL )
240 plexit(
"grid_csa: Insufficient memory" );
245 for ( j = 0; j < nptsy; j++ )
248 for ( i = 0; i < nptsx; i++ )
250 pt->
x = (double) *xt++;
251 pt->
y = (double) *yt;
262 for ( i = 0; i < nptsx; i++ )
264 for ( j = 0; j < nptsy; j++ )
266 pt = &pgrid[j * nptsx + i];
287 const PLFLT *xg,
int nptsx,
const PLFLT *yg,
int nptsy,
295 plabort(
"plgriddata(): GRID_NNIDW: knn_order too big" );
299 if ( knn_order == 0 )
301 plwarn(
"plgriddata(): GRID_NNIDW: knn_order must be specified with 'data' arg. Using 15" );
305 for ( i = 0; i < nptsx; i++ )
307 for ( j = 0; j < nptsy; j++ )
309 dist1( xg[i], yg[j], x, y, npts, knn_order );
311 #ifdef GMS // alternative weight coeficients. I Don't like the results
314 for ( k = 1; k < knn_order; k++ )
315 if ( items[k].dist > md )
318 zops->
set( zgp, i, j, 0.0 );
321 for ( k = 0; k < knn_order; k++ )
323 if ( items[k].item == -1 )
326 wi = ( md - items[k].
dist ) / ( md * items[k].dist );
329 wi = 1. / ( items[k].
dist * items[k].
dist );
331 zops->
add( zgp, i, j, wi * z[items[k].item] );
335 zops->
div( zgp, i, j, nt );
337 zops->
set( zgp, i, j,
NaN );
350 const PLFLT *xg,
int nptsx,
const PLFLT *yg,
int nptsy,
353 PLFLT xx[4], yy[4], zz[4], t, A, B, C, D, d1, d2, d3, max_thick;
354 int i, j, ii, excl, cnt, excl_item;
356 if ( threshold == 0. )
358 plwarn(
"plgriddata(): GRID_NNLI: threshold must be specified with 'data' arg. Using 1.001" );
361 else if ( threshold > 2. || threshold < 1. )
363 plabort(
"plgriddata(): GRID_NNLI: 1. < threshold < 2." );
367 for ( i = 0; i < nptsx; i++ )
369 for ( j = 0; j < nptsy; j++ )
371 dist1( xg[i], yg[j], x, y, npts, 3 );
374 for ( ii = 0; ii < 3; ii++ )
376 xx[ii] = x[items[ii].
item];
377 yy[ii] = y[items[ii].item];
378 zz[ii] = z[items[ii].item];
381 d1 = sqrt( ( xx[1] - xx[0] ) * ( xx[1] - xx[0] ) + ( yy[1] - yy[0] ) * ( yy[1] - yy[0] ) );
382 d2 = sqrt( ( xx[2] - xx[1] ) * ( xx[2] - xx[1] ) + ( yy[2] - yy[1] ) * ( yy[2] - yy[1] ) );
383 d3 = sqrt( ( xx[0] - xx[2] ) * ( xx[0] - xx[2] ) + ( yy[0] - yy[2] ) * ( yy[0] - yy[2] ) );
385 if ( d1 == 0. || d2 == 0. || d3 == 0. )
387 zops->
set( zgp, i, j,
NaN );
394 t = d1; d1 = d2; d2 = t;
400 t = d2; d2 = d3; d3 = t;
403 if ( ( d1 + d2 ) / d3 < threshold )
405 zops->
set( zgp, i, j,
NaN );
410 A = yy[0] * ( zz[1] - zz[2] ) + yy[1] * ( zz[2] - zz[0] ) + yy[2] * ( zz[0] - zz[1] );
411 B = zz[0] * ( xx[1] - xx[2] ) + zz[1] * ( xx[2] - xx[0] ) + zz[2] * ( xx[0] - xx[1] );
412 C = xx[0] * ( yy[1] - yy[2] ) + xx[1] * ( yy[2] - yy[0] ) + xx[2] * ( yy[0] - yy[1] );
413 D = -A * xx[0] - B * yy[0] - C * zz[0];
416 zops->
set( zgp, i, j, -xg[i] * A / C - yg[j] * B / C - D / C );
431 for ( i = 0; i < nptsx; i++ )
433 for ( j = 0; j < nptsy; j++ )
435 if ( zops->
is_nan( zgp, i, j ) )
437 dist1( xg[i], yg[j], x, y, npts, 4 );
451 max_thick = 0.; excl_item = -1;
452 for ( excl = 0; excl < 4; excl++ )
456 for ( ii = 0; ii < 4; ii++ )
460 xx[cnt] = x[items[ii].
item];
461 yy[cnt] = y[items[ii].item];
466 d1 = sqrt( ( xx[1] - xx[0] ) * ( xx[1] - xx[0] ) + ( yy[1] - yy[0] ) * ( yy[1] - yy[0] ) );
467 d2 = sqrt( ( xx[2] - xx[1] ) * ( xx[2] - xx[1] ) + ( yy[2] - yy[1] ) * ( yy[2] - yy[1] ) );
468 d3 = sqrt( ( xx[0] - xx[2] ) * ( xx[0] - xx[2] ) + ( yy[0] - yy[2] ) * ( yy[0] - yy[2] ) );
469 if ( d1 == 0. || d2 == 0. || d3 == 0. )
475 t = d1; d1 = d2; d2 = t;
480 t = d2; d2 = d3; d3 = t;
483 t = ( d1 + d2 ) / d3;
491 if ( excl_item == -1 )
496 for ( ii = 0; ii < 4; ii++ )
498 if ( ii != excl_item )
500 xx[cnt] = x[items[ii].
item];
501 yy[cnt] = y[items[ii].item];
502 zz[cnt] = z[items[ii].item];
507 A = yy[0] * ( zz[1] - zz[2] ) + yy[1] * ( zz[2] - zz[0] ) + yy[2] * ( zz[0] - zz[1] );
508 B = zz[0] * ( xx[1] - xx[2] ) + zz[1] * ( xx[2] - xx[0] ) + zz[2] * ( xx[0] - xx[1] );
509 C = xx[0] * ( yy[1] - yy[2] ) + xx[1] * ( yy[2] - yy[0] ) + xx[2] * ( yy[0] - yy[1] );
510 D = -A * xx[0] - B * yy[0] - C * zz[0];
513 zops->
set( zgp, i, j, -xg[i] * A / C - yg[j] * B / C - D / C );
534 for ( i = 0; i < nptsx; i++ )
536 for ( j = 0; j < nptsy; j++ )
538 dist2( xg[i], yg[j], x, y, npts );
539 zops->
set( zgp, i, j, 0. );
541 for ( k = 0; k < 4; k++ )
543 if ( items[k].item != -1 )
545 d = 1. / ( items[k].
dist * items[k].
dist );
546 zops->
add( zgp, i, j, d * z[items[k].item] );
551 zops->
set( zgp, i, j,
NaN );
553 zops->
div( zgp, i, j, nt );
574 point *pin, *pgrid, *pt;
575 const PLFLT *xt, *yt, *zt;
578 if (
sizeof ( realT ) !=
sizeof (
double ) )
580 plabort(
"plgridata: QHull was compiled for floats instead of doubles" );
584 if ( ( pin = (
point *) malloc( (
size_t) npts *
sizeof (
point ) ) ) == NULL )
586 plexit(
"grid_dtli: Insufficient memory" );
593 for ( i = 0; i < npts; i++ )
595 pt->
x = (double) *xt++;
596 pt->
y = (double) *yt++;
597 pt->
z = (double) *zt++;
601 nptsg = nptsx * nptsy;
603 if ( ( pgrid = (
point *) malloc( (
size_t) nptsg *
sizeof (
point ) ) ) == NULL )
605 plexit(
"grid_dtli: Insufficient memory" );
610 for ( j = 0; j < nptsy; j++ )
613 for ( i = 0; i < nptsx; i++ )
615 pt->
x = (double) *xt++;
616 pt->
y = (double) *yt;
623 for ( i = 0; i < nptsx; i++ )
625 for ( j = 0; j < nptsy; j++ )
627 pt = &pgrid[j * nptsx + i];
648 const PLFLT *xt, *yt, *zt;
649 point *pin, *pgrid, *pt;
653 if (
sizeof ( realT ) !=
sizeof (
double ) )
655 plabort(
"plgridata: QHull was compiled for floats instead of doubles" );
661 plwarn(
"plgriddata(): GRID_NNI: wtmin must be specified with 'data' arg. Using -PLFLT_MAX" );
665 if ( ( pin = (
point *) malloc( (
size_t) npts *
sizeof (
point ) ) ) == NULL )
667 plexit(
"plgridata: Insufficient memory" );
674 for ( i = 0; i < npts; i++ )
676 pt->
x = (double) *xt++;
677 pt->
y = (double) *yt++;
678 pt->
z = (double) *zt++;
682 nptsg = nptsx * nptsy;
684 if ( ( pgrid = (
point *) malloc( (
size_t) nptsg *
sizeof (
point ) ) ) == NULL )
686 plexit(
"plgridata: Insufficient memory" );
691 for ( j = 0; j < nptsy; j++ )
694 for ( i = 0; i < nptsx; i++ )
696 pt->
x = (double) *xt++;
697 pt->
y = (double) *yt;
704 for ( i = 0; i < nptsx; i++ )
706 for ( j = 0; j < nptsy; j++ )
708 pt = &pgrid[j * nptsx + i];
716 #endif // PL_HAVE_QHULL
732 for ( i = 0; i < knn_order; i++ )
738 for ( i = 0; i < npts; i++ )
740 d = ( ( gx - x[i] ) * ( gx - x[i] ) + ( gy - y[i] ) * ( gy - y[i] ) );
748 items[max_slot].
dist = d;
749 items[max_slot].
item = i;
752 max_dist = items[0].
dist;
754 for ( j = 1; j < knn_order; j++ )
756 if ( items[j].dist > max_dist )
758 max_dist = items[j].
dist;
764 for ( j = 0; j < knn_order; j++ )
765 items[j].dist = sqrt( items[j].dist );
779 for ( i = 0; i < 4; i++ )
785 for ( i = 0; i < npts; i++ )
787 d = ( ( gx - x[i] ) * ( gx - x[i] ) + ( gy - y[i] ) * ( gy - y[i] ) );
793 quad = 2 * ( x[i] > gx ) + ( y[i] < gy );
799 if ( d < items[quad].dist )
801 items[quad].
dist = d;
802 items[quad].
item = i;
806 for ( i = 0; i < 4; i++ )
807 if ( items[i].item != -1 )
808 items[i].
dist = sqrt( items[i].dist );
812 #ifdef NONN // another DTLI, based only on QHULL, not nn
818 boolT ismalloc = False;
821 vertexT *vertex, **vertexp;
822 facetT *neighbor, **neighborp;
823 int curlong, totlong;
824 FILE *outfile = NULL;
825 FILE *errfile = stderr;
830 PLFLT xt[3], yt[3], zt[3];
836 int numfacets, numsimplicial, numridges;
837 int totneighbors, numcoplanars, numtricoplanars;
839 plwarn(
"plgriddata: GRID_DTLI, If you have QHull knowledge, FIXME." );
843 strcpy( flags,
"qhull d Qbb Qt", 250 );
845 if ( ( points = (coordT *) malloc( npts * ( dim + 1 ) *
sizeof ( coordT ) ) ) == NULL )
847 plexit(
"grid_adtli: Insufficient memory" );
850 for ( i = 0; i < npts; i++ )
852 points[i * dim] = x[i];
853 points[i * dim + 1] = y[i];
857 exitcode = qh_new_qhull( dim, npts, points, ismalloc,
858 flags, outfile, errfile );
860 qh_init_A( stdin, stdout, stderr, 0, NULL );
861 exitcode = setjmp( qh errexit );
864 qh_initflags( flags );
865 qh PROJECTdelaunay = True;
866 qh_init_B( points, npts, dim, ismalloc );
873 #if 0 // print the triangles vertices
874 printf(
"Triangles\n" );
876 if ( !facet->upperdelaunay )
878 FOREACHvertex_( facet->vertices )
879 printf( " %d", qh_pointid( vertex->point ) );
885 #if 0 // print each triangle neighbors
886 printf(
"Neigbors\n" );
888 qh_findgood_all( qh facet_list );
889 qh_countfacets( qh facet_list, NULL, !qh_ALL, &numfacets, &numsimplicial,
890 &totneighbors, &numridges, &numcoplanars, &numtricoplanars );
893 if ( !facet->upperdelaunay )
895 FOREACHneighbor_( facet )
896 printf( " %d", neighbor->visitid ? neighbor->visitid - 1 : -neighbor->
id );
903 exitcode = setjmp( qh errexit );
906 qh NOerrexit = False;
907 for ( i = 0; i < nptsx; i++ )
908 for ( j = 0; j < nptsy; j++ )
913 qh_setdelaunay( 3, 1, point );
919 facet = qh_findbestfacet( point, qh_ALL, &bestdist, &isoutside );
923 facet = qh_findbest( point, qh facet_list, qh_ALL,
926 &bestdist, &isoutside, &totpart );
930 vertex = qh_nearvertex( facet, point, &bestdist );
946 facet = qh_findfacet_all( point, &bestdist, &isoutside, &totpart );
948 if ( facet->upperdelaunay )
949 zops->
set( zgp, i, j,
NaN );
952 FOREACHvertex_( facet->vertices )
954 k = qh_pointid( vertex->point );
963 A = yt[0] * ( zt[1] - zt[2] ) + yt[1] * ( zt[2] - zt[0] ) + yt[2] * ( zt[0] - zt[1] );
964 B = zt[0] * ( xt[1] - xt[2] ) + zt[1] * ( xt[2] - xt[0] ) + zt[2] * ( xt[0] - xt[1] );
965 C = xt[0] * ( yt[1] - yt[2] ) + xt[1] * ( yt[2] - yt[0] ) + xt[2] * ( yt[0] - yt[1] );
966 D = -A * xt[0] - B * yt[0] - C * zt[0];
969 zops->
set( zgp, i, j, -xg[i] * A / C - yg[j] * B / C - D / C );
977 qh_freeqhull( !qh_ALL );
978 qh_memfreeshort( &curlong, &totlong );
979 if ( curlong || totlong )
981 "qhull: did not free %d bytes of long memory (%d pieces)\n",