
<!--
function G4ns(data,UnitChange,CurrentDate)
  {
    //***********************************************************************
    //*
    //* Function G4ns calculates the gradient using coordinates entered directly
    //*          G4ns multiple points to determine the gradient by fitting a plane
    //*          to the heads
    //*
    //* Language:  JavaScript
    //*
    //* 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
    //*          07-28-2001 created G4ns from G3
    //*          05-08-2002 added option for unconfined aquifer
    //*          08-16-2004 restriction to 6 wells removed
    //*          08-25-2004 scaling of coordinate values > 1000 to prevent numerical error in fitting plane
    //*
    //* 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 aquifertype = "";
   var ucf1 = 1; 
   var ucf2 = 1;
   var ucf3 = 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 k1 = new Array();
   var k2 = new Array();
   var k3 = new Array();
   var k4 = new Array();

   var grad = 0;
   var gradstring = "";
   var degrees = 0;
   var numPoints = 15;

   var x1 = 0;
   var y1 = 0;
   var x2 = 0;
   var y2 = 0;
   var h1 = 0;
   var h2 = 0;
 
  


    
//results
if (data=="noexample"  || data=="save")
   {
      //distances and heads
      xx[0] = InputACharForNaN(f.x1.value);
      yy[0] = InputACharForNaN(f.y1.value);
      xx[1] = InputACharForNaN(f.x2.value);
      yy[1] = InputACharForNaN(f.y2.value);
      xx[2] = InputACharForNaN(f.x3.value);
      yy[2] = InputACharForNaN(f.y3.value);
      xx[3] = InputACharForNaN(f.x4.value);
      yy[3] = InputACharForNaN(f.y4.value);
      xx[4] = InputACharForNaN(f.x5.value);
      yy[4] = InputACharForNaN(f.y5.value);
      xx[5] = InputACharForNaN(f.x6.value);
      yy[5] = InputACharForNaN(f.y6.value);
      xx[6] = InputACharForNaN(f.x7.value);
      yy[6] = InputACharForNaN(f.y7.value);
      xx[7] = InputACharForNaN(f.x8.value);
      yy[7] = InputACharForNaN(f.y8.value);
      xx[8] = InputACharForNaN(f.x9.value);
      yy[8] = InputACharForNaN(f.y9.value);
      xx[9] = InputACharForNaN(f.x10.value);
      yy[9] = InputACharForNaN(f.y10.value);
      xx[10] = InputACharForNaN(f.x11.value);
      yy[10] = InputACharForNaN(f.y11.value);
      xx[11] = InputACharForNaN(f.x12.value);
      yy[11] = InputACharForNaN(f.y12.value);
      xx[12] = InputACharForNaN(f.x13.value);
      yy[12] = InputACharForNaN(f.y13.value);
      xx[13] = InputACharForNaN(f.x14.value);
      yy[13] = InputACharForNaN(f.y14.value);
      xx[14] = InputACharForNaN(f.x15.value);
      yy[14] = InputACharForNaN(f.y15.value);

      zz[0] = InputACharForNaN(f.h1.value);
      zz[1] = InputACharForNaN(f.h2.value);
      zz[2] = InputACharForNaN(f.h3.value);
      zz[3] = InputACharForNaN(f.h4.value);
      zz[4] = InputACharForNaN(f.h5.value);
      zz[5] = InputACharForNaN(f.h6.value);          
      zz[6] = InputACharForNaN(f.h7.value);
      zz[7] = InputACharForNaN(f.h8.value);
      zz[8] = InputACharForNaN(f.h9.value);
      zz[9] = InputACharForNaN(f.h10.value);          
      zz[10] = InputACharForNaN(f.h11.value);
      zz[11] = InputACharForNaN(f.h12.value);          
      zz[12] = InputACharForNaN(f.h13.value);
      zz[13] = InputACharForNaN(f.h14.value);
      zz[14] = InputACharForNaN(f.h15.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    
     aquifertype = f.AquiferType.options[f.AquiferType.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] = 1.;
        Ent[1] = f.DistUnit0.selectedIndex
        Ent[2] = xx[0];
        Ent[3] = yy[0];
        Ent[4] = xx[1];
        Ent[5] = yy[1];
        Ent[6] = 1.;
        Ent[7] = 0.;
        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=="example2")
   {

     //example data set
     fn = 0;
     xx[0] = 1240417.29;
     yy[0] = 244617.46;
     xx[1] = 1240455.69;
     yy[1] = 244623.86;
     xx[2] = 1240485.89;
     yy[2] = 244633.06;
     xx[3] = 1240494.29;
     yy[3] = 244656.86;
     xx[4] = 1240533.69;
     yy[4] = 244682.46;
     xx[5] = 1240520.89;
     yy[5] = 244712.66;
     xx[6] = 1240469.49;
     yy[6] = 244754.86;
     xx[7] = 1240497.89;
     yy[7] = 244796.06;
     xx[8] = 1240522.69;
     yy[8] = 244643.06;
     xx[9] = 1240547.39;
     yy[9] = 244556.96;
     xx[10] = 1240666.49;
     yy[10] = 224348.06;
     xx[11] = 1240612.49;
     yy[11] = 244308.66;
     xx[12] = 1240568.49;
     yy[12] = 244378.46;
     xx[13] = 1240596.09;
     yy[13] = 244309.46;
     xx[14] = "";
     yy[14] = "";

     zz[0] = 56.63;
     zz[1] = 56.56;
     zz[2] = 56.66;
     zz[3] = 56.64;
     zz[4] = 56.58;
     zz[5] = 56.31;
     zz[6] = 56.67;
     zz[7] = 56.11;
     zz[8] = 56.52;
     zz[9] = 56.59;
     zz[10] = "x";
     zz[11] = "x";
     zz[12] = "x";
     zz[13] = "x";
     zz[14] = "x";


     unithead = "ft";
     f.HeadUnit.selectedIndex = 0;
     unitdist0 = "ft";
     unitdist1 = "ft";
     f.DistUnit0.selectedIndex = 0;
     aquifertype = "h";
     f.AquiferType.selectedIndex = 0;
    
       
     SiteName = "ITRC Example Aug 2005";
     SiteDate = ShortDate(date);
    
     //arbitrary identifiers
     f.id1.value = "mw-1";
     f.id2.value = "mw-2";
     f.id3.value = "mw-3";
     f.id4.value = "mw-4";
     f.id5.value = "mw-5";
     f.id6.value = "mw-6";
     f.id7.value = "mw-7";
     f.id8.value = "mw-9";
     f.id9.value = "mw-10";
     f.id10.value = "mw-11";
     f.id11.value = "ml-1h";
     f.id12.value = "ml-2j";
     f.id13.value = "ml-3j";
     f.id14.value = "ml-4a";
     f.id15.value = "";
    

    }


if (data=="example" || data=="example3" || data=="example4")
   {

     //example data set
     fn = 0;
     xx[0] = 100;
     yy[0] = 0;
     xx[1] = 0;
     yy[1] = 100;
     xx[2] = 100;
     yy[2] = 100;
     xx[3] = 100;
     yy[3] = 0;
     xx[4] = 0;
     yy[4] = 100;
     xx[5] = 100;
     yy[5] = 100;
     xx[6] = "";
     yy[6] = "";
     xx[7] = "";
     yy[7] = "";
     xx[8] = "";
     yy[8] = "";
     xx[9] = "";
     yy[9] = "";
     xx[10] = "";
     yy[10] = "";
     xx[11] = "";
     yy[11] = "";
     xx[12] = "";
     yy[12] = "";
     xx[13] = "";
     yy[13] = "";
     xx[14] = "";
     yy[14] = "";

     zz[0] = 20;
     zz[1] = 20;
     zz[2] = 19.75;
     zz[3] = 20;
     zz[4] = 20;
     zz[5] = 19.75;
     zz[6] = "x";
     zz[7] = "x";
     zz[8] = "x";
     zz[9] = "x";
     zz[10] = "x";
     zz[11] = "x";
     zz[12] = "x";
     zz[13] = "x";
     zz[14] = "x";


     unithead = "ft";
     f.HeadUnit.selectedIndex = 0;
     unitdist0 = "ft";
     unitdist1 = "ft";
     f.DistUnit0.selectedIndex = 0;
     aquifertype = "h";
     f.AquiferType.selectedIndex = 0;
    
       
     SiteName = "Map Gradient Ex 1";
     SiteDate = ShortDate(date);
    
     //arbitrary identifiers
     f.id1.value = "mw-1";
     f.id2.value = "mw-2";
     f.id3.value = "mw-3";
     f.id4.value = "mw-4";
     f.id5.value = "mw-5";
     f.id6.value = "mw-6";
     f.id7.value = "";
     f.id8.value = "";
     f.id9.value = "";
     f.id10.value = "";
     f.id11.value = "";
     f.id12.value = "";
     f.id13.value = "";
     f.id14.value = "";
     f.id15.value = "";


    }
    


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");


      
      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');
      
      f.HeadUnit.selectedIndex = restore("ng","UnitHead");  
      zz[0] = restore("ng","h1");
      zz[1] = restore("ng","h2");
      zz[2] = restore('g3','h3');
 



      unithead = f.HeadUnit.options[f.HeadUnit.selectedIndex].value
      unitdist0 = f.DistUnit0.options[f.DistUnit0.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.x4.value = xx[3];
    f.y4.value = yy[3];
    f.x5.value = xx[4];
    f.y5.value = yy[4];
    f.x6.value = xx[5];
    f.y6.value = yy[5];
    f.x7.value = xx[6];
    f.y7.value = yy[6];
    f.x8.value = xx[7];
    f.y8.value = yy[7];
    f.x9.value = xx[8];
    f.y9.value = yy[8];
    f.x10.value = xx[9];
    f.y10.value = yy[9];
    f.x11.value = xx[10];    
    f.y11.value = yy[10];
    f.x12.value = xx[11];
    f.y12.value = yy[11];
    f.x13.value = xx[12];
    f.y13.value = yy[12];
    f.x14.value = xx[13];
    f.y14.value = yy[13];
    f.x15.value = xx[14];
    f.y15.value = yy[14];
   


    f.h1.value = zz[0];
    f.h2.value = zz[1];
    f.h3.value = zz[2];
    f.h4.value = zz[3];
    f.h5.value = zz[4];
    f.h6.value = zz[5];
    f.h7.value = zz[6];
    f.h8.value = zz[7];
    f.h9.value = zz[8];
    f.h10.value = zz[9];
    f.h11.value = zz[10];
    f.h12.value = zz[11];
    f.h13.value = zz[12];
    f.h14.value = zz[13];
    f.h15.value = zz[14];

  

  }

if (data=="clear") {clearAll(f); return;}

 

  //do all calculation in meters
  ucfdist = 1;
  if (unitdist0=="ft") {ucfdist=0.3048;}
  ucfhead = 1;
  if (unithead=="ft") {ucfhead=0.3048;} 

  //apply the scale factor to the distances
  //if very large coordinate values are used then the solution may not be correct
  //find minimum and maximum values for each coordinate
  var xmin = 1e20;
  var xmax = -1e20;
  var ymin = 1e20;
  var ymax = -1e20;
  

  //convert quantities before performing gradient calculation
  for (i=0;i<numPoints;i++)
  {
    if (!isNaN(xx[i])) {xx[i] = xx[i]*ucfdist; if (xx[i]<xmin){xmin=xx[i];}; if(xx[i]>xmax){xmax=xx[i];} }
    if (!isNaN(yy[i])) {yy[i] = yy[i]*ucfdist; if (yy[i]<ymin){ymin=yy[i];}; if(yy[i]>ymax){ymax=yy[i];} }
    if (!isNaN(zz[i])) {zz[i] = zz[i]*ucfhead;}
  }

  //subtract the minimum value from each coordinate to prevent miscalculation in linear fitting to the plane
  //8-25-2004
  if (xmin>1000) {for (i=0;i<numPoints;i++) {if (!isNaN(xx[i])) {xx[i] = xx[i]-xmin; }}}
  if (ymin>1000) {for (i=0;i<numPoints;i++) {if (!isNaN(yy[i])) {yy[i] = yy[i]-ymin; }}}



  var hMin = 1.e20;
  var hMax = -1.e20;
  //determine the range of head values
  for (i=0;i<numPoints;i++)
  {
    if (zz[i]<hMin) {hMin = zz[i];}
    if (zz[i]>hMax) {hMax = zz[i];}
  }  
  var range = hMax - hMin;


  //use head squared for an unconfined aquifer (head squared calculation basis
  if (aquifertype=="h2")
  {
    for (i=0;i<numPoints;i++) {if (!isNaN(zz[i])) {zz[i] = zz[i]*zz[i];}}
  }

  


  //calculate the gradient

  //set up required sums for the least squares solution:
  var sumX = 0.;
  var sumY = 0.;
  var sumXY = 0.;
  var sumXX = 0.;
  var sumYY = 0.;
  var sumZ = 0.;
  var sumZX = 0.;
  var sumZY = 0.;
  var sumZZ = 0.;
  var numb = 0;  
  var r2 = 0;

  for (i=0;i<numPoints;i++)
  {
    //an x, y and z must have been entered for the element 
    //to be included in the least squares
    if (!isNaN(xx[i]) && !isNaN(yy[i]) && !isNaN(zz[i]))
    {
      if (" " !== zz[i] && " " !== xx[i] && " " !== yy[i])
      {
        sumX = sumX + xx[i];
        sumY = sumY + yy[i];
        sumZ = sumZ + zz[i];
        sumXX = sumXX + xx[i]*xx[i];
        sumYY = sumYY + yy[i]*yy[i];
        sumXY = sumXY + xx[i]*yy[i];
        sumZX = sumZX + xx[i]*zz[i];
        sumZY = sumZY + yy[i]*zz[i];
        sumZZ = sumZZ + zz[i]*zz[i];
        numb = numb + 1;
  
      }
    }
  }
   
  k1[0] = sumX;
  k1[1] = sumXY;
  k1[2] = sumXX;

  k2[0] = sumY;
  k2[1] = sumYY;
  k2[2] = sumXY;

  k3[0] = numb;
  k3[1] = sumY;
  k3[2] = sumX;

  k4[0] = sumZ;
  k4[1] = sumZY;
  k4[2] = sumZX;

  

  //solve the 3 x 3 matrix for the plane passing through all the points
  //equation is ax + by + c = z
  var denominator = determinant(k1,k2,k3);
 
  if (denominator!=0)
   {
     //constants defining the plane
     var numerator = determinant(k4,k2,k3);
     a = numerator/denominator;
     numerator = determinant(k1,k4,k3);
     b = numerator/denominator;
     numerator = determinant(k1,k2,k4);
     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;
      }
   
     //determine the coefficient of determination (R^^2)
     //Introduction to probability and statistics, Milton and Arnold, 1995 page 495, 487
     if (numb > 0)
     {
       var syy = (numb*sumZZ - sumZ*sumZ)/numb
       var srr = c*sumZ + a*sumZX + b*sumZY - sumZ*sumZ/numb
       if (srr != 0) {r2 = srr/syy}
     }
   }
  else {f.grad.value=""; f.degrees.value=""; return;}
 


  
  gradstring = Num2String(Math.abs(grad),4,-10,10,-4,4); 
  f.grad.value = gradstring;
  f.degrees.value = Num2String(degrees,4,-10,10,-4,4);
  f.headRange.value = Num2String(range,4,-10,10,-4,4);
  f.points.value = numb;
  f.r2.value = Num2String(r2,3,-10,10,-4,4);

  if (data == "save") 
   {
     /*
     //save the gradient result
     Ent[0] = gradstring;
     save ("gr",Ent);
     */
   }

}
//-->
<!-- end gradient4plus-ns_1.js -->