//Function: converting coordinates between state plane and geograohic
//          Converts from/to latitude/Longitude to/from Delaware State Plane Coordinates.
//          values for latitude of first standard parallel and latitude of second standard parallel
//          are predicted by John R. Collier from DelDOT GIS survey section, because those two values are not
//          required in the project for State of Delaware.
//          The formulae this program is based on are from "Map Projections,
//          A Working Manual" by John P. Snyder, U.S. Geological Survey
//          Professional Paper 1395, 1987, pages 295-298
//          code: // Code based on asp code from Gerry Daumiller, Montana State Library 8-23-02 email. 
//          ASP code on web at http://nris.state.mt.us/gis/projection/projection.html.  
//Modified by Li Luo

var a = 6378206.4;               //major radius of ellipsoid, map units in meters (NAD 83)
var ec = 0.08181905782;          //eccentricity of ellipsoid (NAD 83)
var angRad = 0.01745329252;      //number of radians in a degree
var pi4 = Math.PI / 4.0;
var p0 = 38 * angRad;            //latitude of origin (Delaware)
var p1 = 38.5 * angRad;          //latitude of first standard parallel (predicted)
var p2 = 40 * angRad;            //latitude of second standard parallel (predicted)
var m0 = - 75.41666667 * angRad; //central meridian (Delaware)
var x0 = 200000;                 //False easting of central meridian, map units (Delaware)

var dLat;
var mLat;
var sLat;
var dLon;
var mLon;
var sLon;
var latDD;
var lonDD;

function mapToLatLon ( uX, uY ) {
	uX = uX/3.2808399;
	uY = uY/3.2808399;
    // Calculate the coordinate system constants.
    with ( Math ) {
        m1 = cos(p1) / sqrt(1 - (pow(ec, 2)) * pow(sin(p1), 2));
        m2 = cos(p2) / sqrt(1 - (pow(ec, 2)) * pow(sin(p2), 2));
        t0 = tan(pi4 - (p0 / 2));
        t1 = tan(pi4 - (p1 / 2));
        t2 = tan(pi4 - (p2 / 2));
        t0 = t0 / pow(((1 - (ec * (sin(p0)))) / (1 + (ec * (sin(p0))))), ec / 2);
        t1 = t1 / pow(((1 - (ec * (sin(p1)))) / (1 + (ec * (sin(p1))))), ec / 2);
        t2 = t2 / pow(((1 - (ec * (sin(p2)))) / (1 + (ec * (sin(p2))))), ec / 2);
        n = log(m1 / m2) / log(t1 / t2);
        f = m1 / (n * pow(t1, n));
        rho0 = a * f * pow(t0, n);

        // Convert the coordinate to Lat/Lon

        // Calculate the Longitude.
        uX = uX - x0;
        pi2 = pi4 * 2;

        rho = sqrt(pow(uX, 2) + pow((rho0 - uY), 2));
        theta = atan(uX / (rho0 - uY));
        txy = pow((rho / (a * f)), (1 / n));
        lon = (theta / n) + m0;
        uX = uX + x0;

        // Estimate the Latitude
        lat0 = pi2 - (2 * atan(txy));

        // Substitute the estimate into the iterative calculation that
        // converges on the correct Latitude value.
        part1 = (1 - (ec * sin(lat0))) / (1 + (ec * sin(lat0)));
        lat1 = pi2 - (2 * atan(txy * pow(part1, (ec / 2))));

        while ( (abs(lat1 - lat0)) > 0.000000002 ) {
            lat0 = lat1;
            part1 = (1 - (ec * sin(lat0))) / (1 + (ec * sin(lat0)));
            lat1 = pi2 - (2 * atan(txy * pow(part1, (ec / 2))));
        }

        // Convert from radians to degrees.
        Lat = lat1 / angRad;
        Lon = lon / angRad;
        //window.status = "Lat: " + ddToDegree(Lat, true) + " Lon: " + ddToDegree(Lon, false);
        return "<b> Lat: </b>" + Lat.toFixed(6) + "<br><b> Lon: </b>" + Lon.toFixed(6); //+latlonToMap(Lat, Lon);
    }
}

