1 /* $Id: plvect.c,v 1.1 2007/05/08 10:48:08 rice Exp $
2 
3 	Vector plotting routines.
4 
5    Copyright (C) 2004  Andrew Ross
6 
7    This file is part of PLplot.
8 
9    PLplot is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Library Public License as published
11    by the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13 
14    PLplot is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU Library General Public License for more details.
18 
19    You should have received a copy of the GNU Library General Public License
20    along with PLplot; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23 
24 #define NEED_PLDEBUG
25 #include "plplotP.h"
26 #include <float.h>
27 #include <ctype.h>
28 
29 /* Static function prototypes */
30 
31 static void plP_plotvect(PLFLT x, PLFLT y, PLFLT u, PLFLT v, PLFLT scale);
32 
33 /*--------------------------------------------------------------------------*\
34  * void c_plarrows()
35  *
36  * simple arrow plotter
37  * copyright 1993 Wesley Ebisuzaki
38  *
39  * an arrow is defined by its location (x, y) and its direction (u, v)
40  *
41  * inputs:
42  *   u[i], v[i]      arrow's horizontal and vertical projection
43  *   x[i], y[i]      arrow's location (world coordinates)
44  *   n               number of arrows to draw
45  *   scale           > 0  scaling factor for arrows
46  *                   0    default scaling factor
47  *                   < 0  default scaling factor * (-scale)
48  *   dx, dy          distance between arrows
49  *                   used when calculating the default arrow scaling
50  *                   so that arrows don't overlap
51  *
52 \*--------------------------------------------------------------------------*/
53 
54 #define SCALE0 2.0
55 
56 /* definition of original arrow: 2 line segments */
57 
58 static PLFLT arrow_x[4] = {0.5, -0.5, -0.27, -0.5};
59 static PLFLT arrow_y[4] = {0.0, 0.0, 0.0, 0.20};
60 
61 void
c_plarrows(PLFLT * u,PLFLT * v,PLFLT * x,PLFLT * y,PLINT n,PLFLT scale,PLFLT dx,PLFLT dy)62 c_plarrows(PLFLT *u, PLFLT *v, PLFLT *x, PLFLT *y, PLINT n,
63 	 PLFLT scale, PLFLT dx, PLFLT dy)
64 {
65     PLFLT uu, vv;
66     PLINT i, j, npts = 4;
67     PLINT px0, py0, dpx, dpy;
68     PLINT a_x[4], a_y[4];
69     PLFLT max_u, max_v;
70     double t;
71 
72     if (n <= 0) return;
73 
74     if (scale <= 0.0) {
75 
76     /* automatic scaling */
77     /* find max / min values of data */
78 
79 	max_u = u[0];
80 	max_v = v[0];
81 	for (i = 1; i < n; i++) {
82 	    t = fabs((double) u[i]);
83 	    max_u = t > max_u ? t : max_u;
84 	    t = fabs((double) v[i]);
85 	    max_v = t > max_v ? t : max_v;
86 	}
87 
88     /* measure distance in grid boxs */
89 
90 	max_u = max_u / fabs( (double) dx);
91 	max_v = max_v / fabs( (double) dy);
92 
93 	t = (max_u > max_v ? max_u : max_v);
94 	t = SCALE0 / t;
95 	if (scale < 0) {
96 	    scale = -scale * t;
97 	}
98 	else {
99 	    scale = t;
100 	}
101     }
102     pldebug("plarrows", "scale factor=%lf n=%d\n", scale,n);
103 
104     for (i = 0; i < n; i++) {
105 	uu = scale * u[i];
106 	vv = scale * v[i];
107 	if (uu == 0.0 && uu == 0.0) continue;
108 
109     /* conversion to physical coordinates */
110 
111 	px0 = plP_wcpcx(x[i]);
112 	py0 = plP_wcpcy(y[i]);
113 
114 	pldebug("plarrows", "%f %f %d %d\n",x[i],y[i],px0,py0);
115 
116 	dpx = plP_wcpcx(x[i] + 0.5*uu) - px0;
117 	dpy = plP_wcpcy(y[i] + 0.5*vv) - py0;
118 
119     /* transform arrow -> a */
120 
121 	for (j = 0; j < npts; j++) {
122 	    a_x[j] = arrow_x[j] * dpx -
123 		arrow_y[j] * dpy + px0;
124 	    a_y[j] = arrow_x[j] * dpy +
125 		arrow_y[j] * dpx + py0;
126 	}
127 
128     /* draw the arrow */
129 	plP_movphy(a_x[0], a_y[0]);
130 	plP_draphy(a_x[1], a_y[1]);
131 	plP_movphy(a_x[2], a_y[2]);
132 	plP_draphy(a_x[3], a_y[3]);
133     }
134 
135 }
136 
137 /*--------------------------------------------------------------------------*\
138  * void c_plsvect()
139  *
140  * Set the style of the arrow used by plarrows
141 \*--------------------------------------------------------------------------*/
142 
143 void
c_plsvect(PLFLT * arrowx,PLFLT * arrowy,PLINT npts,PLINT fill)144 c_plsvect(PLFLT *arrowx, PLFLT *arrowy, PLINT npts, PLINT fill) {
145     int i;
146 
147     if (plsc->arrow_x) free_mem(plsc->arrow_x);
148     if (plsc->arrow_y) free_mem(plsc->arrow_y);
149 
150     plsc->arrow_x = (PLFLT *)malloc(npts*sizeof(PLFLT));
151     plsc->arrow_y = (PLFLT *)malloc(npts*sizeof(PLFLT));
152 
153     plsc->arrow_npts = npts;
154     plsc->arrow_fill = fill;
155     for (i=0; i<npts; i++) {
156       plsc->arrow_x[i] = arrowx[i];
157       plsc->arrow_y[i] = arrowy[i];
158     }
159 }
160 
161 /*
162  * Plot an individual vector
163  */
164 static void
plP_plotvect(PLFLT x,PLFLT y,PLFLT u,PLFLT v,PLFLT scale)165 plP_plotvect(PLFLT x, PLFLT y, PLFLT u, PLFLT v, PLFLT scale) {
166 
167     PLFLT uu, vv, px0, py0, dpx, dpy;
168     PLINT *a_x, *a_y;
169     int j;
170 
171     uu = scale*u;
172     vv = scale*v;
173 
174     if(uu == 0.0 && vv == 0.0) return;
175 
176     a_x = (PLINT *)malloc(sizeof(PLINT)*(plsc->arrow_npts));
177     a_y = (PLINT *)malloc(sizeof(PLINT)*(plsc->arrow_npts));
178 
179     px0 = plP_wcpcx(x);
180     py0 = plP_wcpcy(y);
181 
182     pldebug("plP_plotvect", "%f %f %d %d\n",x,y,px0,py0);
183 
184     dpx = plP_wcpcx(x + 0.5*uu) - px0;
185     dpy = plP_wcpcy(y + 0.5*vv) - py0;
186 
187     /* transform arrow -> a */
188 
189     for (j = 0; j < plsc->arrow_npts; j++) {
190         a_x[j] = plsc->arrow_x[j] * dpx - plsc->arrow_y[j] * dpy + px0;
191 	a_y[j] = plsc->arrow_x[j] * dpy + plsc->arrow_y[j] * dpx + py0;
192     }
193 
194     /* draw the arrow */
195     plP_draphy_poly(a_x,a_y,plsc->arrow_npts);
196     if (plsc->arrow_fill) {
197 	plP_plfclp(a_x, a_y, plsc->arrow_npts, plsc->clpxmi, plsc->clpxma,
198 	plsc->clpymi, plsc->clpyma, plP_fill);
199     }
200 
201     free((void *)a_x);
202     free((void *)a_y);
203 
204 }
205 
206 /*
207  * void plfvect()
208  *
209  * Internal routine to plot a vector array with arbitrary coordinate
210  * and vector transformations
211  */
plfvect(PLFLT (* myplf2eval)(PLINT,PLINT,PLPointer),PLPointer f2eval_data1,PLPointer f2eval_data2,PLINT nx,PLINT ny,PLFLT scale,void (* pltr)(PLFLT,PLFLT,PLFLT *,PLFLT *,PLPointer),PLPointer pltr_data)212 void plfvect(PLFLT (*myplf2eval) (PLINT, PLINT, PLPointer),
213 		PLPointer f2eval_data1, PLPointer f2eval_data2,
214 		PLINT nx, PLINT ny, PLFLT scale,
215 		void (*pltr) (PLFLT, PLFLT, PLFLT *, PLFLT *, PLPointer),
216 		PLPointer pltr_data) {
217     PLINT i, j, ii1, jj1;
218     PLFLT **u, **v, **x, **y;
219     PLFLT lscale, dx, dy, dxmin, dymin, umax, vmax;
220 
221     plAlloc2dGrid(&u, nx, ny);
222     plAlloc2dGrid(&v, nx, ny);
223     plAlloc2dGrid(&x, nx, ny);
224     plAlloc2dGrid(&y, nx, ny);
225 
226     for (j=0; j<ny; j++) {
227         for (i=0 ;i<nx ;i++) {
228 	    u[i][j] = myplf2eval(i,j,f2eval_data1);
229 	    v[i][j] = myplf2eval(i,j,f2eval_data2);
230 	    pltr((PLFLT) i, (PLFLT) j, &x[i][j], &y[i][j], pltr_data);
231 	}
232     }
233 
234     /* Calculate apropriate scaling if necessary */
235     if (scale <= 0.0 ) {
236         if (nx <= 1 && ny <= 1) {
237             fprintf(stderr,"plfvect: not enough points for autoscaling\n");
238             return;
239         }
240 	dxmin = 10E10;
241 	dymin = 10E10;
242         for (j=0; j<ny; j++) {
243             for (i=0 ;i<nx ;i++) {
244                 for (jj1=j; jj1<ny; jj1++) {
245                     for (ii1=0 ;ii1<nx ;ii1++) {
246 		        dx = fabs(x[ii1][jj1]-x[i][j]);
247 		        dy = fabs(y[ii1][jj1]-y[i][j]);
248 			if (dx > 0) {
249 		            dxmin = (dx<dxmin)?dx:dxmin;
250 			}
251 			if (dy > 0) {
252 		            dymin = (dy<dymin)?dy:dymin;
253 			}
254 		    }
255 		}
256 	    }
257 	}
258 	umax = u[0][0];
259 	vmax = v[0][0];
260         for (j=0; j<ny; j++) {
261             for (i=0 ;i<nx ;i++) {
262 		umax = (u[i][j]>umax)?u[i][j]:umax;
263 		vmax = (v[i][j]>vmax)?v[i][j]:vmax;
264 	    }
265 	}
266 	umax = umax/dxmin;
267 	vmax = vmax/dymin;
268 	lscale = (umax<vmax)?umax:vmax;
269 	lscale = 1.5/lscale;
270 	if (scale < 0.0) {
271 	    scale = -scale*lscale;
272 	}
273 	else {
274 	    scale = lscale;
275 	}
276     }
277 
278     for (j=0; j<ny; j++) {
279         for (i=0 ;i<nx ;i++) {
280 	    plP_plotvect(x[i][j],y[i][j],u[i][j],v[i][j],scale);
281 	}
282     }
283 
284     plFree2dGrid(u, nx, ny);
285     plFree2dGrid(v, nx, ny);
286     plFree2dGrid(x, nx, ny);
287     plFree2dGrid(y, nx, ny);
288 
289 }
290 
291 void
c_plvect(PLFLT ** u,PLFLT ** v,PLINT nx,PLINT ny,PLFLT scale,void (* pltr)(PLFLT,PLFLT,PLFLT *,PLFLT *,PLPointer),PLPointer pltr_data)292 c_plvect(PLFLT **u, PLFLT **v, PLINT nx, PLINT ny, PLFLT scale,
293 	void (*pltr) (PLFLT, PLFLT, PLFLT *, PLFLT *, PLPointer),
294 	PLPointer pltr_data)
295 {
296     PLfGrid2 grid1, grid2;
297 
298     grid1.f = u;
299     grid2.f = v;
300 
301     plfvect(plf2eval2, (PLPointer) &grid1, (PLPointer) &grid2,
302 	       nx, ny, scale, pltr, pltr_data);
303 }
304