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

Last change on this file since 177 was 163, checked in by navarro, 18 years ago

header improvements : type of parameters and keywords, default values, spell checking + idldoc assistant (IDL online_help)

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