//-------------------------------------------------------------------------- // Copyright (C) 2004 Andrew Ross // Copyright (C) 2004 Alan W. Irwin // // This file is part of PLplot. // // PLplot is free software; you can redistribute it and/or modify // it under the terms of the GNU Library General Public License as published by // the Free Software Foundation; version 2 of the License. // // PLplot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Library General Public License for more details. // // You should have received a copy of the GNU Library General Public License // along with PLplot; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA //-------------------------------------------------------------------------- // //-------------------------------------------------------------------------- // Implementation of PLplot example 14 in C++. //-------------------------------------------------------------------------- #include "plc++demos.h" #ifdef PL_USE_NAMESPACE using namespace std; #endif class x14 { public: x14( int, char ** ); void plot1( plstream * ); void plot2( plstream * ); void plot3( plstream * ); void plot4( plstream * ); void plot5( plstream * ); static void mypltr( PLFLT, PLFLT, PLFLT *, PLFLT *, void * ); private: // Class data plstream *pls1, *pls2; PLFLT x[101], y[101]; PLFLT xscale, yscale, xoff, yoff, xs[6], ys[6]; static PLINT space0, mark0, space1, mark1; static const int xpts, ypts; static const PLFLT xspa, yspa; static const PLFLT tr[6]; }; PLINT x14::space0 = 0, x14::mark0 = 0, x14::space1 = 1500, x14::mark1 = 1500; const int x14:: xpts = 35; const int x14:: ypts = 46; const PLFLT x14::xspa = 2. / ( x14::xpts - 1 ); const PLFLT x14::yspa = 2. / ( x14::ypts - 1 ); const PLFLT x14::tr[6] = { x14::xspa, 0.0, -1.0, 0.0, x14::yspa, -1.0 }; void x14::mypltr( PLFLT x, PLFLT y, PLFLT *tx, PLFLT *ty, void * /* pltr_data */ ) { *tx = tr[0] * x + tr[1] * y + tr[2]; *ty = tr[3] * x + tr[4] * y + tr[5]; } static PLFLT clevel[11] = { -1., -.8, -.6, -.4, -.2, 0, .2, .4, .6, .8, 1. }; //-------------------------------------------------------------------------- // x14() // // Plots several simple functions from other example programs. // // This version sends the output of the first 4 plots (one page) to two // independent streams. //-------------------------------------------------------------------------- x14::x14( int argc, char ** argv ) { int digmax; // Select either TK or DP driver and use a small window // Using DP results in a crash at the end due to some odd cleanup problems // The geometry strings MUST be in writable memory char driver[80] = ""; PLINT fam, num, bmax; const char geometry_master[] = "500x410+100+200"; const char geometry_slave[] = "500x410+650+200"; PLFLT xp0, yp0; PLINT xleng0, yleng0, xoff0, yoff0; int valid_geometry; // plplot initialization pls1 = new plstream(); // Parse and process command line arguments. pls1->parseopts( &argc, argv, PL_PARSE_FULL ); //If valid geometry specified on command line, use it for both streams. pls1->gpage( xp0, yp0, xleng0, yleng0, xoff0, yoff0 ); valid_geometry = ( xleng0 > 0 && yleng0 > 0 ); // Set up first stream if ( valid_geometry ) pls1->spage( xp0, yp0, xleng0, yleng0, xoff0, yoff0 ); else pls1->setopt( "geometry", geometry_master ); pls1->ssub( 2, 2 ); // Initialize PLplot. pls1->init(); pls1->gdev( driver ); pls1->gfam( fam, num, bmax ); cout << "Demo of multiple output streams via the " << driver << " driver." << endl; cout << "Running with the second stream as slave to the first.\n" << endl; pls2 = new plstream(); if ( valid_geometry ) pls2->spage( xp0, yp0, xleng0, yleng0, xoff0, yoff0 ); else pls2->setopt( "geometry", geometry_slave ); // Turn off pause to make this a slave (must follow master) pls2->spause( false ); pls2->sdev( driver ); pls2->sfam( fam, num, bmax ); // Currently number of digits in format number can only be // set via the command line option pls2->setopt( "fflen", "2" ); pls2->init(); // Set up the data & plot // Original case xscale = 6.; yscale = 1.; xoff = 0.; yoff = 0.; plot1( pls1 ); // Set up the data & plot xscale = 1.; yscale = 1.e+6; plot1( pls1 ); // Set up the data & plot xscale = 1.; yscale = 1.e-6; digmax = 2; pls1->syax( digmax, 0 ); plot1( pls1 ); // Set up the data & plot xscale = 1.; yscale = 0.0014; yoff = 0.0185; digmax = 5; pls1->syax( digmax, 0 ); plot1( pls1 ); // To slave // The eop() ensures the eop indicator gets lit. plot4( pls2 ); pls2->eop(); // Back to master plot2( pls1 ); plot3( pls1 ); // To slave plot5( pls2 ); pls2->eop(); // Back to master to wait for user to advance pls1->eop(); delete pls1; delete pls2; } //-------------------------------------------------------------------------- void x14::plot1( plstream *pls ) { int i; PLFLT xmin, xmax, ymin, ymax; for ( i = 0; i < 60; i++ ) { x[i] = xoff + xscale * ( i + 1 ) / 60.0; y[i] = yoff + yscale * pow( x[i], 2. ); } xmin = x[0]; xmax = x[59]; ymin = y[0]; ymax = y[59]; for ( i = 0; i < 6; i++ ) { xs[i] = x[i * 10 + 3]; ys[i] = y[i * 10 + 3]; } // Set up the viewport and window using PLENV. The range in X is // 0.0 to 6.0, and the range in Y is 0.0 to 30.0. The axes are // scaled separately (just = 0), and we just draw a labelled // box (axis = 0). pls->col0( 1 ); pls->env( xmin, xmax, ymin, ymax, 0, 0 ); pls->col0( 6 ); pls->lab( "(x)", "(y)", "#frPLplot Example 1 - y=x#u2" ); // Plot the data points pls->col0( 9 ); pls->poin( 6, xs, ys, 9 ); // Draw the line through the data pls->col0( 4 ); pls->line( 60, x, y ); pls->flush(); } //-------------------------------------------------------------------------- void x14::plot2( plstream *pls ) { int i; // Set up the viewport and window using PLENV. The range in X is -2.0 to // 10.0, and the range in Y is -0.4 to 2.0. The axes are scaled separately // (just = 0), and we draw a box with axes (axis = 1). pls->col0( 1 ); pls->env( -2.0, 10.0, -0.4, 1.2, 0, 1 ); pls->col0( 2 ); pls->lab( "(x)", "sin(x)/x", "#frPLplot Example 1 - Sinc Function" ); // Fill up the arrays for ( i = 0; i < 100; i++ ) { x[i] = ( i - 19.0 ) / 6.0; y[i] = 1.0; if ( x[i] != 0.0 ) y[i] = sin( x[i] ) / x[i]; } // Draw the line pls->col0( 3 ); pls->line( 100, x, y ); pls->flush(); } //-------------------------------------------------------------------------- void x14::plot3( plstream *pls ) { int i; // For the final graph we wish to override the default tick intervals, and // so do not use PLENV pls->adv( 0 ); // Use standard viewport, and define X range from 0 to 360 degrees, Y range // from -1.2 to 1.2. pls->vsta(); pls->wind( 0.0, 360.0, -1.2, 1.2 ); // Draw a box with ticks spaced 60 degrees apart in X, and 0.2 in Y. pls->col0( 1 ); pls->box( "bcnst", 60.0, 2, "bcnstv", 0.2, 2 ); // Superimpose a dashed line grid, with 1.5 mm marks and spaces. plstyl // expects a pointer!! pls->styl( 1, &mark1, &space1 ); pls->col0( 2 ); pls->box( "g", 30.0, 0, "g", 0.2, 0 ); pls->styl( 0, &mark0, &space0 ); pls->col0( 3 ); pls->lab( "Angle (degrees)", "sine", "#frPLplot Example 1 - Sine function" ); for ( i = 0; i < 101; i++ ) { x[i] = 3.6 * i; y[i] = sin( x[i] * M_PI / 180.0 ); } pls->col0( 4 ); pls->line( 101, x, y ); pls->flush(); } //-------------------------------------------------------------------------- void x14::plot4( plstream *pls ) { int i, j; PLFLT dtr, theta, dx, dy, r; char text[4]; PLFLT x0[361], y0[361]; PLFLT x[361], y[361]; dtr = M_PI / 180.0; for ( i = 0; i <= 360; i++ ) { x0[i] = cos( dtr * i ); y0[i] = sin( dtr * i ); } // Set up viewport and window, but do not draw box pls->env( -1.3, 1.3, -1.3, 1.3, 1, -2 ); for ( i = 1; i <= 10; i++ ) { for ( j = 0; j <= 360; j++ ) { x[j] = 0.1 * i * x0[j]; y[j] = 0.1 * i * y0[j]; } // Draw circles for polar grid pls->line( 361, x, y ); } pls->col0( 2 ); for ( i = 0; i <= 11; i++ ) { theta = 30.0 * i; dx = cos( dtr * theta ); dy = sin( dtr * theta ); // Draw radial spokes for polar grid pls->join( 0.0, 0.0, dx, dy ); sprintf( text, "%d", (int) ROUND( theta ) ); // Write labels for angle //Slightly off zero to avoid floating point logic flips at 90 and 270 deg. if ( dx >= -0.00001 ) pls->ptex( dx, dy, dx, dy, -0.15, text ); else pls->ptex( dx, dy, -dx, -dy, 1.15, text ); } // Draw the graph for ( i = 0; i <= 360; i++ ) { r = sin( dtr * ( 5 * i ) ); x[i] = x0[i] * r; y[i] = y0[i] * r; } pls->col0( 3 ); pls->line( 361, x, y ); pls->col0( 4 ); pls->mtex( "t", 2.0, 0.5, 0.5, "#frPLplot Example 3 - r(#gh)=sin 5#gh" ); pls->flush(); } //-------------------------------------------------------------------------- // Demonstration of contour plotting void x14::plot5( plstream *pls ) { int i, j; PLFLT xx, yy; PLFLT **z, **w; static PLINT mark = 1500, space = 1500; // Set up function arrays pls->Alloc2dGrid( &z, xpts, ypts ); pls->Alloc2dGrid( &w, xpts, ypts ); for ( i = 0; i < xpts; i++ ) { xx = (PLFLT) ( i - ( xpts / 2 ) ) / (PLFLT) ( xpts / 2 ); for ( j = 0; j < ypts; j++ ) { yy = (PLFLT) ( j - ( ypts / 2 ) ) / (PLFLT) ( ypts / 2 ) - 1.0; z[i][j] = xx * xx - yy * yy; w[i][j] = 2 * xx * yy; } } pls->env( -1.0, 1.0, -1.0, 1.0, 0, 0 ); pls->col0( 2 ); pls->cont( z, xpts, ypts, 1, xpts, 1, ypts, clevel, 11, x14::mypltr, NULL ); pls->styl( 1, &mark, &space ); pls->col0( 3 ); pls->cont( w, xpts, ypts, 1, xpts, 1, ypts, clevel, 11, x14::mypltr, NULL ); pls->col0( 1 ); pls->lab( "X Coordinate", "Y Coordinate", "Streamlines of flow" ); pls->flush(); // Clean up pls->Free2dGrid( z, xpts, ypts ); pls->Free2dGrid( w, xpts, ypts ); } int main( int argc, char ** argv ) { x14 *x = new x14( argc, argv ); delete x; } //-------------------------------------------------------------------------- // End of x14.cc //--------------------------------------------------------------------------