PLplot 5.9.6
plvect.c
00001 /* $Id$
00002  *
00003  *      Vector plotting routines.
00004  *
00005  * Copyright (C) 2004  Andrew Ross
00006  *
00007  * This file is part of PLplot.
00008  *
00009  * PLplot is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Library Public License as published
00011  * by the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * PLplot is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU Library General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Library General Public License
00020  * along with PLplot; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00022  */
00023 
00024 #define NEED_PLDEBUG
00025 #include "plplotP.h"
00026 #include <float.h>
00027 #include <ctype.h>
00028 
00029 /* Static function prototypes */
00030 
00031 static void plP_plotvect( PLFLT x, PLFLT y, PLFLT u, PLFLT v, PLFLT scale );
00032 
00033 /*--------------------------------------------------------------------------*\
00034  * void c_plsvect()
00035  *
00036  * Set the style of the arrow used by plvect
00037  \*--------------------------------------------------------------------------*/
00038 
00039 void
00040 c_plsvect( PLFLT *arrowx, PLFLT *arrowy, PLINT npts, PLINT fill )
00041 {
00042     int i;
00043 
00044     if ( plsc->arrow_x )
00045         free_mem( plsc->arrow_x );
00046     if ( plsc->arrow_y )
00047         free_mem( plsc->arrow_y );
00048 
00049     if ( ( ( plsc->arrow_x = (PLFLT *) malloc( npts * sizeof ( PLFLT ) ) ) == NULL ) ||
00050          ( ( plsc->arrow_y = (PLFLT *) malloc( npts * sizeof ( PLFLT ) ) ) == NULL ) )
00051     {
00052         plexit( "c_plsvect: Insufficient memory" );
00053     }
00054 
00055     plsc->arrow_npts = npts;
00056     plsc->arrow_fill = fill;
00057     for ( i = 0; i < npts; i++ )
00058     {
00059         plsc->arrow_x[i] = arrowx[i];
00060         plsc->arrow_y[i] = arrowy[i];
00061     }
00062 }
00063 
00064 /*
00065  * Plot an individual vector
00066  */
00067 static void
00068 plP_plotvect( PLFLT x, PLFLT y, PLFLT u, PLFLT v, PLFLT scale )
00069 {
00070     PLFLT uu, vv, px0, py0, dpx, dpy;
00071     PLINT *a_x, *a_y;
00072     int   j;
00073 
00074     uu = scale * u;
00075     vv = scale * v;
00076 
00077     if ( uu == 0.0 && vv == 0.0 )
00078         return;
00079 
00080     if ( ( ( a_x = (PLINT *) malloc( sizeof ( PLINT ) * ( plsc->arrow_npts ) ) ) == NULL ) ||
00081          ( ( a_y = (PLINT *) malloc( sizeof ( PLINT ) * ( plsc->arrow_npts ) ) ) == NULL ) )
00082     {
00083         plexit( "plP_plotvect: Insufficient memory" );
00084     }
00085 
00086     px0 = plP_wcpcx( x );
00087     py0 = plP_wcpcy( y );
00088 
00089     pldebug( "plP_plotvect", "%f %f %d %d\n", x, y, px0, py0 );
00090 
00091     dpx = plP_wcpcx( x + 0.5 * uu ) - px0;
00092     dpy = plP_wcpcy( y + 0.5 * vv ) - py0;
00093 
00094     /* transform arrow -> a */
00095 
00096     for ( j = 0; j < plsc->arrow_npts; j++ )
00097     {
00098         a_x[j] = (PLINT) ( plsc->arrow_x[j] * dpx - plsc->arrow_y[j] * dpy + px0 );
00099         a_y[j] = (PLINT) ( plsc->arrow_x[j] * dpy + plsc->arrow_y[j] * dpx + py0 );
00100     }
00101 
00102     /* draw the arrow */
00103     plP_draphy_poly( a_x, a_y, plsc->arrow_npts );
00104     if ( plsc->arrow_fill )
00105     {
00106         plP_plfclp( a_x, a_y, plsc->arrow_npts, plsc->clpxmi, plsc->clpxma,
00107             plsc->clpymi, plsc->clpyma, plP_fill );
00108     }
00109 
00110     free( (void *) a_x );
00111     free( (void *) a_y );
00112 }
00113 
00114 /*
00115  * void plfvect()
00116  *
00117  * Routine to plot a vector array with arbitrary coordinate
00118  * and vector transformations
00119  */
00120 void plfvect( PLFLT ( *getuv )( PLINT, PLINT, PLPointer ),
00121               PLPointer up, PLPointer vp,
00122               PLINT nx, PLINT ny, PLFLT scale,
00123               void ( *pltr )( PLFLT, PLFLT, PLFLT *, PLFLT *, PLPointer ),
00124               PLPointer pltr_data )
00125 {
00126     PLINT i, j, i1, j1;
00127     PLFLT **u, **v, **x, **y;
00128     PLFLT lscale, dx, dy, dxmin, dymin, umax, vmax;
00129 
00130     plAlloc2dGrid( &u, nx, ny );
00131     plAlloc2dGrid( &v, nx, ny );
00132     plAlloc2dGrid( &x, nx, ny );
00133     plAlloc2dGrid( &y, nx, ny );
00134 
00135     for ( j = 0; j < ny; j++ )
00136     {
00137         for ( i = 0; i < nx; i++ )
00138         {
00139             u[i][j] = getuv( i, j, up );
00140             v[i][j] = getuv( i, j, vp );
00141             pltr( (PLFLT) i, (PLFLT) j, &x[i][j], &y[i][j], pltr_data );
00142         }
00143     }
00144 
00145     /* Calculate apropriate scaling if necessary */
00146     if ( scale <= 0.0 )
00147     {
00148         if ( nx <= 1 && ny <= 1 )
00149         {
00150             fprintf( stderr, "plfvect: not enough points for autoscaling\n" );
00151             return;
00152         }
00153         dxmin = 10E10;
00154         dymin = 10E10;
00155         for ( j = 0; j < ny; j++ )
00156         {
00157             for ( i = 0; i < nx; i++ )
00158             {
00159                 for ( j1 = j; j1 < ny; j1++ )
00160                 {
00161                     for ( i1 = 0; i1 < nx; i1++ )
00162                     {
00163                         dx = fabs( x[i1][j1] - x[i][j] );
00164                         dy = fabs( y[i1][j1] - y[i][j] );
00165                         if ( dx > 0 )
00166                         {
00167                             dxmin = ( dx < dxmin ) ? dx : dxmin;
00168                         }
00169                         if ( dy > 0 )
00170                         {
00171                             dymin = ( dy < dymin ) ? dy : dymin;
00172                         }
00173                     }
00174                 }
00175             }
00176         }
00177         umax = u[0][0];
00178         vmax = v[0][0];
00179         for ( j = 0; j < ny; j++ )
00180         {
00181             for ( i = 0; i < nx; i++ )
00182             {
00183                 umax = ( u[i][j] > umax ) ? u[i][j] : umax;
00184                 vmax = ( v[i][j] > vmax ) ? v[i][j] : vmax;
00185             }
00186         }
00187         umax   = umax / dxmin;
00188         vmax   = vmax / dymin;
00189         lscale = ( umax < vmax ) ? umax : vmax;
00190         lscale = 1.5 / lscale;
00191         if ( scale < 0.0 )
00192         {
00193             scale = -scale * lscale;
00194         }
00195         else
00196         {
00197             scale = lscale;
00198         }
00199     }
00200 
00201     for ( j = 0; j < ny; j++ )
00202     {
00203         for ( i = 0; i < nx; i++ )
00204         {
00205             plP_plotvect( x[i][j], y[i][j], u[i][j], v[i][j], scale );
00206         }
00207     }
00208 
00209     plFree2dGrid( u, nx, ny );
00210     plFree2dGrid( v, nx, ny );
00211     plFree2dGrid( x, nx, ny );
00212     plFree2dGrid( y, nx, ny );
00213 }
00214 
00215 void
00216 c_plvect( PLFLT **u, PLFLT **v, PLINT nx, PLINT ny, PLFLT scale,
00217           void ( *pltr )( PLFLT, PLFLT, PLFLT *, PLFLT *, PLPointer ),
00218           PLPointer pltr_data )
00219 {
00220     plfvect( plf2eval1, ( PLPointer ) u, ( PLPointer ) v,
00221         nx, ny, scale, pltr, pltr_data );
00222 }
 All Data Structures Files Functions