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