source: trunk/Interpolation/map_npoints.pro @ 59

Last change on this file since 59 was 59, checked in by pinsard, 18 years ago

upgrade of Interpolation according to cerbere.lodyc.jussieu.fr: /usr/home/smasson/SAXO_RD/

  • Property svn:executable set to *
File size: 6.6 KB
Line 
1;+
2; NAME:
3;       Map_nPoints
4;
5; PURPOSE:
6;       Return the distance in meter between all np0 points P0 and all
7;       np1 points P1 on a sphere. If keyword /TWO_BY_TWO is given then
8;       returns the distances between number n of P0 points and number
9;       n of P1 points (in that case, np0 and np1 must be equal).
10;       Same as map_2points with the meter parameter but for n points
11;       without do loop.
12;
13; CATEGORY:
14;       Maps.
15;
16; CALLING SEQUENCE:
17;       Result = Map_nPoints(lon0, lat0, lon1, lat1)
18;
19; INPUTS:
20;       Lon0, Lat0 = np0 elements vector. longitudes and latitudes of
21;       np0 points P0
22;       Lon1, Lat1 = np1 elements vector. longitude and latitude of
23;       np1 points P1
24;
25; KEYWORD PARAMETERS:
26;
27;   AZIMUTH: A named variable that will receive the azimuth of the great
28;       circle  connecting the two points, P0 to P1
29;   /MIDDLE: to get the longitude/latitude of the middle point betwen P0 and P1.
30;   RADIANS = if set, inputs and angular outputs are in radians, otherwise
31;       degrees.
32;   RADIUS: If given, return the distance between the two points
33;       calculated using the given radius.
34;       Default value is the earth radius : 6378206.4d0
35;   TWO_BY_TWO:If given,then Map_nPoints returns the distances between
36;       number n of P0 points and number n of P1 points (in that case,
37;       np0 and np1 must be equal).
38;
39; OUTPUTS:
40;       An (np0,np1) array giving the distance in meter between np0
41;       points P0 and np1 points P1. Element (i,j) of the ouput is the
42;       distance between element P0[i] and P1[j].
43;       If keyword /TWO_BY_TWO is given then Map_nPoints returns
44;       an np-element vector giving the distance in meter between P0[i]
45;       and P1[i] (in that case, we have np0 = np1 = np)
46;       if /MIDDLE see this keyword.
47;
48; EXAMPLES:
49;       IDL> print, $
50;       map_npoints([-105.15,1],[40.02,1],[-0.07,100,50],[51.30,20,0])
51;              7551369.3       5600334.8
52;              12864354.       10921254.
53;              14919237.       5455558.8
54;       
55;       IDL> lon0 = [-10, 20, 100]
56;       IDL> lat0 = [0, -10, 45]
57;       IDL> lon1 = [10, 60, 280]
58;       IDL> lat1 = [0, 10, 45]
59;       IDL> dist = map_npoints(lon0, lat0, lon1, lat1, azimuth = azi)
60;       IDL> help, dist, azi
61;       DIST            DOUBLE    = Array[3, 3]
62;       AZI             DOUBLE    = Array[3, 3]
63;       IDL> print, dist[4*lindgen(3)], azi[4*lindgen(3)]
64;              2226414.0       4957944.5       10018863.
65;              90.000000       64.494450   4.9615627e-15
66;       IDL> dist = map_npoints(lon0, lat0, lon1, lat1, azimuth = azi, /two_by_two)
67;       IDL> help, dist, azi
68;       DIST            DOUBLE    = Array[3]
69;       AZI             DOUBLE    = Array[3]
70;       IDL> print, dist, azi
71;              2226414.0       4957944.5       10018863.
72;              90.000000       64.494450   4.9615627e-15
73;       IDL> print, map_2points(lon0[0], lat0[0], lon1[0], lat1[0])
74;              20.000000       90.000000
75;       IDL> print, map_npoints(lon0[0], lat0[0], lon1[0], lat1[0], azi=azi)/6378206.4d0 / !dtor, azi
76;              20.000000
77;              90.000000
78;
79;       IDL> lon0 = [-10, 20, 100]
80;       IDL> lat0 = [0, -10, 45]
81;       IDL> lon1 = [10, 60, 280]
82;       IDL> lat1 = [0, 10, 45]
83;       IDL> mid = map_npoints(lon0, lat0, lon1, lat1, /middle, /two_by_two)
84;       IDL> print, reform(mid[0,*]), reform(mid[1,*])
85;              0.0000000       40.000000       190.00000
86;              0.0000000  -1.5902773e-15       90.000000
87;       IDL> print, (map_2points(lon0[0], lat0[0], lon1[0], lat1[0], npath = 3))[*, 1]
88;              0.0000000       0.0000000
89;       IDL> print, (map_2points(lon0[1], lat0[1], lon1[1], lat1[1], npath = 3))[*, 1]
90;              40.000000  -1.5902773e-15
91;       IDL> print, (map_2points(lon0[2], lat0[2], lon1[2], lat1[2], npath = 3))[*, 1]
92;              190.00000       90.000000
93;       
94; MODIFICATION HISTORY:
95;       Based on the IDL function map_2points.pro,v 1.6 2001/01/15
96;       Sebastien Masson (smasson@lodyc.jussieu.fr)
97;                  October 2003
98;-
99Function Map_npoints, lon0, lat0, lon1, lat1, azimuth = azimuth $
100  ,  RADIANS = radians, RADIUS = radius, MIDDLE = middle, TWO_BY_TWO = two_by_two
101
102  COMPILE_OPT idl2
103  ON_ERROR, 2                   ; return to caller
104
105  IF (N_PARAMS() LT 4) THEN $
106    MESSAGE, 'Incorrect number of arguments.'
107
108  np0 = n_elements(lon0)
109  IF n_elements(lat0) NE np0 THEN $
110    MESSAGE, 'lon0 and lat0 must have the same number of elements'
111  np1 = n_elements(lon1)
112  IF n_elements(lat1) NE np1 THEN $
113    MESSAGE, 'lon1 and lat1 must have the same number of elements'
114  if keyword_set(two_by_two) AND np0 NE np1 then $
115    MESSAGE, 'When using two_by_two keyword, P0 and P1 must have the same number of elements'
116
117  mx = MAX(ABS([lat0, lat1]))
118  pi2 = !dpi/2
119  IF (mx GT (KEYWORD_SET(radians) ? pi2 : 90)) THEN $
120    MESSAGE, 'Value of Latitude is out of allowed range.'
121
122  k = KEYWORD_SET(radians) ? 1.0d0 : !dpi/180.0
123;Earth equatorial radius, meters, Clarke 1866 ellipsoid
124  r_sphere =  n_elements(RADIUS) NE 0 ? RADIUS : 6378206.4d0
125;
126  coslt1 = cos(k*lat1[*])
127  sinlt1 = sin(k*lat1[*])
128  coslt0 = cos(k*lat0[*])
129  sinlt0 = sin(k*lat0[*])
130;
131  IF np0 EQ np1 AND np1 EQ 1 THEN two_by_two = 1
132;
133  if NOT keyword_set(two_by_two) THEN BEGIN
134    coslt1 = replicate(1.0d0, np0)#temporary(coslt1)
135    sinlt1 = replicate(1.0d0, np0)#temporary(sinlt1)
136    coslt0 = temporary(coslt0)#replicate(1.0d0, np1)
137    sinlt0 = temporary(sinlt0)#replicate(1.0d0, np1)
138  ENDIF
139;
140  if keyword_set(two_by_two) THEN BEGIN
141    cosl0l1 = cos(k*(lon1[*]-lon0[*]))
142    sinl0l1 = sin(k*(lon1[*]-lon0[*]))
143  ENDIF ELSE BEGIN
144    cosl0l1 = cos(k*(replicate(1.0d0, np0)#lon1[*]-lon0[*]#replicate(1.0d0, np1)))
145    sinl0l1 = sin(k*(replicate(1.0d0, np0)#lon1[*]-lon0[*]#replicate(1.0d0, np1)))
146  ENDELSE
147
148  cosc = sinlt0 * sinlt1 + coslt0 * coslt1 * cosl0l1 ;Cos of angle between pnts
149; Avoid roundoff problems by clamping cosine range to [-1,1].
150  cosc = -1.0d0 > cosc < 1.0d0
151;
152  if arg_present(azimuth) OR keyword_set(middle) then begin
153    sinc = sqrt(1.0d0 - cosc*cosc)
154    bad = where(abs(sinc) le 1.0e-7)
155    IF bad[0] NE -1 THEN sinc[bad] = 1
156    cosaz = (coslt0 * sinlt1 - sinlt0*coslt1*cosl0l1) / sinc
157    sinaz = sinl0l1*coslt1/sinc
158    IF bad[0] NE -1 THEN BEGIN
159      sinc[bad] = 0.0d0
160      sinaz[bad] = 0.0d0
161      cosaz[bad] = 1.0d0
162    ENDIF
163  ENDIF
164;
165  IF keyword_set(middle) then BEGIN
166
167    s0 = 0.5d0 * acos(cosc)
168 ;
169    coss = cos(s0)
170    sins = sin(s0)
171;   
172    lats = asin(sinlt0 * coss + coslt0 * sins * cosaz) / k
173    lons = atan(sins * sinaz, coslt0 * coss - sinlt0 * sins * cosaz) / k
174;
175    if keyword_set(two_by_two) THEN BEGIN
176      return, transpose([[lon0[*] + lons], [lats]])
177    ENDIF ELSE BEGIN
178      return, [ [[lon0[*]#replicate(1.0d0, np1) + lons]], [[lats]] ]
179    ENDELSE
180;
181  ENDIF
182;
183  if arg_present(azimuth) then begin
184    azimuth = atan(sinaz, cosaz)
185    IF k NE 1.0d0 THEN azimuth = temporary(azimuth) / k
186   ENDIF
187 return, acos(cosc) * r_sphere
188;
189end
Note: See TracBrowser for help on using the repository browser.