﻿//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//
//  Purpose:
//      This file holds routines that are used to optimize the performance of the Google maps GPolyLine. When over a hundred items are added to the
//      map (GPolyline and GMark) there is a noticeable degradation in the performance of the maps.
//
//
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  Purpose:    This method attempts to put as many lines together as possible. It will then apply an algorithm in order
//              to minimize the number of points displayed.
//
//
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function OptimizeGPolylines(polylineArray) {

    polylineArray.length = 0;  //empty it out for each call...
    
    var _spdLnWd = 4;
    var _spdLnOp = 1;
   
    try {

        var zoom = googleMap.getZoom();
        var verySmall = GetVerySmallParameter();
        var polylineEncoder = new PolylineEncoder(18, zoom, verySmall, true);
        var lineInformationArray = Array(0);

        var myLength = _mdaSpd.length;
        for (var index = 0; index < myLength; ) {
            var originalIndex = index;
            var points = Array(0);
            index = GetNextLine(points, index, lineInformationArray);

            //var polyline = polylineEncoder.dpEncodeToGPolyline(points);
            var polyline = polylineEncoder.dpEncodeToGPolyline(points, _mdaSpd[originalIndex][6], _spdLnWd, _spdLnOp);
            polyline.tooltip = ("<table cellpadding=0 cellspacing=0 ><tr><td align=center class=tdDevName>" + _mdaSpd[originalIndex][2] + "</td></tr><tr><td class=tdTTTxt>" + _mdaSpd[originalIndex][3] + " MPH<br>" + _mdaSpd[originalIndex][5] + "</td></tr></table>");

            GEvent.addListener(polyline, "mouseover", function() {
                if (this.tooltip != "undefined") {
                    showtip(this.tooltip);
                }
            });
            GEvent.addListener(polyline, "mouseout", function() {
                hidetip();
            });
            polylineArray.push(polyline);
            //googleMap.addOverlay(polyline);
            //points = null;
        }

    }
    catch (err) {
        alert(err.description)
    }

}

///////////////////////////////////////////////////////////////////////////////////////
//
//  Purpose:    This method is used to retrieve the points for a line.
//
//  Parameters:
//      pointsForLine:  This is an array that will hold the points in the line.
//      currentIndex:   This is the index in the _mdaSpd that the points in the line will be extracted from.
//
//
////////////////////////////////////////////////////////////////////////////////////////
function GetPointsForLine(pointsForLine, currentIndex) {

    var myVertex = _mdaSpd[currentIndex][4];
    var latlongPairs = myVertex.split(' ');
    var latlongPairsLength = latlongPairs.length;

    var pointsIndex = 0;

    for (var indexVertex = 0; indexVertex < latlongPairsLength; indexVertex++) {


        var latlongString = latlongPairs[indexVertex];
        var latlongArray = latlongString.split(',');
        var latlongArrayLength = latlongArray.length;

        if (2 == latlongArrayLength) {

            var latitude = parseFloat(latlongArray[0]);
            var longditude = parseFloat(latlongArray[1]);
            pointsForLine[pointsIndex] = new GLatLng(latitude, longditude);
            pointsIndex++;

        }
    }

}

////////////////////////////////////////////////////////////////////////////////////////
//
//  Purpose:    This method returns the points in the next line. This will be try to concatenate
//              lines together as an optimization.
//
//  Parameters:
//      pointsForNextLine:  This will hold the points for the next line. The points for this line
//                          may hold the points from several lines from the xml file.
//
//      index:  This is the index to the _mdaSpd array that will be the starting point for the line information.
//
//      lineInformationArray:   This will hold the information about the first point in the line.
//
//  Returns:    
//      This next index in the _mdaSpd array that the next line should be extracted from.
//
//////////////////////////////////////////////////////////////////////////////////////////
function GetNextLine(pointsForNextLine, index, lineInformationArray) {

    var latAndLonDiff = 0.001;

    var currentIndex = index;
    GetPointsForLine(pointsForNextLine, index);

    currentIndex++;

    while (currentIndex < _mdaSpd.length) {
        var tempPointsArray = Array(0);
        GetPointsForLine(tempPointsArray, currentIndex);

        if (tempPointsArray.length > 0 && pointsForNextLine.length > 0) {

            // Get all of the information to determine if the lines can be connected.
            var begLat   = tempPointsArray[0].lat();
            var endLat   = pointsForNextLine[pointsForNextLine.length - 1].lat();
            var begLon   = tempPointsArray[0].lng();
            var endLon   = pointsForNextLine[pointsForNextLine.length - 1].lng();
            var begColor = _mdaSpd[index][6];
            var endColor = _mdaSpd[currentIndex][6];
            var begDir   = _mdaSpd[index][7];
            var endDir   = _mdaSpd[currentIndex][7];

            var latDiff = endLat - begLat;
            var lonDiff = endLon - begLon;

            latDiff = Math.abs(latDiff);
            lonDiff = Math.abs(lonDiff);

            // This does the check to see if the lines can be connected.
            if ((latDiff <= latAndLonDiff) && (lonDiff <= latAndLonDiff) && (begColor == endColor) && (begDir == endDir)) {
                checkNextLine = true;
                lineInformationArray.push(_mdaSpd[index]);
                
                // Connect the lines.
                for (var currentLineIndex = 0; currentLineIndex < tempPointsArray.length; currentLineIndex++) {
                    pointsForNextLine.push(tempPointsArray[currentLineIndex]);
                }
            }
            else {
                break;
            }

            currentIndex++;

        }

    }

    return currentIndex;

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  Purpose:    This method is used to retrieve the very small parameter for the algorithm for removing the points from the
//              GPolyline. Depending on the zoom level some points can be removed from the GPolyline because the Google map
//              can not display that kind of detail at that zoom level.
//
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function GetVerySmallParameter() {

    var verySmall = 0.00001;
    
    // The very small level depends on the zoom level of the google map.
    var zoomLevel = googleMap.getZoom();

    if (!zoomLevel) {
        zoomLevel = 11;
    }

    // Determine the very small leve from the zoom level.
    if (11 == zoomLevel) {

        verySmall = 0.0001;
    }
    else if (zoomLevel > 11) {
        verySmall = 0.00001;
    }
    else if (13 < zoomLevel) {
        verySmall = 0.001;
    }
    else {
        verySmall = 0.00001;
    }

    return verySmall;
}
    
