*
;
*This SAS program moves the borders of Canada provinces and of Hawaii
to the borders of States of USA. That one map (North America) is for
use in SAS/GRAPH procedure GMAP.
Note: for draft/presentation graphics only.
Try this example, and you can see what this means;
options nosource;
%macro trans (data,result,plotds,x,y,x_range,y_range,
x_move ,y_move,
angle, deg);
/*developed by Arnold Schick, University of Marburg/Germany
December 9, 1994, modified: January 4, 1995
note: on plot dataset PLOTDS there are dummy-corner-points
which are the X-,Y-Range from the input dataset and
from the new transformated data
*/
options nosource nostimer nosymbolgen nonotes;
%if &data = %then %do;
%put ;
%put macro-note: This macro is to call: ;
%put ;
%put macro-note: trans(data,result,plotds,x,y,x_r,y_r,x_m,y_m,angle,deg);
%put ;
%put macro-note: and it scales X-,Y-Values from input dataset DATA into;
%put macro-note: wanted ranges of 0 to X and 0 to Y with possibility of moving;
%put macro-note: in X-,Y-Directions and rotation about origin in X=0, Y=0. ;
%put macro-note: The new values are written into dataset RESULT, ;
%put macro-note: dataset PLOTDS has data for plotting (proc GPLOT with;
%put macro-note: plot option SKIPMISS) for showing the effect.;
%put macro-note: All transformations are from scope {x|0,1} and {y|1,0}.;
%put ;
%goto fin;
%end;
/*set default values*/
data _NULL_;
k=symget('x_range')/1.0; if k=. then k=1; call symput('x_range',k);
k=symget('y_range')/1.0; if k=. then k=1; call symput('y_range',k);
k=symget('x_move')/1.0; if k=. then k=0; call symput('x_move',k);
k=symget('y_move')/1.0; if k=. then k=0; call symput('y_move',k);
k=symget('angle')/1.0; if k=. then k=0; call symput('angle',k);
if k ^= 0 then k=1; call symput('k',k);
run;
/*set default variablenames*/
%if &data = . %then %do;
%let data = _LAST_ ;
%put macro-note: default input dataset is the _LAST_;
%end;
%if &result = or &result = . %then %do;
%let result = _NEW_ ;
%put macro-note: default result dataset is _NEW_;
%end;
%if &plotds = or &plotds = . %then %do;
%let plotds = _PLOTDS_ ;
%put macro-note: default plotting data set is _PLOTDS_;
%end;
%if &x = or &x = . %then %let x = x;
%if &y = or &y = . %then %let y = y;
%if °= or ° = . or °=degrees or °=DEGREES or
°=GRAD or °=grad %then %let deg = deg;
proc means data=&data noprint min max;
var &x &y ;
output out=_minmax_ min=x_min y_min max=x_max y_max ;
run;
data _NULL_;
set _minmax_;
call symput('x_min',x_min); call symput('x_max',x_max);
call symput('y_min',y_min); call symput('y_max',y_max);
run;
options notes;
data &result;
set &data;
length default=8;
&x = ((&x - &x_min)/(&x_max - &x_min))*&x_range + &x_move;
&y = ((&y - &y_min)/(&y_max - &y_min))*&y_range + &y_move;
run;
options nonotes;
%if &k ^= 0 %then %do;
data &result;
set &result;
keep &x &y;
angle=∠
if upcase("°") ^= upcase("DEG") then angle=angle*45/atan(1);
r = sqrt(&x**2 + &y**2);
if r ^= 0 then phi = arcos(&x/r); else phi=0;
if &y < 0 then phi = 360 - phi * 45/atan(1);
else phi = phi * 45/atan(1);
phi + angle;
phi = phi * atan(1)/45;
&x = r*cos(phi);
&y = r*sin(phi);
run;
%end;
data &plotds;
set &result;
run;
data _scope_ ;
if &x_min = 0 then xd=0.01/(&x_max-&x_min); else xd=0;
if &x_max = 0 then xr=0.01/(&x_max-&x_min); else xr=0;
if &y_min = 0 then yd=0.01/(&y_max-&y_min); else yd=0;
if &y_max = 0 then yr=0.01/(&y_max-&y_min); else yr=0;
keep &x &y ;
&x =.; &y =.; output;
&x = &x_min - xd; &y = &y_min - yd; output;
&x = &x_max + xr; &y = &y_min - yd; output;
&x = &x_max + xr; &y = &y_max + yr; output;
&x = &x_min - xd; &y = &y_max + yr; output;
&x = &x_min - xd; &y = &y_min - yd; output;
&x =.; &y =.; output;
run;
proc append base=&plotds data= _scope_ force; run;
proc append base=&plotds data= &data force; run;
proc means data=_scope_ noprint min max;
var &x &y ;
output out=_minmax_ min=x_min y_min max=x_max y_max ;
run;
data _NULL_;
set _minmax_;
call symput('x_min',x_min); call symput('x_max',x_max);
call symput('y_min',y_min); call symput('y_max',y_max);
run;
data _scope_;
set _scope_;
keep &x &y;
&x = ((&x - &x_min)/(&x_max - &x_min))*&x_range + &x_move;
&y = ((&y - &y_min)/(&y_max - &y_min))*&y_range + &y_move;
angle=∠
if angle ^=0 then do;
if upcase("°") ^= upcase("DEG") then angle=angle*45/atan(1);
r = sqrt(&x**2 + &y**2);
if r ^= 0 then phi = arcos(&x/r); else phi=0;
if &y < 0 then phi = 360 - phi * 45/atan(1);
else phi = phi * 45/atan(1);
phi + angle;
phi = phi * atan(1)/45;
&x = r*cos(phi);
&y = r*sin(phi);
end;
run;
proc append base=&plotds data= _scope_ force; run;
%fin : ;
options source stimer notes;
%mend trans; options source;
data one;
set maps.canada2;
x=x-0.0115 + 0.017*x;
y=y+0.447 - 0.015*x - abs(sin(x/14));
run;
data two alaska hawaii;
set maps.us;
if x > 0 or state=2 then y=y+sin(x/41);
if state=2 then output alaska;
else if state=15 then output hawaii;
else output two;
run;
*trans(data ,result,plotds,x,y,x_range, y_range, x_move ,y_move ,angle,deg);
%trans(alaska,eins, ,x,y,0.287, 0.287 , -0.8025, 0.022 ,-44.11);
%trans(hawaii,zwei, ,x,y,0.075, 0.075 , -0.9 ,-0.25);
data three;
set one two eins zwei;
run;
goptions device=win rotate=landscape border lfactor=2;
*goptions targetdevice=hpljs3a4 rotate=landscape border lfactor=2;
pattern v=e c=black r=123;
* USABLE IN SAS 6.10 OR ABOVE (i.e. 6.12) ONLY;
* OTHERS: CONVERT STATE AND PROVINCE TO THE SAME DATATYPE;
proc gmap data=three
map =three
all;
id state province;
choro state /
nolegend
discrete
;
run;
quit;
*;