From: <ai...@us...> - 2010-03-14 18:10:12
|
Revision: 10868 http://plplot.svn.sourceforge.net/plplot/?rev=10868&view=rev Author: airwin Date: 2010-03-14 17:04:57 +0000 (Sun, 14 Mar 2010) Log Message: ----------- Apply patch from David MacMahon to support arbitrary storage of 2D user data. This is a roll-up of all previous PLplot patches related to supporting arbitrary storage of 2D user data. This patch is based on (and should apply cleanly to) svn trunk r10859. Adds support for arbitrary storage of 2D user data. This is very similar to the technique employed by some existing functions (e.g. plfcont and plfshade) that use "evaluator" functions to access 2D user data that is stored in an arbtrary format. The new approach extends the concept of a user-supplied (or predefined) "evaluator" function to a group of user-supplied (or predefined) "operator" functions. The operator functions provide for various operations on the arbitrarily stored 2D data including: get, set, +=, -=, *=, /=, isnan, minmax, and f2eval. To facilitate the passing of an entire family of operator functions (via function pointers), a plf2ops_t structure is defined to contain a pointer to each type of operator function. Predefined operator functions are defined for several common 2D data storage techniques. Variables (of type plf2ops_t) containing function pointers for these operator functions are also defined. New variants of functions that accept 2D data are created. The new variants accept the 2D data as two parameters: a pointer to a plf2ops_t structure containing (pointers to) suitable operator functions and a PLPointer to the actual 2D data store. Existing functions that accept 2D data are modified to simply pass their parameters to the corresponding new variant of the function, along with a pointer to the suitable predefined plf2ops_t stucture of operator function pointers. The list of functions for which new variants are created is: c_plimage, c_plimagefr, c_plmesh, c_plmeshc, c_plot3d, c_plot3dc, c_plot3dcl, c_plshade1, c_plshades, c_plsurf3d, and c_plsurf3dl, and c_plgriddata. The new variants are named the same as their corresponding existing function except that the "c_" prefix is changed to "plf" (e.g. the new variant of c_plmesh is called plfmesh). Adds plfvect declaration to plplot.h and changes the names (and only the names) of some plfvect arguments to make them slightly clearer. In order to maintain backwards API compatibility, this function and the other existing functions that use "evaluator" functions are NOT changed to use the new operator functions. Makes plplot.h and libplplot consistent vis-a-vis pltr0f and pltr2d. Moves the definitions of pltr2f (already declared in plplot.h) from the sccont.c files of the FORTRAN 77 and Fortran 95 bindings into plcont.c. Removes pltr0f declaration from plplot.h. Changes x08c.c to demonstrate use of new support for arbitrary storage of 2D data arrays. Shows how to do surface plots with the following four types of 2D data arrays: 1) PLFLT z[nx][ny]; 2) PLfGrid2 z; 3) PLFLT z[nx*ny]; /* row major order */ 4) PLFLT z[nx*ny]; /* column major order */ --- bindings/f77/sccont.c | 182 --------------------- bindings/f95/sccont.c | 182 --------------------- examples/c/x08c.c | 45 ++++-- include/plplot.h | 238 ++++++++++++++++++++++++++-- src/CMakeLists.txt | 1 + src/plcont.c | 207 +++++++++++++++++++++++- src/plf2ops.c | 426 +++++++++++++++++++++++++++++++++++++++++++++++++ src/plgridd.c | 120 ++++++++------ src/plimage.c | 49 +++++-- src/plot3d.c | 212 ++++++++++++++++--------- src/plshade.c | 81 ++++++++-- src/plvect.c | 17 +-- 12 files changed, 1200 insertions(+), 560 deletions(-) Added Paths: ----------- trunk/src/plf2ops.c Added: trunk/src/plf2ops.c =================================================================== --- trunk/src/plf2ops.c (rev 0) +++ trunk/src/plf2ops.c 2010-03-14 17:04:57 UTC (rev 10868) @@ -0,0 +1,426 @@ +/* $Id$ + * + * Predefined 2-D data access functions. + * + * Copyright (C) 2010 David H. E. MacMahon + * + * This file is part of PLplot. + * + * PLplot is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Library Public License as published + * by the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 + */ + +#include "plplotP.h" + +/* + * 2-D data access functions for data stored in (PLFLT **), such as the C + * variable z declared as... + * + * PLFLT z[nx][ny]; + * + * These functions are named plf2OP1, where OP is "get", "set", etc. The + * plf2ops_t instance named "plf2ops1" is also defined below. + */ + +static PLFLT +plf2ops_c_get( PLPointer p, PLINT ix, PLINT iy ) +{ + return ( (PLFLT **) p )[ix][iy]; +} + +static PLFLT +plf2ops_c_f2eval( PLINT ix, PLINT iy, PLPointer p ) +{ + return ( (PLFLT **) p )[ix][iy]; +} + +static PLFLT +plf2ops_c_set( PLPointer p, PLINT ix, PLINT iy, PLFLT z ) +{ + return ( ( (PLFLT **) p )[ix][iy] = z ); +} + +static PLFLT +plf2ops_c_add( PLPointer p, PLINT ix, PLINT iy, PLFLT z ) +{ + return ( ( (PLFLT **) p )[ix][iy] += z ); +} + +static PLFLT +plf2ops_c_sub( PLPointer p, PLINT ix, PLINT iy, PLFLT z ) +{ + return ( ( (PLFLT **) p )[ix][iy] -= z ); +} + +static PLFLT +plf2ops_c_mul( PLPointer p, PLINT ix, PLINT iy, PLFLT z ) +{ + return ( ( (PLFLT **) p )[ix][iy] *= z ); +} + +static PLFLT +plf2ops_c_div( PLPointer p, PLINT ix, PLINT iy, PLFLT z ) +{ + return ( ( (PLFLT **) p )[ix][iy] /= z ); +} + +static PLINT +plf2ops_c_isnan( PLPointer p, PLINT ix, PLINT iy ) +{ + return isnan( ( (PLFLT **) p )[ix][iy] ); +} + +static void +plf2ops_c_minmax( PLPointer p, PLINT nx, PLINT ny, PLFLT *zmin, PLFLT *zmax ) +{ + int i, j; + PLFLT min, max; + PLFLT **z = (PLFLT **) p; + + if ( !finite( z[0][0] ) ) + { + max = -HUGE_VAL; + min = HUGE_VAL; + } + else + min = max = z[0][0]; + + for ( i = 0; i < nx; i++ ) + { + for ( j = 0; j < ny; j++ ) + { + if ( !finite( z[i][j] ) ) continue; + if ( z[i][j] < min ) min = z[i][j]; + if ( z[i][j] > max ) max = z[i][j]; + } + } + *zmin = min; + *zmax = max; +} + +static plf2ops_t s_plf2ops_c = { + plf2ops_c_get, + plf2ops_c_set, + plf2ops_c_add, + plf2ops_c_sub, + plf2ops_c_mul, + plf2ops_c_div, + plf2ops_c_isnan, + plf2ops_c_minmax, + plf2ops_c_f2eval +}; + +PLF2OPS +plf2ops_c() +{ + return &s_plf2ops_c; +} + +/* + * 2-D data access functions for data stored in (PLfGrid2 *), with the + * PLfGrid2's "f" field treated as type (PLFLT **). + */ + +static PLFLT +plf2ops_grid_c_get( PLPointer p, PLINT ix, PLINT iy ) +{ + return ( ( (PLfGrid2 *) p )->f )[ix][iy]; +} + +static PLFLT +plf2ops_grid_c_f2eval( PLINT ix, PLINT iy, PLPointer p ) +{ + return ( ( (PLfGrid2 *) p )->f )[ix][iy]; +} + +static PLFLT +plf2ops_grid_c_set( PLPointer p, PLINT ix, PLINT iy, PLFLT z ) +{ + return ( ( ( (PLfGrid2 *) p )->f )[ix][iy] = z ); +} + +static PLFLT +plf2ops_grid_c_add( PLPointer p, PLINT ix, PLINT iy, PLFLT z ) +{ + return ( ( ( (PLfGrid2 *) p )->f )[ix][iy] += z ); +} + +static PLFLT +plf2ops_grid_c_sub( PLPointer p, PLINT ix, PLINT iy, PLFLT z ) +{ + return ( ( ( (PLfGrid2 *) p )->f )[ix][iy] -= z ); +} + +static PLFLT +plf2ops_grid_c_mul( PLPointer p, PLINT ix, PLINT iy, PLFLT z ) +{ + return ( ( ( (PLfGrid2 *) p )->f )[ix][iy] *= z ); +} + +static PLFLT +plf2ops_grid_c_div( PLPointer p, PLINT ix, PLINT iy, PLFLT z ) +{ + return ( ( ( (PLfGrid2 *) p )->f )[ix][iy] /= z ); +} + +static PLINT +plf2ops_grid_c_isnan( PLPointer p, PLINT ix, PLINT iy ) +{ + return isnan( ( ( (PLfGrid2 *) p )->f )[ix][iy] ); +} + +static void +plf2ops_grid_c_minmax( PLPointer p, PLINT nx, PLINT ny, PLFLT *zmin, PLFLT *zmax ) +{ + int i, j; + PLFLT min, max; + PLfGrid2 *g = (PLfGrid2 *) p; + PLFLT **z = g->f; + + /* Ignore passed in parameters */ + nx = g->nx; + ny = g->ny; + + if ( !finite( z[0][0] ) ) + { + max = -HUGE_VAL; + min = HUGE_VAL; + } + else + min = max = z[0][0]; + + for ( i = 0; i < nx; i++ ) + { + for ( j = 0; j < ny; j++ ) + { + if ( !finite( z[i][j] ) ) continue; + if ( z[i][j] < min ) min = z[i][j]; + if ( z[i][j] > max ) max = z[i][j]; + } + } + *zmin = min; + *zmax = max; +} + +static plf2ops_t s_plf2ops_grid_c = { + plf2ops_grid_c_get, + plf2ops_grid_c_set, + plf2ops_grid_c_add, + plf2ops_grid_c_sub, + plf2ops_grid_c_mul, + plf2ops_grid_c_div, + plf2ops_grid_c_isnan, + plf2ops_grid_c_minmax, + plf2ops_grid_c_f2eval +}; + +PLF2OPS +plf2ops_grid_c() +{ + return &s_plf2ops_grid_c; +} + +/* + * 2-D data access functions for data stored in (PLfGrid2 *), with the + * PLfGrid2's "f" field treated as type (PLFLT *) pointing to 2-D data stored + * in row-major order. In the context of plotting, it might be easier to think + * of it as "X-major" order. In this ordering, values for a single X index are + * stored in consecutive memory locations. + */ + +static PLFLT +plf2ops_grid_row_major_get( PLPointer p, PLINT ix, PLINT iy ) +{ + PLfGrid2 *g = (PLfGrid2 *) p; + return ( (PLFLT *) g->f )[ix * g->ny + iy]; +} + +static PLFLT +plf2ops_grid_row_major_f2eval( PLINT ix, PLINT iy, PLPointer p ) +{ + PLfGrid2 *g = (PLfGrid2 *) p; + return ( (PLFLT *) g->f )[ix * g->ny + iy]; +} + +static PLFLT +plf2ops_grid_row_major_set( PLPointer p, PLINT ix, PLINT iy, PLFLT z ) +{ + PLfGrid2 *g = (PLfGrid2 *) p; + return ( ( (PLFLT *) g->f )[ix * g->ny + iy] = z ); +} + +static PLFLT +plf2ops_grid_row_major_add( PLPointer p, PLINT ix, PLINT iy, PLFLT z ) +{ + PLfGrid2 *g = (PLfGrid2 *) p; + return ( ( (PLFLT *) g->f )[ix * g->ny + iy] += z ); +} + +static PLFLT +plf2ops_grid_row_major_sub( PLPointer p, PLINT ix, PLINT iy, PLFLT z ) +{ + PLfGrid2 *g = (PLfGrid2 *) p; + return ( ( (PLFLT *) g->f )[ix * g->ny + iy] -= z ); +} + +static PLFLT +plf2ops_grid_row_major_mul( PLPointer p, PLINT ix, PLINT iy, PLFLT z ) +{ + PLfGrid2 *g = (PLfGrid2 *) p; + return ( ( (PLFLT *) g->f )[ix * g->ny + iy] *= z ); +} + +static PLFLT +plf2ops_grid_row_major_div( PLPointer p, PLINT ix, PLINT iy, PLFLT z ) +{ + PLfGrid2 *g = (PLfGrid2 *) p; + return ( ( (PLFLT *) g->f )[ix * g->ny + iy] /= z ); +} + +static PLINT +plf2ops_grid_row_major_isnan( PLPointer p, PLINT ix, PLINT iy ) +{ + PLfGrid2 *g = (PLfGrid2 *) p; + return isnan( ( (PLFLT *) g->f )[ix * g->ny + iy] ); +} + +static void +plf2ops_grid_xxx_major_minmax( PLPointer p, PLINT nx, PLINT ny, PLFLT *zmin, PLFLT *zmax ) +{ + int i; + PLFLT min, max; + PLfGrid2 *g = (PLfGrid2 *) p; + PLFLT *z = (PLFLT *) ( (PLFLT *) g->f ); + + /* Ignore passed in parameters */ + nx = g->nx; + ny = g->ny; + + if ( !finite( z[0] ) ) + { + max = -HUGE_VAL; + min = HUGE_VAL; + } + else + min = max = z[0]; + + for ( i = 0; i < nx * ny; i++ ) + { + if ( !finite( z[i] ) ) continue; + if ( z[i] < min ) min = z[i]; + if ( z[i] > max ) max = z[i]; + } + *zmin = min; + *zmax = max; +} + +static plf2ops_t s_plf2ops_grid_row_major = { + plf2ops_grid_row_major_get, + plf2ops_grid_row_major_set, + plf2ops_grid_row_major_add, + plf2ops_grid_row_major_sub, + plf2ops_grid_row_major_mul, + plf2ops_grid_row_major_div, + plf2ops_grid_row_major_isnan, + plf2ops_grid_xxx_major_minmax, + plf2ops_grid_row_major_f2eval +}; + +PLF2OPS +plf2ops_grid_row_major() +{ + return &s_plf2ops_grid_row_major; +} + +/* + * 2-D data access functions for data stored in (PLfGrid2 *), with the + * PLfGrid2's "f" field treated as type (PLFLT *) pointing to 2-D data stored + * in column-major order. In the context of plotting, it might be easier to + * think of it as "Y-major" order. In this ordering, values for a single Y + * index are stored in consecutive memory locations. + */ + +static PLFLT +plf2ops_grid_col_major_get( PLPointer p, PLINT ix, PLINT iy ) +{ + PLfGrid2 *g = (PLfGrid2 *) p; + return ( (PLFLT *) g->f )[ix + g->nx * iy]; +} + +static PLFLT +plf2ops_grid_col_major_f2eval( PLINT ix, PLINT iy, PLPointer p ) +{ + PLfGrid2 *g = (PLfGrid2 *) p; + return ( (PLFLT *) g->f )[ix + g->nx * iy]; +} + +static PLFLT +plf2ops_grid_col_major_set( PLPointer p, PLINT ix, PLINT iy, PLFLT z ) +{ + PLfGrid2 *g = (PLfGrid2 *) p; + return ( ( (PLFLT *) g->f )[ix + g->nx * iy] = z ); +} + +static PLFLT +plf2ops_grid_col_major_add( PLPointer p, PLINT ix, PLINT iy, PLFLT z ) +{ + PLfGrid2 *g = (PLfGrid2 *) p; + return ( ( (PLFLT *) g->f )[ix + g->nx * iy] += z ); +} + +static PLFLT +plf2ops_grid_col_major_sub( PLPointer p, PLINT ix, PLINT iy, PLFLT z ) +{ + PLfGrid2 *g = (PLfGrid2 *) p; + return ( ( (PLFLT *) g->f )[ix + g->nx * iy] -= z ); +} + +static PLFLT +plf2ops_grid_col_major_mul( PLPointer p, PLINT ix, PLINT iy, PLFLT z ) +{ + PLfGrid2 *g = (PLfGrid2 *) p; + return ( ( (PLFLT *) g->f )[ix + g->nx * iy] *= z ); +} + +static PLFLT +plf2ops_grid_col_major_div( PLPointer p, PLINT ix, PLINT iy, PLFLT z ) +{ + PLfGrid2 *g = (PLfGrid2 *) p; + return ( ( (PLFLT *) g->f )[ix + g->nx * iy] /= z ); +} + +static PLINT +plf2ops_grid_col_major_isnan( PLPointer p, PLINT ix, PLINT iy ) +{ + PLfGrid2 *g = (PLfGrid2 *) p; + return isnan( ( (PLFLT *) g->f )[ix + g->nx * iy] ); +} + +plf2ops_t s_plf2ops_grid_col_major = { + plf2ops_grid_col_major_get, + plf2ops_grid_col_major_set, + plf2ops_grid_col_major_add, + plf2ops_grid_col_major_sub, + plf2ops_grid_col_major_mul, + plf2ops_grid_col_major_div, + plf2ops_grid_col_major_isnan, + plf2ops_grid_xxx_major_minmax, + plf2ops_grid_col_major_f2eval +}; + +PLF2OPS +plf2ops_grid_col_major() +{ + return &s_plf2ops_grid_col_major; +} Property changes on: trunk/src/plf2ops.c ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |