source: trunk/PLOTS/VECTEUR/vecteur.pro @ 2

Last change on this file since 2 was 2, checked in by opalod, 22 years ago

Initial revision

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 14.3 KB
Line 
1;------------------------------------------------------------
2;------------------------------------------------------------
3;------------------------------------------------------------
4;+
5; NAME:vecteur
6;
7; PURPOSE: trace des vecteurs (meme situees sur une grille tordue) sur
8; n''importe quelle projection, de telle sorte que tous les vecteurs
9; aient une norme comparable sur le dessin (en clair, un vecteur qui
10; doit faire 1cm le fait quelque soit la projection et sa position sur
11; la sphere)
12;
13; CATEGORY:trace de vecteur
14;
15; CALLING SEQUENCE:vecteur, composanteu, composantev, normevecteur, indice2d, reduitindice2d
16;
17; INPUTS: COMPOSANTEU et COMPOSANTEV: ce sont les composantes des
18; vecteurs a tracer. Ces tableaux 2d ont la meme dimension que
19; reduitindice2d (cf apres).
20;       INDICE2D: indice permettant de passer d''un tableau jpi,jpj au
21;       zoom surlequel on fait le dessin.
22;       REDUITINDICE2D: indice permettant de passer d''un tableau
23;       definit par indice2d au tableau pourlequel on a reelement des
24;       vecteurs a tracer (en clair: c''est par ex qd on ne trace par exemple
25;       que un vecteur sur 2)
26;
27; KEYWORD PARAMETERS:
28;
29;      CMREF: la longeur en cm sur le papier que diot faire la fleche
30;      de norme normeref. par defaut ajuste au dessin et compris entre
31;      .5 et 1.5 cm
32;
33;      MISSING: la valeur d''une missing value. ne pas utilisder ce
34;      mot cle. fixe a 1e5 par ajoutvect.pro
35;     
36;      NORMEREF: la norme de la fleche de reference. par defaut on
37;      essaie de faire qqch qui colle pas trop mal!
38;
39;      VECTCOLOR: la couleur de la fleche. Par defaut noir (couleur 0)
40;
41;      VECTTHICK; l''epaissuer de la fleche. par defaut 1.
42;
43;      VECTREFPOS: vecteur de 2 elements specifiant la position en
44;      coordonnees DATA du debut du vecteur de reference. Par defaut
45;      en bas a droite du dessin.
46;
47;      VECTREFFORMAT: format a utiliser pour specifier la norme du
48;      vecteur de reference.
49;
50;      /NOVECTREF: pour supprimer l'affichage du vecteur de reference.
51;
52; OUTPUTS:
53;
54; COMMON BLOCKS:common.pro
55;
56; SIDE EFFECTS:
57;
58; RESTRICTIONS:
59;
60; EXAMPLE:
61;
62; MODIFICATION HISTORY:
63;  Creation : 13/02/98 G. Roullet (grlod@lodyc.jussieu.fr)
64;  Modification : 14/01/99 realise la transformation
65;  spherique<->cartesien G. Roullet
66;                 12/03/99 verification de la routine G. Roullet
67;  8/11/1999:
68;  G. Roullet et Sebastien Masson (smasson@lodyc.jussieu.fr)
69;  adaptation pour les zoom. reverification...traitement separe de la
70;  direction et de la norme des vecteurs. mots cles NORMEREF et CMREF.
71;-
72;------------------------------------------------------------
73;------------------------------------------------------------
74;------------------------------------------------------------
75
76FUNCTION cv_cm2normal, angle
77;
78; donne la longeur en coordonnes normales d''un trait ortiente de
79; angle par rapport a l''axe des x et qui doit faire 1 cm sur le
80; dessin.
81; angle peut etre un tableau.
82;
83@common
84; quelle est la longeur en coordonnees normales d''un trait qui fera 1
85; cm sur le parier et qui est parallele a x?
86   sizexfeuille = petitfeuille*key_portrait+grandfeuille*(1-key_portrait)
87   sizeyfeuille = grandfeuille*key_portrait+petitfeuille*(1-key_portrait)
88   cm_en_normal = 1./sizexfeuille
89;
90;  si le rapport d''aspect de la fenetre n''est pas egale a 1, la
91;  longeur en coordonees normalise d''un trait de 1cm varie suivant
92;  l''angle polaire de ce trait.
93;
94   aspect = sizexfeuille/sizeyfeuille
95   cm_en_normal = cm_en_normal*sqrt( 1 +(aspect^2-1)*sin(angle)^2 )
96;
97   return, cm_en_normal
98END
99;
100PRO normalise, u, v, w
101;
102; normalise le vecteur
103;
104   IF n_elements(w) NE 0 THEN BEGIN
105      norme = sqrt(u^2.+v^2.+w^2.)
106      ind = where(norme NE 0)
107      u(ind) = u(ind)/norme[ind]
108      v(ind) = v(ind)/norme[ind]
109      w(ind) = w(ind)/norme[ind]
110   ENDIF ELSE BEGIN
111      norme = sqrt(u^2.+v^2.)
112      ind = where(norme NE 0)
113      u(ind) = u(ind)/norme[ind]
114      v(ind) = v(ind)/norme[ind]
115   ENDELSE
116END
117PRO vecteur, composanteu, composantev, normevecteur, indice2d, reduitindice2d $
118             , CMREF = cmref, MISSING = missing, NORMEREF = normeref $
119             , VECTCOLOR = vectcolor, VECTTHICK = vectthick, VECTREFPOS = vectrefpos $
120             , VECTREFFORMAT = vectrefformat, NOVECTREF = novectref, _extra = extra
121@common
122   tempsun = systime(1)         ; pour key_performance
123;
124;
125   taille = size(composanteu)
126   nx = taille[1]
127   ny = taille[2]
128   if n_elements(reduitindice2d) EQ 0 then reduitindice2d = lindgen(nx, ny)
129   zu = composanteu
130   zv = composantev
131   norme = normevecteur
132   taille = size(indice2d)
133   nxgd = taille[1]
134   nygd = taille[2]
135;
136   msk = replicate(1, nx, ny)
137   if keyword_set(missing) then terre = where(abs(zu) GE missing/10) ELSE terre = -1
138   if terre[0] NE -1  then BEGIN
139      msk[terre] = 0
140      zu[terre] = 0
141      zv[terre] = 0
142      norme[terre] = 0
143   ENDIF
144;
145; Etape 1:
146;
147; etant donne la direction et le sens que le vecteur a sur la
148; sphere, il faut se debrouiller pour determiner cette direction et le
149; sens qu'aura le vecteur sur l''ecran ou la feuille une fois qu''il
150; aura ete projete.
151;
152; En theorie: sur la sphere, un vecteur en un point donne a pour
153; direction la tangente au cercle qui passe par le centre de la terre
154; et par le vecteur. Donc trouver la direction une fois la projection
155; faite ds le plan 2d, c''est trouver la tangente a la courbe
156; representant la projection du cercle sur le plan 2d au point
157; representant la projection du point de depart de la shere sur le
158; plan 2d!!!
159;
160; En pratique on ne connait pas la definition de la courbe que donne
161; la projection d''un cercle alors trouver sa tangente en un point...
162;
163; Ce que l''on fait:
164; Ds un repere cartesien 3d,
165;       a) on trouve les coordonnees du point T (debut de la fleche)
166;       situe sur la shere.
167;       b) pour chaque point T on determine les directions locales
168;       definies par la grille en ce point et auxquelles se rapportent
169;       les coordonnes (u,v) du vecteur. Ces directions locales sont
170;       definies par les gradiants des glam et gphi. Une fois ces
171;       directions obtenues, on les considere comme orthogonales et en
172;       les normant on construit un repere orthonormal (nu,nv) auquel se
173;       rapporte les coordonnes (u,v) du vecteur. Ds le repere
174;       cartesien 3d de depart, le vecteur est definit par:
175;       V=u*nu+v*nv (ou V, nu et nv sont des vecteurs 3d et u et v des
176;       scalaires)
177;       c) pour approximer la tangente au cercle par la corde definie
178;       par le debut et la fin de la fleche, on va normaliser V puis
179;       le diviser par 100.
180;       d) ceci nous permet de determiner les coordonnees ds le repere
181;       cartesien 3d des extremites de la corde, on les passe en
182;       coordonnes sphereriques de facon a recuperer les positions en
183;       latitude longitude de ces points sur la sphere.
184;       e) on passe les coordonnees de ces points en coordonnees
185;       normalise puis en corrdonnes polaire de facon a trouver
186;       l''angle et la direction qu''ils determinent sur le dessin...
187;
188;
189; etape 1, a)
190;
191;
192; coordonnes du point T (debut de la fleche) en coordonnes sheriques
193   glam = glamt[indice2d[reduitindice2d]]
194   gphi = gphit[indice2d[reduitindice2d]]
195;
196; coordonnes du point T (debut de la fleche) dans le repere cartesien
197; on utilise comme shere, une shere de rayon 1.
198;
199   radius = replicate(1,nx*ny)
200   coord_sphe = transpose([ [glam[*]], [gphi[*]], [radius[*]] ])
201   r = cv_coord(from_sphere=coord_sphe,/to_rect,/degrees)
202;
203   x0 = reform(r(0, *), nx, ny)
204   y0 = reform(r(1, *), nx, ny)
205   z0 = reform(r(2, *), nx, ny)
206;
207; etape 1, b)
208;
209; Construction du vecteur nu (resp. nv), vecteur norme porte par
210; l''axe des points u(i,j) et u(i-1,j) (resp v(i,j) et v(i,j-1))
211; qui definissent pour chaque point sur la shere les directions locales
212; associee a u et v. ces vecteurs definissent un repere orthonorme
213; local.
214; ces vecteurs sont construits dans un repere cartesien (cv_coord)
215; on a choisit un rayon de la terre unite (unit).
216;
217; definition de nu
218   radius = replicate(1,nxgd*nygd)
219   coord_sphe = transpose([ [(glamu[indice2d])[*]], [(gphiu[indice2d])[*]], [radius(*)] ])
220   r = cv_coord(from_sphere=coord_sphe,/to_rect,/degrees)
221; coordonnes de points de la grille u en cartesien
222   ux = reform(r(0, *), nxgd, nygd)
223   uy = reform(r(1, *), nxgd, nygd)
224   uz = reform(r(2, *), nxgd, nygd)
225; calcul de nu
226   nux = ux-shift(ux, 1, 0)
227   nuy = uy-shift(uy, 1, 0)
228   nuz = uz-shift(uz, 1, 0)
229; conditions aux limites
230   if NOT keyword_set(key_periodique) OR nxgd NE jpi then begin
231      nux[0, *] = nux[1, *]
232      nuy[0, *] = nuy[1, *]
233      nuz[0, *] = nuz[1, *]
234   ENDIF
235; reduction de la grille
236   nux = nux[reduitindice2d]
237   nuy = nuy[reduitindice2d]
238   nuz = nuz[reduitindice2d]
239; definition de nv
240   coord_sphe = transpose([ [(glamv[indice2d])[*]], [(gphiv[indice2d])[*]], [radius(*)] ])
241   r = cv_coord(from_sphere=coord_sphe,/to_rect,/degrees)
242; coordonnes de points de la grille v en cartesien
243   vx = reform(r(0, *), nxgd, nygd)
244   vy = reform(r(1, *), nxgd, nygd)
245   vz = reform(r(2, *), nxgd, nygd)
246; calcul de nv
247   nvx = vx-shift(vx, 0, 1)
248   nvy = vy-shift(vy, 0, 1)
249   nvz = vz-shift(vz, 0, 1)
250; conditions aux limites
251   nvx[*, 0] = nvx[*, 1]
252   nvy[*, 0] = nvy[*, 1]
253   nvz[*, 0] = nvz[*, 1]
254; reduction de la grille
255   nvx = nvx[reduitindice2d]
256   nvy = nvy[reduitindice2d]
257   nvz = nvz[reduitindice2d]
258;
259; normalisation
260;
261   normalise, nux, nuy, nuz
262   normalise, nvx, nvy, nvz
263;
264; etape 1, c)
265;
266; coordonnes du vecteur V ds le repere cartesion
267;
268   direcx = zu*nux + zv*nvx
269   direcy = zu*nuy + zv*nvy
270   direcz = zu*nuz + zv*nvz
271; normalisation du vecteur v
272   normalise, direcx, direcy, direcz
273; on divise par 100.
274   direcx = direcx/100.
275   direcy = direcy/100.
276   direcz = direcz/100.
277;
278; etape 1, d)
279; coordonnees de la pointe de la fleche dans le repere cartesien
280
281   x1 = x0 + direcx
282   y1 = y0 + direcy
283   z1 = z0 + direcz
284
285; coordonnees de la pointe en spherique
286
287   coord_rect = transpose([ [x1(*)], [y1(*)], [z1(*)] ])
288   r = cv_coord(from_rect=coord_rect,/to_sphere,/degrees)
289   glam1 = reform(r(0, *), nx, ny)
290   gphi1 = reform(r(1, *), nx, ny)
291
292;
293; modif des glam tout se passe bien au niveau de la ligne de
294; changement de date...attention, il ne faut pas couper les fleches
295; qui sortent de la fenetre!
296; test: si il sort du cadre mais qu''avec un +/- 360 il y rentre on le
297; modifie...
298;
299   ind = where(glam1 LT !x.range[0] AND glam1+360. LE !x.range[1])
300   if ind[0] NE -1 then glam1(ind) = glam1(ind)+360.
301   ind = where(glam1 GT !x.range[1] AND glam1-360. GE !x.range[0])
302   if ind[0] NE -1 then glam1(ind) = glam1(ind)-360.
303
304   ind = where(glam LT !x.range[0] AND glam+360. LE !x.range[1])
305   if ind[0] NE -1 then glam(ind) = glam(ind)+360.
306   ind = where(glam  GT !x.range[1] AND glam-360. GE !x.range[0])
307   if ind[0] NE -1 then glam(ind) = glam(ind)-360.
308;
309;
310; etape 1, e)
311;
312   r = convert_coord(glam,gphi,/data,/to_normal)
313   x0 = r(0, *)                 ; coordonnes normales du debut de la fleche
314   y0 = r(1, *)                 ;
315   
316   r = convert_coord(glam1,gphi1,/data,/to_normal)
317   x1 = r(0, *)                 ; coordonnes normales de la fin de la fleche (avant scaling)
318   y1 = r(1, *)                 ;
319;
320; tests pour eviter que des fleches soient dessineees hors du domaine
321;
322   out = where(x0 LT !p.position[0] OR x0 GT !p.position[2]  $
323               OR y0 LT !p.position[1] OR y0 GT !p.position[3])
324   if out[0] NE -1 THEN x0[out] = !values.f_nan
325;
326; suivant les projections, il peu y a voir des points a nan qd on
327; passe en coordonnes normales. on supprime ces points.
328;
329   nan = finite(x0*y0*x1*y1)
330   number = where(nan EQ 1)
331   x0 = x0[number] & x1 = x1[number]
332   y0 = y0[number] & y1 = y1[number]
333   msk = msk[number]
334   norme = norme[number]
335;
336; on definit le vecteur direction dans le repere normalise
337;
338   dirx = x1-x0
339   diry = y1-y0
340;
341; on passe en polaire pour recuperer l''angle qui etait le but de
342; toute la partie 1!!!
343;
344
345   dirpol = cv_coord(from_rect = transpose([ [dirx[*]], [diry[*]] ]), /to_polar)
346   dirpol = msk*dirpol[0, *]
347;
348; 2eme etape....
349;
350; maintenant on s''occupe de la norme...
351;
352; Mise a l''echelle automatique
353;
354   if NOT keyword_set(cmref) then BEGIN
355      sizexfeuille = petitfeuille*key_portrait+grandfeuille*(1-key_portrait)
356      sizexfeuille = 10.*sizexfeuille
357      cmref = 5 > floor(sizexfeuille/10.) < 15
358      cmref = cmref/10.
359   ENDIF
360   if NOT keyword_set(normeref) then BEGIN
361      value = max(norme)
362      puissance10 = 10.^floor(alog10(value))
363      normeref = puissance10*floor(value/puissance10)
364   endif
365   cm = 1.*normeref/cmref
366;
367; on modifie le tableau norme de facon a ce que un element qui a la
368; valeur cm soit represente par un trait de longueur 1cm sur le
369; papier.
370; norme contient la norme des vecteur que l''on veut dessiner
371;
372   norme = 1/(1.*cm)*norme*cv_cm2normal(dirpol)
373;
374;
375; 3eme etape....
376; maintenant qu''on a l''angle et la norme, et bien on recupere les
377; coordonnes en rectangulaire et on dessine les fleches.
378;
379   r = cv_coord(from_polar = transpose([ [dirpol[*]], [norme[*]] ]), /to_rect)
380   composantex = r(0, *)
381   composantey = r(1, *)
382;
383   x1 = x0+composantex
384   y1 = y0+composantey
385;
386; c''est parti pour le trace !
387;
388   if NOT KEYWORD_SET(vectcolor) then vectcolor = 0
389
390   points = where(msk EQ 1)
391   IF points[0] NE -1 THEN arrow, x0(points), y0(points), x1(points), y1(points), /norm $
392    , hsize = -.2, COLOR = vectcolor, THICK = vectthick
393;
394;  Dessine une fleche en bas a droite de la figure en guise de legende
395;
396   if NOT keyword_set(novectref) then BEGIN
397      dx = cmref*cv_cm2normal(0) ; longuer du vecteur de reference en coordonnes normalisees.
398      if keyword_set(vectrefformat) then $
399       normelegende = strtrim(string(normeref, format = vectrefformat), 1)+' ' $
400      ELSE normelegende = strtrim(normeref, 1)+' '
401;
402      if keyword_set(vectrefpos) then begin
403         r = convert_coord(vectrefpos,/data, /to_normal)
404         x0 = r[0]
405         y0 = r[1]
406      ENDIF ELSE BEGIN
407         x0 = !x.window[1]-dx
408         r = convert_coord(!d.x_ch_size, !d.y_ch_size, /device, /to_normal)
409         dy = 3*r[1]*!p.charsize
410         y0 = !y.window[0]-dy
411      ENDELSE
412
413      arrow, x0, y0, x0+dx, y0, /norm, hsize = -.2, color = 0
414      xyouts, x0, y0, normelegende, /norm, align = 1, charsize = !p.charsize, color = 0
415
416   endif
417;
418;
419
420   if keyword_set(key_performance) NE 0 THEN print, 'temps vecteur', systime(1)-tempsun
421;------------------------------------------------------------
422;------------------------------------------------------------
423   return
424END
425
426
427
428
Note: See TracBrowser for help on using the repository browser.