source: trunk/SRC/ToBeReviewed/PLOTS/VECTEUR/vecteur.pro @ 325

Last change on this file since 325 was 325, checked in by pinsard, 17 years ago

modification of some headers (+some corrections) to prepare usage of the new idldoc

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 14.7 KB
RevLine 
[157]1;+
[231]2;
[226]3; @file_comments
4;
[157]5; @categories
6;
[325]7; @param angle
[226]8;
[157]9; @returns
[226]10;
[157]11; @restrictions
[226]12;
[157]13; @examples
14;
15; @history
16;
17; @version
18; $Id$
[325]19;
[157]20;-
[142]21FUNCTION cv_cm2normal, angle
[2]22;
[163]23; Give the length in normal coordinates of a trait oriented of an angle
[142]24; by rapport at the x axis and which must do 1 cm on the drawing.
25; Angle can be an array.
[2]26;
27;
[226]28;
[114]29  compile_opt idl2, strictarrsubs
30;
[2]31@common
[163]32; What is the length in normal coordinates of a trait which will do 1 cm
[142]33; on the paper an which is parallel to x?
[41]34  mipgsz = min(page_size, max = mapgsz)
35   sizexfeuille = mipgsz*key_portrait+mapgsz*(1-key_portrait)
36   sizeyfeuille = mapgsz*key_portrait+mipgsz*(1-key_portrait)
[2]37   cm_en_normal = 1./sizexfeuille
38;
[163]39; If the aspect rapport of the window is not equal to 1, the length in
[142]40; normalized coordinates of  a trait of 1 cm vary following the polar
41; angle of this trait.
[2]42;
43   aspect = sizexfeuille/sizeyfeuille
44   cm_en_normal = cm_en_normal*sqrt( 1 +(aspect^2-1)*sin(angle)^2 )
45;
46   return, cm_en_normal
47END
48;
[157]49;+
[231]50;
[226]51; @file_comments
52;
[157]53; @categories
[226]54;
[325]55; @param u
[157]56;
[325]57; @param v
[157]58;
[325]59; @param w
[157]60;
[226]61; @restrictions
[157]62;
63; @examples
64;
65; @history
66;
67; @version
68; $Id$
[325]69;
[157]70;-
[2]71PRO normalise, u, v, w
72;
[142]73; normalize the vector
[2]74;
[114]75;
76  compile_opt idl2, strictarrsubs
77;
[226]78   IF n_elements(w) NE 0 THEN BEGIN
[2]79      norme = sqrt(u^2.+v^2.+w^2.)
80      ind = where(norme NE 0)
[114]81      u[ind] = u[ind]/norme[ind]
82      v[ind] = v[ind]/norme[ind]
83      w[ind] = w[ind]/norme[ind]
[2]84   ENDIF ELSE BEGIN
85      norme = sqrt(u^2.+v^2.)
86      ind = where(norme NE 0)
[114]87      u[ind] = u[ind]/norme[ind]
88      v[ind] = v[ind]/norme[ind]
[226]89   ENDELSE
[2]90END
[232]91;
[142]92;+
93;
94; @file_comments
95; Trace vectors (even if they are on a deformed grid) on any projection.
96; In this way, all vectors have a comparable norme on the drawing (to be
97; clear, a vector which measure 1 cm measure it, no matter the projection
98; and is position on the sphere).
99;
[226]100; @categories
[157]101; Graphics
[226]102;
[325]103; @param composanteu {in}{required}
[226]104; It is the u component of the vector to be traced. This 2d array has the
[142]105; same dimension that reduitindice2d (see further)
[226]106;
[325]107; @param composantev {in}{required}
[226]108; It is the v component of the vector to be traced. This 2d array has the
[142]109; same dimension that reduitindice2d (see further)
[226]110;
[325]111; @param normevecteur
[157]112;
[325]113; @param indice2d {in}{required}
[226]114; It in an index allowing to to pass from an jpi or jpj array to the zoom
[142]115; on which we do the drawing
[226]116;
[325]117; @param reduitindice2d {in}{required}
[226]118; It is an index allowing to pass from an array defined by indice2d to the
119; array for which we really have vectors to be traced (to be clear, it is
[142]120; for example when we trace only one vector on two).
121;
[163]122; @keyword CMREF {default=between .5 and 1.5 cm}
[226]123; The length in cm that must measure the arrow normed normeref. By default,
[163]124; it is adjusted to other drawing and included between .5 and 1.5 cm.
[142]125;
126; @keyword MISSING
[226]127; The value of a missing value. Do not use this keyword. Fixed at 1e5 by
[142]128; ajoutvect.pro
[226]129;
130; @keyword NORMEREF
[142]131; The norme of the reference arrow.
132;
[163]133; @keyword VECTCOLOR {default=0}
[142]134; The color of the arrow. Black by default (color 0)
[226]135;
[163]136; @keyword VECTTHICK {default=1}
[226]137; The thick of the arrow.
[142]138;
139; @keyword VECTREFPOS
[226]140; Vector composed of 2 elements specifying the position on DATA coordinates
141; from the beginning of the reference vector. By default at the right bottom
[142]142; of the drawing.
143;
144; @keyword VECTREFFORMAT
145; The format to be used to specify the norme of the reference vector.
146;
147; @keyword NOVECTREF
148; To delete the display of the reference vector.
[226]149;
[142]150; @keyword _EXTRA
[231]151; Used to pass keywords
[142]152;
[226]153; @uses
[142]154; common.pro
155;
156; @history
[157]157;  Creation : 13/02/98 G. Roullet (grlod\@lodyc.jussieu.fr)
[142]158;  Modification : 14/01/99 realise la transformation
159;  spherique<->cartesien G. Roullet
160;                 12/03/99 verification de la routine G. Roullet
161;  8/11/1999:
[157]162;  G. Roullet et Sebastien Masson (smasson\@lodyc.jussieu.fr)
[142]163;  adaptation pour les zoom. reverification...traitement separe de la
164;  direction et de la norme des vecteurs. mots cles NORMEREF et CMREF.
165;
166; @version
[226]167; $Id$
[142]168;
169;-
[2]170PRO vecteur, composanteu, composantev, normevecteur, indice2d, reduitindice2d $
171             , CMREF = cmref, MISSING = missing, NORMEREF = normeref $
[325]172             , VECTCOLOR = vectcolor, VECTTHICK = vectthick $
173             , VECTREFPOS = vectrefpos $
174             , VECTREFFORMAT = vectrefformat, NOVECTREF = novectref $
175             , _EXTRA = extra
[114]176;
177  compile_opt idl2, strictarrsubs
178;
[2]179@common
[142]180   tempsun = systime(1)         ; For key_performance
[2]181;
182;
183   taille = size(composanteu)
184   nx = taille[1]
185   ny = taille[2]
186   if n_elements(reduitindice2d) EQ 0 then reduitindice2d = lindgen(nx, ny)
187   zu = composanteu
188   zv = composantev
189   norme = normevecteur
190   taille = size(indice2d)
191   nxgd = taille[1]
192   nygd = taille[2]
193;
194   msk = replicate(1, nx, ny)
195   if keyword_set(missing) then terre = where(abs(zu) GE missing/10) ELSE terre = -1
[226]196   if terre[0] NE -1  then BEGIN
[2]197      msk[terre] = 0
198      zu[terre] = 0
199      zv[terre] = 0
200      norme[terre] = 0
201   ENDIF
202;
[226]203; Stage 1:
[2]204;
[226]205; Given that the directions and the sense that the vector has on the sphere,
206; we have to try to determinate this direction and the sense that the vector
[142]207; will have on the screen once it will have been projected.
[2]208;
[226]209; In theory: on the sphere, a vector in a given point has for direction the
210; tangent at the circle passing by the center of the Earth and by the vector.
[142]211; So, find the direction once the projection is done, it is find the tangent
[226]212; to the curve representing the projection of the circle on the 2d plan at the
213; point representing the projection of the starting point of the sphere on the
[142]214; 2d plan.
[226]215;
216; In practice we do no know the definition of the curve given by the projection
[142]217; of a circle so find its tangente in a point...
[2]218;
[142]219; What we do:
220; In a 3d cartesian reference,
[226]221;       a) We find coordinates of the point T (starting of the arrow) situed
[142]222;       on the sphere.
223;       b) To each point T, we determine local directions defined by the grid
224;       on this point and on which coordinates (u,v) of the vector refer to.
225;       These local directions are defined by gradients of glam and gphi. Once
[226]226;       we have obtain these directions, we consider them like orthogonal and
[142]227;       by norming them, we build an orthonormal reference (nu,nv) on which
228;       coordinates (u,v) of the vector refer to. In the starting 3d cartesian
229;       reference, the vector is defined by:
230;       V=u*nu+v*nv
231;       (where V, nu and nv are 3d vectors and u and v are scalars).
232;       c) To approximate the tangente to the circle by the chord defined by
233;       the beginning and the ending of the arrow, we will normalize V, and
234;       then divide it by 100.
235;       d) This allows us to determine coordinates of extremities of the chord
236;       in the 3d cartesian reference. We pass them in spherical coordinates in
237;       order to recuperate latitude and longitude position of these points on
238;       the sphere.
239;       e) We pass coordinates of these points in normalized coordinates, then
240;       in polar coordinates in order to find the angle and the direction they
[226]241;       determine on the drawing.
[2]242;
243;
[142]244; Stage 1, a)
[2]245;
246;
[142]247; coordinates of the point T (beginning of the arrow) in spherical coordinates.
[2]248   glam = glamt[indice2d[reduitindice2d]]
249   gphi = gphit[indice2d[reduitindice2d]]
250;
[142]251; Coordinates of the point T (beginning of the arrow) in the cartesian reference.
252; For the sphere, we use a sphere with a radius of 1.
[2]253;
254   radius = replicate(1,nx*ny)
255   coord_sphe = transpose([ [glam[*]], [gphi[*]], [radius[*]] ])
256   r = cv_coord(from_sphere=coord_sphe,/to_rect,/degrees)
257;
[114]258   x0 = reform(r[0, *], nx, ny)
259   y0 = reform(r[1, *], nx, ny)
260   z0 = reform(r[2, *], nx, ny)
[2]261;
[142]262; Stage 1, b)
[2]263;
[142]264; Construction of a vector nu (resp. nv), vectr normed carried by the axis of
265; points u[i,j] and u[i-1,j] (resp v[i,j] and v[i,j-1]) which define, for each
266; point on the sphere, local directions associated with u and v. These vectors
[226]267; define a local orthonormal reference.
268; These vectors are built in a cartesian reference (cv_coord). We have choose a
[142]269; unity radius of the Earth (unit).
[2]270;
[142]271; definition of nu
[2]272   radius = replicate(1,nxgd*nygd)
[41]273   IF finite(glamu[0]*gphiu[0]) NE 0 THEN $
[114]274     coord_sphe = transpose([ [(glamu[indice2d])[*]], [(gphiu[indice2d])[*]], [radius[*]] ]) $
275   ELSE coord_sphe = transpose([ [(glamf[indice2d])[*]], [(gphit[indice2d])[*]], [radius[*]] ])
[2]276   r = cv_coord(from_sphere=coord_sphe,/to_rect,/degrees)
[142]277; coordinates of points of the grid u in cartesian.
[114]278   ux = reform(r[0, *], nxgd, nygd)
279   uy = reform(r[1, *], nxgd, nygd)
280   uz = reform(r[2, *], nxgd, nygd)
[226]281; calculation of nu
[2]282   nux = ux-shift(ux, 1, 0)
283   nuy = uy-shift(uy, 1, 0)
284   nuz = uz-shift(uz, 1, 0)
[142]285; conditions at extremities.
[41]286   if NOT keyword_set(key_periodic) OR nxgd NE jpi then begin
[2]287      nux[0, *] = nux[1, *]
288      nuy[0, *] = nuy[1, *]
289      nuz[0, *] = nuz[1, *]
290   ENDIF
[142]291; reduction of the grid
[2]292   nux = nux[reduitindice2d]
293   nuy = nuy[reduitindice2d]
294   nuz = nuz[reduitindice2d]
[142]295; definition of nv
[41]296   IF finite(glamv[0]*gphiv[0]) NE 0 THEN $
[114]297   coord_sphe = transpose([ [(glamv[indice2d])[*]], [(gphiv[indice2d])[*]], [radius[*]] ]) $
[226]298   ELSE coord_sphe = transpose([ [(glamt[indice2d])[*]], [(gphif[indice2d])[*]], [radius[*]] ])
[2]299   r = cv_coord(from_sphere=coord_sphe,/to_rect,/degrees)
[142]300; coordinates of points of the grid in cartesian.
[114]301   vx = reform(r[0, *], nxgd, nygd)
302   vy = reform(r[1, *], nxgd, nygd)
303   vz = reform(r[2, *], nxgd, nygd)
[226]304; calcul of nv
[2]305   nvx = vx-shift(vx, 0, 1)
306   nvy = vy-shift(vy, 0, 1)
307   nvz = vz-shift(vz, 0, 1)
[142]308; conditions at extremities
[2]309   nvx[*, 0] = nvx[*, 1]
310   nvy[*, 0] = nvy[*, 1]
311   nvz[*, 0] = nvz[*, 1]
[142]312; reduction of the grid
[2]313   nvx = nvx[reduitindice2d]
314   nvy = nvy[reduitindice2d]
315   nvz = nvz[reduitindice2d]
316;
[142]317; normalization
[2]318;
319   normalise, nux, nuy, nuz
320   normalise, nvx, nvy, nvz
321;
[142]322; Stage 1, c)
[2]323;
[142]324; coordinates of the vector V in the cartesian reference
[2]325;
326   direcx = zu*nux + zv*nvx
327   direcy = zu*nuy + zv*nvy
328   direcz = zu*nuz + zv*nvz
[142]329; normalization of the vector V
[2]330   normalise, direcx, direcy, direcz
[142]331; on divide by 100
[2]332   direcx = direcx/100.
333   direcy = direcy/100.
334   direcz = direcz/100.
335;
[292]336; Stage 1, d)
[142]337; coordinates of the point of the arrow in the cartesian reference.
[2]338
339   x1 = x0 + direcx
340   y1 = y0 + direcy
341   z1 = z0 + direcz
342
[142]343; coordinates of the point of the arrow in spherical coordinates.
[2]344
[114]345   coord_rect = transpose([ [x1[*]], [y1[*]], [z1[*]] ])
[2]346   r = cv_coord(from_rect=coord_rect,/to_sphere,/degrees)
[114]347   glam1 = reform(r[0, *], nx, ny)
348   gphi1 = reform(r[1, *], nx, ny)
[2]349
350;
[142]351; modification of glams. Everything take place at the level of the line
352; of changing of date... BEWARE, do not cut arrow which goes out of the
353; window!
354; test: If it goes out of the frame, but, thanks to +/- 360° it come in,
355; we modify it
[2]356;
357   ind = where(glam1 LT !x.range[0] AND glam1+360. LE !x.range[1])
[114]358   if ind[0] NE -1 then glam1[ind] = glam1[ind]+360.
[2]359   ind = where(glam1 GT !x.range[1] AND glam1-360. GE !x.range[0])
[114]360   if ind[0] NE -1 then glam1[ind] = glam1[ind]-360.
[2]361
362   ind = where(glam LT !x.range[0] AND glam+360. LE !x.range[1])
[114]363   if ind[0] NE -1 then glam[ind] = glam[ind]+360.
[2]364   ind = where(glam  GT !x.range[1] AND glam-360. GE !x.range[0])
[114]365   if ind[0] NE -1 then glam[ind] = glam[ind]-360.
[2]366;
367;
[142]368; Stage 1, e)
[2]369;
[226]370   r = convert_coord(glam,gphi,/data,/to_normal)
[142]371   x0 = r[0, *]                 ; normal coordinates of the beginning of the array.
[226]372   y0 = r[1, *]                 ;
373
374   r = convert_coord(glam1,gphi1,/data,/to_normal)
[142]375   x1 = r[0, *]                 ; normal coordinates of the ending of the array (Before scaling).
[226]376   y1 = r[1, *]                 ;
[2]377;
[142]378; tests to avoid that arrows be drawing out of the domain.
[2]379;
380   out = where(x0 LT !p.position[0] OR x0 GT !p.position[2]  $
381               OR y0 LT !p.position[1] OR y0 GT !p.position[3])
382   if out[0] NE -1 THEN x0[out] = !values.f_nan
383;
[226]384; Following projections, there may are points at NaN when we pass in normal coordinates.
[142]385; We delete these points.
[2]386;
387   nan = finite(x0*y0*x1*y1)
388   number = where(nan EQ 1)
389   x0 = x0[number] & x1 = x1[number]
390   y0 = y0[number] & y1 = y1[number]
391   msk = msk[number]
392   norme = norme[number]
393;
[142]394; We define the vector direction in the normalize reference.
[2]395;
396   dirx = x1-x0
397   diry = y1-y0
398;
[142]399;We pass in polar coordinates to recuperate the angle which wasb the goal of all the first stage!!!
[2]400;
401
402   dirpol = cv_coord(from_rect = transpose([ [dirx[*]], [diry[*]] ]), /to_polar)
403   dirpol = msk*dirpol[0, *]
404;
[142]405; Stage 2
[2]406;
[142]407; Now we take care of the norme...
[2]408;
[226]409; Automatic putting at the scale
[2]410;
[226]411   if NOT keyword_set(cmref) then BEGIN
[41]412      mipgsz = min(page_size, max = mapgsz)
413      sizexfeuille = mipgsz*key_portrait+mapgsz*(1-key_portrait)
[2]414      sizexfeuille = 10.*sizexfeuille
415      cmref = 5 > floor(sizexfeuille/10.) < 15
416      cmref = cmref/10.
417   ENDIF
418   if NOT keyword_set(normeref) then BEGIN
419      value = max(norme)
420      puissance10 = 10.^floor(alog10(value))
421      normeref = puissance10*floor(value/puissance10)
422   endif
423   cm = 1.*normeref/cmref
424;
[226]425; We modify the array norme to an element having the value cm be represented
426; by a trait of lenght 1 cm on the paper. Norme contain the norme of vectors
[142]427; we want to draw.
[2]428;
429   norme = 1/(1.*cm)*norme*cv_cm2normal(dirpol)
430;
431;
[142]432; Stage 3
[226]433; Now that we have the angle and the norme, we recuperate coordinates in
[142]434; rectangular and we draw arrows.
[2]435;
436   r = cv_coord(from_polar = transpose([ [dirpol[*]], [norme[*]] ]), /to_rect)
[114]437   composantex = r[0, *]
438   composantey = r[1, *]
[2]439;
440   x1 = x0+composantex
441   y1 = y0+composantey
442;
[142]443; Drawing
[2]444;
445   if NOT KEYWORD_SET(vectcolor) then vectcolor = 0
446
447   points = where(msk EQ 1)
[114]448   IF points[0] NE -1 THEN arrow, x0[points], y0[points], x1[points], y1[points], /norm $
[2]449    , hsize = -.2, COLOR = vectcolor, THICK = vectthick
450;
[142]451;  Draw an arrow at the right bottom of the drawing as a caption.
[2]452;
453   if NOT keyword_set(novectref) then BEGIN
[297]454      dx = cmref*cv_cm2normal(0) ; Length of the vector of reference in normalized coordinates.
[2]455      if keyword_set(vectrefformat) then $
456       normelegende = strtrim(string(normeref, format = vectrefformat), 1)+' ' $
457      ELSE normelegende = strtrim(normeref, 1)+' '
458;
459      if keyword_set(vectrefpos) then begin
460         r = convert_coord(vectrefpos,/data, /to_normal)
461         x0 = r[0]
462         y0 = r[1]
463      ENDIF ELSE BEGIN
464         x0 = !x.window[1]-dx
465         r = convert_coord(!d.x_ch_size, !d.y_ch_size, /device, /to_normal)
466         dy = 3*r[1]*!p.charsize
467         y0 = !y.window[0]-dy
468      ENDELSE
469
470      arrow, x0, y0, x0+dx, y0, /norm, hsize = -.2, color = 0
471      xyouts, x0, y0, normelegende, /norm, align = 1, charsize = !p.charsize, color = 0
472
473   endif
474;
475;
476
[226]477   if keyword_set(key_performance) NE 0 THEN print, 'temps vecteur', systime(1)-tempsun
[2]478;------------------------------------------------------------
479;------------------------------------------------------------
480   return
[226]481END
[2]482
483
484
485
Note: See TracBrowser for help on using the repository browser.