//*****************************************************
// Functies voor het werken met coördinaten
//
// Martin Mollet, Apr 2008
//
// Versie historie 
// ----------------------------------------------------
// Versie Datum    Omschrijving
// ----------------------------------------------------
// 0.10   25Apr08  Eerste versie, met dank aan GPSGEK.NL
//                 voor de WGS <--> RD formules.
//            
// 
// 
//*****************************************************



//*****************************************************
//*****************************************************
//
// Definities
//
//*****************************************************
//*****************************************************


//*****************************************************
// TYPE definitie van alle kaartbladen van Nederland
//*****************************************************
function TKaart (KaartNr, XKm, YKm, Breedte)
{
   this.KaartNr= KaartNr;
   this.XKm=     XKm;
   this.YKm=     YKm;
   this.Breedte= Breedte;
}


//*****************************************************
// verdeling van NL in kaartbladen 
//*****************************************************
var KaartTab = new Array
(
   new TKaart( 0,140,650, 0),  //  ?
   new TKaart( 1,140,625,40),  //  0
   new TKaart( 4,100,600,40),  //  1
   new TKaart( 8,260,600,20),  //  2
   new TKaart( 9,100,575,40),  //  3
   new TKaart(13,260,575,20),  //  4
   new TKaart(14,100,550,40),  //  5
   new TKaart(18,260,550,20),  //  6
   new TKaart(19,100,525,40),  //  7
   new TKaart(23,260,525,20),  //  8
   new TKaart(24, 60,500,40),  //  9
   new TKaart(29,260,500,20),  // 12
   new TKaart(30, 60,475,40),  // 13
   new TKaart(35,260,475,20),  // 14
   new TKaart(36, 20,450,40),  // 15
   new TKaart(37, 60,450,40),  // 16
   new TKaart(42, 20,425,40),  // 17
   new TKaart(47,-20,400,20),  // 18  <<< neg waarden worden weggevangen
   new TKaart(48, 20,400,40),  // 19
   new TKaart(53,-20,375,20),  // 20  <<< neg waarden worden weggevangen
   new TKaart(54, 20,375,40),  // 21
   new TKaart(59,140,350,40),  // 25
   new TKaart(61,140,325,40),  // 27
   new TKaart(62,180,325,40)   // 28
);


//*****************************************************
// TYPE definition van een AtlasBlok
//*****************************************************
function TKmBlok (Kaart,Blok,KmBlok)
{
   this.Kaart= Kaart;
   this.Blok=  Blok;
   this.KmBlok= KmBlok;
}


//*****************************************************
// TYPE definition for AmCo (Amersfoort Coordinaat = RD)
//*****************************************************
function TAmCo (iX, iY)
{
   if (iX<1000) iX = iX*1000; 
   if (iY<1000) iY = iY*1000; 
 
   this.iAmCoX= iX;        // integer, in meters  
   this.iAmCoY= iY;        // integer, in meters  
}
 

//*****************************************************
// TYPE definition for WGS84 
//*****************************************************
function TWgs (rLat, rLong)
{
   this.rLat = rLat;       // float, degrees
   this.rLong = rLong;     // float, degrees
}


//*****************************************************
//*****************************************************
//
// Functies
//
//*****************************************************
//*****************************************************


