// Build a solid colored icon to use instead of the classic pin function dotSymbol(color) { var iconPath = iconVDSwhite; if (color == 'red') { iconPath = iconVDSred; } else if (color == 'yellow') { iconPath = iconVDSyellow; } else if (color == 'lime') { iconPath = iconVDSgreen; } return { url: iconPath, anchor: new google.maps.Point(6, 6) }; } // Load the map data from a json file and style all the points function loadVDSlayer() { // Load the static map data and call saveCoords when done map.data.loadGeoJson(kMapStartupFile, null, saveCoords) // Style the map data by applying the desired properties to each feature (marker) // The function will be called every time a feature's properties are updated. map.data.setStyle(function(feature) { // Get the postmile id var name = feature.getId(); // Get the desired color value var ptColor = feature.getProperty("color"); var street = feature.getProperty("street"); // Build the marker var iconSymbol = dotSymbol(ptColor); // return the StyleOptions return { icon: iconSymbol, title: name + " @" + street, // set rollover text // set zIndex for slowed traffic to a higher value so they overlap zIndex: colorZvalues[ptColor] }; }); } // callback when load GeoJson completes // save each feature's Point as the original coordinates for later reference function saveCoords(features) { // Iterate over all the features in the map features.forEach(function(feature) { var pt = feature.getGeometry().get(); vds_coords[feature.getId()] = pt; // save the Point in a dictionary }); // update the dot colors from the dynamic json data updateVDSlayer(); // go adjust the marker coordinates so dots don't overlap adjustCoords(calcDistanceFactor()); } // magic formula controls distance between dots proportionate to zoom factor function calcDistanceFactor() { // 15 is maximum zoom, the point at which no adjustment is needed return (.0005 * (15 - map.getZoom())); } // Adjust the coordinates of dots so they appear side-by-side // The perpendicular vector for each dot has been provided, // so we just need to multiply by a scaling factor (adjAmount) // @param adjAmount amount by which to adjust coordinate function adjustCoords(adjAmount) { // Adjust the NB points a slight amount map.data.forEach(function(feature) { // get the name of the current feature var name = feature.getId(); // lookup the original coordinates for this feature var coords = vds_coords[name]; //retrieve the perpendicular vector (precomputed) var perpx = feature.getProperty("perpx") var perpy = feature.getProperty("perpy") // Make adjustment and save it var myLat = coords.lat() + perpy * adjAmount var myLong = coords.lng() + perpx * adjAmount feature.setGeometry( { lat: myLat, lng: myLong }); }); } // update the color (as needed) for a given marker function updateMarker(marker) { target = marker.id; newColor = marker.properties.color; // see if new color is different than current color currentFeature = map.data.getFeatureById(target); currentColor = currentFeature.getProperty("color"); // if a new color is desired then assign it to the feature's color property if (currentColor != newColor) { currentFeature.setProperty("color", newColor); // set zIndex for slowed traffic to a higher value so they overlap currentFeature.setProperty("zIndex", colorZvalues[newColor]); } } function storePrev(marker, targetMarkers) { target = marker.id; newColor = marker.properties.color; // see if new color is different than current color currentFeature = map.data.getFeatureById(target); currentColor = currentFeature.getProperty("color"); // if a new color is desired then assign it to the feature's color property if (currentColor != newColor) { targetMarkers.push({"id" : currentFeature.getId(), "properties" : {"color" : currentColor}}); } } // Load the highways dynamic json file and update the map function updateVDSlayer() { index = -1; var parsed_JSON; loadJSON(kVDSstatusFile, function(response) { // Parse JSON string into object parsed_JSON = JSON.parse(response); // Process each new marker - lookup in current map parsed_JSON.features.forEach(updateMarker); }); } function getColorName(str){ if (str === "R\r" || str === "R") return "red"; else if (str === "Y\r" || str === "Y") return "yellow"; else if (str === "G\r" || str === "G") return "lime"; } function processVDS() { var parsed_JSON; loadJSON(kVDSstatusFile, function(response) { // Parse JSON string into object parsed_JSON = JSON.parse(response); // Process each new marker - lookup in current map var array = parsed_JSON.features; var txt = ''; var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function(){ if(xmlhttp.status == 200 && xmlhttp.readyState == 4){ txt = xmlhttp.responseText; var lines = txt.toString().split("\n"); for (var line = 1; line < lines.length; line++) { filters[line-1] = []; var event = lines[line].split(/[ ,]+/); var start = parseFloat(event[4]); // 7.73 var range = parseFloat(event[5]); // 0.5 var newColor = getColorName(event[6]); // "R" times.push(event[1]); array.forEach(function (marker) { var id_arr = marker.id.split(" "); if (id_arr[0] === event[2] && id_arr[1] === event[3]){ var dist = parseFloat(id_arr[2]) - start; //difference of postmiles if (dist <= range && dist >= 0){ filters[line-1].push({"marker": marker, "color": newColor}); } } }); } } }; xmlhttp.open("GET",trafficEventsFile,true); //read traffic events text file xmlhttp.send(); }); } // updates color for each marker based on color in filters array function updateVDS(forwards) { if (forwards) { index++; if (index >= filters.length) { index = filters.length - 1; } if (filters[index] !== undefined) { filters[index].forEach(function(item){ item.marker.properties.color = item.color; updateMarker(item.marker); }); } } else { if (diff_arr[index] !== undefined) { diff_arr[index].forEach(function(item){ updateMarker(item); }); } index--; if (index < -1) { index = -1; } } } function buildDiff() { for (var i = 0; i <= filters.length; i++) { if (filters[i] !== undefined) { var targetMarkers = new Array(); filters[i].forEach(function(item){ item.marker.properties.color = item.color; storePrev(item.marker, targetMarkers); updateMarker(item.marker); }); diff_arr.push(targetMarkers); } } } function initVDSbutton() { var vdsBtnDiv = document.getElementById('vdsButton'); map.controls[google.maps.ControlPosition.LEFT_BOTTOM].push(vdsBtnDiv) vdsBtnDiv.title = 'Click to toggle vds view'; // Setup the click event listeners to toggle icon display vdsBtnDiv.addEventListener('click', function() { vds_showing = !vds_showing; // reveal or hide all the dots map.data.forEach(function(feature) { map.data.overrideStyle(feature, { visible: vds_showing }); }); // Determine which button image to show if (vds_showing) { pic = "images/btnDepressed_VDS.png" } else { pic = "images/btnReady_VDS.png" } document.getElementById('vdsBtnImg').src = pic; }); } // init beginning and next buttons as well as time display on map function initForwardbutton() { var i = 0; var time = document.getElementById('time'); map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(time) var start = document.getElementById('start'); map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(start) start.title = 'Click to see the first event'; var forward = document.getElementById('forward'); map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(forward) var backward = document.getElementById('backward'); map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(backward) forward.title = 'Click to see the next event'; //console.log(diff_arr); forward.addEventListener('click', function() { updateVDS(1); if (i < times.length - 1) { ++i; time.innerHTML = times[i]; } }); backward.addEventListener('click', function() { updateVDS(0); if (i > 0) { --i; time.innerHTML = times[i]; } }); start.addEventListener('click', function() { updateVDSlayer(); i = 0; time.innerHTML = "00:00:00"; }); }