source: tmcsimulator/trunk/webapps/GTEC/js/vdsLayer.js @ 566

Revision 566, 18.7 KB checked in by jdalbey, 6 years ago (diff)

GTEC vdsLayer.js Add color buttons.

Line 
1var postmileList = [];  // the list of postmiles saved from the json file.
2var chosenColor = null;
3
4Array.prototype.diff = function(a) {
5    return this.filter(function(i) {return a.indexOf(i) < 0;});
6};
7
8    // Build a solid colored icon to use instead of the classic pin
9    function dotSymbol(color) 
10    {
11        var iconPath = iconVDSwhite;
12        if (color == 'red')
13        {
14           iconPath = iconVDSred;
15        }
16        else if (color == 'yellow')
17        {
18            iconPath = iconVDSyellow;
19        }
20        else if (color == 'lime')
21        {
22            iconPath = iconVDSgreen;
23        }
24        return {
25            url: iconPath, 
26            anchor: new google.maps.Point(6, 6)
27        };
28    }
29
30    // Load the map data from a json file and style all the points
31    function loadVDSlayer()
32    {
33        // Load the static map data and call saveCoords when done
34        map.data.loadGeoJson(kMapStartupFile, null, saveCoords)
35        // Style the map data by applying the desired properties to each feature (marker)
36        // The function will be called every time a feature's properties are updated.
37        map.data.setStyle(function(feature)
38        {
39            // Get the postmile id
40            var name = feature.getId();
41            // Get the desired color value
42            var ptColor = feature.getProperty("color");
43            var street = feature.getProperty("street");
44            // Build the marker
45            var iconSymbol = dotSymbol(ptColor);
46            // return the StyleOptions
47            return {
48                icon: iconSymbol,
49                title: name + " @" + street, // set rollover text
50                // set zIndex for slowed traffic to a higher value so they overlap
51                zIndex: colorZvalues[ptColor]
52            };
53        });
54        var clicked = false;
55        var first = [];
56        var asc = false;
57        var color_arr = [];
58        var white_arr = [];
59        map.data.addListener('click', function(event) 
60        {
61            var event_arr = event.feature.getId().split(/[ ,]+/);
62            // var start = parseFloat(event[4]); // extract postmile field
63            if (clicked && event_arr[0] === first[0] && event_arr[1] === first[1])
64            {
65                // console.log('clicked ' + first + "/" + event_arr + event.feature);
66                var range = Math.abs(parseFloat(event_arr[2]) - parseFloat(first[2]));
67                var clicked_dots = [];
68                if (parseFloat(event_arr[2]) < parseFloat(first[2]))
69                {
70                    asc = false;
71                }
72                else 
73                {
74                    asc = true;
75                }
76                map.data.forEach(function (marker) 
77                {
78                    var marker_arr = marker.getId().split(/[ ,]+/);
79                    if (marker_arr[0] === event_arr[0] && marker_arr[1] === event_arr[1])
80                    {
81                        if (asc)
82                        {
83                            var dist = parseFloat(marker_arr[2]) - parseFloat(first[2]);
84                        }
85                        else 
86                        {
87                            var dist = parseFloat(parseFloat(first[2]) - (marker_arr[2]));
88                        }
89                        if (dist <= range && dist >= 0)
90                        {
91                            clicked_dots.push(marker);
92                        }
93                    }
94                });
95                color_arr.push(clicked_dots);
96                console.log(clicked_dots);
97                console.log(range);
98                var white_arr_ids = white_arr.map(function (marker) {
99                    return marker.id;
100                });
101                var clicked_dots_ids = clicked_dots.map(function (marker) {
102                    return marker.getId();
103                });
104                var unused_ids = white_arr_ids.diff(clicked_dots_ids);
105                console.log("Unused: ",unused_ids, "White: ",white_arr_ids);
106                unused_ids.forEach(function (id){
107                    var marker = white_arr.filter(function (dot) {
108                        return dot.id === id;
109                    })[0];
110                    var feature = map.data.getFeatureById(marker.id); 
111                    feature.setProperty("color", marker.color);
112                });
113                white_arr = [];
114                if (chosenColor)
115                {
116                    clicked_dots.forEach(function (dot) {
117                        dot.setProperty("color", chosenColor);
118                    });
119                }
120
121                // Assemble the line to be written to the events file
122                var lineOut = "181   00:00:00    " + first[0] + "       " + 
123                first[1] + "            " + first[2] + "        " + range.toFixed(3) + "         " 
124                + getColorAbbr(chosenColor);
125
126                // Using Ajax POST to send the data
127                var xhr = new XMLHttpRequest();
128                xhr.open("POST", "../../cgi-bin/saveTrafficEvent.py", true);
129                xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
130                // send the collected data
131                xhr.send("msg="+lineOut + "\n")
132            }
133            else if (!clicked)
134            {
135                first = event_arr;
136
137                // turns relevant dots white
138                selectedID = event.feature.getId();  // get the id of the clicked dot
139                curr = postmileList.indexOf(selectedID); // find the id in the postmile list
140                var firstBlank = postmileList[curr].indexOf(" ", 0);  // find direction substring
141                var secondBlank = firstBlank+2; 
142                var direction = postmileList[curr].charAt(firstBlank+1); // extract direction
143                target = event.feature.getId().substring(0,secondBlank); // extract target string
144                console.log("making white dots from " + selectedID + " in direction "+direction)
145                // Decide whether to increment or decrement based on direction of hwy;
146                //  N and E increment,  S and W decrement
147                if (direction == 'N' || direction == 'E')
148                {
149                    // Process all dots with same hwy and direction
150                    while  (postmileList[curr].startsWith(target) && curr < postmileList.length)
151                    {
152                        // turn the dot white
153                        currFeat = map.data.getFeatureById(postmileList[curr]);
154                        white_arr.push({id : currFeat.getId(), color : currFeat.getProperty("color")});         
155                        currFeat.setProperty("color", "white"); 
156                        curr++;
157               
158                    } 
159                }
160                else
161                {
162                    // Process all dots with same hwy and direction
163                    while  (postmileList[curr].startsWith(target) && curr > 0)
164                    {
165                        currFeat = map.data.getFeatureById(postmileList[curr]);
166                        white_arr.push({id : currFeat.getId(), color : currFeat.getProperty("color")});
167                        // turn the dot white
168                        currFeat.setProperty("color", "white"); 
169                        curr--;
170                    }                 
171                }
172            }
173            else 
174            {
175                console.log('wrong choice');
176            }
177            clicked = !clicked;
178        });
179    }
180    // callback when load GeoJson completes
181    // save each feature's Point as the original coordinates for later reference
182    function saveCoords(features)
183    {
184        // Iterate over all the features in the map
185        features.forEach(function(feature)
186        {
187            var pt = feature.getGeometry().get();
188            vds_coords[feature.getId()] = pt; // save the Point in a dictionary
189            postmileList.push(feature.getId()); // save the postmile in a list
190        });
191        // update the dot colors from the dynamic json data
192        updateVDSlayer();
193        // go adjust the marker coordinates so dots don't overlap
194        adjustCoords(calcDistanceFactor());
195    } 
196
197    // magic formula controls distance between dots proportionate to zoom factor
198    function calcDistanceFactor()
199    {
200        // 15 is maximum zoom, the point at which no adjustment is needed
201        return (.0005 * (15 - map.getZoom()));
202    }
203
204    // Adjust the coordinates of dots so they appear side-by-side
205    // The perpendicular vector for each dot has been provided,
206    // so we just need to multiply by a scaling factor (adjAmount)
207    // @param adjAmount amount by which to adjust coordinate
208    function adjustCoords(adjAmount)
209    {
210        // Adjust the NB points a slight amount
211        map.data.forEach(function(feature)
212        {
213            // get the name of the current feature
214            var name = feature.getId();
215            // lookup the original coordinates for this feature
216            var coords = vds_coords[name];
217
218            //retrieve the perpendicular vector (precomputed)
219            var perpx = feature.getProperty("perpx")
220            var perpy = feature.getProperty("perpy")
221                // Make adjustment and save it
222            var myLat = coords.lat() + perpy * adjAmount
223            var myLong = coords.lng() + perpx * adjAmount
224            feature.setGeometry(
225            {
226                lat: myLat,
227                lng: myLong
228            });
229        });
230    }
231
232    // update the color (as needed) for a given marker
233    function updateMarker(marker)
234    {
235        target = marker.id;
236        newColor = marker.properties.color;
237        // see if new color is different than current color
238        currentFeature = map.data.getFeatureById(target);
239        if (currentFeature) {
240            currentColor = currentFeature.getProperty("color");
241            // if a new color is desired then assign it to the feature's color property
242            if (currentColor != newColor)
243            {
244                currentFeature.setProperty("color", newColor);
245                // set zIndex for slowed traffic to a higher value so they overlap
246                currentFeature.setProperty("zIndex", colorZvalues[newColor]);
247            }
248        }
249    }
250
251    // Builds array to store the previous colors of the targetDots
252    /*function storePrev(marker, targetMarkers)
253    {
254        target = marker.id;
255        newColor = marker.properties.color;
256        // see if new color is different than current color
257        currentFeature = map.data.getFeatureById(target);
258        currentColor = currentFeature.getProperty("color");
259        // if a new color is desired then assign it to the feature's color property
260        if (currentColor != newColor)
261        {
262            targetMarkers.push({"id" : currentFeature.getId(),
263                "properties" : {"color" : currentColor}});
264        }
265    }*/
266
267    // Load the highways dynamic json file and update the map
268    function updateVDSlayer()
269    {
270        eventIndex = -1;
271        var parsed_JSON;
272        loadJSON(kVDSstatusFile, function(response)
273        {
274            // Parse JSON string into object
275            parsed_JSON = JSON.parse(response);
276            // Process each new marker - lookup in current map
277            parsed_JSON.features.forEach(updateMarker);
278        });
279    }
280
281    function getColorName(str){
282        if (str === "R\r" || str === "R")
283            return "red";
284        else if (str === "Y\r" || str === "Y")
285            return "yellow";
286        else if (str === "G\r" || str === "G")
287            return "lime";
288    }
289
290    function getColorAbbr(str){
291        if (str === "red")
292            return "R";
293        else if (str === "yellow")
294            return "Y";
295        else if (str === "lime")
296            return "G";
297    }
298
299// Parses the traffic events file and builds an array of target dots for each line
300    /*function processVDS() {
301        var parsed_JSON;
302        loadJSON(kVDSstatusFile, function(response)
303        {
304            // Parse JSON string into object
305            parsed_JSON = JSON.parse(response);
306            // Process each new marker - lookup in current map
307            var parsed_features =  parsed_JSON.features;
308            var eventsFile = '';
309            var xmlhttp = new XMLHttpRequest();
310            xmlhttp.onreadystatechange = function(){
311                if(xmlhttp.status == 200 && xmlhttp.readyState == 4){
312                    eventsFile = xmlhttp.responseText;
313                    var lines = eventsFile.toString().split("\n");
314                    for (var line = 1; line < lines.length; line++) {
315                        if (lines[line][0] !== '#') //ignores lines with #
316                        {
317                            var dots = [];
318                            var event = lines[line].split(/[ ,]+/);
319                            var start = parseFloat(event[4]); // extract postmile field
320                            var range = parseFloat(event[5]); // extract distance
321                            var newColor = getColorName(event[6]); // extract DotColor
322                            eventTimes.push(event[1]);
323                            parsed_features.forEach(function (marker) {
324                                var id_arr = marker.id.split(" ");
325                                if (id_arr[0] === event[2] && id_arr[1] === event[3]){
326                                    var dist = parseFloat(id_arr[2]) - start; //computes difference in postmiles
327                                    if (dist <= range && dist >= 0){ // adds all dots within computed range
328                                        dots.push({"marker": marker, "color": newColor});
329                                    }
330                                }
331                            });
332                            targetDots.push(dots);
333                        }
334                    }
335                }
336            };
337            xmlhttp.open("GET",trafficEventsFile,true); //read traffic events text file
338            xmlhttp.send();
339        });
340    }
341
342    // Increments the eventIndex from and updates all the targetDots on map
343    function updateForwards() {
344        eventIndex++;
345        // limit eventIndex to length of targetDots
346        if (eventIndex >= targetDots.length)
347        {
348            eventIndex = targetDots.length - 1;
349        }
350        // update all the target dots
351        if  (targetDots[eventIndex] !== undefined) {
352            targetDots[eventIndex].forEach(function(item){
353            item.marker.properties.color = item.color;
354            updateMarker(item.marker);
355            });
356        }
357    }
358
359    // Decrements the eventIndex and updates all the targetDots from diff_arr on map
360    function updateBackwards() {
361        //update each target dot in order to revert to previous color
362        if  (diff_arr[eventIndex] !== undefined) {
363            diff_arr[eventIndex].forEach(function(item){
364                updateMarker(item);
365            });
366        }
367        eventIndex--;
368        // restrict eventIndex to -1
369        if (eventIndex < -1)
370        {
371            eventIndex = -1;
372        }
373    }
374   
375    // Calls updateMarker for all targetDots after storing the previous marker in diff_arr
376    function buildDiff() {
377        for (var i = 0; i <= targetDots.length; i++)
378        {
379            if  (targetDots[i] !== undefined)
380            {
381                var targetMarkers = new Array();
382                targetDots[i].forEach(function(item){
383                    item.marker.properties.color = item.color;
384                    storePrev(item.marker, targetMarkers);
385                    updateMarker(item.marker);
386                });
387                diff_arr.push(targetMarkers);
388            }
389        }
390    }
391*/
392/*function initVDSbutton()
393{
394
395    var vdsBtnDiv = document.getElementById('vdsButton');
396    map.controls[google.maps.ControlPosition.LEFT_BOTTOM].push(vdsBtnDiv)
397    vdsBtnDiv.title = 'Click to toggle vds view';
398
399    // Setup the click event listeners to toggle icon display
400    vdsBtnDiv.addEventListener('click', function()
401    {
402        vds_showing = !vds_showing;
403        // reveal or hide all the dots
404        map.data.forEach(function(feature)
405        {
406            map.data.overrideStyle(feature,
407            {
408                visible: vds_showing
409            });
410        });
411        // Determine which button image to show
412        if (vds_showing)
413        {
414            pic = "images/btnDepressed_VDS.png"
415        }
416        else
417        {
418            pic = "images/btnReady_VDS.png"
419        }
420        document.getElementById('vdsBtnImg').src = pic;
421    });
422}*/
423
424function initColorButtons()
425{
426    var redColor = document.getElementById('redButton');
427    var greenColor = document.getElementById('greenButton');
428    var yellowColor = document.getElementById('yellowButton');
429    map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(redColor);
430    map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(greenColor);
431    map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(yellowColor);
432    redColor.addEventListener('click', function() {
433        chosenColor = "red";
434    });
435    greenColor.addEventListener('click', function() {
436        chosenColor = "lime";
437    });
438    yellowColor.addEventListener('click', function(){
439        chosenColor = "yellow";
440    });
441}
442
443// init beginning, forward and back buttons as well as time display on map
444/*function initControlButtons()
445{
446    var i = 0;
447    var time = document.getElementById('time');
448    map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(time)
449    var start = document.getElementById('start');
450    map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(start)
451    start.title = 'Click to see the first event';
452    var forward = document.getElementById('forward');
453    map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(forward)
454        var backward = document.getElementById('backward');
455        map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(backward)
456    forward.title = 'Click to see the next event';
457    forward.addEventListener('click', function() {
458        updateForwards();
459        backward.disabled = false;
460        if (i < eventTimes.length - 1) // get the next eventTime
461        {
462            ++i;
463            time.innerHTML = eventTimes[i];
464        }
465        if (eventIndex === targetDots.length - 1) // disable next button if last event reached
466        {
467            forward.disabled = true;
468        }
469    });
470        backward.addEventListener('click', function() {
471        updateBackwards();
472        forward.disabled = false;
473        if (i > 0)  // get the prev eventTime
474        {
475            --i;
476            time.innerHTML = eventTimes[i];
477        }
478        if (eventIndex < 0) // disable back button if at first event
479        {
480            backward.disabled = true;
481        }
482        });
483    start.addEventListener('click', function() {
484        updateVDSlayer(); // redraw markers on map from startup file
485        i = 0;
486        time.innerHTML = "00:00:00";
487    });
488}
489*/
Note: See TracBrowser for help on using the repository browser.