source: tmcsimulator/trunk/webapps/visualizer/js/vdsLayer.js @ 580

Revision 580, 12.7 KB checked in by jdalbey, 6 years ago (diff)

Fix visualizer so it ignores blank lines in traffic events file, and enables Next button when Beginning is clicked.

Line 
1    // Load the map data from a json file and style all the points
2    function initializeVDSlayer()
3    {
4        // Load the static map data and call saveCoords when done
5        map.data.loadGeoJson(kMapStartupFile, null, saveCoords)
6        // Style the map data by applying the desired properties to each feature (marker)
7        // The function will be called every time a feature's properties are updated.
8        map.data.setStyle(function(feature)
9        {
10            // Get the postmile id
11            var name = feature.getId();
12            // Get the desired color value
13            var ptColor = feature.getProperty("color");
14            var street = feature.getProperty("street");
15            // Build the marker
16            var iconSymbol = dotSymbol(ptColor);
17            // return the StyleOptions
18            return {
19                icon: iconSymbol,
20                title: name + " @" + street, // set rollover text
21                // set zIndex for slowed traffic to a higher value so they overlap
22                zIndex: colorZvalues[ptColor]
23            };
24        });
25    }
26
27    // Build a solid colored icon to use instead of the classic pin
28    function dotSymbol(color) 
29    {
30        var iconPath = iconVDSwhite;
31        if (color == 'red')
32        {
33           iconPath = iconVDSred;
34        }
35        else if (color == 'yellow')
36        {
37            iconPath = iconVDSyellow;
38        }
39        else if (color == 'lime')
40        {
41            iconPath = iconVDSgreen;
42        }
43        return {
44            url: iconPath, 
45            anchor: new google.maps.Point(6, 6)
46        };
47    }
48
49    // callback when load GeoJson completes
50    // save each feature's Point as the original coordinates for later reference
51    function saveCoords(features)
52    {
53        // Iterate over all the features in the map
54        features.forEach(function(feature)
55        {
56            var pt = feature.getGeometry().get();
57            vds_coords[feature.getId()] = pt; // save the Point in a dictionary
58        });
59        // go adjust the marker coordinates so dots don't overlap
60        adjustCoords(calcDistanceFactor());
61        processVDS();
62    } 
63
64    // magic formula controls distance between dots proportionate to zoom factor
65    function calcDistanceFactor()
66    {
67        // 15 is maximum zoom, the point at which no adjustment is needed
68        return (.0005 * (15 - map.getZoom()));
69    }
70
71    // Adjust the coordinates of dots so they appear side-by-side
72    // The perpendicular vector for each dot has been provided,
73    // so we just need to multiply by a scaling factor (adjAmount)
74    // @param adjAmount amount by which to adjust coordinate
75    function adjustCoords(adjAmount)
76    {
77        // Adjust the NB points a slight amount
78        map.data.forEach(function(feature)
79        {
80            // get the name of the current feature
81            var name = feature.getId();
82            // lookup the original coordinates for this feature
83            var coords = vds_coords[name];
84
85            //retrieve the perpendicular vector (precomputed)
86            var perpx = feature.getProperty("perpx")
87            var perpy = feature.getProperty("perpy")
88                // Make adjustment and save it
89            var myLat = coords.lat() + perpy * adjAmount
90            var myLong = coords.lng() + perpx * adjAmount
91            feature.setGeometry(
92            {
93                lat: myLat,
94                lng: myLong
95            });
96        });
97    }
98
99    // update the color (as needed) for a given marker
100    function updateMarker(marker)
101    {
102        target = marker.id;
103        newColor = marker.properties.color;
104        // see if new color is different than current color
105        currentFeature = map.data.getFeatureById(target);
106        currentColor = currentFeature.getProperty("color");
107        // if a new color is desired then assign it to the feature's color property
108        if (currentColor != newColor)
109        {
110            currentFeature.setProperty("color", newColor);
111            // set zIndex for slowed traffic to a higher value so they overlap
112            currentFeature.setProperty("zIndex", colorZvalues[newColor]);
113        }
114    }
115
116    // Load the highways static json file and update the map
117    function resetVDSlayer()
118    {
119        eventIndex = -1;
120        loadJSON(kMapStartupFile, function(response)
121        {
122            // Parse JSON string into object
123            //initialVDSjson = JSON.parse(response);
124            // Process each new marker - lookup in current map
125            var initialVDSjsonFeatures = JSON.parse(response).features
126            initialVDSjsonFeatures.forEach(updateMarker);
127        });
128    }
129
130    function getColorName(str){
131        if (str === "R\r" || str === "R")
132            return "red";
133        else if (str === "Y\r" || str === "Y")
134            return "yellow";
135        else if (str === "G\r" || str === "G")
136            return "lime";
137    }
138
139// Parses the traffic events file and builds an array of target dots for each line
140    function processVDS() {
141        //var parsed_JSON;
142        loadJSON(kMapStartupFile, function(response)
143        { 
144            // Parse JSON string into object
145            parsed_JSON = JSON.parse(response);
146            // Process each new marker - lookup in current map
147            var parsed_features =  parsed_JSON.features;
148            parsed_features.forEach(updateMarker);
149            var eventsFile = '';
150            // Request the traffic events data file
151            var xmlhttp = new XMLHttpRequest();
152            xmlhttp.open("GET",trafficEventsFile,true); // Ask the server for the traffic events file
153            // Establish listener for handling the traffic events once file is read
154            xmlhttp.onreadystatechange = function()
155            {
156                if(xmlhttp.status == 200 && xmlhttp.readyState == 4)
157                {
158                    eventsFile = xmlhttp.responseText;
159                    // Process the traffic events file
160                    var lines = eventsFile.toString().split("\n");
161                    // For each line in the events file
162                    for (var line = 0; line < lines.length; line++) 
163                    {
164                        var trimmedLine = lines[line].trim();
165                        if (trimmedLine.length>0 && trimmedLine[0] !== '#' ) //ignores lines with #
166                        {
167                            console.log(trimmedLine);
168                            var dots = [];                           
169                            var event = trimmedLine.split(/[ ,\t]+/);
170                            var start = parseFloat(event[4]); // extract postmile field
171                            var range = parseFloat(event[5]); // extract distance
172                            var newColor = getColorName(event[6]); // extract DotColor
173                            eventTimes.push(event[1]);  // extract the event time
174                            // Process each VDS in the highway network
175                            parsed_features.forEach(function (marker) {
176                                var marker_fields = marker.id.split(" ");
177                                // See if this marker's highway and direction match to this event
178                                if (marker_fields[0] === event[2] && marker_fields[1] === event[3])
179                                {   //computes difference in postmiles
180                                    var dist = parseFloat(marker_fields[2]) - start; 
181                                    // If this marker is within computed range
182                                    if (dist <= range && dist >= 0) 
183                                    {
184                                        // Add the marker to the dots representing this event
185                                        dots.push({"marker": marker, "color": newColor});
186                                    }
187                                }
188                            });
189                            targetDots.push(dots); // add this events dots to the list of targetdots
190                        } // end if
191                    }  // end for             
192                    // After the traffic events are processed,  go build the differences array
193                    buildDiff();      // side effect: leaves map with last event showing
194                    resetVDSlayer();  // restore the map to initial state
195                }
196            };
197            xmlhttp.send();
198        });
199    }
200
201    // Calls updateMarker for all targetDots after storing the previous marker in diff_arr
202    // This function only needs to be done once, during startup.
203    function buildDiff() 
204    {
205        for (var i = 0; i <= targetDots.length; i++)
206        {
207            if  (targetDots[i] !== undefined)
208            {
209                var targetMarkers = new Array();
210                targetDots[i].forEach(function(item)
211                {
212                    item.marker.properties.color = item.color;
213                    storePrev(item.marker, targetMarkers);
214                    updateMarker(item.marker);
215                });
216                diff_arr.push(targetMarkers);
217            }
218        }
219    }
220    // Helper function for BuildDiff
221    // Store the previous colors of the targetDots
222    // so it will available if the user goes "back".
223    function storePrev(marker, targetMarkers) 
224    {
225        target = marker.id;
226        newColor = marker.properties.color;
227        // see if new color is different than current color
228        currentFeature = map.data.getFeatureById(target);
229        currentColor = currentFeature.getProperty("color");
230        // if a new color is desired then assign it to the feature's color property
231        if (currentColor != newColor)
232        {
233            targetMarkers.push({"id" : currentFeature.getId(),
234                "properties" : {"color" : currentColor}});
235        }
236    }
237
238
239
240    // Increments the eventIndex from and updates all the targetDots on map
241    function updateForwards() {
242        eventIndex++;
243        // limit eventIndex to length of targetDots
244        if (eventIndex >= targetDots.length) 
245        {
246            eventIndex = targetDots.length - 1;
247        }
248        // update all the target dots
249        if  (targetDots[eventIndex] !== undefined) {
250            targetDots[eventIndex].forEach(function(item){
251                item.marker.properties.color = item.color;
252                updateMarker(item.marker);
253            });
254        }
255    }
256
257    // Decrements the eventIndex and updates all the targetDots from diff_arr on map
258    function updateBackwards() {
259        //update each target dot in order to revert to previous color
260        if  (diff_arr[eventIndex] !== undefined) {
261            diff_arr[eventIndex].forEach(function(item){
262                updateMarker(item);
263            });
264        }
265        eventIndex--; 
266        // restrict eventIndex to -1
267        if (eventIndex < -1)
268        {
269            eventIndex = -1;
270        }
271    }
272   
273
274// init beginning, forward and back buttons as well as time display on map
275function initControlButtons()
276{
277    var i = 0;
278    // setup the time display
279    var time = document.getElementById('time');
280    map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(time)
281    // set up the "beginning" button
282    var beginning = document.getElementById('beginning');
283    map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(beginning)
284    beginning.title = 'Click to see the first event';
285    // set up the "next" button
286    var forward = document.getElementById('forward');
287    map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(forward)
288    // set up the "back" button
289        var backward = document.getElementById('backward');
290        map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(backward)
291    forward.title = 'Click to see the next event';
292    //console.log(targetDots, eventTimes);
293    // Establish the listeners for each button
294    forward.addEventListener('click', function() {
295        updateForwards();
296        backward.disabled = false;
297        if (i < eventTimes.length - 1) // get the next eventTime
298        {
299            ++i;
300            time.innerHTML = eventTimes[i];
301        }
302        if (eventIndex === targetDots.length - 1) // disable next button if last event reached
303        {
304            forward.disabled = true;
305        }
306    });
307        backward.addEventListener('click', function() {
308        updateBackwards();
309        forward.disabled = false;
310        if (i > 0)  // get the prev eventTime
311        {
312            --i;
313            time.innerHTML = eventTimes[i];
314        }
315        if (eventIndex < 0) // disable back button if at first event
316        {
317            backward.disabled = true;
318        }
319        });
320    beginning.addEventListener('click', function() {
321        resetVDSlayer(); // redraw markers on map from startup file
322        i = 0;
323        time.innerHTML = "00:00:00";
324        forward.disabled = false;
325    });
326}
327
Note: See TracBrowser for help on using the repository browser.