function [X,Y,vals,labI]=mp_azim(optn,varargin); % MP_AZIM Azimuthal projections % This function should not be used directly; instead it is % is accessed by various high-level functions named M_*. % Rich Pawlowicz (rich@ocgy.ubc.ca) 2/Apr/1997 % % 13/5/97 - Added satellite perspective % 1/6/97 - Another stab at removing some /0 errors. % 10/8/00 - Rotation for projections? % % This software is provided "as is" without warranty of any kind. But % it's mine, so you can't sell it. % % Mathematical formulas for the projections and their inverses are taken from % % Snyder, John P., Map Projections used by the US Geological Survey, % Geol. Surv. Bull. 1532, 2nd Edition, USGPO, Washington D.C., 1983. % % These are azimuthal projections, best suited for circular areas. The % stereographic is commonlu used for polar regions. % Stereographic - conformal % Orthographic - neither conformal nor equal-area, but looks like globe % with viewpoint at infinity. % Az Equal-area - equal area, but not conformal (by Lambert) % Az Equidistant - distance and direction from center are true % Gnomonic - all great circles are straight lines. % Satellite - a perspective view from a finite distance global MAP_PROJECTION MAP_VAR_LIST name={'Stereographic','Orthographic ','Azimuthal Equal-area','Azimuthal Equidistant','Gnomonic','Satellite'}; pi180=pi/180; switch optn, case 'name', X=name; case {'usage','set'} X=char({[' ''' varargin{1} ''''],... ' <,''lon'',center_long>',... ' <,''lat'', center_lat>',... ' <,''rad'', ( degrees | [longitude latitude] ) | ''alt'', alt_frac >',... ' <,''rec'', ( ''on'' | ''off'' | ''circle'' )>',... ' <,''rot'', degrees CCW>'}); case 'get', X=char([' Projection: ' MAP_PROJECTION.name ' (function: ' MAP_PROJECTION.routine ')'],... [' center longitude: ' num2str(MAP_VAR_LIST.ulong) ],... [' center latitude: ' num2str(MAP_VAR_LIST.ulat) ],... [' radius/altitude : ' num2str(MAP_VAR_LIST.uradius) ],... [' Rectangular border: ' MAP_VAR_LIST.rectbox ],... [' Rotation angle: ' num2str(MAP_VAR_LIST.rotang) ]); case 'initialize', MAP_VAR_LIST=[]; MAP_PROJECTION.name=varargin{1}; MAP_VAR_LIST.ulong=0; MAP_VAR_LIST.ulat=60; MAP_VAR_LIST.rectbox='circle'; MAP_VAR_LIST.uradius=90; MAP_VAR_LIST.rotang=0; k=2; while k0 for points on the other side of the % globe whereas c does not! % Also, we clip on rho even if we later clip on X/Y because in some projections (e.g. the % orthographic) the X/Y locations wrap back. if ~strcmp(varargin{4},'off'), vals = vals | cosc<=MAP_VAR_LIST.cosradius+eps*10; [rho,Az]=mu_util('clip',varargin{4},rho,MAP_VAR_LIST.rhomax,cosc=MAP_VAR_LIST.xlims(2)-eps*10 | ... Y<=MAP_VAR_LIST.ylims(1)+eps*10 | Y>=MAP_VAR_LIST.ylims(2)-eps*10; [X,Y]=mu_util('clip',varargin{4},X,MAP_VAR_LIST.xlims(1),XMAP_VAR_LIST.xlims(2) | isnan(X),Y); [Y,X]=mu_util('clip',varargin{4},Y,MAP_VAR_LIST.ylims(1),YMAP_VAR_LIST.ylims(2) | isnan(Y),X); end; case 'xy2ll', rho=sqrt(varargin{1}.^2+varargin{2}.^2); Z=exp(i*(atan2(varargin{2},varargin{1})-MAP_VAR_LIST.rotang*pi180)); V1=rho.*real(Z); V2=rho.*imag(Z); ir=rho==0; % To prevent /0 warnings when rho is 0 rho(ir)=eps; switch MAP_PROJECTION.name, case name(1), c=2*atan(rho/2); case name(2), c=asin(rho); case name(3), c=2*asin(rho/2); case name(4), c=rho; case name(5), c=atan(rho); case name(6), c=asin((MAP_VAR_LIST.uradius+1)./sqrt(1+(MAP_VAR_LIST.uradius./rho).^2)) - atan(rho/MAP_VAR_LIST.uradius); end; c(ir)=eps; % we offset this slightly so that the correct limit is achieved in the % division below: % Y=(asin(cos(c)*sin(MAP_VAR_LIST.rlat) + ... % cos(MAP_VAR_LIST.rlat)*sin(c).*varargin{2}./rho))/pi180; % % switch MAP_VAR_LIST.ulat, % case 90, % X=(MAP_VAR_LIST.rlong+atan2(varargin{1},-varargin{2}))/pi180; % case -90, % X=(MAP_VAR_LIST.rlong+atan2(varargin{1},varargin{2}))/pi180; % otherwise % X=(MAP_VAR_LIST.rlong+atan2( varargin{1}.*sin(c), ... % cos(MAP_VAR_LIST.rlat)*cos(c).*rho - sin(MAP_VAR_LIST.rlat)*varargin{2}.*sin(c) ) )/pi180; % end; Y=(asin(cos(c)*sin(MAP_VAR_LIST.rlat) + ... cos(MAP_VAR_LIST.rlat)*sin(c).*V2./rho))/pi180; switch MAP_VAR_LIST.ulat, case 90, X=(MAP_VAR_LIST.rlong+atan2(V1,-V2))/pi180; case -90, X=(MAP_VAR_LIST.rlong+atan2(V1,V2))/pi180; otherwise X=(MAP_VAR_LIST.rlong+atan2( V1.*sin(c), ... cos(MAP_VAR_LIST.rlat)*cos(c).*rho - sin(MAP_VAR_LIST.rlat)*V2.*sin(c) ) )/pi180; end; case 'xgrid', [X,Y,vals,labI]=mu_util('xgrid',MAP_VAR_LIST.longs,MAP_VAR_LIST.lats,varargin{1},31,varargin{2:3}); case 'ygrid', [X,Y,vals,labI]=mu_util('ygrid',MAP_VAR_LIST.lats,MAP_VAR_LIST.longs,varargin{1},91,varargin{2:3}); case 'box', [X,Y]=mu_util('box',31); end;