function latlonToMap ( x, y ) {
    var lat = x;
    var lon = y;

    with ( Math ) {
        m1 = cos(p1) / sqrt(1 - (pow(ec, 2)) * pow(sin(p1), 2));
        m2 = cos(p2) / sqrt(1 - (pow(ec, 2)) * pow(sin(p2), 2));
        t0 = tan(pi4 - (p0 / 2));
        t1 = tan(pi4 - (p1 / 2));
        t2 = tan(pi4 - (p2 / 2));
        t0 = t0 / pow(((1 - (ec * (sin(p0)))) / (1 + (ec * (sin(p0))))), ec / 2);
        t1 = t1 / pow(((1 - (ec * (sin(p1)))) / (1 + (ec * (sin(p1))))), ec / 2);
        t2 = t2 / pow(((1 - (ec * (sin(p2)))) / (1 + (ec * (sin(p2))))), ec / 2);
        n = log(m1 / m2) / log(t1 / t2);
        f = m1 / (n * pow(t1, n));
        rho0 = a * f * pow(t0, n);

        //Convert the latitude/longitude to a coordinate.
        lat = lat * angRad;
        lon = lon * angRad;
        t = tan(pi4 - (lat / 2));
        t = t / (pow(((1 - (ec * (sin(lat)))) / (1 + (ec * (sin(lat))))), (ec / 2)));
        rho = a * f * pow(t, n);
        theta = n * (lon - m0);
        x = (rho * sin(theta)) + x0;
        y = rho0 - (rho * cos(theta));

        lat = lat / angRad;
        lon = lon / angRad;

        //Round the coordinates
        x = (round(x * 100)) / 100;
        y = (round(y * 100)) / 100;
        lat = (round(lat * 100000)) / 100000;
        lon = (round(lon * 100000)) / 100000;
        latDD = x;
        lonDD = y;
        return "<b>X:</b> " + x + "	<b>Y:</b> " + y;
    }
}

//convert decimal degree format of lat/lon into degree, minutes, seconds
function ddToDegree ( dd, isLat ) {
    if ( isLat ) {
        if ( dd < 0 )
            sDir = "S";

        else
            sDir = "N";
    } else {
        if ( dd < 0 )
            sDir = "W";

        else
            sDir = "E";
    }

    var d = getIntegerOnly(dd);
    var m = 60 * (dd - d);
    var s = 60 * (m - getIntegerOnly(m));
    return d + "\u00b0" + getIntegerOnly(Math.abs(m)) + "' " + getIntegerOnly(Math.abs(s)) + "\" " + sDir;
}

//convert degree, minutes, seconds format of lat/lon into decimal degree
function degreeToDD () {
    if ( mLat == "" )
        mLat = 0;

    if ( sLat == "" )
        sLat = 0;

    latDD = parseFloat(dLat) + mLat / 60 + sLat / 3600;

    if ( dLon > 0 )
        dLon = 0 - dLon;

    if ( mLon == "" )
        mLon = 0;

    if ( sLon == "" )
        sLon = 0;

    lonDD = dLon - mLon / 60 - sLon / 3600;
}

//get the integer part of the decimal value for degree munites and seconds calculation
function getIntegerOnly ( xy ) {
    //debugger;
    if ( Math.abs(Math.round(xy)) - Math.abs(xy) > 0 ) {
        if ( xy > 0 )
            return Math.round(xy) - 1;

        else
            return Math.round(xy) + 1;
    } else {
        return Math.round(xy);
    }
}

//convert degree values into map coordinates
function findLocation ( source ) {
    //get the value from user's input
    dLat = document.all.dLat.value;
    mLat = document.all.mLat.value;
    sLat = document.all.sLat.value;
    dLon = document.all.dLon.value;
    mLon = document.all.mLon.value;
    sLon = document.all.sLon.value;
    latDD = document.all.latitudedd.value;
    lonDD = document.all.longitudedd.value;
    xm = document.all.x.value;
    ym = document.all.y.value;

    //convert degree minutes seconds into decimal values, 
    //then convert it to map coordinates through latlonToMap() function
    if ( source == "dms" ) {
        if ( dLat == "" ) {
            alert("Please Enter the Correct Latitude Value!");
        }

        if ( dLon == "" ) {
            alert("Please Enter the Correct Longitude Value!");
        } else {
            //convert to decimal value first then calculate the map coordinates
            degreeToDD();
            latlonToMap(latDD, lonDD);
            //alert(latDD+"|"+lonDD);
            window.opener.zoomToGPS(latDD, lonDD);
        }
    } else if ( source == "dd" ) {
        if ( document.all.latitudedd.value == "" ) {
            alert("Please Enter the Correct Latitude Value!");
        }

        if ( document.all.longitudedd.value == "" ) {
            alert("Please Enter the Correct Longitude Value!");
        } else {
            latlonToMap(latDD, lonDD);
            //alert(latDD+"|"+lonDD);
            window.opener.zoomToGPS(latDD, lonDD);
        }
    } else if ( source == "meter" ) {
        if ( document.all.x.value == "" ) {
            alert("Please Enter the Correct X Value!");
        }

        if ( document.all.y.value == "" ) {
            alert("Please Enter the Correct Y Value!");
        } else {
            window.opener.zoomToGPS(xm, ym);
        }
    } else if ( source == "utm" ) {
        var latlon = btnToGeographic_OnClick(document.all.utmX.value, document.all.utmY.value, document.all.zone.value);

        latlonToMap(latlon[0], latlon[1]);

        window.opener.zoomToGPS(latDD, lonDD);
    }
}
