
<!--
function G3(data,UnitChange,CurrentDate)
  {
    //***********************************************************************
    //*
    //* Function G3 calculates the gradient using coordinates directly scaled from
    //*          from a map or entered directly
    //*          G3 uses three points to determine the gradient by fitting a plane
    //*          to the heads
    //*
    //* Language:  JavaScript1.1
    //*
    //* Inputs: 
    //*  data                  string signal for type of processing values:
    //*                        noexample--perform calculation using user data
    //*                        example--paste example data and calculate
    //*                        example2--paste second example data set and calculate
    //*                        clear--clear all data and exit
    //*                        save--save data to cookie file
    //*                        restore--read data from cookie file
    //*  UnitChage             signal to change units
    //*                        if none no unit change
    //*                        if head change head unit
    //*                        if map change map unit
    //*                        if field change field unit
    //*  CurrentDate           boolean signal to paste current date in the date field
    //*
    //* Returns:
    //*  nothing
    //*
    //* Limitations: Only for use with gradient3.htm
    //*
    //* Author:
    //*  Dr. Jim Weaver
    //*  Hydrologist
    //*  Regulatory Support Branch
    //*  Ecosystems Research Division
    //*  National Exposure Research Laboratory
    //*  United States Environmental Protection Agency
    //*  960 College Station Road
    //*  Athens, Georgia 30605
    //*  weaver.jim@epa.gov
    //* 
    //*
    //* Reference:
    //*  Flanagan, D., 1997, JavaScript: The Definitive Guide, 2ed, O'Reilly and Associates
    //*
    //* Created: 12-16-1999 created from newgradient.htm
    //*          02-04-2001 cookies removed
    //*          02-10-2001 tenths added as map scale options
    //*
    //* Required functions: clearAll, Input, ShortDate, save, restore, Num2String, determine
    //*
    //* Required scripts: input.js, digits.js, sdate.js, cookie.js, back.js, determine.js, clear.js
    //*
    //***********************************************************************
   var f=document.Gradient;
   var unithead = "";
   var unitdist0 = "";
   var unitdist1 = "";
   var ucf1 = 1; 
   var ucf2 = 1;
   var ucf3 = 1;
   var ucf4 = 1;
   var ucfdist = 1;
   var ucfhead = 1;
   var SiteDate = "";
   var SiteName = "";
   var date = new Date();
   var Ent = new Array();
   var a = 0;
   var b = 0;
   var c = 0;
   var xx = new Array();
   var yy = new Array();
   var zz = new Array();
   var ww = new Array();

   var grad = 0;
   var gradstring = "";
   var degrees = 0;

   var x1 = 0;
   var y1 = 0;
   var x2 = 0;
   var y2 = 0;
   var h1 = 0;
   var h2 = 0;
   var fn = 0;
   var fd = 1;
   var ScaleIn = 1;
   var ScaleOut = 1;

   var fn1 = 0;
   var fd1 = 1;
   var fn2 = 0;
   var fd2 = 1;
   var fn3 = 0;
   var fd3 = 1;
   var fn4 = 0;
   var fd4 = 1;
   var fn5 = 0;
   var fd5 = 1;
   var fn6 = 0;
   var fd6 = 1;

    
//results
if (data=="noexample"  || data=="save")
   {
      //distances and heads
      xx[0] = Input(f.x1.value);
      yy[0] = Input(f.y1.value);
      xx[1] = Input(f.x2.value);
      yy[1] = Input(f.y2.value);
      xx[2] = Input(f.x3.value);
      yy[2] = Input(f.y3.value);
      zz[0] = Input(f.h1.value);
      zz[1] = Input(f.h2.value);
      zz[2] = Input(f.h3.value);
      fn = Input(f.InNum.value);
      fd = parseInt(f.InDen.options[f.InDen.selectedIndex].value);
      fn = Input(f.InNum.value);
      fd = parseInt(f.InDen.options[f.InDen.selectedIndex].value);

      fn1 = Input(f.InNum1.value);
      fd1 = parseInt(f.InDen1.options[f.InDen1.selectedIndex].value);
      fn2 = Input(f.InNum2.value);
      fd2 = parseInt(f.InDen2.options[f.InDen2.selectedIndex].value);
      fn3 = Input(f.InNum3.value);
      fd3 = parseInt(f.InDen3.options[f.InDen3.selectedIndex].value);
      fn4 = Input(f.InNum4.value);
      fd4 = parseInt(f.InDen4.options[f.InDen4.selectedIndex].value);
      fn5 = Input(f.InNum5.value);
      fd5 = parseInt(f.InDen5.options[f.InDen5.selectedIndex].value);
      fn6 = Input(f.InNum6.value);
      fd6 = parseInt(f.InDen6.options[f.InDen6.selectedIndex].value);
            

      ScaleIn = Input(f.ScaleIn.value);
      ScaleOut = Input(f.ScaleOut.value);
     
      SiteName = f.site.value;
      if (CurrentDate==true) {SiteDate=ShortDate(date); f.date.value = SiteDate;}
      else {SiteDate = f.date.value;}
    
        
     unithead = f.HeadUnit.options[f.HeadUnit.selectedIndex].value
     unitdist0 = f.DistUnit0.options[f.DistUnit0.selectedIndex].value    
     unitdist1 = f.DistUnit1.options[f.DistUnit1.selectedIndex].value  

     if (data=="save") 
       {
        //display the cookie message
        window.open('../../home/storage.html','storage','width=620,height=400,resizable');
        return;

         /*
         //store the data in an array for saving to a cookie
         Ent[0] = SiteDate;
         Ent[1] = SiteName;

         //create the id cookie
         save("id",Ent);
   
        //save the "new gradient" data
        Ent[0] = ScaleIn;
        Ent[1] = f.DistUnit0.selectedIndex
        Ent[2] = xx[0];
        Ent[3] = yy[0];
        Ent[4] = xx[1];
        Ent[5] = yy[1];
        Ent[6] = ScaleOut;
        Ent[7] = f.DistUnit1.selectedIndex
        Ent[8] = f.HeadUnit.selectedIndex
        Ent[9] = zz[0];
        Ent[10] = zz[1];
        Ent[11] = fn;
        Ent[12] = f.InDen.selectedIndex;
        Ent[13] = fn1;
        Ent[14] = f.InDen1.selectedIndex;

        //create the "ng" cookie
        save("ng",Ent);

        //create the 'g3' cookie
        Ent[0] = xx[2];
        Ent[1] = yy[2];
        Ent[2] = zz[2];
        Ent[3] = fn2;
        Ent[4] = f.InDen2.selectedIndex;
        Ent[5] = fn3;
        Ent[6] = f.InDen3.selectedIndex;
        Ent[7] = fn4;
        Ent[8] = f.InDen4.selectedIndex;
        Ent[9] = fn5;
        Ent[10] = f.InDen5.selectedIndex;
        Ent[11] = fn6;
        Ent[12] = f.InDen6.selectedIndex;
        save ('g3',Ent);
        */
       }  

   }
if (data=="example" || data=="example2" || data=="example3" || data=="example4")
   {

     //example data set
     ScaleIn = 1;
     ScaleOut = 1;
     fn = 0;
     xx[0] = 100;
     yy[0] = 0;
     xx[1] = 0;
     yy[1] = 100;
     xx[2] = 100;
     yy[2] = 100;
     zz[0] = 20;
     zz[1] = 20;
     zz[2] = 19.75;

     unithead = "ft";
     f.HeadUnit.selectedIndex = 0;
     unitdist0 = "ft";
     unitdist1 = "ft";
     f.DistUnit0.selectedIndex = 1;
     f.DistUnit1.selectedIndex = 0;
       
     SiteName = "Map Gradient Ex 1";
     SiteDate = ShortDate(date);
    
     //change to a map scale example
     if (data=="example2" || data=="example3")
       {
         ScaleOut = 100;
         xx[0] = 1;
         xx[1] = 1;
         xx[2] = 1;
         yy[2] = 1;
         unitdist0 = "in"
         f.DistUnit0.selectedIndex = 0;
         SiteName = "Map Gradient Ex 2";
         //change to a fractional example
        if (data=="example3")
         {
           fn = 3;
           f.InDen.selectedIndex = 2;
           SiteName = "Map Gradient Ex 3"
         }

       }

      //OUST 2001 example
      if (data=="example4")
      {
        xx[0] = 190.
        yy[0] = 163.
        xx[1] = 138.
        yy[1] = 153.
        xx[2] = 217.
        yy[2] = 43.
        zz[0] = 90.24
        zz[1] = 90.27
        zz[2] = 90.01
      }
    }


if (data=="restore")
     {
      //display the cookie message
      window.open('../../home/storage.html','storage','width=620,height=400,resizable');
      return;

      /*
      //recover each value from the cookie
      SiteDate = restore("id","date");
      SiteName = restore("id","site");


      ScaleIn = restore("ng","ScaleIn");
      f.DistUnit0.selectedIndex = restore("ng","UnitIn");
      xx[0] = restore("ng","x1");
      yy[0] = restore("ng","y1");
      xx[1] = restore("ng","x2");
      yy[1] = restore("ng","y2");
      xx[2] = restore('g3','x3');
      yy[2] = restore('g3','y3');
      ScaleOut = restore("ng","ScaleOut");
      f.DistUnit1.selectedIndex = restore("ng","UnitOut");
      f.HeadUnit.selectedIndex = restore("ng","UnitHead");  
      zz[0] = restore("ng","h1");
      zz[1] = restore("ng","h2");
      zz[2] = restore('g3','h3');
      fn = restore('ng','fn');
      f.InDen.selectedIndex = restore('ng','fd');
      fn1 = restore('ng','fn1');
      f.InDen1.selectedIndex = restore('ng','fd1');

      fn2 = restore('g3','fn2');
      f.InDen2.selectedIndex = restore('g3','fd2');
      fn3 = restore('g3','fn3');
      f.InDen3.selectedIndex = restore('g3','fd3');
      fn4 = restore('g3','fn4');
      f.InDen4.selectedIndex = restore('g3','fd4');
      fn5 = restore('g3','fn5');
      f.InDen5.selectedIndex = restore('g3','fd5');
      fn6 = restore('g3','fn6');
      f.InDen6.selectedIndex = restore('g3','fd6');



      unithead = f.HeadUnit.options[f.HeadUnit.selectedIndex].value
      unitdist0 = f.DistUnit0.options[f.DistUnit0.selectedIndex].value    
      unitdist1 = f.DistUnit1.options[f.DistUnit1.selectedIndex].value
      */  
     }

if ( data=="restore" || data=="example" || data=="example2" || data=="example3" || data=="example4")
  {
    f.date.value = SiteDate; 
    f.site.value = SiteName;  
    f.x1.value = xx[0];
    f.y1.value = yy[0];
    f.x2.value = xx[1];
    f.y2.value = yy[1];
    f.x3.value = xx[2];
    f.y3.value = yy[2];
    f.h1.value = zz[0];
    f.h2.value = zz[1];
    f.h3.value = zz[2];
    f.ScaleIn.value = ScaleIn;
    f.ScaleOut.value = ScaleOut;
    f.InNum.value = fn;
    fd = parseInt(f.InDen.options[f.InDen.selectedIndex].value);

    f.InNum1.value = fn1;
    fd1 = parseInt(f.InDen1.options[f.InDen1.selectedIndex].value);
    f.InNum2.value = fn2;
    fd2 = parseInt(f.InDen2.options[f.InDen2.selectedIndex].value);
    f.InNum3.value = fn3;
    fd3 = parseInt(f.InDen3.options[f.InDen3.selectedIndex].value);
    f.InNum4.value = fn4;
    fd4 = parseInt(f.InDen4.options[f.InDen4.selectedIndex].value);
    f.InNum5.value = fn5;
    fd5 = parseInt(f.InDen5.options[f.InDen5.selectedIndex].value);
    f.InNum6.value = fn6;
    fd6 = parseInt(f.InDen6.options[f.InDen6.selectedIndex].value);

  }

if (data=="clear") {clearAll(f); return;}



  
  

  //Head unit conversions;
  ucf1 = 1;
  if (UnitChange=="head")
    {
     if (f.HeadUnit.options[f.HeadUnit.selectedIndex].value=="ft") {ucf1=1/0.3048; unithead="ft";}
     if (f.HeadUnit.options[f.HeadUnit.selectedIndex].value=="m") {ucf1=0.3048; unithead="m";}
    }
 
  zz[0] = zz[0]*ucf1;
  zz[1] = zz[1]*ucf1;   
  zz[2] = zz[2]*ucf1;  
  f.h1.value = Num2String(zz[0],4,-10,10,-6,6);
  f.h2.value = Num2String(zz[1],4,-10,10,-6,6);
  f.h3.value = Num2String(zz[2],4,-10,10,-6,6);

  //Distance unit conversions
  ucf2 = 1;
  if (UnitChange=="map")
    {
     if (f.DistUnit0.options[f.DistUnit0.selectedIndex].value=="ft") {ucf2=1/0.3048; unitdist0="ft";}
     if (f.DistUnit0.options[f.DistUnit0.selectedIndex].value=="m") {ucf2=0.3048; unitdist0="m";}
     if (f.DistUnit0.options[f.DistUnit0.selectedIndex].value=="in") {ucf2=1/0.3048; unitdist0="in";}
     if (f.DistUnit0.options[f.DistUnit0.selectedIndex].value=="cm") {ucf2=0.3048; unitdist0="cm";}
    }

  //Distance unit conversions
  ucf3 = 1;
  if (UnitChange=="field")
    {
     if (f.DistUnit1.options[f.DistUnit1.selectedIndex].value=="ft") {ucf3=1/0.3048; unitdist1="ft";}
     if (f.DistUnit1.options[f.DistUnit1.selectedIndex].value=="m") {ucf3=0.3048; unitdist1="m";}
    }
 
  xx[0] = xx[0] + fn1/fd1;
  yy[0] = yy[0] + fn2/fd2;
  xx[1] = xx[1] + fn3/fd3;
  yy[1] = yy[1] + fn4/fd4;
  xx[2] = xx[2] + fn5/fd5;
  yy[2] = yy[2] + fn6/fd6;

   
  ucf4 = ScaleOut/(ScaleIn + fn/fd);

  xx[0] = xx[0]*ucf4;
  yy[0] = yy[0]*ucf4;
  xx[1] = xx[1]*ucf4;
  yy[1] = yy[1]*ucf4;
  xx[2] = xx[2]*ucf4;
  yy[2] = yy[2]*ucf4;
 
  f.x1Out.value = Num2String(xx[0],4,-10,10,-7,7) + " " + unitdist1;
  f.y1Out.value = Num2String(yy[0],4,-10,10,-7,7) + " " + unitdist1;
  f.x2Out.value = Num2String(xx[1],4,-10,10,-7,7) + " " + unitdist1;
  f.y2Out.value = Num2String(yy[1],4,-10,10,-7,7) + " " + unitdist1;
  f.x3Out.value = Num2String(xx[2],4,-10,10,-7,7) + " " + unitdist1;
  f.y3Out.value = Num2String(yy[2],4,-10,10,-7,7) + " " + unitdist1;



  //do all calculation in meters
  ucfdist = 1;
  if (unitdist1=="ft") {ucfdist=0.3048;}
  ucfhead = 1;
  if (unithead=="ft") {ucfhead=0.3048;} 

  //apply the scale factor to the distances


  //convert quantities before performing gradient calculation
  xx[0] = xx[0]*ucfdist;
  yy[0] = yy[0]*ucfdist;
  xx[1] = xx[1]*ucfdist;
  yy[1] = yy[1]*ucfdist;
  xx[2] = xx[2]*ucfdist;
  yy[2] = yy[2]*ucfdist;


  zz[0] = zz[0]*ucfhead;
  zz[1] = zz[1]*ucfhead;
  zz[2] = zz[2]*ucfhead;

 
  ww[0] = 1;
  ww[1] = 1;
  ww[2] = 1;

  //calculate the gradient
  //solve the 3 x 3 matrix for the plane passing through all the points
  //equation is ax + by + c = z
  var denominator = determinant(xx,yy,ww);
  if (denominator!=0)
   {
     //constants defining the plane
     var numerator = determinant(zz,yy,ww);
     a = numerator/denominator;
     numerator = determinant(xx,zz,ww);
     b = numerator/denominator;
     numerator = determinant(xx,yy,zz);
     c = numerator/denominator;
     //the gradient
     grad = -Math.sqrt(a*a + b*b);
     //the angle
     //the following combinations are opposite of what you think they should be 
     //because the flow is in the direction of minus the gradient
     if (a<0 && b<0) 
      {
       //solution in the first quadrant
       degrees = Math.atan(a/b)*180/Math.PI;
      }
     if (a<0 && b>0)
      {
       //solution in the second quadrant
       degrees = Math.atan(-b/a)*180/Math.PI + 90;
      }
     if (a>0 && b>0)
      {
       //solution in the third quadrant
       degrees = Math.atan(-a/-b)*180/Math.PI + 180;
      }
     if (a>0 && b<0)
      {
       //solution in the forth quadrant
       degrees = Math.atan(b/-a)*180/Math.PI + 270;
      }
   

   }
  else {f.grad.value=""; f.degrees.value=""; return;}
 


 
  gradstring = Num2String(grad,4,-10,10,-4,4); 
  f.grad.value = gradstring;
  f.degrees.value = Num2String(degrees,4,-10,10,-4,4);

  if (data == "save") 
   {
     /*
     //save the gradient result
     Ent[0] = gradstring;
     save ("gr",Ent);
     */
   }

}
//-->
<!-- end gradient3_1.js -->