PLplot  5.10.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
plstripc.c
Go to the documentation of this file.
1 // $Id: plstripc.c 11973 2011-10-17 21:16:39Z andrewross $
2 //
3 // Plots a simple stripchart.
4 //
5 // Copyright (C) 2004 Alan W. Irwin
6 //
7 // This file is part of PLplot.
8 //
9 // PLplot is free software; you can redistribute it and/or modify
10 // it under the terms of the GNU Library General Public License as published
11 // by the Free Software Foundation; either version 2 of the License, or
12 // (at your option) any later version.
13 //
14 // PLplot is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU Library General Public License for more details.
18 //
19 // You should have received a copy of the GNU Library General Public License
20 // along with PLplot; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 //
24 // ToDo: better way of clearing plot. search for `plvsta'.
25 //
26 
27 #include "plplotP.h"
28 
29 // Data declarations for stripcharts.
30 
31 #define PEN 4
32 
33 typedef struct
34 {
35  PLFLT xmin, xmax, ymin, ymax, xjump, xlen;
36  PLFLT wxmin, wxmax, wymin, wymax; // FIXME - some redundancy might exist
37  char *xspec, *yspec, *labx, *laby, *labtop;
38  PLINT y_ascl, acc, colbox, collab;
39  PLFLT xlpos, ylpos;
40  PLFLT *x[PEN], *y[PEN];
41  PLINT npts[PEN], nptsmax[PEN];
42  PLINT colline[PEN], styline[PEN];
43  char *legline[PEN];
44 } PLStrip;
45 
46 static int sid; // strip id number
47 #define MAX_STRIPC 1000 // Max allowed
48 static PLStrip *strip[MAX_STRIPC]; // Array of pointers
49 static PLStrip *stripc; // current strip chart
50 
51 // Generates a complete stripchart plot.
52 
53 static void
54 plstrip_gen( PLStrip *strip );
55 
56 // draw legend
57 
58 static void
59 plstrip_legend( PLStrip *strip, int flag );
60 
61 //--------------------------------------------------------------------------
62 // plstripc
63 //
64 // Create 1d stripchart.
65 //--------------------------------------------------------------------------
66 
67 void
68 c_plstripc( PLINT *id, const char *xspec, const char *yspec,
70  PLFLT xlpos, PLFLT ylpos,
71  PLINT y_ascl, PLINT acc,
72  PLINT colbox, PLINT collab,
73  const PLINT *colline, const PLINT *styline, const char *legline[],
74  const char *labx, const char *laby, const char *labtop )
75 {
76  int i;
77 
78 // Get a free strip id and allocate it
79 
80  for ( i = 0; i < MAX_STRIPC; i++ )
81  if ( strip[i] == NULL )
82  break;
83 
84  if ( i == MAX_STRIPC )
85  {
86  plabort( "plstripc: Cannot create new strip chart" );
87  *id = -1;
88  return;
89  }
90  else
91  {
92  sid = *id = i;
93  strip[sid] = (PLStrip *) calloc( 1, (size_t) sizeof ( PLStrip ) );
94  if ( strip[sid] == NULL )
95  {
96  plabort( "plstripc: Out of memory." );
97  *id = -1;
98  return;
99  }
100  }
101 
102 // Fill up the struct with all relevant info
103 
104  stripc = strip[sid];
105 
106  for ( i = 0; i < PEN; i++ )
107  {
108  stripc->npts[i] = 0;
109  stripc->nptsmax[i] = 100;
110  stripc->colline[i] = colline[i];
111  stripc->styline[i] = styline[i];
112  stripc->legline[i] = plstrdup( legline[i] );
113  stripc->x[i] = (PLFLT *) malloc( (size_t) sizeof ( PLFLT ) * (size_t) ( stripc->nptsmax[i] ) );
114  stripc->y[i] = (PLFLT *) malloc( (size_t) sizeof ( PLFLT ) * (size_t) ( stripc->nptsmax[i] ) );
115  if ( stripc->x[i] == NULL || stripc->y[i] == NULL )
116  {
117  plabort( "plstripc: Out of memory." );
118  plstripd( sid );
119  *id = -1;
120  return;
121  }
122  }
123 
124  stripc->xlpos = xlpos; // legend position [0..1]
125  stripc->ylpos = ylpos;
126  stripc->xmin = xmin; // initial bounding box
127  stripc->xmax = xmax;
128  stripc->ymin = ymin;
129  stripc->ymax = ymax;
130  stripc->xjump = xjump; // jump x step(%) when x attains xmax (xmax is then set to xmax+xjump)
131  stripc->xlen = xmax - xmin; // length of x scale
132  stripc->y_ascl = y_ascl; // autoscale y between x jump scale
133  stripc->acc = acc; // accumulate plot (not really stripchart)
134  stripc->xspec = plstrdup( xspec ); // x axis specification
135  stripc->yspec = plstrdup( yspec );
136  stripc->labx = plstrdup( labx ); // x label
137  stripc->laby = plstrdup( laby );
138  stripc->labtop = plstrdup( labtop ); // title
139  stripc->colbox = colbox; // box color
140  stripc->collab = collab; // label color
141 
142 // Generate the plot
143 
144  plstrip_gen( stripc );
145  plstrip_legend( stripc, 1 );
146 }
147 
148 static void plstrip_legend( PLStrip *stripcloc, int first )
149 {
150  int i;
151  PLFLT sc, dy;
152 
153 // draw legend
154 
155  plgchr( &sc, &dy );
156  sc = dy = dy / 100;
157  plwind( -0.01, 1.01, -0.01, 1.01 );
158  for ( i = 0; i < PEN; i++ )
159  {
160  if ( stripcloc->npts[i] || first )
161  {
162  plcol0( stripcloc->colline[i] ); pllsty( stripcloc->styline[i] );
163  pljoin( stripcloc->xlpos, stripcloc->ylpos - sc, stripcloc->xlpos + 0.1, stripcloc->ylpos - sc );
164  plcol0( stripcloc->collab );
165  plptex( stripcloc->xlpos + 0.11, stripcloc->ylpos - sc, 0., 0., 0, stripcloc->legline[i] ); sc += dy;
166  }
167  }
168  plwind( stripcloc->xmin, stripcloc->xmax, stripcloc->ymin, stripcloc->ymax );
169  plflush();
170 }
171 
172 //--------------------------------------------------------------------------
173 // plstrip_gen
174 //
175 // Generates a complete stripchart plot. Used either initially or
176 // during rescaling.
177 //--------------------------------------------------------------------------
178 
179 static void plstrip_gen( PLStrip *striploc )
180 {
181  int i;
182 
183 // Set up window
184 
185  plvpor( 0, 1, 0, 1 );
186  plwind( 0, 1, 0, 1 );
187  plcol0( 0 ); plpsty( 0 );
188  plclear();
189  plvsta();
190 
191 // Draw box and same window dimensions
192  striploc->wxmin = striploc->xmin; striploc->wxmax = striploc->xmax;
193  striploc->wymin = striploc->ymin; striploc->wymax = striploc->ymax; // FIXME - can exist some redundancy here
194 
195  plwind( striploc->xmin, striploc->xmax, striploc->ymin, striploc->ymax );
196 
197  pllsty( 1 );
198  plcol0( striploc->colbox );
199  plbox( striploc->xspec, 0.0, 0, striploc->yspec, 0.0, 0 );
200 
201  plcol0( striploc->collab );
202  pllab( striploc->labx, striploc->laby, striploc->labtop );
203 
204  for ( i = 0; i < PEN; i++ )
205  {
206  if ( striploc->npts[i] > 0 )
207  {
208  plcol0( striploc->colline[i] ); pllsty( striploc->styline[i] );
209  plline( striploc->npts[i], striploc->x[i], striploc->y[i] );
210  }
211  }
212 
213  plstrip_legend( striploc, 0 );
214 }
215 
216 //--------------------------------------------------------------------------
217 // plstripa
218 //
219 // Add a point to a stripchart.
220 // Allocates memory and rescales as necessary.
221 //--------------------------------------------------------------------------
222 
223 void c_plstripa( PLINT id, PLINT p, PLFLT x, PLFLT y )
224 {
225  int j, yasc = 0, istart;
226 
227  if ( p >= PEN )
228  {
229  plabort( "Non existent pen" );
230  return;
231  }
232 
233  if ( ( id < 0 ) || ( id >= MAX_STRIPC ) ||
234  ( ( stripc = strip[id] ) == NULL ) )
235  {
236  plabort( "Non existent stripchart" );
237  return;
238  }
239 
240 // Add new point, allocating memory if necessary
241 
242  if ( ++stripc->npts[p] > stripc->nptsmax[p] )
243  {
244  stripc->nptsmax[p] += 32;
245  stripc->x[p] = (PLFLT *) realloc( (void *) stripc->x[p], sizeof ( PLFLT ) * (size_t) ( stripc->nptsmax[p] ) );
246  stripc->y[p] = (PLFLT *) realloc( (void *) stripc->y[p], sizeof ( PLFLT ) * (size_t) ( stripc->nptsmax[p] ) );
247  if ( stripc->x[p] == NULL || stripc->y[p] == NULL )
248  {
249  plabort( "plstripc: Out of memory." );
250  plstripd( id );
251  return;
252  }
253  }
254 
255  stripc->x[p][stripc->npts[p] - 1] = x;
256  stripc->y[p][stripc->npts[p] - 1] = y;
257 
258  stripc->xmax = x;
259 
260  if ( stripc->y_ascl == 1 && ( y > stripc->ymax || y < stripc->ymin ) )
261  yasc = 1;
262 
263  if ( y > stripc->ymax )
264  stripc->ymax = stripc->ymin + 1.1 * ( y - stripc->ymin );
265  if ( y < stripc->ymin )
266  stripc->ymin = stripc->ymax - 1.1 * ( stripc->ymax - y );
267 
268 // Now either plot new point or regenerate plot
269 
270  if ( stripc->xmax - stripc->xmin < stripc->xlen )
271  {
272  if ( yasc == 0 )
273  {
274  // If user has changed subwindow, make shure we have the correct one
275  plvsta();
276  plwind( stripc->wxmin, stripc->wxmax, stripc->wymin, stripc->wymax ); // FIXME - can exist some redundancy here
277  plcol0( stripc->colline[p] ); pllsty( stripc->styline[p] );
278  if ( ( stripc->npts[p] - 2 ) < 0 )
279  plP_movwor( stripc->x[p][stripc->npts[p] - 1], stripc->y[p][stripc->npts[p] - 1] );
280  else
281  plP_movwor( stripc->x[p][stripc->npts[p] - 2], stripc->y[p][stripc->npts[p] - 2] );
282  plP_drawor( stripc->x[p][stripc->npts[p] - 1], stripc->y[p][stripc->npts[p] - 1] );
283  plflush();
284  }
285  else
286  {
287  stripc->xmax = stripc->xmin + stripc->xlen;
288  plstrip_gen( stripc );
289  }
290  }
291  else
292  {
293 // Regenerating plot
294  if ( stripc->acc == 0 )
295  {
296  for ( j = 0; j < PEN; j++ )
297  {
298  if ( stripc->npts[j] > 0 )
299  {
300  istart = 0;
301  while ( stripc->x[j][istart] < stripc->xmin + stripc->xlen * stripc->xjump )
302  istart++;
303 
304  stripc->npts[j] = stripc->npts[j] - istart;
305  memcpy( &stripc->x[j][0], &stripc->x[j][istart], (size_t) ( stripc->npts[j] ) * sizeof ( PLFLT ) );
306  memcpy( &stripc->y[j][0], &stripc->y[j][istart], (size_t) ( stripc->npts[j] ) * sizeof ( PLFLT ) );
307  }
308  }
309  }
310  else
311  stripc->xlen = stripc->xlen * ( 1 + stripc->xjump );
312 
313  if ( stripc->acc == 0 )
314  stripc->xmin = stripc->xmin + stripc->xlen * stripc->xjump;
315  else
316  stripc->xmin = stripc->x[p][0];
317  stripc->xmax = stripc->xmax + stripc->xlen * stripc->xjump;
318 
319  plstrip_gen( stripc );
320  }
321 }
322 
323 //--------------------------------------------------------------------------
324 // plstripd
325 //
326 // Deletes and releases memory used by a stripchart.
327 //--------------------------------------------------------------------------
328 
329 void c_plstripd( PLINT id )
330 {
331  int i;
332 
333  if ( ( id < 0 ) || ( id >= MAX_STRIPC ) ||
334  ( ( stripc = strip[id] ) == NULL ) )
335  {
336  plabort( "Non existent stripchart" );
337  return;
338  }
339 
340  for ( i = 0; i < PEN; i++ )
341  {
342  if ( stripc->npts[i] )
343  {
344  free( (void *) stripc->x[i] );
345  free( (void *) stripc->y[i] );
346  free( stripc->legline[i] );
347  }
348  }
349 
350  free( stripc->xspec );
351  free( stripc->yspec );
352  free( stripc->labx );
353  free( stripc->laby );
354  free( stripc->labtop );
355  free( (void *) stripc );
356  strip[id] = NULL;
357 }