; ancillary MAP* procedure, set limits (uv_box and ll_box) for maps. pro gdl_set_map_limits, myMap, limits compile_opt idl2, hidden ; map_limits may have 4 or 8 elements. if n_elements(limits) ne 8 and n_elements(limits) ne 4 then message, 'Map limit must have 4 or 8 points' map_limits=limits ; do not change limits xmin=-1d & ymin=-1d & xmax=1d & ymax=1d if n_elements(map_limits) eq 4 then begin ; filter map_limits to [-180,+180] in both directions however keeping orientation lonmin=map_limits[1] & lonmax=map_limits[3] & latmin=map_limits[0] & latmax=map_limits[2] ; longitudes: beautify map_adjlon,lonmin map_adjlon,lonmax if (lonmin gt lonmax) then begin temp=lonmin & lonmin=lonmax & lonmax=temp & end if (lonmin eq lonmax) then begin lonmin=-180 & lonmax=180 & endif ; latitudes: beautify latmin = -90 > latmin < 90 latmax = -90 > latmax < 90 if (latmin gt latmax) then begin temp=latmin & latmin=latmax & latmax=temp & end if (latmin eq latmax) then begin latmin=-90 & latmax=90 & endif map_limits=[latmin, lonmin, latmax, lonmax] if ( map_limits[0] eq map_limits[2]) then message,/informational,"GDL_SET_MAP_LIMITS: Warning, MAP limits are invalid." ; range of values lonrange = lonmax - lonmin latrange = latmax - latmin ; is there another way (PROJ) to get ranges except brute force on a grid of possible points? ; epsilon useful as projections are not precise (see #define EPS in PROJ c files: apparently < 1e-6) epsx = 1d-6*ABS(lonrange) epsy = 1d-6*ABS(latrange) n_lons = 90 lons = [ lonmin + epsx, DINDGEN(n_lons)*(lonrange/(n_lons-1d)) + lonmin, lonmax - epsx] & n_lons += 2 n_lats = 45 lats = [latmin + epsy, DINDGEN(n_lats)*(latrange/(n_lats-1d)) + latmin, latmax - epsy] & n_lats += 2 if ((latmin lt 0) && (latmax gt 0)) then begin lats = [lats, -epsy, epsy] & n_lats += 2 & end lons = reform(rebin(lons, n_lons, n_lats), 1, n_lons*n_lats) lats = reform(rebin(transpose(lats), n_lons, n_lats), 1, n_lons*n_lats) tmp = [temporary(lons), temporary(lats)] xy = map_proj_forward(tmp, MAP=myMap) ; Default if no points are valid is just the map_limits. good = WHERE(FINITE(xy[0,*]) and FINITE(xy[1,*]), ngood) if (ngood gt 0) then begin xy = xy[*, good] lonlat = tmp[*, good] ; further check: are backprojected good points really close to original point? tmp = MAP_PROJ_INVERSE(xy, MAP=myMap) bad = WHERE(~FINITE(tmp[0,*]) or ~FINITE(tmp[1,*]), nbad) if (nbad gt 0) then tmp[*, bad] = -9999 diff = ABS(lonlat - tmp) diff[0,*] = diff[0,*] mod 360 ; Ignore 360 degre differences for longitude. w = where(diff[0,*] gt 359.99, count) & if count gt 0 then diff[0,w] = 0 w = where((abs(tmp[0,*]) le 720) and (abs(tmp[1,*]) le 90) and (total(diff,1) lt 1d), count) if (count gt 0) then begin ; Only those good during forward and inverse projection. lonlat = lonlat[*, w] xy = xy[*,w] endif xmin = min(xy[0,*], max=xmax) ymin = min(xy[1,*], max=ymax) lonmin = min(lonlat[0,*], max=lonmax) latmin = min(lonlat[1,*], max=latmax) endif endif else begin ; easy: convert and pray. ; 8 point limit as in [latLeft,lonLeft, latTop, lonTop, LatRight, lonRight, LatBottom, LonBottom] ; lons=map_limits[[1,3,5,7]] & lats=map_limits[[0,2,4,6]] xy=map_proj_forward(lons,lats,map=myMap) good = WHERE(FINITE(xy[0,*]) and FINITE(xy[1,*]), ngood) if (ngood ge 2 ) then begin xmin = min(xy[0,*], max=xmax) ymin = min(xy[1,*], max=ymax) lonmin = min(lons, max=lonmax) latmin = min(lats, max=latmax) endif else message, 'Unmappable limit point(s) in LIMIT keyword' endelse ; Fill in map structure. myMap.ll_box = [latmin, lonmin, latmax, lonmax] myMap.uv_box = [xmin, ymin, xmax, ymax] end