1 // Simple line plot and multiple windows demo.
2 //
3 // Copyright (C) 2004 Rafael Laboissiere
4 // Copyright (C) 2000-2018 Alan W. Irwin
5 //
6 // This file is part of PLplot.
7 //
8 // PLplot is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU Library General Public License as published
10 // by the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // PLplot is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Library General Public License for more details.
17 //
18 // You should have received a copy of the GNU Library General Public License
19 // along with PLplot; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 //
22 //
23
24 #include "plcdemos.h"
25 #include "plevent.h"
26 #ifdef PL_HAVE_NANOSLEEP
27 #include <time.h>
28 #endif
29 #ifdef PL_HAVE_UNISTD_H
30 # include <unistd.h>
31 #endif
32
33 // Variables and data arrays used by plot generators
34
35 static PLFLT x[101], y[101];
36 static PLFLT xscale, yscale, xoff, yoff, xs[6], ys[6];
37 static PLGraphicsIn gin;
38
39 static int locate_mode;
40 static int test_xor;
41 static int fontset = 1;
42 static int pl_parse_skip_mode;
43 static char *f_name = NULL;
44
45 // Options data structure definition.
46
47 static PLOptionTable options[] = {
48 {
49 "pl_parse_skip",
50 NULL,
51 NULL,
52 &pl_parse_skip_mode,
53 PL_OPT_BOOL,
54 "-pl_parse_skip",
55 "Test using PL_PARSE_SKIP mode for plparseopts (this option must precede non-PLplot options)"
56 },
57 {
58 "locate", // Turns on test of API locate function
59 NULL,
60 NULL,
61 &locate_mode,
62 PL_OPT_BOOL,
63 "-locate",
64 "Turns on test of API locate function"
65 },
66 {
67 "xor", // Turns on test of xor function
68 NULL,
69 NULL,
70 &test_xor,
71 PL_OPT_BOOL,
72 "-xor",
73 "Turns on test of XOR"
74 },
75 {
76 "font", // For switching between font set 1 & 2
77 NULL,
78 NULL,
79 &fontset,
80 PL_OPT_INT,
81 "-font number",
82 "Selects stroke font set (0 or 1, def:1)"
83 },
84 {
85 "save", // For saving in postscript
86 NULL,
87 NULL,
88 &f_name,
89 PL_OPT_STRING,
90 "-save filename",
91 "Save plot in color postscript `file'"
92 },
93 {
94 NULL, // option
95 NULL, // handler
96 NULL, // client data
97 NULL, // address of variable to set
98 0, // mode flag
99 NULL, // short syntax
100 NULL
101 } // long syntax
102 };
103
104 PLCHAR_VECTOR notes[] = { "Make sure you get it right!", NULL };
105
106 // Function prototypes
107
108 void plot1( int );
109 void plot2( void );
110 void plot3( void );
111
112 //--------------------------------------------------------------------------
113 // main
114 //
115 // Generates several simple line plots. Demonstrates:
116 // - subwindow capability
117 // - setting up the window, drawing plot, and labelling
118 // - changing the color
119 // - automatic axis rescaling to exponential notation
120 // - placing the axes in the middle of the box
121 // - gridded coordinate axes
122 //--------------------------------------------------------------------------
123
124 int
main(int argc,char * argv[])125 main( int argc, char *argv[] )
126 {
127 PLINT digmax, cur_strm, new_strm;
128 char ver[80];
129 PLINT i;
130
131 // plplot initialization
132
133 // Parse and process command line arguments
134
135 plMergeOpts( options, "x01c options", notes );
136 // See if -pl_parse_skip has been specified without
137 // changing argc or argv
138 plparseopts( &argc, argv, PL_PARSE_NODELETE );
139 if ( pl_parse_skip_mode )
140 {
141 printf( "argv prior to call of plparseopts(..., PL_PARSE_SKIP)\n" );
142 for ( i = 0; i < argc; i++ )
143 {
144 printf( "i = %3d, argument = %s\n", i, argv[i] );
145 }
146 plparseopts( &argc, argv, PL_PARSE_SKIP );
147 printf( "argv after call to plparseopts(..., PL_PARSE_SKIP)\n" );
148 for ( i = 0; i < argc; i++ )
149 {
150 printf( "i = %3d, argument = %s\n", i, argv[i] );
151 }
152 }
153 else
154 {
155 // parse the command line again, and after such parsing
156 // argc and argv are typically reduced to 1 and the name
157 // of the programme that is being executed.
158 plparseopts( &argc, argv, PL_PARSE_FULL );
159 }
160
161 // Get version number, just for kicks
162
163 plgver( ver );
164 fprintf( stdout, "PLplot library version: %s\n", ver );
165
166 // Initialize plplot
167 // Divide page into 2x2 plots
168 // Note: calling plstar replaces separate calls to plssub and plinit
169 plstar( 2, 2 );
170
171 // Select font set as per input flag
172
173 if ( fontset )
174 plfontld( 1 );
175 else
176 plfontld( 0 );
177
178 // Set up the data
179 // Original case
180
181 xscale = 6.;
182 yscale = 1.;
183 xoff = 0.;
184 yoff = 0.;
185
186 // Do a plot
187
188 plot1( 0 );
189
190 // Set up the data
191
192 xscale = 1.;
193 yscale = 0.0014;
194 yoff = 0.0185;
195
196 // Do a plot
197
198 digmax = 5;
199 plsyax( digmax, 0 );
200
201 plot1( 1 );
202
203 plot2();
204
205 plot3();
206
207 //
208 // Show how to save a plot:
209 // Open a new device, make it current, copy parameters,
210 // and replay the plot buffer
211 //
212
213 if ( f_name ) // command line option '-save filename'
214
215 {
216 printf( "The current plot was saved in color Postscript under the name `%s'.\n", f_name );
217 plgstrm( &cur_strm ); // get current stream
218 plmkstrm( &new_strm ); // create a new one
219
220 plsfnam( f_name ); // file name
221 plsdev( "psc" ); // device type
222
223 plcpstrm( cur_strm, 0 ); // copy old stream parameters to new stream
224 plreplot(); // do the save by replaying the plot buffer
225 plend1(); // finish the device
226
227 plsstrm( cur_strm ); // return to previous stream
228 }
229
230 // Let's get some user input
231
232 if ( locate_mode )
233 {
234 for (;; )
235 {
236 if ( !plGetCursor( &gin ) )
237 break;
238 if ( gin.keysym == PLK_Escape )
239 break;
240
241 pltext();
242 printf( "subwin = %d, wx = %f, wy = %f, dx = %f, dy = %f\n",
243 gin.subwindow, gin.wX, gin.wY, gin.dX, gin.dY );
244 printf( "keysym = 0x%02x, button = 0x%02x, string = '%s', type = 0x%02x, state = 0x%02x\n",
245 gin.keysym, gin.button, gin.string, gin.type, gin.state );
246 plgra();
247 }
248 }
249
250 // Don't forget to call plend() to finish off!
251
252 plend();
253 exit( 0 );
254 }
255
256 //--------------------------------------------------------------------------
257
258 void
plot1(int do_test)259 plot1( int do_test )
260 {
261 int i;
262 PLFLT xmin, xmax, ymin, ymax;
263
264 for ( i = 0; i < 60; i++ )
265 {
266 x[i] = xoff + xscale * ( i + 1 ) / 60.0;
267 y[i] = yoff + yscale * pow( x[i], 2. );
268 }
269
270 xmin = x[0];
271 xmax = x[59];
272 ymin = y[0];
273 ymax = y[59];
274
275 for ( i = 0; i < 6; i++ )
276 {
277 xs[i] = x[i * 10 + 3];
278 ys[i] = y[i * 10 + 3];
279 }
280
281 // Set up the viewport and window using PLENV. The range in X is
282 // 0.0 to 6.0, and the range in Y is 0.0 to 30.0. The axes are
283 // scaled separately (just = 0), and we just draw a labelled
284 // box (axis = 0).
285 //
286 plcol0( 1 );
287 plenv( xmin, xmax, ymin, ymax, 0, 0 );
288 plcol0( 2 );
289 pllab( "(x)", "(y)", "#frPLplot Example 1 - y=x#u2" );
290
291 // Plot the data points
292
293 plcol0( 4 );
294 plpoin( 6, xs, ys, 9 );
295
296 // Draw the line through the data
297
298 plcol0( 3 );
299 plline( 60, x, y );
300
301 // xor mode enable erasing a line/point/text by replotting it again
302 // it does not work in double buffering mode, however
303
304 if ( do_test && test_xor )
305 {
306 #ifdef PL_HAVE_NANOSLEEP
307 PLINT st;
308 struct timespec ts;
309 ts.tv_sec = 0;
310 ts.tv_nsec = 50000000;
311 plxormod( 1, &st ); // enter xor mode
312 if ( st )
313 {
314 for ( i = 0; i < 60; i++ )
315 {
316 plpoin( 1, x + i, y + i, 9 ); // draw a point
317 nanosleep( &ts, NULL ); // wait a little
318 plflush(); // force an update of the tk driver
319 plpoin( 1, x + i, y + i, 9 ); // erase point
320 }
321 plxormod( 0, &st ); // leave xor mode
322 }
323 #else
324 printf( "The -xor command line option can only be exercised if your "
325 "system\nhas nanosleep(), which does not seem to happen.\n" );
326 #endif
327 }
328 }
329
330 //--------------------------------------------------------------------------
331
332 void
plot2(void)333 plot2( void )
334 {
335 int i;
336
337 // Set up the viewport and window using PLENV. The range in X is -2.0 to
338 // 10.0, and the range in Y is -0.4 to 2.0. The axes are scaled separately
339 // (just = 0), and we draw a box with axes (axis = 1).
340 //
341 plcol0( 1 );
342 plenv( -2.0, 10.0, -0.4, 1.2, 0, 1 );
343 plcol0( 2 );
344 pllab( "(x)", "sin(x)/x", "#frPLplot Example 1 - Sinc Function" );
345
346 // Fill up the arrays
347
348 for ( i = 0; i < 100; i++ )
349 {
350 x[i] = ( i - 19.0 ) / 6.0;
351 y[i] = 1.0;
352 if ( x[i] != 0.0 )
353 y[i] = sin( x[i] ) / x[i];
354 }
355
356 // Draw the line
357
358 plcol0( 3 );
359 plwidth( 2 );
360 plline( 100, x, y );
361 plwidth( 1 );
362 }
363
364 //--------------------------------------------------------------------------
365
366 void
plot3(void)367 plot3( void )
368 {
369 PLINT space0 = 0, mark0 = 0, space1 = 1500, mark1 = 1500;
370 int i;
371
372 // For the final graph we wish to override the default tick intervals, and
373 // so do not use plenv().
374 //
375 pladv( 0 );
376
377 // Use standard viewport, and define X range from 0 to 360 degrees, Y range
378 // from -1.2 to 1.2.
379 //
380 plvsta();
381 plwind( 0.0, 360.0, -1.2, 1.2 );
382
383 // Draw a box with ticks spaced 60 degrees apart in X, and 0.2 in Y.
384
385 plcol0( 1 );
386 plbox( "bcnst", 60.0, 2, "bcnstv", 0.2, 2 );
387
388 // Superimpose a dashed line grid, with 1.5 mm marks and spaces.
389 // plstyl expects a pointer!
390 //
391 plstyl( 1, &mark1, &space1 );
392 plcol0( 2 );
393 plbox( "g", 30.0, 0, "g", 0.2, 0 );
394 plstyl( 0, &mark0, &space0 );
395
396 plcol0( 3 );
397 pllab( "Angle (degrees)", "sine", "#frPLplot Example 1 - Sine function" );
398
399 for ( i = 0; i < 101; i++ )
400 {
401 x[i] = 3.6 * i;
402 y[i] = sin( x[i] * M_PI / 180.0 );
403 }
404
405 plcol0( 4 );
406 plline( 101, x, y );
407 }
408