//-------------------------------------------------------------------------- // Copyright (C) 2006 Andrew Ross // Copyright (C) 2004-2014 Alan W. Irwin // // This file is part of PLplot. // // PLplot is free software; you can redistribute it and/or modify // it under the terms of the GNU Library General Public License as published by // the Free Software Foundation; version 2 of the License. // // PLplot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Library General Public License for more details. // // You should have received a copy of the GNU Library General Public License // along with PLplot; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA //-------------------------------------------------------------------------- // //-------------------------------------------------------------------------- // Implementation of PLplot example 21 in Java. //-------------------------------------------------------------------------- package plplot.examples; import plplot.core.*; import static plplot.core.plplotjavacConstants.*; import java.lang.Math; class x21 { // Class data PLStream pls = new PLStream(); double xm, xM, ym, yM; // Options data structure definition. static int pts = 500; static int xp = 25; static int yp = 20; static int nl = 16; static int knn_order = 20; static double threshold = 1.001; static double wmin = -1e3; static int randn = 0; static int rosen = 0; // static PLOptionTable options[]; // PLOptionTable options[] = { // { // "npts", // NULL, // NULL, // &pts, // PL_OPT_INT, // "-npts points", // "Specify number of random points to generate [500]" }, // { // "randn", // NULL, // NULL, // &randn, // PL_OPT_BOOL, // "-randn", // "Normal instead of uniform sampling -- the effective // number of points will be smaller than the specified." }, // { // "rosen", // NULL, // NULL, // &rosen, // PL_OPT_BOOL, // "-rosen", // "Generate points from the Rosenbrock function."}, // { // "nx", // NULL, // NULL, // &xp, // PL_OPT_INT, // "-nx points", // "Specify grid x dimension [25]" }, // { // "ny", // NULL, // NULL, // &yp, // PL_OPT_INT, // "-ny points", // "Specify grid y dimension [20]" }, // { // "nlevel", // NULL, // NULL, // &nl, // PL_OPT_INT, // "-nlevel ", // "Specify number of contour levels [16]" }, // { // "knn_order", // NULL, // NULL, // &knn_order, // PL_OPT_INT, // "-knn_order order", // "Specify the number of neighbors [20]" }, // { // "threshold", // NULL, // NULL, // &threshold, // PL_OPT_FLOAT, // "-threshold float", // "Specify what a thin triangle is [1. < [1.001] < 2.]" }, // { // NULL, /* option */ // NULL, /* handler */ // NULL, /* client data */ // NULL, /* address of variable to set */ // 0, /* mode flag */ // NULL, /* short syntax */ // NULL } /* long syntax */ // }; x21( String[] args ) { double x[], y[], z[], clev[]; double xg[], yg[], zg[][]; double xg0[][], yg0[][]; double xx[], yy[]; double zmin, zmax, lzm[], lzM[]; int i, j, k; int alg; String title[] = { "Cubic Spline Approximation", "Delaunay Linear Interpolation", "Natural Neighbors Interpolation", "KNN Inv. Distance Weighted", "3NN Linear Interpolation", "4NN Around Inv. Dist. Weighted" }; double opt[] = { 0., 0., 0., 0., 0., 0. }; xm = ym = -0.2; xM = yM = 0.6; // plplot initialization // Parse and process command line arguments. // pls.MergeOpts(options, "x22c options", NULL); pls.parseopts( args, PL_PARSE_FULL | PL_PARSE_NOPROGRAM ); opt[2] = wmin; opt[3] = knn_order; opt[4] = threshold; // Initialize PLplot. pls.init(); cmap1_init(); pls.seed( 5489 ); x = new double[pts]; y = new double[pts]; z = new double[pts]; xx = new double[1]; yy = new double[1]; create_data( x, y, z ); // the sampled data zmin = z[0]; zmax = z[0]; for ( i = 1; i < pts; i++ ) { if ( z[i] > zmax ) zmax = z[i]; if ( z[i] < zmin ) zmin = z[i]; } xg = new double[xp]; yg = new double[yp]; create_grid( xg, yg ); // grid the data at zg = new double[xp][yp]; // the output grided data xg0 = new double[xp][yp]; yg0 = new double[xp][yp]; for ( i = 0; i < xp; i++ ) { for ( j = 0; j < yp; j++ ) { xg0[i][j] = xg[i]; yg0[i][j] = yg[j]; } } clev = new double[nl]; pls.col0( 1 ); pls.env( xm, xM, ym, yM, 2, 0 ); pls.col0( 15 ); pls.lab( "X", "Y", "The original data sampling" ); for ( i = 0; i < pts; i++ ) { pls.col1( ( z[i] - zmin ) / ( zmax - zmin ) ); // The following plstring call should be the the equivalent of // plpoin( 1, &x[i], &y[i], 5 ); Use plstring because it is // not deprecated like plpoin and has much more powerful // capabilities. N.B. symbol 141 works for Hershey devices // (e.g., -dev xwin) only if plfontld( 0 ) has been called // while symbol 727 works only if plfontld( 1 ) has been // called. The latter is the default which is why we use 727 // here to represent a centred X (multiplication) symbol. // This dependence on plfontld is one of the limitations of // the Hershey escapes for PLplot, but the upside is you get // reasonable results for both Hershey and Unicode devices. xx[0] = x[i]; yy[0] = y[i]; pls.string( xx, yy, "#(727)" ); } pls.adv( 0 ); pls.ssub( 3, 2 ); for ( k = 0; k < 2; k++ ) { pls.adv( 0 ); for ( alg = 1; alg < 7; alg++ ) { pls.griddata( x, y, z, xg, yg, zg, alg, opt[alg - 1] ); // - CSA can generate NaNs (only interpolates?!). // - DTLI and NNI can generate NaNs for points outside the // convex hull of the data points. // - NNLI can generate NaNs if a sufficiently thick triangle // is not found // // PLplot should be NaN/Inf aware, but changing it now is // quite a job... so, instead of not plotting the NaN // regions, a weighted average over the neighbors is done. // if ( alg == GRID_CSA || alg == GRID_DTLI || alg == GRID_NNLI || alg == GRID_NNI ) { int ii, jj; double dist, d; for ( i = 0; i < xp; i++ ) { for ( j = 0; j < yp; j++ ) { if ( Double.isNaN( zg[i][j] ) ) // average (IDW) over the 8 neighbors { zg[i][j] = 0.; dist = 0.; for ( ii = i - 1; ii <= i + 1 && ii < xp; ii++ ) { for ( jj = j - 1; jj <= j + 1 && jj < yp; jj++ ) { if ( ii >= 0 && jj >= 0 && !Double.isNaN( zg[ii][jj] ) ) { d = ( Math.abs( ii - i ) + Math.abs( jj - j ) ) == 1 ? 1. : 1.4142; zg[i][j] += zg[ii][jj] / ( d * d ); dist += d; } } } if ( dist != 0. ) zg[i][j] /= dist; else zg[i][j] = zmin; } } } } lzm = new double[1]; lzM = new double[1]; pls.minMax2dGrid( zg, lzM, lzm ); lzm[0] = Math.min( lzm[0], zmin ); lzM[0] = Math.max( lzM[0], zmax ); lzm[0] = lzm[0] - 0.01; lzM[0] = lzM[0] + 0.01; pls.col0( 1 ); pls.adv( alg ); if ( k == 0 ) { for ( i = 0; i < nl; i++ ) clev[i] = lzm[0] + ( lzM[0] - lzm[0] ) / ( nl - 1 ) * i; pls.env0( xm, xM, ym, yM, 2, 0 ); pls.col0( 15 ); pls.lab( "X", "Y", title[alg - 1] ); pls.shades( zg, xm, xM, ym, yM, clev, 1., 0, 1., true, xg0, yg0 ); pls.col0( 2 ); } else { for ( i = 0; i < nl; i++ ) clev[i] = lzm[0] + ( lzM[0] - lzm[0] ) / ( nl - 1 ) * i; pls.vpor( 0.0, 1.0, 0.0, 0.9 ); pls.wind( -1.1, 0.75, -0.65, 1.20 ); // // For the comparison to be fair, all plots should have the // same z values, but to get the max/min of the data // generated by all algorithms would imply two passes. // Keep it simple. // // plw3d(1., 1., 1., xm, xM, ym, yM, zmin, zmax, 30, -60); // pls.w3d( 1., 1., 1., xm, xM, ym, yM, lzm[0], lzM[0], 30, -40 ); pls.box3( "bntu", "X", 0.0, 0, "bntu", "Y", 0.0, 0, "bcdfntu", "Z", 0.5, 0 ); pls.col0( 15 ); pls.lab( "", "", title[alg - 1] ); pls.plot3dc( xg, yg, zg, DRAW_LINEXY | MAG_COLOR | BASE_CONT, clev ); } } } pls.end(); } void cmap1_init() { double i[] = new double[2]; double h[] = new double[2]; double l[] = new double[2]; double s[] = new double[2]; i[0] = 0.0; // left boundary i[1] = 1.0; // right boundary h[0] = 240; // blue . green . yellow . h[1] = 0; // . red l[0] = 0.6; l[1] = 0.6; s[0] = 0.8; s[1] = 0.8; pls.scmap1n( 256 ); pls.scmap1l( false, i, h, l, s ); } void create_grid( double xx[], double yy[] ) { int i; int px = xx.length; int py = yy.length; for ( i = 0; i < px; i++ ) xx[i] = xm + ( xM - xm ) * i / ( px - 1. ); for ( i = 0; i < py; i++ ) yy[i] = ym + ( yM - ym ) * i / ( py - 1. ); } void create_data( double x[], double y[], double z[] ) { int i; double r; double xt, yt; int pts = x.length; for ( i = 0; i < pts; i++ ) { xt = ( xM - xm ) * pls.randd(); yt = ( yM - ym ) * pls.randd(); if ( randn == 0 ) { x[i] = xt + xm; y[i] = yt + ym; } else // std=1, meaning that many points are outside the plot range { x[i] = Math.sqrt( -2. * Math.log( xt ) ) * Math.cos( 2. * Math.PI * yt ) + xm; y[i] = Math.sqrt( -2. * Math.log( xt ) ) * Math.sin( 2. * Math.PI * yt ) + ym; } if ( rosen == 0 ) { r = Math.sqrt( ( x[i] ) * ( x[i] ) + ( y[i] ) * ( y[i] ) ); z[i] = Math.exp( -r * r ) * Math.cos( 2.0 * Math.PI * r ); } else { z[i] = Math.log( Math.pow( ( 1. - x[i] ), 2. ) + 100. * Math.pow( ( y[i] - Math.pow( x[i], 2. ) ), 2. ) ); } } } public static void main( String[] args ) { new x21( args ); } } //-------------------------------------------------------------------------- // End of x21.java //--------------------------------------------------------------------------