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