source: trunk/SRC/Interpolation/map_npoints.pro @ 325

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

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

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