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