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