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

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