Math.abs(endValue-value)) { closestIndex = endIndex; } else { closestIndex = startIndex; } return closestIndex; } var midIndex : int = (endIndex + startIndex) / 2; var midValue : Number = elevationData[midIndex].x; if (midValue > value) { return binarySearch(value, startIndex, midIndex-1); } else if (midValue < value) { return binarySearch(value, midIndex+1, endIndex); } else { return midIndex; } } private function chartToolTip(e:HitData) : String { var nf : NumberFormatter = new NumberFormatter(); nf.precision = 2; var s:String; s = "" + LineSeries(e.element).displayName + "\n"; s += "Distance: " + nf.format(e.item.x) + " miles\n"; s += "Time: " + nf.format(e.item.time) + " decimal hours\n"; s += "Elevation: " + nf.format(e.item.y) + " feet\n"; nf.precision = 4; s += "Latitude: " + nf.format(e.item.lat) + " degrees\n"; s += "Longitude: " + nf.format(e.item.lon) + " degrees\n"; var u:URLRequest = new URLRequest("javascript:centerMap('" + e.item.lat + "','" + e.item.lon + "')"); navigateToURL(u,"_self"); return s; } private function distance(point1: Object, point2 : Object) : Number { var lat1 : Number; var lat2 : Number; var lon1 : Number; var lon2 : Number; if (point1 == null) return 0; // convert degrees to radians lat1 = point1.lat * Math.PI / 180.0; lat2 = point2.lat * Math.PI / 180.0; lon1 = point1.lon * Math.PI / 180.0; lon2 = point2.lon * Math.PI / 180.0; // radius of earth in Kilometers converted to miles var radius : Number = 6378.1 * 0.621371192; var latDist : Number = lat2 - lat1; var lonDist : Number = lon2 - lon1; var sinLatDist : Number = Math.sin(latDist/2.0); var sinLonDist : Number = Math.sin(lonDist / 2.0); var a : Number = sinLatDist * sinLatDist + Math.cos(lat1) * Math.cos(lat2) * sinLonDist * sinLonDist; var c : Number = 2.0 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); var distance : Number = radius * c; return distance; } private var gpx:XML = new XML(); private var myLoader:URLLoader; private function loadData() : void { var myXMLURL:URLRequest = new URLRequest(gpxUrl); myLoader = new URLLoader(myXMLURL); myLoader.addEventListener("complete", xmlLoaded); var u:URLRequest = new URLRequest("javascript:getGpxDistance()"); navigateToURL(u,"_self"); } [Bindable] public var computedDistance : Number = 0; [Bindable] public var computedDistanceLabel : String = ""; private function xmlLoaded(evtObj:Event) : void { gpx = XML(myLoader.data); trace("Data loaded:" + gpxUrl); var ed : ArrayCollection = new ArrayCollection(); var firstTimePoint : Number = 0; var prevItem : Object; for each (var trkpt:XML in gpx..trkpt) { var item : Object = new Object(); var ele : Number = Number(trkpt.ele); if (elevationMin == -1 ) { elevationMin = ele; } else { elevationMin = Math.min(elevationMin, ele); } if (elevationMax == -1) { elevationMax = ele; } else { elevationMax = Math.max(elevationMax, ele); } var time : String = trkpt.time; var dt : Number = getDecimalTime(time); if (firstTimePoint == 0) { firstTimePoint = dt; } dt -= firstTimePoint; if (timeMin == -1) { timeMin = dt; } else { timeMin = Math.min(dt, timeMin); } if (timeMax == -1) { timeMax = dt; } else { timeMax = Math.max(dt, timeMax); } var lat : String = trkpt.@lat; var lon : String = trkpt.@lon; item.time = dt; // convert meters to feet item.y = ele * 3.28; item.lat = lat; item.lon = lon; item.x = distance(prevItem, item); computedDistance += item.x; item.x = computedDistance; ed.addItem(item); prevItem = item; trace(item.x + ", " + item.y + ", " + item.time); } // convert meters to feet elevationMax *= 3.28; elevationMin *= 3.28; var minPoint : Object = new Object(); var maxPoint : Object = new Object(); minPoint.x = 0; //timeMax; minPoint.y = 0; maxPoint.x = 0; //timeMax; maxPoint.y = elevationMax; timeLineData.addItem(minPoint); timeLineData.addItem(maxPoint); var nf : NumberFormatter = new NumberFormatter(); nf.precision = 2; minElevationLabel = "Min. Elevation: " + nf.format(elevationMin) + " feet"; maxElevationLabel = "Max. Elevation: " + nf.format(elevationMax) + " feet"; elevationData = ed; computedDistanceLabel = "Distance: " + nf.format(computedDistance) + " miles"; } private function getDecimalTime(date:String) : Number { var hour : int = Number(date.substr(11,2)); var minute : int = Number(date.substr(14,2)); var second : int = Number(date.substr(17,2)); var decimalTime : Number = hour + minute/60 + second/3600; return decimalTime; } private var elevationChartLength : int = elevationData.toArray().length - 1; private function animate() : void { var timer : Timer = new Timer(elevationChartLength); timer.addEventListener("timer", onTimer); timer.start(); } public function onTimer(event:TimerEvent) : void { var i : int = event.target.currentCount - 1; var v : String = elevationData.getItemAt(i)["x"]; sliderMove(v); } [Bindable] private var routeTitle : String = ""; private var gpxUrl : String; public function setGpxDataSource(value:String, title:String):void { gpxUrl = value; routeTitle = title; loadData(); } [Bindable] private var gpxDistance : Number; [Bindable] private var gpxDistanceLabel : String; public function setGpxDistance(value : Number) : void { gpxDistance = value * 0.0006 var nf : NumberFormatter = new NumberFormatter(); nf.precision = 2; gpxDistanceLabel = "Google Distance: " + nf.format(gpxDistance) + " miles"; } public function initApp() : void { ExternalInterface.addCallback("setDataSource", setGpxDataSource); ExternalInterface.addCallback("setDistance", setGpxDistance); var u:URLRequest = new URLRequest("javascript:getGpxUrl()"); navigateToURL(u,"_self"); slider.callback = sliderMove; } public function sliderChange(event: Event) : void { sliderMove(event.currentTarget.value); } public function startPlayer(goback: Boolean) : void { pauseButton.enabled = true; pauseButton.visible = true; resumeButton.visible = false; myMove.play(null, goback); } public function stopPlayer() : void { pauseButton.enabled = true; pauseButton.visible = true; resumeButton.visible = false; myMove.pause(); myMove.play(null, true); } public function pausePlayer() : void { pauseButton.visible = false; resumeButton.visible = true; resumeButton.enabled = true; myMove.pause(); } public function resumePlayer() : void { pauseButton.visible = true; resumeButton.visible = false; pauseButton.enabled = true; myMove.resume(); } ]]>