*
;

               options nosource;
%macro scale3d (data,result,x,y,z,x_scale,y_scale,z_scale,
                                  x_move ,y_move ,z_move);

 /*Developed by Arnold Schick, University of Marburg/Germany

   note: Result dataset includes four dummy-corner-points
         which are the X-,Y-Ranges from the input dataset. 
         If these points are not wanted, please delete the last
         four points in result dataset.                      */

 options nosource nostimer nosymbolgen nonotes;

%if &data =  %then %do;
  %put ;
  %put This macro is to call: ;
  %put ;
  %put      SCALE3D(data,result,x,y,z,x_sc,y_sc,z_sc,x_m,y_m,z_m);
  %put ;
  %put and scales X-,Y-,Z-Values from input dataset DATA into;
  %put wanted ranges of X-,Y-,Z-Planes with possibility of moving;
  %put in X-,Y-,Z-Directions. ;
  %put The new values are written into dataset RESULT. ;
  %put ;
  %goto fin;
%end;

/*set default variablenames*/
%if &data    = . %then %let data    = _LAST_ ;
%if &result  =  or &result  = . %then %let result  = _NEW_ ;
%if &x       =  or &x       = . %then %let x       = x;
%if &y       =  or &y       = . %then %let y       = y;
%if &z       =  or &z       = . %then %let z       = z;

/*set default values*/
data _NULL_;
 k=symget('x_scale')/1.0; if k=. then k=1; call symput('x_scale',k);
 k=symget('y_scale')/1.0; if k=. then k=1; call symput('y_scale',k);
 k=symget('z_scale')/1.0; if k=. then k=1; call symput('z_scale',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('z_move')/1.0; if k=. then k=0; call symput('z_move',k);
run;

proc means data=&data noprint min max;
  var x y z ;
  output out=_minmax_ min=x_min y_min z_min max=x_max y_max z_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);
  call symput('z_min',z_min);  call symput('z_max',z_max);
run;

data &result;
  set &data;
  length default=8;
  &x = ((&x - &x_min)/(&x_max - &x_min))*&x_scale + &x_move;
  &y = ((&y - &y_min)/(&y_max - &y_min))*&y_scale + &y_move;
  &z = ((&z - &z_min)/(&z_max - &z_min))*&z_scale + &z_move;
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 &z;
  &x = &x_min - xd;  &y = &y_min - yd;  &z = &z_max; output;
  &x = &x_max + xr;  &y = &y_min - yd;  &z = &z_max; output;
  &x = &x_max + xr;  &y = &y_max + yr;  &z = &z_max; output;
  &x = &x_min - xd;  &y = &y_max + yr;  &z = &z_max; output;
run;

proc append base=&result data= _scope_ ; run;

%fin : ;
options source stimer symbolgen notes;
%mend;    options source;

 %scale3d;

/* Example:

data eins;
  do x=-5 to 5 by 0.5;
    do y=-5 to 5  by 0.5;
       z= sin(sqrt(x**2 + y**2));
       output;
    end;
  end;
run;

*%scale3d(eins,zwei);   * scales into {x|0,1} , {y|0,1} and {z|0,1} ;

 %scale3d(eins,zwei,x,y,z, 1,2,0.25, -0.3,.1,0.2);

proc g3d data=zwei;
  plot y*x=z;
run; quit;
*/

*
;