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

Revision 556, 17.4 KB checked in by jdalbey, 6 years ago (diff)

Ver 0.1 of Graphic Traffic Events Creator.

Line 
1var postmileList = [];  // the list of postmiles saved from the json file.
2
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 initializeVDSlayer()
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                // Assemble the line to be written to the events file
115                var lineOut = "0:01:00  " + range.toFixed(3);
116
117                // Using Ajax POST to send the data
118                var xhr = new XMLHttpRequest();
119                xhr.open("POST", "../cgi-bin/saveTrafficEvent.py", true);
120                xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
121                // send the collected data
122                xhr.send("msg="+lineOut + "\n")
123            }
124            else if (!clicked)
125            {
126                first = event_arr;
127
128                // turns relevant dots white
129                selectedID = event.feature.getId();  // get the id of the clicked dot
130                curr = postmileList.indexOf(selectedID); // find the id in the postmile list
131                var firstBlank = postmileList[curr].indexOf(" ", 0);  // find direction substring
132                var secondBlank = firstBlank+2; 
133                var direction = postmileList[curr].charAt(firstBlank+1); // extract direction
134                target = event.feature.getId().substring(0,secondBlank); // extract target string
135                console.log("making white dots from " + selectedID + " in direction "+direction)
136                // Decide whether to increment or decrement based on direction of hwy;
137                //  N and E increment,  S and W decrement
138                if (direction == 'N' || direction == 'E')
139                {
140                    // Process all dots with same hwy and direction
141                    while  (postmileList[curr].startsWith(target) && curr < postmileList.length)
142                    {
143                        // turn the dot white
144                        currFeat = map.data.getFeatureById(postmileList[curr]);
145                        white_arr.push({id : currFeat.getId(), color : currFeat.getProperty("color")});         
146                        currFeat.setProperty("color", "white"); 
147                        curr++;
148               
149                    } 
150                }
151                else
152                {
153                    // Process all dots with same hwy and direction
154                    while  (postmileList[curr].startsWith(target) && curr > 0)
155                    {
156                        currFeat = map.data.getFeatureById(postmileList[curr]);
157                        white_arr.push({id : currFeat.getId(), color : currFeat.getProperty("color")});
158                        // turn the dot white
159                        currFeat.setProperty("color", "white"); 
160                        curr--;
161                    }                 
162                }
163            }
164            else 
165            {
166                console.log('wrong choice');
167            }
168            clicked = !clicked;
169        });
170    }
171    // callback when load GeoJson completes
172    // save each feature's Point as the original coordinates for later reference
173    function saveCoords(features)
174    {
175        // Iterate over all the features in the map
176        features.forEach(function(feature)
177        {
178            var pt = feature.getGeometry().get();
179            vds_coords[feature.getId()] = pt; // save the Point in a dictionary
180            postmileList.push(feature.getId()); // save the postmile in a list
181        });
182        // update the dot colors from the dynamic json data
183        updateVDSlayer();
184        // go adjust the marker coordinates so dots don't overlap
185        adjustCoords(calcDistanceFactor());
186    } 
187
188    // magic formula controls distance between dots proportionate to zoom factor
189    function calcDistanceFactor()
190    {
191        // 15 is maximum zoom, the point at which no adjustment is needed
192        return (.0005 * (15 - map.getZoom()));
193    }
194
195    // Adjust the coordinates of dots so they appear side-by-side
196    // The perpendicular vector for each dot has been provided,
197    // so we just need to multiply by a scaling factor (adjAmount)
198    // @param adjAmount amount by which to adjust coordinate
199    function adjustCoords(adjAmount)
200    {
201        // Adjust the NB points a slight amount
202        map.data.forEach(function(feature)
203        {
204            // get the name of the current feature
205            var name = feature.getId();
206            // lookup the original coordinates for this feature
207            var coords = vds_coords[name];
208
209            //retrieve the perpendicular vector (precomputed)
210            var perpx = feature.getProperty("perpx")
211            var perpy = feature.getProperty("perpy")
212                // Make adjustment and save it
213            var myLat = coords.lat() + perpy * adjAmount
214            var myLong = coords.lng() + perpx * adjAmount
215            feature.setGeometry(
216            {
217                lat: myLat,
218                lng: myLong
219            });
220        });
221    }
222
223    // update the color (as needed) for a given marker
224    function updateMarker(marker)
225    {
226        target = marker.id;
227        newColor = marker.properties.color;
228        // see if new color is different than current color
229        currentFeature = map.data.getFeatureById(target);
230        currentColor = currentFeature.getProperty("color");
231        // if a new color is desired then assign it to the feature's color property
232        if (currentColor != newColor)
233        {
234            currentFeature.setProperty("color", newColor);
235            // set zIndex for slowed traffic to a higher value so they overlap
236            currentFeature.setProperty("zIndex", colorZvalues[newColor]);
237        }
238    }
239
240    // Builds array to store the previous colors of the targetDots
241    /*function storePrev(marker, targetMarkers)
242    {
243        target = marker.id;
244        newColor = marker.properties.color;
245        // see if new color is different than current color
246        currentFeature = map.data.getFeatureById(target);
247        currentColor = currentFeature.getProperty("color");
248        // if a new color is desired then assign it to the feature's color property
249        if (currentColor != newColor)
250        {
251            targetMarkers.push({"id" : currentFeature.getId(),
252                "properties" : {"color" : currentColor}});
253        }
254    }*/
255
256    // Load the highways dynamic json file and update the map
257    function updateVDSlayer()
258    {
259        eventIndex = -1;
260        var parsed_JSON;
261        loadJSON(kVDSstatusFile, function(response)
262        {
263            // Parse JSON string into object
264            parsed_JSON = JSON.parse(response);
265            // Process each new marker - lookup in current map
266            parsed_JSON.features.forEach(updateMarker);
267        });
268    }
269
270    function getColorName(str){
271        if (str === "R\r" || str === "R")
272            return "red";
273        else if (str === "Y\r" || str === "Y")
274            return "yellow";
275        else if (str === "G\r" || str === "G")
276            return "lime";
277    }
278
279// Parses the traffic events file and builds an array of target dots for each line
280    /*function processVDS() {
281        var parsed_JSON;
282        loadJSON(kVDSstatusFile, function(response)
283        {
284            // Parse JSON string into object
285            parsed_JSON = JSON.parse(response);
286            // Process each new marker - lookup in current map
287            var parsed_features =  parsed_JSON.features;
288            var eventsFile = '';
289            var xmlhttp = new XMLHttpRequest();
290            xmlhttp.onreadystatechange = function(){
291                if(xmlhttp.status == 200 && xmlhttp.readyState == 4){
292                    eventsFile = xmlhttp.responseText;
293                    var lines = eventsFile.toString().split("\n");
294                    for (var line = 1; line < lines.length; line++) {
295                        if (lines[line][0] !== '#') //ignores lines with #
296                        {
297                            var dots = [];
298                            var event = lines[line].split(/[ ,]+/);
299                            var start = parseFloat(event[4]); // extract postmile field
300                            var range = parseFloat(event[5]); // extract distance
301                            var newColor = getColorName(event[6]); // extract DotColor
302                            eventTimes.push(event[1]);
303                            parsed_features.forEach(function (marker) {
304                                var id_arr = marker.id.split(" ");
305                                if (id_arr[0] === event[2] && id_arr[1] === event[3]){
306                                    var dist = parseFloat(id_arr[2]) - start; //computes difference in postmiles
307                                    if (dist <= range && dist >= 0){ // adds all dots within computed range
308                                        dots.push({"marker": marker, "color": newColor});
309                                    }
310                                }
311                            });
312                            targetDots.push(dots);
313                        }
314                    }
315                }
316            };
317            xmlhttp.open("GET",trafficEventsFile,true); //read traffic events text file
318            xmlhttp.send();
319        });
320    }
321
322    // Increments the eventIndex from and updates all the targetDots on map
323    function updateForwards() {
324        eventIndex++;
325        // limit eventIndex to length of targetDots
326        if (eventIndex >= targetDots.length)
327        {
328            eventIndex = targetDots.length - 1;
329        }
330        // update all the target dots
331        if  (targetDots[eventIndex] !== undefined) {
332            targetDots[eventIndex].forEach(function(item){
333            item.marker.properties.color = item.color;
334            updateMarker(item.marker);
335            });
336        }
337    }
338
339    // Decrements the eventIndex and updates all the targetDots from diff_arr on map
340    function updateBackwards() {
341        //update each target dot in order to revert to previous color
342        if  (diff_arr[eventIndex] !== undefined) {
343            diff_arr[eventIndex].forEach(function(item){
344                updateMarker(item);
345            });
346        }
347        eventIndex--;
348        // restrict eventIndex to -1
349        if (eventIndex < -1)
350        {
351            eventIndex = -1;
352        }
353    }
354   
355    // Calls updateMarker for all targetDots after storing the previous marker in diff_arr
356    function buildDiff() {
357        for (var i = 0; i <= targetDots.length; i++)
358        {
359            if  (targetDots[i] !== undefined)
360            {
361                var targetMarkers = new Array();
362                targetDots[i].forEach(function(item){
363                    item.marker.properties.color = item.color;
364                    storePrev(item.marker, targetMarkers);
365                    updateMarker(item.marker);
366                });
367                diff_arr.push(targetMarkers);
368            }
369        }
370    }
371*/
372/*function initVDSbutton()
373{
374
375    var vdsBtnDiv = document.getElementById('vdsButton');
376    map.controls[google.maps.ControlPosition.LEFT_BOTTOM].push(vdsBtnDiv)
377    vdsBtnDiv.title = 'Click to toggle vds view';
378
379    // Setup the click event listeners to toggle icon display
380    vdsBtnDiv.addEventListener('click', function()
381    {
382        vds_showing = !vds_showing;
383        // reveal or hide all the dots
384        map.data.forEach(function(feature)
385        {
386            map.data.overrideStyle(feature,
387            {
388                visible: vds_showing
389            });
390        });
391        // Determine which button image to show
392        if (vds_showing)
393        {
394            pic = "images/btnDepressed_VDS.png"
395        }
396        else
397        {
398            pic = "images/btnReady_VDS.png"
399        }
400        document.getElementById('vdsBtnImg').src = pic;
401    });
402}*/
403
404// init beginning, forward and back buttons as well as time display on map
405function initControlButtons()
406{
407    var i = 0;
408    /*var time = document.getElementById('time');
409    map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(time)
410    var start = document.getElementById('start');
411    map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(start)
412    start.title = 'Click to see the first event';
413    var forward = document.getElementById('forward');
414    map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(forward)
415        var backward = document.getElementById('backward');
416        map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(backward)
417    forward.title = 'Click to see the next event';
418    forward.addEventListener('click', function() {
419        updateForwards();
420        backward.disabled = false;
421        if (i < eventTimes.length - 1) // get the next eventTime
422        {
423            ++i;
424            time.innerHTML = eventTimes[i];
425        }
426        if (eventIndex === targetDots.length - 1) // disable next button if last event reached
427        {
428            forward.disabled = true;
429        }
430    });
431        backward.addEventListener('click', function() {
432        updateBackwards();
433        forward.disabled = false;
434        if (i > 0)  // get the prev eventTime
435        {
436            --i;
437            time.innerHTML = eventTimes[i];
438        }
439        if (eventIndex < 0) // disable back button if at first event
440        {
441            backward.disabled = true;
442        }
443        });
444    start.addEventListener('click', function() {
445        updateVDSlayer(); // redraw markers on map from startup file
446        i = 0;
447        time.innerHTML = "00:00:00";
448    });*/
449}
450
Note: See TracBrowser for help on using the repository browser.