PLplot
5.10.0
|
00001 // Plots a simple stripchart. 00002 // 00003 // Copyright (C) 2004-2014 Alan W. Irwin 00004 // 00005 // This file is part of PLplot. 00006 // 00007 // PLplot is free software; you can redistribute it and/or modify 00008 // it under the terms of the GNU Library General Public License as published 00009 // by the Free Software Foundation; either version 2 of the License, or 00010 // (at your option) any later version. 00011 // 00012 // PLplot is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 // GNU Library General Public License for more details. 00016 // 00017 // You should have received a copy of the GNU Library General Public License 00018 // along with PLplot; if not, write to the Free Software 00019 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 // 00021 // 00022 // ToDo: better way of clearing plot. search for `plvsta'. 00023 // 00024 00025 #include "plplotP.h" 00026 00027 // Data declarations for stripcharts. 00028 00029 #define PEN 4 00030 00031 typedef struct 00032 { 00033 PLFLT xmin, xmax, ymin, ymax, xjump, xlen; 00034 PLFLT wxmin, wxmax, wymin, wymax; // FIXME - some redundancy might exist 00035 char *xspec, *yspec, *labx, *laby, *labtop; 00036 PLINT y_ascl, acc, colbox, collab; 00037 PLFLT xlpos, ylpos; 00038 PLFLT *x[PEN], *y[PEN]; 00039 PLINT npts[PEN], nptsmax[PEN]; 00040 PLINT colline[PEN], styline[PEN]; 00041 char *legline[PEN]; 00042 } PLStrip; 00043 00044 static int sid; // strip id number 00045 #define MAX_STRIPC 1000 // Max allowed 00046 static PLStrip *strip[MAX_STRIPC]; // Array of pointers 00047 static PLStrip *stripc; // current strip chart 00048 00049 // Generates a complete stripchart plot. 00050 00051 static void 00052 plstrip_gen( PLStrip *strip ); 00053 00054 // draw legend 00055 00056 static void 00057 plstrip_legend( PLStrip *strip, int flag ); 00058 00059 //-------------------------------------------------------------------------- 00060 // plstripc 00061 // 00062 // Create 1d stripchart. 00063 //-------------------------------------------------------------------------- 00064 00065 void 00066 c_plstripc( PLINT *id, const char *xspec, const char *yspec, 00067 PLFLT xmin, PLFLT xmax, PLFLT xjump, PLFLT ymin, PLFLT ymax, 00068 PLFLT xlpos, PLFLT ylpos, 00069 PLINT y_ascl, PLINT acc, 00070 PLINT colbox, PLINT collab, 00071 const PLINT *colline, const PLINT *styline, const char *legline[], 00072 const char *labx, const char *laby, const char *labtop ) 00073 { 00074 int i; 00075 00076 // Get a free strip id and allocate it 00077 00078 for ( i = 0; i < MAX_STRIPC; i++ ) 00079 if ( strip[i] == NULL ) 00080 break; 00081 00082 if ( i == MAX_STRIPC ) 00083 { 00084 plabort( "plstripc: Cannot create new strip chart" ); 00085 *id = -1; 00086 return; 00087 } 00088 else 00089 { 00090 sid = *id = i; 00091 strip[sid] = (PLStrip *) calloc( 1, (size_t) sizeof ( PLStrip ) ); 00092 if ( strip[sid] == NULL ) 00093 { 00094 plabort( "plstripc: Out of memory." ); 00095 *id = -1; 00096 return; 00097 } 00098 } 00099 00100 // Fill up the struct with all relevant info 00101 00102 stripc = strip[sid]; 00103 00104 for ( i = 0; i < PEN; i++ ) 00105 { 00106 stripc->npts[i] = 0; 00107 stripc->nptsmax[i] = 100; 00108 stripc->colline[i] = colline[i]; 00109 stripc->styline[i] = styline[i]; 00110 stripc->legline[i] = plstrdup( legline[i] ); 00111 stripc->x[i] = (PLFLT *) malloc( (size_t) sizeof ( PLFLT ) * (size_t) ( stripc->nptsmax[i] ) ); 00112 stripc->y[i] = (PLFLT *) malloc( (size_t) sizeof ( PLFLT ) * (size_t) ( stripc->nptsmax[i] ) ); 00113 if ( stripc->x[i] == NULL || stripc->y[i] == NULL ) 00114 { 00115 plabort( "plstripc: Out of memory." ); 00116 plstripd( sid ); 00117 *id = -1; 00118 return; 00119 } 00120 } 00121 00122 stripc->xlpos = xlpos; // legend position [0..1] 00123 stripc->ylpos = ylpos; 00124 stripc->xmin = xmin; // initial bounding box 00125 stripc->xmax = xmax; 00126 stripc->ymin = ymin; 00127 stripc->ymax = ymax; 00128 stripc->xjump = xjump; // jump x step(%) when x attains xmax (xmax is then set to xmax+xjump) 00129 stripc->xlen = xmax - xmin; // length of x scale 00130 stripc->y_ascl = y_ascl; // autoscale y between x jump scale 00131 stripc->acc = acc; // accumulate plot (not really stripchart) 00132 stripc->xspec = plstrdup( xspec ); // x axis specification 00133 stripc->yspec = plstrdup( yspec ); 00134 stripc->labx = plstrdup( labx ); // x label 00135 stripc->laby = plstrdup( laby ); 00136 stripc->labtop = plstrdup( labtop ); // title 00137 stripc->colbox = colbox; // box color 00138 stripc->collab = collab; // label color 00139 00140 // Generate the plot 00141 00142 plstrip_gen( stripc ); 00143 plstrip_legend( stripc, 1 ); 00144 } 00145 00146 static void plstrip_legend( PLStrip *stripcloc, int first ) 00147 { 00148 int i; 00149 PLFLT sc, dy; 00150 00151 // draw legend 00152 00153 plgchr( &sc, &dy ); 00154 sc = dy = dy / 100; 00155 plwind( -0.01, 1.01, -0.01, 1.01 ); 00156 for ( i = 0; i < PEN; i++ ) 00157 { 00158 if ( stripcloc->npts[i] || first ) 00159 { 00160 plcol0( stripcloc->colline[i] ); pllsty( stripcloc->styline[i] ); 00161 pljoin( stripcloc->xlpos, stripcloc->ylpos - sc, stripcloc->xlpos + 0.1, stripcloc->ylpos - sc ); 00162 plcol0( stripcloc->collab ); 00163 plptex( stripcloc->xlpos + 0.11, stripcloc->ylpos - sc, 0., 0., 0, stripcloc->legline[i] ); sc += dy; 00164 } 00165 } 00166 plwind( stripcloc->xmin, stripcloc->xmax, stripcloc->ymin, stripcloc->ymax ); 00167 plflush(); 00168 } 00169 00170 //-------------------------------------------------------------------------- 00171 // plstrip_gen 00172 // 00173 // Generates a complete stripchart plot. Used either initially or 00174 // during rescaling. 00175 //-------------------------------------------------------------------------- 00176 00177 static void plstrip_gen( PLStrip *striploc ) 00178 { 00179 int i; 00180 00181 // Set up window 00182 00183 plvpor( 0, 1, 0, 1 ); 00184 plwind( 0, 1, 0, 1 ); 00185 plcol0( 0 ); plpsty( 0 ); 00186 plclear(); 00187 plvsta(); 00188 00189 // Draw box and same window dimensions 00190 striploc->wxmin = striploc->xmin; striploc->wxmax = striploc->xmax; 00191 striploc->wymin = striploc->ymin; striploc->wymax = striploc->ymax; // FIXME - can exist some redundancy here 00192 00193 plwind( striploc->xmin, striploc->xmax, striploc->ymin, striploc->ymax ); 00194 00195 pllsty( 1 ); 00196 plcol0( striploc->colbox ); 00197 plbox( striploc->xspec, 0.0, 0, striploc->yspec, 0.0, 0 ); 00198 00199 plcol0( striploc->collab ); 00200 pllab( striploc->labx, striploc->laby, striploc->labtop ); 00201 00202 for ( i = 0; i < PEN; i++ ) 00203 { 00204 if ( striploc->npts[i] > 0 ) 00205 { 00206 plcol0( striploc->colline[i] ); pllsty( striploc->styline[i] ); 00207 plline( striploc->npts[i], striploc->x[i], striploc->y[i] ); 00208 } 00209 } 00210 00211 plstrip_legend( striploc, 0 ); 00212 } 00213 00214 //-------------------------------------------------------------------------- 00215 // plstripa 00216 // 00217 // Add a point to a stripchart. 00218 // Allocates memory and rescales as necessary. 00219 //-------------------------------------------------------------------------- 00220 00221 void c_plstripa( PLINT id, PLINT p, PLFLT x, PLFLT y ) 00222 { 00223 int j, yasc = 0, istart; 00224 00225 if ( p >= PEN ) 00226 { 00227 plabort( "Non existent pen" ); 00228 return; 00229 } 00230 00231 if ( ( id < 0 ) || ( id >= MAX_STRIPC ) || 00232 ( ( stripc = strip[id] ) == NULL ) ) 00233 { 00234 plabort( "Non existent stripchart" ); 00235 return; 00236 } 00237 00238 // Add new point, allocating memory if necessary 00239 00240 if ( ++stripc->npts[p] > stripc->nptsmax[p] ) 00241 { 00242 stripc->nptsmax[p] += 32; 00243 stripc->x[p] = (PLFLT *) realloc( (void *) stripc->x[p], sizeof ( PLFLT ) * (size_t) ( stripc->nptsmax[p] ) ); 00244 stripc->y[p] = (PLFLT *) realloc( (void *) stripc->y[p], sizeof ( PLFLT ) * (size_t) ( stripc->nptsmax[p] ) ); 00245 if ( stripc->x[p] == NULL || stripc->y[p] == NULL ) 00246 { 00247 plabort( "plstripc: Out of memory." ); 00248 plstripd( id ); 00249 return; 00250 } 00251 } 00252 00253 stripc->x[p][stripc->npts[p] - 1] = x; 00254 stripc->y[p][stripc->npts[p] - 1] = y; 00255 00256 stripc->xmax = x; 00257 00258 if ( stripc->y_ascl == 1 && ( y > stripc->ymax || y < stripc->ymin ) ) 00259 yasc = 1; 00260 00261 if ( y > stripc->ymax ) 00262 stripc->ymax = stripc->ymin + 1.1 * ( y - stripc->ymin ); 00263 if ( y < stripc->ymin ) 00264 stripc->ymin = stripc->ymax - 1.1 * ( stripc->ymax - y ); 00265 00266 // Now either plot new point or regenerate plot 00267 00268 if ( stripc->xmax - stripc->xmin < stripc->xlen ) 00269 { 00270 if ( yasc == 0 ) 00271 { 00272 // If user has changed subwindow, make shure we have the correct one 00273 plvsta(); 00274 plwind( stripc->wxmin, stripc->wxmax, stripc->wymin, stripc->wymax ); // FIXME - can exist some redundancy here 00275 plcol0( stripc->colline[p] ); pllsty( stripc->styline[p] ); 00276 if ( ( stripc->npts[p] - 2 ) < 0 ) 00277 plP_movwor( stripc->x[p][stripc->npts[p] - 1], stripc->y[p][stripc->npts[p] - 1] ); 00278 else 00279 plP_movwor( stripc->x[p][stripc->npts[p] - 2], stripc->y[p][stripc->npts[p] - 2] ); 00280 plP_drawor( stripc->x[p][stripc->npts[p] - 1], stripc->y[p][stripc->npts[p] - 1] ); 00281 plflush(); 00282 } 00283 else 00284 { 00285 stripc->xmax = stripc->xmin + stripc->xlen; 00286 plstrip_gen( stripc ); 00287 } 00288 } 00289 else 00290 { 00291 // Regenerating plot 00292 if ( stripc->acc == 0 ) 00293 { 00294 for ( j = 0; j < PEN; j++ ) 00295 { 00296 if ( stripc->npts[j] > 0 ) 00297 { 00298 istart = 0; 00299 while ( stripc->x[j][istart] < stripc->xmin + stripc->xlen * stripc->xjump ) 00300 istart++; 00301 00302 stripc->npts[j] = stripc->npts[j] - istart; 00303 memcpy( &stripc->x[j][0], &stripc->x[j][istart], (size_t) ( stripc->npts[j] ) * sizeof ( PLFLT ) ); 00304 memcpy( &stripc->y[j][0], &stripc->y[j][istart], (size_t) ( stripc->npts[j] ) * sizeof ( PLFLT ) ); 00305 } 00306 } 00307 } 00308 else 00309 stripc->xlen = stripc->xlen * ( 1 + stripc->xjump ); 00310 00311 if ( stripc->acc == 0 ) 00312 stripc->xmin = stripc->xmin + stripc->xlen * stripc->xjump; 00313 else 00314 stripc->xmin = stripc->x[p][0]; 00315 stripc->xmax = stripc->xmax + stripc->xlen * stripc->xjump; 00316 00317 plstrip_gen( stripc ); 00318 } 00319 } 00320 00321 //-------------------------------------------------------------------------- 00322 // plstripd 00323 // 00324 // Deletes and releases memory used by a stripchart. 00325 //-------------------------------------------------------------------------- 00326 00327 void c_plstripd( PLINT id ) 00328 { 00329 int i; 00330 00331 if ( ( id < 0 ) || ( id >= MAX_STRIPC ) || 00332 ( ( stripc = strip[id] ) == NULL ) ) 00333 { 00334 plabort( "Non existent stripchart" ); 00335 return; 00336 } 00337 00338 for ( i = 0; i < PEN; i++ ) 00339 { 00340 if ( stripc->npts[i] ) 00341 { 00342 free( (void *) stripc->x[i] ); 00343 free( (void *) stripc->y[i] ); 00344 free( stripc->legline[i] ); 00345 } 00346 } 00347 00348 free( stripc->xspec ); 00349 free( stripc->yspec ); 00350 free( stripc->labx ); 00351 free( stripc->laby ); 00352 free( stripc->labtop ); 00353 free( (void *) stripc ); 00354 strip[id] = NULL; 00355 }