//*****************************************************
//
//*****************************************************
function AmCoNaarKmBlok (AmCo)
{
   var KmBlok= new TKmBlok(1,2,3);
   var i;
   var iKaartXOffset;
   var iCheckAmCoY;
   var iCheckAmCoX;
   var iBlokX;
   var iBlokY;
   var KTAB_LEN=29;
   var AmCoX;
   var AmCoY;

   if (AmCo.iAmCoX>1000) AmCo.iAmCoX = AmCo.iAmCoX /1000;
   if (AmCo.iAmCoY>1000) AmCo.iAmCoY = AmCo.iAmCoY /1000;

   AmCoX= Math.floor(AmCo.iAmCoX);
   AmCoY= Math.floor(AmCo.iAmCoY);

   for (i=0; i<KTAB_LEN; i++)  // zoek regel kaarten op
   {
      if ((KaartTab[i].YKm-25)<=AmCoY)
         break;
   }

   if ( (i<KTAB_LEN) && (KaartTab[i].KaartNr>0) && (KaartTab[i].XKm<=AmCoX) )
   { // geldig coord
      KmBlok.Kaart= KaartTab[i].KaartNr;

      if (KaartTab[i].Breedte==20)
      {
         if ((AmCoX-KaartTab[i].XKm)>=20)
         {
            i++;
            KmBlok.Kaart= KaartTab[i].KaartNr;
            iKaartXOffset = Math.floor((AmCoX-KaartTab[i].XKm)/40);
         }
      }
      else
      {
        iKaartXOffset = Math.floor((AmCoX-KaartTab[i].XKm)/40);
      }
      KmBlok.Kaart = KmBlok.Kaart + iKaartXOffset;
      iBlokX = AmCoX - (KaartTab[i].XKm + iKaartXOffset*40);
      iBlokY = KaartTab[i].YKm - AmCoY -1 ;
      KmBlok.Blok =  ((1+Math.floor(iBlokY/5)) *10) + (1+Math.floor(iBlokX/5));
      KmBlok.KmHok = (((iBlokY % 5)+1) *10) + ((iBlokX % 5)+1);
      return KmBlok;
   }
   else // coordinaat niet geldig
   {
      KmBlok.Kaart= -1;
      KmBlok.Blok=  -1;
      KmBlok.KmHok= -1;
      return KmBlok;
   }
} 



//*****************************************************
// 
//*****************************************************
function KmBlokNaarAmCo (KmBlok)
{
   var AmCo = new TAmCo(88,99);
   var i;
   var iXco;
   var iYco;
   var iXOffset;
   var iYOffset;
   var KTAB_LEN=29;

   iXOffset = (KmBlok.Blok%10 -1)*5 + (KmBlok.KmBlok%10-1);
   iYOffset = (Math.floor(KmBlok.Blok/10) -1)*5 + (Math.floor(KmBlok.KmBlok/10)-1);

   for (i=0; i<KTAB_LEN; i++)
   {
      if (KaartTab[i].KaartNr>KmBlok.Kaart)
         break;
   }

   //alert("KmHok " + KmBlok.Kaart + "-" + KmBlok.Blok + "-" + KmBlok.KmBlok + " KaartTab=" + i + " OffX=" + iXOffset + " Y=" + iYOffset + "!");

   if ( (i<KTAB_LEN) && (KaartTab[i].KaartNr>0) )
   {
      i--;
      iXco = KaartTab[i].XKm + 40*(KmBlok.Kaart-KaartTab[i].KaartNr);
      iYco = KaartTab[i].YKm;
      AmCo.iAmCoX = iXco + iXOffset;
      AmCo.iAmCoY = iYco - iYOffset-1;
      //alert("if KmHok " + KmBlok.Kaart + "-" + KmBlok.Blok + "-" + KmBlok.KmBlok + " KaartTab=" + i + " OffX=" + iXOffset + " Y=" + iYOffset + "!");

   }
   else
   {
      AmCo.iAmCoX = iXOffset;
      AmCo.iAmCoY = iYOffset;
      //alert("else KmHok " + KmBlok.Kaart + "-" + KmBlok.Blok + "-" + KmBlok.KmBlok + " KaartTab=" + i + " OffX=" + iXOffset + " Y=" + iYOffset + "!");
   }

   return AmCo;
}







//*****************************************************
// Get WGS of lose meter coördinates
//   GetWgsOfMeterCoords(99000,414000)
//*****************************************************
function GetWgsOfMeterCoords (iX, iY)
{
   var recAmCo = new TAmCo(iX,iY);
 
   var TestWgs = GetWGS84(recAmCo);

   //alert("AmCo=" + recAmCo.iAmCoX + "/" + recAmCo.iAmCoY ); // +  "  >>> Lat " +  GetLatDegrees(TestWgs) + " ' " + GetLatMinutes(TestWgs) + "   Long " + GetLongDegrees(TestWgs) + " ' " + GetLongMinutes(TestWgs) );
   
   return(TestWgs);
}
 




