// Simple vector plot example // Copyright (C) 2004 Andrew Ross // Copyright (C) 2004 Rafael Laboissiere // // // 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; either version 2 of the License, or // (at your option) any later version. // // 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 // // #include "plcdemos.h" void circulation( void ); void constriction( int astyle ); void transform( PLFLT x, PLFLT y, PLFLT *xt, PLFLT *yt, PLPointer data ); void constriction2( void ); void potential( void ); void f2mnmx( PLFLT **f, PLINT nx, PLINT ny, PLFLT *fnmin, PLFLT *fnmax ); // Pairs of points making the line segments used to plot the user defined arroW static PLFLT arrow_x[6] = { -0.5, 0.5, 0.3, 0.5, 0.3, 0.5 }; static PLFLT arrow_y[6] = { 0.0, 0.0, 0.2, 0.0, -0.2, 0.0 }; static PLFLT arrow2_x[6] = { -0.5, 0.3, 0.3, 0.5, 0.3, 0.3 }; static PLFLT arrow2_y[6] = { 0.0, 0.0, 0.2, 0.0, -0.2, 0.0 }; //-------------------------------------------------------------------------- // main // // Generates several simple vector plots. //-------------------------------------------------------------------------- // // Vector plot of the circulation about the origin // void circulation( void ) { int i, j; PLFLT dx, dy, x, y; PLcGrid2 cgrid2; PLFLT **u, **v; const int nx = 20; const int ny = 20; PLFLT xmin, xmax, ymin, ymax; dx = 1.0; dy = 1.0; xmin = -nx / 2 * dx; xmax = nx / 2 * dx; ymin = -ny / 2 * dy; ymax = ny / 2 * dy; plAlloc2dGrid( &cgrid2.xg, nx, ny ); plAlloc2dGrid( &cgrid2.yg, nx, ny ); plAlloc2dGrid( &u, nx, ny ); plAlloc2dGrid( &v, nx, ny ); cgrid2.nx = nx; cgrid2.ny = ny; // Create data - circulation around the origin. for ( i = 0; i < nx; i++ ) { x = ( i - nx / 2 + 0.5 ) * dx; for ( j = 0; j < ny; j++ ) { y = ( j - ny / 2 + 0.5 ) * dy; cgrid2.xg[i][j] = x; cgrid2.yg[i][j] = y; u[i][j] = y; v[i][j] = -x; } } // Plot vectors with default arrows plenv( xmin, xmax, ymin, ymax, 0, 0 ); pllab( "(x)", "(y)", "#frPLplot Example 22 - circulation" ); plcol0( 2 ); plvect( (const PLFLT * const *) u, (const PLFLT * const *) v, nx, ny, 0.0, pltr2, (void *) &cgrid2 ); plcol0( 1 ); plFree2dGrid( cgrid2.xg, nx, ny ); plFree2dGrid( cgrid2.yg, nx, ny ); plFree2dGrid( u, nx, ny ); plFree2dGrid( v, nx, ny ); } // // Vector plot of flow through a constricted pipe // void constriction( int astyle ) { int i, j; PLFLT dx, dy, x, y; PLFLT xmin, xmax, ymin, ymax; PLFLT Q, b, dbdx; PLcGrid2 cgrid2; PLFLT **u, **v; const int nx = 20; const int ny = 20; char title[80]; dx = 1.0; dy = 1.0; xmin = -nx / 2 * dx; xmax = nx / 2 * dx; ymin = -ny / 2 * dy; ymax = ny / 2 * dy; plAlloc2dGrid( &cgrid2.xg, nx, ny ); plAlloc2dGrid( &cgrid2.yg, nx, ny ); plAlloc2dGrid( &u, nx, ny ); plAlloc2dGrid( &v, nx, ny ); cgrid2.nx = nx; cgrid2.ny = ny; Q = 2.0; for ( i = 0; i < nx; i++ ) { x = ( i - nx / 2 + 0.5 ) * dx; for ( j = 0; j < ny; j++ ) { y = ( j - ny / 2 + 0.5 ) * dy; cgrid2.xg[i][j] = x; cgrid2.yg[i][j] = y; b = ymax / 4.0 * ( 3 - cos( M_PI * x / xmax ) ); if ( fabs( y ) < b ) { dbdx = ymax / 4.0 * sin( M_PI * x / xmax ) * M_PI / xmax * y / b; u[i][j] = Q * ymax / b; v[i][j] = dbdx * u[i][j]; } else { u[i][j] = 0.0; v[i][j] = 0.0; } } } plenv( xmin, xmax, ymin, ymax, 0, 0 ); sprintf( title, "#frPLplot Example 22 - constriction (arrow style %d)", astyle ); pllab( "(x)", "(y)", title ); plcol0( 2 ); plvect( (const PLFLT * const *) u, (const PLFLT * const *) v, nx, ny, -1.0, pltr2, (void *) &cgrid2 ); plcol0( 1 ); plFree2dGrid( cgrid2.xg, nx, ny ); plFree2dGrid( cgrid2.yg, nx, ny ); plFree2dGrid( u, nx, ny ); plFree2dGrid( v, nx, ny ); } // // Global transform function for a constriction using data passed in // This is the same transformation used in constriction. // void transform( PLFLT x, PLFLT y, PLFLT *xt, PLFLT *yt, PLPointer data ) { PLFLT *trdata; PLFLT xmax; trdata = (PLFLT *) data; xmax = *trdata; *xt = x; *yt = y / 4.0 * ( 3 - cos( M_PI * x / xmax ) ); } // // Vector plot of flow through a constricted pipe // with a coordinate transform // void constriction2( void ) { int i, j; PLFLT dx, dy, x, y; PLFLT xmin, xmax, ymin, ymax; PLFLT Q, b; PLcGrid2 cgrid2; PLFLT **u, **v; const int nx = 20; const int ny = 20; #define NC 11 const int nc = NC; const int nseg = 20; PLFLT clev[NC]; dx = 1.0; dy = 1.0; xmin = -nx / 2 * dx; xmax = nx / 2 * dx; ymin = -ny / 2 * dy; ymax = ny / 2 * dy; plstransform( transform, ( PLPointer ) & xmax ); plAlloc2dGrid( &cgrid2.xg, nx, ny ); plAlloc2dGrid( &cgrid2.yg, nx, ny ); plAlloc2dGrid( &u, nx, ny ); plAlloc2dGrid( &v, nx, ny ); cgrid2.nx = nx; cgrid2.ny = ny; Q = 2.0; for ( i = 0; i < nx; i++ ) { x = ( i - nx / 2 + 0.5 ) * dx; for ( j = 0; j < ny; j++ ) { y = ( j - ny / 2 + 0.5 ) * dy; cgrid2.xg[i][j] = x; cgrid2.yg[i][j] = y; b = ymax / 4.0 * ( 3 - cos( M_PI * x / xmax ) ); u[i][j] = Q * ymax / b; v[i][j] = 0.0; } } for ( i = 0; i < nc; i++ ) { clev[i] = Q + i * Q / ( nc - 1 ); } plenv( xmin, xmax, ymin, ymax, 0, 0 ); pllab( "(x)", "(y)", "#frPLplot Example 22 - constriction with plstransform" ); plcol0( 2 ); plshades( (const PLFLT * const *) u, nx, ny, NULL, xmin + dx / 2, xmax - dx / 2, ymin + dy / 2, ymax - dy / 2, clev, nc, 0.0, 1, 1.0, plfill, 0, NULL, NULL ); plvect( (const PLFLT * const *) u, (const PLFLT * const *) v, nx, ny, -1.0, pltr2, (void *) &cgrid2 ); // Plot edges using plpath (which accounts for coordinate transformation) rather than plline plpath( nseg, xmin, ymax, xmax, ymax ); plpath( nseg, xmin, ymin, xmax, ymin ); plcol0( 1 ); plFree2dGrid( cgrid2.xg, nx, ny ); plFree2dGrid( cgrid2.yg, nx, ny ); plFree2dGrid( u, nx, ny ); plFree2dGrid( v, nx, ny ); plstransform( NULL, NULL ); } void f2mnmx( PLFLT **f, PLINT nx, PLINT ny, PLFLT *fnmin, PLFLT *fnmax ) { int i, j; *fnmax = f[0][0]; *fnmin = *fnmax; for ( i = 0; i < nx; i++ ) { for ( j = 0; j < ny; j++ ) { *fnmax = MAX( *fnmax, f[i][j] ); *fnmin = MIN( *fnmin, f[i][j] ); } } } // // Vector plot of the gradient of a shielded potential (see example 9) // void potential( void ) { #if !defined ( WIN32 ) const int nper = 100; const int nlevel = 10; const int nr = 20; const int ntheta = 20; #else #define nper 100 #define nlevel 10 #define nr 20 #define ntheta 20 #endif int i, j; PLFLT eps, q1, d1, q1i, d1i, q2, d2, q2i, d2i; PLFLT div1, div1i, div2, div2i; PLFLT **u, **v, **z, r, theta, x, y, dz; PLFLT xmin, xmax, ymin, ymax, rmax, zmax, zmin; PLFLT px[nper], py[nper], clevel[nlevel]; PLcGrid2 cgrid2; // Create data to be plotted plAlloc2dGrid( &cgrid2.xg, nr, ntheta ); plAlloc2dGrid( &cgrid2.yg, nr, ntheta ); plAlloc2dGrid( &u, nr, ntheta ); plAlloc2dGrid( &v, nr, ntheta ); plAlloc2dGrid( &z, nr, ntheta ); cgrid2.nx = nr; cgrid2.ny = ntheta; // Potential inside a conducting cylinder (or sphere) by method of images. // Charge 1 is placed at (d1, d1), with image charge at (d2, d2). // Charge 2 is placed at (d1, -d1), with image charge at (d2, -d2). // Also put in smoothing term at small distances. // rmax = (double) nr; eps = 2.; q1 = 1.; d1 = rmax / 4.; q1i = -q1 * rmax / d1; d1i = pow( rmax, 2. ) / d1; q2 = -1.; d2 = rmax / 4.; q2i = -q2 * rmax / d2; d2i = pow( rmax, 2. ) / d2; for ( i = 0; i < nr; i++ ) { r = 0.5 + (double) i; for ( j = 0; j < ntheta; j++ ) { theta = 2. * M_PI / ( ntheta - 1 ) * ( 0.5 + (double) j ); x = r * cos( theta ); y = r * sin( theta ); cgrid2.xg[i][j] = x; cgrid2.yg[i][j] = y; div1 = sqrt( pow( x - d1, 2. ) + pow( y - d1, 2. ) + pow( eps, 2. ) ); div1i = sqrt( pow( x - d1i, 2. ) + pow( y - d1i, 2. ) + pow( eps, 2. ) ); div2 = sqrt( pow( x - d2, 2. ) + pow( y + d2, 2. ) + pow( eps, 2. ) ); div2i = sqrt( pow( x - d2i, 2. ) + pow( y + d2i, 2. ) + pow( eps, 2. ) ); z[i][j] = q1 / div1 + q1i / div1i + q2 / div2 + q2i / div2i; u[i][j] = -q1 * ( x - d1 ) / pow( div1, 3. ) - q1i * ( x - d1i ) / pow( div1i, 3.0 ) - q2 * ( x - d2 ) / pow( div2, 3. ) - q2i * ( x - d2i ) / pow( div2i, 3. ); v[i][j] = -q1 * ( y - d1 ) / pow( div1, 3. ) - q1i * ( y - d1i ) / pow( div1i, 3.0 ) - q2 * ( y + d2 ) / pow( div2, 3. ) - q2i * ( y + d2i ) / pow( div2i, 3. ); } } f2mnmx( cgrid2.xg, nr, ntheta, &xmin, &xmax ); f2mnmx( cgrid2.yg, nr, ntheta, &ymin, &ymax ); f2mnmx( z, nr, ntheta, &zmin, &zmax ); plenv( xmin, xmax, ymin, ymax, 0, 0 ); pllab( "(x)", "(y)", "#frPLplot Example 22 - potential gradient vector plot" ); // Plot contours of the potential dz = ( zmax - zmin ) / (double) nlevel; for ( i = 0; i < nlevel; i++ ) { clevel[i] = zmin + ( (double) i + 0.5 ) * dz; } plcol0( 3 ); pllsty( 2 ); plcont( (const PLFLT * const *) z, nr, ntheta, 1, nr, 1, ntheta, clevel, nlevel, pltr2, (void *) &cgrid2 ); pllsty( 1 ); plcol0( 1 ); // Plot the vectors of the gradient of the potential plcol0( 2 ); plvect( (const PLFLT * const *) u, (const PLFLT * const *) v, nr, ntheta, 25.0, pltr2, (void *) &cgrid2 ); plcol0( 1 ); // Plot the perimeter of the cylinder for ( i = 0; i < nper; i++ ) { theta = ( 2. * M_PI / ( nper - 1 ) ) * (double) i; px[i] = rmax * cos( theta ); py[i] = rmax * sin( theta ); } plline( nper, px, py ); plFree2dGrid( z, nr, ntheta ); plFree2dGrid( cgrid2.xg, nr, ntheta ); plFree2dGrid( cgrid2.yg, nr, ntheta ); plFree2dGrid( u, nr, ntheta ); plFree2dGrid( v, nr, ntheta ); } int main( int argc, const char *argv[] ) { PLINT narr, fill; // Parse and process command line arguments plparseopts( &argc, argv, PL_PARSE_FULL ); // Initialize plplot plinit(); circulation(); narr = 6; fill = 0; // Set arrow style using arrow_x and arrow_y then // plot using these arrows. plsvect( arrow_x, arrow_y, narr, fill ); constriction( 1 ); // Set arrow style using arrow2_x and arrow2_y then // plot using these filled arrows. fill = 1; plsvect( arrow2_x, arrow2_y, narr, fill ); constriction( 2 ); constriction2(); // Reset arrow style to the default by passing two // NULL arrays plsvect( NULL, NULL, 0, 0 ); potential(); plend(); exit( 0 ); }