PLplot  5.10.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
plvect.c
Go to the documentation of this file.
1 // Vector plotting routines.
2 //
3 // Copyright (C) 2004 Andrew Ross
4 //
5 // This file is part of PLplot.
6 //
7 // PLplot is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU Library General Public License as published
9 // by the Free Software Foundation; either version 2 of the License, or
10 // (at your option) any later version.
11 //
12 // PLplot is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Library General Public License for more details.
16 //
17 // You should have received a copy of the GNU Library General Public License
18 // along with PLplot; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 //
21 
22 #define NEED_PLDEBUG
23 #include "plplotP.h"
24 #include <float.h>
25 #include <ctype.h>
26 
27 // Static function prototypes
28 
29 static void plP_plotvect( PLFLT x, PLFLT y, PLFLT u, PLFLT v, PLFLT scale );
30 
31 //--------------------------------------------------------------------------
32 // void c_plsvect()
33 //
34 // Set the style of the arrow used by plvect
35 //--------------------------------------------------------------------------
36 
37 void
38 c_plsvect( const PLFLT *arrowx, const PLFLT *arrowy, PLINT npts, PLINT fill )
39 {
40  int i;
41  PLFLT def_arrow_x[6] = { -0.5, 0.5, 0.3, 0.5, 0.3, 0.5 };
42  PLFLT def_arrow_y[6] = { 0.0, 0.0, 0.2, 0.0, -0.2, 0.0 };
43 
44  if ( plsc->arrow_x )
45  free_mem( plsc->arrow_x );
46  if ( plsc->arrow_y )
47  free_mem( plsc->arrow_y );
48 
49  // Reset default arrow if null pointers are passed.
50  if ( arrowx == NULL && arrowy == NULL )
51  {
52  arrowx = def_arrow_x;
53  arrowy = def_arrow_y;
54  npts = 6;
55  fill = 0;
56  }
57 
58  if ( ( ( plsc->arrow_x = (PLFLT *) malloc( (size_t) npts * sizeof ( PLFLT ) ) ) == NULL ) ||
59  ( ( plsc->arrow_y = (PLFLT *) malloc( (size_t) npts * sizeof ( PLFLT ) ) ) == NULL ) )
60  {
61  plexit( "c_plsvect: Insufficient memory" );
62  }
63 
64  plsc->arrow_npts = npts;
65  plsc->arrow_fill = fill;
66  for ( i = 0; i < npts; i++ )
67  {
68  plsc->arrow_x[i] = arrowx[i];
69  plsc->arrow_y[i] = arrowy[i];
70  }
71 }
72 
73 //
74 // Plot an individual vector
75 //
76 static void
77 plP_plotvect( PLFLT x, PLFLT y, PLFLT u, PLFLT v, PLFLT scale )
78 {
79  PLFLT uu, vv, px0, py0, dpx, dpy;
80  PLFLT xt, yt;
81  // Unnecessarily initialize a_y to quiet a -O1 -Wuninitialized warning
82  // which is a false alarm. (If something goes wrong with the
83  // a_x malloc below any further use of a_y does not occur.)
84  PLINT *a_x, *a_y = NULL;
85  int j;
86 
87  uu = scale * u;
88  vv = scale * v;
89 
90  if ( uu == 0.0 && vv == 0.0 )
91  return;
92 
93  if ( ( ( a_x = (PLINT *) malloc( sizeof ( PLINT ) * (size_t) ( plsc->arrow_npts ) ) ) == NULL ) ||
94  ( ( a_y = (PLINT *) malloc( sizeof ( PLINT ) * (size_t) ( plsc->arrow_npts ) ) ) == NULL ) )
95  {
96  plexit( "plP_plotvect: Insufficient memory" );
97  }
98 
99  TRANSFORM( x, y, &xt, &yt );
100  px0 = plP_wcpcx( xt );
101  py0 = plP_wcpcy( yt );
102 
103  pldebug( "plP_plotvect", "%f %f %d %d\n", x, y, px0, py0 );
104 
105  TRANSFORM( x + 0.5 * uu, y + 0.5 * vv, &xt, &yt );
106  //printf("plvect: %f %f %f %f %f %f %f\n",scale, x,0.5*uu, y,0.5*vv, xt, yt);
107  dpx = plP_wcpcx( xt ) - px0;
108  dpy = plP_wcpcy( yt ) - py0;
109 
110  // transform arrow -> a
111 
112  for ( j = 0; j < plsc->arrow_npts; j++ )
113  {
114  a_x[j] = (PLINT) ( plsc->arrow_x[j] * dpx - plsc->arrow_y[j] * dpy + px0 );
115  a_y[j] = (PLINT) ( plsc->arrow_x[j] * dpy + plsc->arrow_y[j] * dpx + py0 );
116  }
117 
118  // draw the arrow
119  plP_draphy_poly( a_x, a_y, plsc->arrow_npts );
120  if ( plsc->arrow_fill )
121  {
122  plP_plfclp( a_x, a_y, plsc->arrow_npts, plsc->clpxmi, plsc->clpxma,
123  plsc->clpymi, plsc->clpyma, plP_fill );
124  }
125 
126  free( (void *) a_x );
127  free( (void *) a_y );
128 }
129 
130 //
131 // void plfvect()
132 //
133 // Routine to plot a vector array with arbitrary coordinate
134 // and vector transformations
135 //
136 void plfvect( PLFLT ( *getuv )( PLINT, PLINT, PLPointer ),
137  PLPointer up, PLPointer vp,
138  PLINT nx, PLINT ny, PLFLT scale,
139  void ( *pltr )( PLFLT, PLFLT, PLFLT *, PLFLT *, PLPointer ),
140  PLPointer pltr_data )
141 {
142  PLINT i, j, i1, j1;
143  PLFLT **u, **v, **x, **y;
144  PLFLT lscale, dx, dy, dxmin, dymin, umax, vmax;
145 
146  plAlloc2dGrid( &u, nx, ny );
147  plAlloc2dGrid( &v, nx, ny );
148  plAlloc2dGrid( &x, nx, ny );
149  plAlloc2dGrid( &y, nx, ny );
150 
151  for ( j = 0; j < ny; j++ )
152  {
153  for ( i = 0; i < nx; i++ )
154  {
155  u[i][j] = getuv( i, j, up );
156  v[i][j] = getuv( i, j, vp );
157  pltr( (PLFLT) i, (PLFLT) j, &x[i][j], &y[i][j], pltr_data );
158  }
159  }
160 
161  // Calculate apropriate scaling if necessary
162  if ( scale <= 0.0 )
163  {
164  if ( nx <= 1 && ny <= 1 )
165  {
166  fprintf( stderr, "plfvect: not enough points for autoscaling\n" );
167  return;
168  }
169  dxmin = 10E10;
170  dymin = 10E10;
171  for ( j = 0; j < ny; j++ )
172  {
173  for ( i = 0; i < nx; i++ )
174  {
175  for ( j1 = j; j1 < ny; j1++ )
176  {
177  for ( i1 = 0; i1 < nx; i1++ )
178  {
179  dx = fabs( x[i1][j1] - x[i][j] );
180  dy = fabs( y[i1][j1] - y[i][j] );
181  if ( dx > 0 )
182  {
183  dxmin = ( dx < dxmin ) ? dx : dxmin;
184  }
185  if ( dy > 0 )
186  {
187  dymin = ( dy < dymin ) ? dy : dymin;
188  }
189  }
190  }
191  }
192  }
193  umax = u[0][0];
194  vmax = v[0][0];
195  for ( j = 0; j < ny; j++ )
196  {
197  for ( i = 0; i < nx; i++ )
198  {
199  umax = ( u[i][j] > umax ) ? u[i][j] : umax;
200  vmax = ( v[i][j] > vmax ) ? v[i][j] : vmax;
201  }
202  }
203  if ( umax != 0.0 )
204  {
205  dxmin = dxmin / umax;
206  }
207  else
208  {
209  dxmin = 10E10;
210  }
211  if ( vmax != 0.0 )
212  {
213  dymin = dymin / vmax;
214  }
215  else
216  {
217  dymin = 10E10;
218  }
219  lscale = 1.5 * MIN( dxmin, dymin );
220  if ( scale < 0.0 )
221  {
222  scale = -scale * lscale;
223  }
224  else
225  {
226  scale = lscale;
227  }
228  }
229 
230  for ( j = 0; j < ny; j++ )
231  {
232  for ( i = 0; i < nx; i++ )
233  {
234  plP_plotvect( x[i][j], y[i][j], u[i][j], v[i][j], scale );
235  }
236  }
237 
238  plFree2dGrid( u, nx, ny );
239  plFree2dGrid( v, nx, ny );
240  plFree2dGrid( x, nx, ny );
241  plFree2dGrid( y, nx, ny );
242 }
243 
244 void
245 c_plvect( const PLFLT * const *u, const PLFLT * const *v, PLINT nx, PLINT ny, PLFLT scale,
246  void ( *pltr )( PLFLT, PLFLT, PLFLT *, PLFLT *, PLPointer ),
247  PLPointer pltr_data )
248 {
250  nx, ny, scale, pltr, pltr_data );
251 }