//*****************************************************
// Get WGS84 value of AmCo (RD)
//*****************************************************
function GetWGS84 (recAmCo)
{
   var dX = (recAmCo.iAmCoX - 155000) * Math.pow(10,-5);
   var dY = (recAmCo.iAmCoY - 463000) * Math.pow(10,-5);
 
   var SomN = (3235.65389 * dY) + (-32.58297 * Math.pow(dX,2) ) + (-0.2475 * Math.pow(dY,2) ) + (-0.84978 * Math.pow(dX,2) * dY) + (-0.0655 * Math.pow(dY,3) ) + (-0.01709 * Math.pow(dX,2) * Math.pow(dY,2) ) + (-0.00738 * dX) + (0.0053 * Math.pow(dX,4) ) + (-0.00039 * Math.pow(dX,2) * Math.pow(dY,3) ) + (0.00033 * Math.pow(dX,4) * dY) + (-0.00012 * dX * dY);
   var SomE = (5260.52916 * dX) + (105.94684 * dX * dY) + (2.45656 * dX * Math.pow(dY,2) ) + (-0.81885 * Math.pow(dX,3) ) + (0.05594 * dX * Math.pow(dY,3) ) + (-0.05607 * Math.pow(dX,3) * dY) + (0.01199 * dY) + (-0.00256 * Math.pow(dX,3) * Math.pow(dY,2) ) + (0.00128 * dX * Math.pow(dY,4) ) + (0.00022 * Math.pow(dY,2) ) + (-0.00022 * Math.pow(dX,2) ) + (0.00026 * Math.pow(dX,5) );
 
   var Latitude = 52.15517 + (SomN / 3600);
   var Longitude = 5.387206 + (SomE / 3600);
 
   var LatitudeGraden = Math.floor(Latitude)
   var LongitudeGraden = Math.floor(Longitude)
 
   var LatitudeMinuten = (Latitude - LatitudeGraden) * 60.0
   var LongitudeMinuten = (Longitude - LongitudeGraden) * 60.0
 
   //alert(" AmCo=" + recAmCo.iAmCoX + "/" + recAmCo.iAmCoY +  "  >>> Lat " + LatitudeGraden + " ' " + LatitudeMinuten+  "  Long " + LongitudeGraden + " ' " + LongitudeMinuten );
 
   var recWgs= new TWgs(Latitude,Longitude);
 
   return (recWgs);
}
 

//*****************************************************
// Get AmCo (RD) value of WGS co-ord
//*****************************************************
function GetAmCo (recWgs)
{
   var Latitude = recWgs.rLat;
   var Longitude = recWgs.rLong;
 
   var dF = 0.36 * (Latitude - 52.15517440);
   var dL = 0.36 * (Longitude - 5.38720621);
 
   var SomX= (190094.945 * dL) + (-11832.228 * dF * dL) + (-144.221 * Math.pow(dF,2) * dL) + (-32.391 * Math.pow(dL,3)) + (-0.705 * dF) + (-2.340 * Math.pow(dF,3) * dL) + (-0.608 * dF * Math.pow(dL,3)) + (-0.008 * Math.pow(dL,2)) + (0.148 * Math.pow(dF,2) * Math.pow(dL,3));
   var SomY = (309056.544 * dF) + (3638.893 * Math.pow(dL,2)) + (73.077 * Math.pow(dF,2) ) + (-157.984 * dF * Math.pow(dL,2)) + (59.788 * Math.pow(dF,3) ) + (0.433 * dL) + (-6.439 * Math.pow(dF,2) * Math.pow(dL,2)) + (-0.032 * dF * dL) + (0.092 * Math.pow(dL,4)) + (-0.054 * dF * Math.pow(dL,4));
 
   var X = Math.round(155000 + SomX);
   var Y = Math.round(463000 + SomY);
 
   var recAmCo= new TAmCo(X,Y);
 
   //alert(" AmCo=" + recAmCo.iAmCoX + "/" + recAmCo.iAmCoY);
 
   return (recAmCo);
}
 
 
//*****************************************************
// Get Longitude degrees of WGS84
//*****************************************************
function GetLongDegrees (recWgs)
{
   return( Math.floor(recWgs.rLong) );
}

 
//*****************************************************
// Get Longitude minutes of WGS84
//*****************************************************
function GetLongMinutes (recWgs)
{
   var iDegrees = Math.floor(recWgs.rLong);
   return( recWgs.rLong - iDegrees) * 60.0;
}

 
//*****************************************************
// Get Latitude degrees of WGS84
//*****************************************************
function GetLatDegrees (recWgs)
{
   return( Math.floor(recWgs.rLat) );
}

 
//*****************************************************
// Get Latitude minutes of WGS84
//*****************************************************
function GetLatMinutes (recWgs)
{
   var iDegrees = Math.floor(recWgs.rLat);
   return( recWgs.rLat - iDegrees) * 60.0;
}
 
