﻿/* A collection of handy GIS javascript tools. Compiled by David Raybuck.
 */

var GeoTools = {};

GeoTools.DecimalDegreesToStatePlane = function(latitude, longitude){
	//draybuck:  8/6/2009
	//this code was originally created by Gerry Daumiller in ASP at http://nris.state.mt.us/gis/projection/projection.html.
	//it was converted to javasript at http://forums.esri.com/Thread.asp?c=64&f=786&t=75144 by author David Renz and was modified
	//using another author's suggestion of adding a Y0 value for the false northing and adding "+ Y0" at the end of the 'y =' line
	//the coordinate system parameters were then adjusted to North Central Texas 4202.
	
	var Lat = latitude;
    var Lon = longitude;
  
    //' Set up the coordinate system parameters.
    var a = 6378137; 								//' major radius of ellipsoid, map units (NAD 83)
    var e = 0.08181922146; 							//' eccentricity of ellipsoid (NAD 83)
    var angRad = 0.01745329252; 					//' number of radians in a degree
    var pi4 = (3.141592653582 / 4); 				//' Pi / 4
    var p0 = (31.666666666 * angRad);        		//' latitude of origin
    var p1 = (32.133333333 * angRad);               //' latitude of first standard parallel
    var p2 = (33.966666666 * angRad); 						//' latitude of second standard parallel
    var m0 = (-98.5 * angRad); 		 			//' central meridian
    var X0 = 600000; 							//' False easting of central meridian, map units
    var Y0 = 2000000;                           //'False northing
    //' Calculate the coordinate system constants.
    var m1 = Math.cos(p1) / Math.sqrt(1 - (Math.pow(e, 2) * Math.pow(Math.sin(p1), 2)));
    var m2 = Math.cos(p2) / Math.sqrt(1 - (Math.pow(e, 2) * Math.pow(Math.sin(p2), 2)));
    var t0 = Math.tan(pi4 - (p0 / 2));
    var t1 = Math.tan(pi4 - (p1 / 2));
    var t2 = Math.tan(pi4 - (p2 / 2));
    t0 = t0 / Math.pow(((1 - (e * (Math.sin(p0)))) / (1 + (e * (Math.sin(p0))))), (e / 2));
    t1 = t1 / Math.pow(((1 - (e * (Math.sin(p1)))) / (1 + (e * (Math.sin(p1))))), (e / 2));
    t2 = t2 / Math.pow(((1 - (e * (Math.sin(p2)))) / (1 + (e * (Math.sin(p2))))), (e / 2));
    var n = Math.log(m1 / m2) / Math.log(t1 / t2);
    var f = m1 / (n * Math.pow(t1, n));
    var rho0 = a * f * Math.pow(t0, n);
    //' Convert the latitude/longitude to a coordinate.
    Lat = Lat * angRad;
    Lon = Lon * angRad;
    var t = Math.tan(pi4 - (Lat / 2));
    t = t / Math.pow(((1 - (e * (Math.sin(Lat)))) / (1 + (e * (Math.sin(Lat))))), (e / 2));
    var rho = a * f * Math.pow(t, n);
    var theta = n * (Lon - m0);
    var x = (rho * Math.sin(theta)) + X0;
    var y = rho0 - (rho * Math.cos(theta)) + Y0;
    Lat = Lat / angRad;
    Lon = Lon / angRad;
    //'Round the coordinates
    x = (x * 100) / 100;
    y = (y * 100) / 100;
    Lat = (Lat * 100000) / 100000;
    Lon = (Lon * 100000) / 100000;
    //'Convert the X/Y values from meters to International Feet
    x = (x / 0.3048);
    y = (y / 0.3048);
    
    return {
		x: x,
		y: y
	}
}

/*** CALCULATE GEODESIC DISTANCES ***/

    /* ******************************************************** */
    /* The code for the GeodesicCalc class was copied from here: */
    /* http://pietschsoft.com/Blog/Post.aspx?PostID=1452        */
    /* ******************************************************** */
    var GeodesicCalc = {};
    GeodesicCalc.EarthRadiusInMiles = 3956.0;
    GeodesicCalc.EarthRadiusInKilometers = 6367.0;

    GeodesicCalc.ToRadian = function(v) {
        return v * (Math.PI / 180);
    };

    GeodesicCalc.DiffRadian = function(v1, v2) {
        return GeodesicCalc.ToRadian(v2) - GeodesicCalc.ToRadian(v1);
    };

    GeodesicCalc.CalcDistance = function(lat1, lng1, lat2, lng2, radius) {
        return radius * 2 * Math.asin(
                Math.min(1,
                    Math.sqrt(
                        (
                            Math.pow(Math.sin((GeodesicCalc.DiffRadian(lat1, lat2)) / 2.0), 2.0) +
                            Math.cos(GeodesicCalc.ToRadian(lat1)) * Math.cos(GeodesicCalc.ToRadian(lat2)) *
                            Math.pow(Math.sin((GeodesicCalc.DiffRadian(lng1, lng2)) / 2.0), 2.0)
                        )
                   )
               )
           );
    };
    
   GeodesicCalc.ToDegrees = function(radians){
   		return radians * 180 / Math.PI;
   }

    /* *************************************************************************** */
    /* This mathimatical code is a modified version of the code originally posted  */
    /* at the following location:                                                 */
    /* http://viavirtualearth.com/Wiki/Draw+a+circle.ashx                          */
    /* *************************************************************************** */
    GeodesicCalc.CreateCircle = function(loc, radius, units) {
        var earthRadius = parseFloat(units);
        var lat = GeodesicCalc.ToRadian(loc.Latitude); //radians
        var lon = GeodesicCalc.ToRadian(loc.Longitude); //radians
        var d = parseFloat(radius) / earthRadius;  // d = angular distance covered on earth's surface
        var locs = new Array();
        for (x = 0; x <= 360; x++) {
            var p2 = new VELatLong(0, 0)
            brng = GeodesicCalc.ToRadian(x); //radians

            var latRadians = Math.asin(Math.sin(lat) * Math.cos(d) + Math.cos(lat) * Math.sin(d) * Math.cos(brng));
            var lngRadians = lon + Math.atan2(Math.sin(brng) * Math.sin(d) * Math.cos(lat), Math.cos(d) - Math.sin(lat) * Math.sin(latRadians));

            locs.push(new VELatLong(GeodesicCalc.ToDegrees(latRadians), GeodesicCalc.ToDegrees(lngRadians)));
        }

        return new VEShape(VEShapeType.Polygon, locs);
    }

GeoTools.GeodesicCalc = GeodesicCalc; //add to GeoTools namespace

/*** END CALCULATE GEODESIC DISTANCES ***/
