﻿//--------------------------------------------
// DrawingTools.js
//--------------------------------------------
// Drawing/ measure tools for Virtual Earth
//--------------------------------------------
// Mike Juniper - April, 2008
// Data Transfer Solutions
//--------------------------------------------
//TODO: make this self contained - put the markup for the ui in this file too
//TODO: drag & drop shapes

var DrawingTools = function()
{
    var _map = null;
    var slDrawing = new VEShapeLayer();
    var _geomType = null;
    var drawShape = null;
    var shapePoints = null;
    var totalDistance = null;
    var tempShape = null;
    var tempDistance = null;
    var circlePoints = null;
    var tempCircle = null;
    var i = 1;
    var floatDistDiv = null;
    var totalDistanceDiv = null;

    var _lineColor = new VEColor(0, 0, 255, 0.5);
    var _lineWeight = 2;
    var _fillColor = new VEColor(0, 128, 0, 0.3);
    var _fontColor = 'blue';
    var _fontSize = '20';
    var _fontWeight = 'normal';
    var _pushpinCSSClass = null;
    var _pushpinIcon = null;

    var EARTHRADIUS = 6378137; // in metres
    var SQMTOSQKM = 0.000001; //conversion factor
    var SQMTOSQMI = 0.000000386102159; //conversion factor

    return {

        Init: function(map)
        {
            _map = map.GetMap();
            slDrawing.SetTitle('Drawing');
            _map.AddShapeLayer(slDrawing);
            _map.AttachEvent('onmouseover', this.ShapeMouseOver);
            this.SetPointColor('red');
        },

        //Starts drawing the specified geomType
        Draw: function(geomType)
        {
            //initialize variables
            shapePoints = new Array();
            tempPoints = null;
            totalDistance = { mi: 0, km: 0 };
            tempDistance = { mi: 0, km: 0 };

            floatDistDiv = document.getElementById("floatingDistance");
            if (_map.GetMapStyle() == 'a' || _map.GetMapStyle() == 'h')
                floatDistDiv.className = 'light';
            else floatDistDiv.className = 'dark';

            totalDistanceDiv = document.getElementById("txtTotalDistance")
            totalDistanceDiv.innerHTML = " ";

            _geomType = geomType;


            this.MouseClickDelegate = Function.createDelegate(this, this.DrawPolyMouseClick);
            _map.AttachEvent("onclick", this.MouseClickDelegate);

            this.MouseMoveDelegate = Function.createDelegate(this, this.MouseMove);
            _map.AttachEvent("onmousemove", this.MouseMoveDelegate);
        },

        //Hanlder for onmousemove events - forces the cursor to be a crosshair while drawing
        MouseMove: function(e)
        {
            document.getElementById("veMap").style.cursor = 'crosshair';
        },

        //Handler for onclick events - captures click points for shape
        DrawPolyMouseClick: function(e)
        {
            //get the pixel and latlon
            var x = e.mapX;
            var y = e.mapY;
            var pixel = new VEPixel(x, y);
            var LL = _map.PixelToLatLong(pixel);

            //if it's the first point and not the only point
            if (shapePoints.length == 0 && _geomType != "point" && _geomType != "label")
            {
                this.MouseMoveDelegate2 = Function.createDelegate(this, this.DrawPolyMouseMove);
                _map.AttachEvent("onmousemove", this.MouseMoveDelegate2);

                //            this.DblClickDelegate = Function.createDelegate(this, this.FinishSketch);
                //            _map.AttachEvent("ondoubleclick", this.DblClickDelegate);

                floatDistDiv.style.visibility = "visible";
            }

            //if it's the second point and we're drawing a circle
            if (_geomType == "circle" && shapePoints.length == 2)
            {
                //replace the second point and update the distance
                shapePoints[1] = LL;
                totalDistance = tempDistance; //TODO: calculate the distance here instead of using tempDistance to be sure it's right
            }
            else
            {
                //add the point to the collection and update the distance
                shapePoints.push(LL);
                totalDistance = this.AddDistances(totalDistance, tempDistance); //TODO: calculate the distance here instead of using tempDistance to be sure it's right
            }

            //If we're drawing a point finish the sketch
            if (_geomType == "point" || _geomType == "label") this.FinishSketch(e);

            if (e.rightMouseButton) this.FinishSketch(e);
        },

        //Handler for onmousemove events - keeps track of total distance and draws rubberband
        DrawPolyMouseMove: function(e)
        {
            //get the pixel and latlon
            var x = e.mapX;
            var y = e.mapY;
            var pixel = new VEPixel(x, y);
            var LL = _map.PixelToLatLong(pixel);

            //copy the point collection - use it to draw the 'rubberband'
            var tempPoints = shapePoints.slice(0);

            //if it's a circle and there are already 2 points in the array...
            if (_geomType == "circle" && tempPoints.length == 2)
            {
                tempPoints[1] = LL; //replace the second point
                tempDistance = this.getDistance(tempPoints[0], LL); //update the distance
            }
            else    //if it's not a circle OR there are not 2 points in the array...
            {
                tempPoints.push(LL);    //add the point to the collection
                tempDistance = this.getDistance(tempPoints[shapePoints.length - 1], LL); //update the distance
            }

            //update the distance measures
            var formattedDistance = this.GetFormattedDistance(this.AddDistances(totalDistance, tempDistance));

            floatDistDiv.style.left = e.clientX + 12 + "px";
            floatDistDiv.style.top = e.clientY + 7 + "px";
            floatDistDiv.innerHTML = formattedDistance.replace('|', '<br />');

            totalDistanceDiv.innerHTML = formattedDistance.replace('|', '/ ');

            //Draw rubberband
            this.DrawRubberband(tempPoints);
        },

        //Draws the rubberband from tempPoints
        DrawRubberband: function(tempPoints)
        {
            //delete temp shapes
            if (tempShape) slDrawing.DeleteShape(tempShape);
            if (tempCircle) slDrawing.DeleteShape(tempCircle);

            //if this is the second point in the array, draw a 'rubberband'
            if (tempPoints.length == 2)
            {   //draw a polyline (first segment of polyline or polygon, radius of circle)
                tempShape = new VEShape(VEShapeType.Polyline, tempPoints);
                tempShape.HideIcon();
                slDrawing.AddShape(tempShape);

                if (_geomType == "circle")
                {   //if we're drawing a circle, draw it with the current radius
                    this.GetCircle();
                    tempCircle = new VEShape(VEShapeType.Polygon, circlePoints);
                    tempCircle.HideIcon();
                    slDrawing.AddShape(tempCircle);
                }
            }

            //if this is the third point or greater
            if (tempPoints.length > 2)
            {
                switch (_geomType)
                {
                    case "polygon":
                        tempShape = new VEShape(VEShapeType.Polygon, tempPoints);
                        break;
                    case "polyline":
                        tempShape = new VEShape(VEShapeType.Polyline, tempPoints);
                        break;
                }
                tempShape.HideIcon();
                slDrawing.AddShape(tempShape);
            }
        },

        //Handler for ondoubleclick events - draws the sketch, deleting the rubberband
        FinishSketch: function(e)
        {
            //get the pixel and latlon
            var x = e.mapX;
            var y = e.mapY;
            var pixel = new VEPixel(x, y);
            var LL = _map.PixelToLatLong(pixel);

            //Detach the events
            if (this.MouseClickDelegate) _map.DetachEvent("onclick", this.MouseClickDelegate);
            if (this.MouseMoveDelegate) _map.DetachEvent("onmousemove", this.MouseMoveDelegate);
            if (this.MouseMoveDelegate2) _map.DetachEvent("onmousemove", this.MouseMoveDelegate2);
            if (this.DblClickDelegate) _map.DetachEvent("ondoubleclick", this.DblClickDelegate);

            //hide the floating distance measure
            floatDistDiv.style.visibility = "hidden";

            //delete the 'rubberbands'
            if (tempShape) slDrawing.DeleteShape(tempShape);
            if (tempCircle) slDrawing.DeleteShape(tempCircle);

            //create the shapes and update the distance divs
            switch (_geomType)
            {
                case "polygon":
                    drawShape = new VEShape(VEShapeType.Polygon, shapePoints);
                    drawShape.SetLineWidth(_lineWeight); //need to set this here - an exception is thrown if we try to set it on a point
                    totalDistanceDiv.innerHTML = this.GetFormattedDistance(null, drawShape).replace('|', '/ ');
                    break;
                case "polyline":
                    drawShape = new VEShape(VEShapeType.Polyline, shapePoints);
                    drawShape.SetLineWidth(_lineWeight); //need to set this here - an exception is thrown if we try to set it on a point
                    totalDistanceDiv.innerHTML = this.GetFormattedDistance(totalDistance).replace('|', '/ ')
                    break;
                case "circle":
                    drawShape = new VEShape(VEShapeType.Polygon, circlePoints);
                    drawShape.SetLineWidth(_lineWeight); //need to set this here - an exception is thrown if we try to set it on a point
                    totalDistanceDiv.innerHTML = this.GetFormattedDistance(null, drawShape).replace('|', '/ ')
                    break;
                case "point":
                case "label":
                    drawShape = new VEShape(VEShapeType.Pushpin, LL);
                    drawShape.SetCustomIcon(_pushpinIcon);
                    totalDistanceDiv.innerHTML = "Lat: " + LL.Latitude.toFixed(3) + ", Lon: " + LL.Longitude.toFixed(3);
                    break;
            }
            //draw the shape
            drawShape.HideIcon();
            drawShape.SetLineColor(_lineColor);
            drawShape.SetFillColor(_fillColor);
            slDrawing.AddShape(drawShape);

            //draw the dialog that allows the user to set shape properties
            dijit.byId('shapeDetailsDialog').show();

            //reset the cursor
            document.getElementById("veMap").style.cursor = 'http://maps.live.com/cursors/grab.cur';

            //return true to cancel default map double-click behavior
            return true;
        },

        DrawingLayer: slDrawing,

        //Returns the markup for a pushpin's custom icon (for geomType == label)
        GetLabelMarkup: function()
        {
            //need to adjust vertical position
            var topMargin;
            switch (_fontSize)
            {
                case '14':
                    topMargin = 3;
                    break;
                case '20':
                    topMargin = -2;
                    break;
                case '28':
                    topMargin = -5;
                    break;
                default:
                    topMargin = -2
            }
            var markup = dojo.string.substitute('<div style="font-size:${0}px;font-weight:${1};color:${2};padding-left:12px;margin-top:${3}px;white-space:nowrap;">${4}</div>', [_fontSize, _fontWeight, _fontColor, topMargin, dojo.byId('txtShapeTitle').value]);

            return markup;
        },

        //Calculates the distance between 2 VELatLon objects
        //adapted from http://www.movable-type.co.uk/scripts/latlong.html
        getDistance: function(p1, p2)
        {
            p1Lat = this.degreesToRadians(p1.Latitude);
            p1Lon = this.degreesToRadians(p1.Longitude);

            p2Lat = this.degreesToRadians(p2.Latitude);
            p2Lon = this.degreesToRadians(p2.Longitude);

            var R = 6371; // earth's mean radius in km
            var dLat = p2Lat - p1Lat;
            var dLong = p2Lon - p1Lon;
            var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(p1Lat) * Math.cos(p2Lat) * Math.sin(dLong / 2) * Math.sin(dLong / 2);
            var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

            var disKm = R * c;
            var disMiles = disKm * 0.6214;

            var distance = { mi: disMiles, km: disKm };

            return (distance);
        },

        //Converts degrees to radians
        degreesToRadians: function(deg)
        {
            return deg * Math.PI / 180;
        },

        GetFormattedArea: function(shape)
        {
            var returnDistance;
            switch (_geomType)
            {
                case 'label':
                case 'point':
                case 'polyline':
                    break;
                case 'polygon':
                case 'circle':
                    returnDistance = 'Area: ' + this.CalculateArea(shape, true).mi.toFixed(3) + ' sq mi| ' + this.CalculateArea(shape, true).km.toFixed(3) + ' sq km';
                    break;
            }
            return returnDistance;
        },

        GetFormattedLength: function(distance)
        {
            var returnDistance;
            switch (_geomType)
            {
                case 'label':
                case 'point':
                    break;
                case 'polyline':
                    returnDistance = 'Distance: ' + distance.mi.toFixed(3) + ' mi|' + distance.km.toFixed(3) + ' km';
                    break;
                case 'polygon':
                    returnDistance = 'Length: ' + distance.mi.toFixed(3) + ' mi|' + distance.km.toFixed(3) + ' km';
                    break;
                case 'circle':
                    returnDistance = 'Radius: ' + distance.mi.toFixed(3) + ' mi|' + distance.mi.toFixed(3) + ' km';
                    break;
            }
            return returnDistance;
        },

        //Formats a distance object as a string appropriate for the geometry type
        GetFormattedDistance: function(distance, shape)
        {
            if (distance) return this.GetFormattedLength(distance);
            else if (shape) return this.GetFormattedArea(shape);
            else return '';
        },

        //Adds two distance objects together
        AddDistances: function(distance1, distance2)
        {
            var returnDistance = new Object;
            returnDistance.mi = distance1.mi + distance2.mi;
            returnDistance.km = distance1.km + distance2.km;
            return returnDistance;
        },

        //Draws a circle
        GetCircle: function()
        {
            var R = 6371; // earth's mean radius in km
            var lat = (shapePoints[0].Latitude * Math.PI) / 180; //rad
            var lon = (shapePoints[0].Longitude * Math.PI) / 180; //rad
            var d = parseFloat(tempDistance.km) / R;  // d = angular distance covered on earth's surface
            circlePoints = new Array();
            for (x = 0; x <= 360; x++)
            {
                var p2 = new VELatLong(0, 0)
                brng = x * Math.PI / 180; //rad
                p2.Latitude = Math.asin(Math.sin(lat) * Math.cos(d) + Math.cos(lat) * Math.sin(d) * Math.cos(brng));
                p2.Longitude = ((lon + Math.atan2(Math.sin(brng) * Math.sin(d) * Math.cos(lat), Math.cos(d) - Math.sin(lat) * Math.sin(p2.Latitude))) * 180) / Math.PI;
                p2.Latitude = (p2.Latitude * 180) / Math.PI;
                circlePoints.push(p2);
            }
            return circlePoints;
        },

        //Sets the title and description of drawShape
        SetInfo: function()
        {
            drawShape.SetTitle(dojo.byId('txtShapeTitle').value);
            drawShape.GMEDrawingType = drawShape.Type;
            drawShape.GMEIconClass = _pushpinCSSClass;
            drawShape.GMEFontColor = _fontColor;
            drawShape.GMEFontSize = _fontSize;
            drawShape.GMEFontWeight = _fontWeight;

            var totalDistance

            if (_geomType == 'polygon' || _geomType == 'circle')
            {
                var polyArea = this.GetFormattedDistance(null, drawShape);
                drawShape.SetDescription(document.getElementById('txtShapeDetails').value + '<br /><br />' + polyArea.replace('| ', '<br />') + '<br /><br /><a onclick="DrawingTools.Delete(\'' + drawShape.GetID() + '\')">Delete</a>');
            }
            else
            {
                drawShape.SetDescription(document.getElementById('txtShapeDetails').value + '<br /><br />' + dojo.byId('txtTotalDistance').innerHTML.replace('/ ', '<br />') + '<br /><br /><a onclick="DrawingTools.Delete(\'' + drawShape.GetID() + '\')">Delete</a>');
            }
            if (_geomType == 'label')
            {
                var icon = this.GetLabelMarkup();
                drawShape.SetCustomIcon(icon);
                drawShape.GMEDrawingType = 'Label';
            }

            this.StopDrawing();

            dojo.byId('txtShapeTitle').value = '';
            dojo.byId('txtShapeDetails').value = '';

            dijit.byId('shapeDetailsDialog').hide();
        },

        //Disables all event handlers
        StopDrawing: function()
        {
            shapePoints = [];
            tempPoints = null;
            circlePoints = null
            totalDistance = null;
            tempDistance = null;

            if (this.MouseClickDelegate) _map.DetachEvent("onclick", this.MouseClickDelegate);
            if (this.MouseMoveDelegate) _map.DetachEvent("onmousemove", this.MouseMoveDelegate);
            if (this.MouseMoveDelegate2) _map.DetachEvent("onmousemove", this.MouseMoveDelegate2);
            if (this.DblClickDelegate) _map.DetachEvent("ondoubleclick", this.DblClickDelegate);

            drawShape = null;
            if (tempShape) slDrawing.DeleteShape(tempShape);
            tempShape = null;
            if (tempCircle) slDrawing.DeleteShape(tempCircle);
            tempCircle = null;

            if (floatDistDiv) floatDistDiv.innerHTML = "";
            if (totalDistanceDiv) totalDistanceDiv.innerHTML = "";
        },

        //Cancels saving a shape
        CancelShape: function()
        {
            slDrawing.DeleteShape(drawShape);
            dijit.byId('shapeDetailsDialog').hide();
            totalDistanceDiv.innerHTML = ' ';
            this.StopDrawing();
        },

        //Deletes the shape
        Delete: function(shapeId)
        {
            var delShape = slDrawing.GetShapeByID(shapeId);
            _map.HideInfoBox(delShape);
            slDrawing.DeleteShape(delShape);
        },

        //Handler for mouseover events - shows the shape's infobox
        ShapeMouseOver: function(e)
        {
            if (e.elementID)
            {
                var shape = _map.GetShapeByID(e.elementID);
                if (shape)
                {
                    var layer = shape.GetShapeLayer();
                    if (layer == slDrawing) _map.ShowInfoBox(shape)
                }
            }
        },

        //Delete all shapes in the drawing layer
        DeleteAll: function()
        {
            slDrawing.DeleteAllShapes();
            if (totalDistanceDiv) totalDistanceDiv.innerHTML = " ";
        },

        //Set globals
        SetLineColor: function(lineColor) { _lineColor = lineColor; },
        SetLineWeight: function(lineWeight) { _lineWeight = lineWeight; },
        SetFillColor: function(fillColor) { _fillColor = fillColor; },
        SetFontColor: function(fontColor) { _fontColor = fontColor; },
        SetFontSize: function(fontSize) { _fontSize = fontSize; },
        SetFontWeight: function(fontWeight) { _fontWeight = fontWeight; },
        SetPointColor: function(color)
        {
            var cssClass;
            switch (color)
            {
                case 'black':
                    cssClass = 'blackpin';
                    break;
                case 'red':
                    cssClass = 'redpin';
                    break;
                case 'green':
                    cssClass = 'greenpin';
                    break;
                case 'blue':
                    cssClass = 'bluepin';
                    break;
                case 'yellow':
                    cssClass = 'yellowpin';
                    break;
            }

            var markup = this.GetCustomIcon(cssClass);

//            if (dojo.isIE == 6)
//                markup = this.GetCustomIconIE6(cssClass) //'<div class="' + cssClass + 'IE6"></div>';
//            else
//                markup = '<div class="' + cssClass + '"></div>';

            _pushpinCSSClass = cssClass;
            _pushpinIcon = markup;
        },

        GetCustomIcon: function(cssClass)
        {
            var markup;

            if (dojo.isIE == 6)
            {
                markup = this.GetCustomIconIE6(cssClass);
            }
            else
            {
                markup = '<div class="' + cssClass + '"></div>';
            }

            return markup;
        },

        GetCustomIconIE6: function(pinclass)
        {
            var strHtml = '<div style="margin-left: 8px;margin-top:8px; filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + gmePath + 'css/images/{0}.png\', sizingMethod=\'image\'); height:8px; width:8px;"></div>';
            return strHtml.replace('{0}', pinclass);
        },

        //===Area Calculation===
        GetMedianCentroid: function(b)
        {
            var h = b.length - 2;
            var c = [];
            var d = -90;
            var f = 90;
            var e = -180;
            var g = 180;
            c[0] = 0;
            c[1] = 0;
            for (var a = 0; a < h; a = a + 2)
            {
                if (g > b[a]) g = b[a];
                if (e < b[a]) e = b[a];
                if (f > b[a + 1]) f = b[a + 1];
                if (d < b[a + 1]) d = b[a + 1]
            }
            c[0] = (e + g) / 2;
            c[1] = (d + f) / 2;
            return c;
        },

        GetUnitSpherePoint: function(c, d)
        {
            var a = [];
            var b = Math.PI / 180;
            a[0] = Math.cos(c * b);
            a[1] = a[0] * Math.sin(d * b);
            a[0] = a[0] * Math.cos(d * b);
            a[2] = Math.sin(c * b);
            return a;
        },

        GetTangentPlaneBasis: function(a)
        {
            var b = [];
            var e = [];
            var f = [];
            b[0] = 0;
            b[1] = 0;
            b[2] = 0;
            var d = 0;
            var c = 1;
            if (Math.abs(a[2]) > Math.abs(a[0]))
            {
                d = 2;
                if (Math.abs(a[0]) > Math.abs(a[1])) c = 0;
            }
            else if (Math.abs(a[2]) > Math.abs(a[1])) c = 2;
            var g = Math.sqrt(a[d] * a[d] + a[c] * a[c]);
            b[d] = -a[c] / g; b[c] = a[d] / g;
            e[0] = a[1] * b[2] - a[2] * b[1];
            e[1] = a[2] * b[0] - a[0] * b[2];
            e[2] = a[0] * b[1] - a[1] * b[0];
            f[0] = b;
            f[1] = e;
            return f;
        },

        GetProjectedCoordinates: function(c, e, f, g, h)
        {
            var b = [];
            var a = this.GetUnitSpherePoint(g, h);
            var d = a[0] * c[0] + a[1] * c[1] + a[2] * c[2];
            if (d <= 0)
            {
                b.VALID = false;
                return b;
            }
            else
            {
                a[0] = a[0] - c[0];
                a[1] = a[1] - c[1];
                a[2] = a[2] - c[2];
                b[0] = (a[0] * e[0] + a[1] * e[1] + a[2] * e[2]) / d;
                b[1] = (a[0] * f[0] + a[1] * f[1] + a[2] * f[2]) / d;
                b.VALID = true;
                return b;
            }
        },

        SignedExcess: function(a, b, c)
        {
            if (b[0] * c[1] - c[0] * b[1] > 0) return a;
            else return -a
        },

        TriangleExcess: function(e, g, f, h, b, c)
        {
            var d = this.GreatCircleDistance(e, g, f, h) / EARTHRADIUS;
            var a = (b + c + d) / 2;
            a = Math.tan(a / 2) * Math.tan((a - b) / 2) * Math.tan((a - c) / 2) * Math.tan((a - d) / 2);
            if (a > 0)
            {
                a = Math.sqrt(a);
                return 4 * Math.atan(a);
            }
            else return 0;
        },

        GreatCircleDistance: function(i, g, j, h)
        {
            var a = Math.PI / 180;
            var b = i * a;
            var c = j * a;
            var d = Math.sin((b - c) / 2);
            var e = Math.sin((g - h) * a / 2);
            var f = Math.asin(Math.sqrt(d * d + Math.cos(b) * Math.cos(c) * e * e));
            return EARTHRADIUS * 2 * f;
        },

        SemiGreatCircleDistance: function(c, a, d, b)
        {
            if (Math.abs(a - b) > 180) return 2 * EARTHRADIUS * Math.PI - this.GreatCircleDistance(c, a, d, b);
            else return this.GreatCircleDistance(c, a, d, b);
        },

        CalculateAreaP: function(a, f)
        {
            if (!a) return -1;
            if (f) f = true;
            var k = a.length;
            if (k < 8) return -1;
            var c = this.GetMedianCentroid(a);
            var j = this.GetUnitSpherePoint(c[1], c[0]);
            var l = this.GetTangentPlaneBasis(j);
            var m = l[0];
            var n = l[1];
            var g = 0;
            var b = 0;
            var h = this.SemiGreatCircleDistance(c[1], c[0], a[1 + b], a[b]) / EARTHRADIUS;
            var i;
            var d = this.GetProjectedCoordinates(j, m, n, a[1], a[0]);
            var e;

            if (f && !d.VALID) return -1;

            var p = h;
            var o = d;

            for (b = 2; b < k; b = b + 2)
            {
                i = this.SemiGreatCircleDistance(c[1], c[0], a[1 + b], a[b]) / EARTHRADIUS;
                e = this.GetProjectedCoordinates(j, m, n, a[1 + b], a[b]);
                if (f && !e.VALID) return -1;
                g = g + this.SignedExcess(this.TriangleExcess(a[b - 1], a[b - 2], a[1 + b], a[b], h, i), d, e);
                d = e;
                h = i;
            }

            return Math.abs(g) * EARTHRADIUS * EARTHRADIUS;
        },

        CalculateArea: function(b, a)
        {
            var VEPoints = b.GetPoints();
            var pointAry = [];

            for (point in VEPoints)
            {
                pointAry.push(VEPoints[point].Longitude);
                pointAry.push(VEPoints[point].Latitude);
            }

            var sqM = this.CalculateAreaP(pointAry, a);

            var areaObj = new Object;
            areaObj.mi = sqM * SQMTOSQMI;
            areaObj.km = sqM * SQMTOSQKM;
            return areaObj;
        }
    }
} ();

if (typeof(Sys) !== "undefined") 
    Sys.Application.notifyScriptLoaded();