/**
* Copyright kikiroom ( http://wonderfl.net/user/kikiroom )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/47wJ
*/
<!--
Copyright 2010 Google Inc.
Licensed under the Apache License, Version 2.0:
http://www.apache.org/licenses/LICENSE-2.0
-->
−
<mx:Application layout="absolute" width="512" height="618" backgroundGradientAlphas="[1.0, 1.0]" backgroundGradientColors="[#FFFFFF, #FFFFFF]">
−
<mx:Script>
import com.google.maps.LatLngBounds;
</mx:Script>
<maps:Map3D mapevent_mappreinitialize="onMapPreinitialize(event)" mapevent_mapready="onMapReady(event)" id="map" width="512" height="390" key="ABQIAAAAileP5HJrxmFV0kOk2fke8BQGj0PqsCtxKvarsoS-iqLdqZSKfxQxinA9ISZ9agV9VWN-NZQKaGAr5g" sensor="false" themeColor="#FFFFFF"/>
−
<mx:ColumnChart id="chart" width="512" height="192" showDataTips="true" x="0" y="426" itemRollOver="chartRollOver(event)" itemRollOut="chartRollOut(event)" seriesFilters="[]" dataTipFunction="dtFunc" columnWidthRatio="1.0">
−
<mx:verticalAxis>
<mx:LinearAxis title="Elevation (m)"/>
</mx:verticalAxis>
−
<mx:horizontalAxisRenderer>
<mx:AxisRenderer showLabels="false"/>
</mx:horizontalAxisRenderer>
−
<mx:series>
<mx:ColumnSeries yField="elevation" displayName="Elevation" dataProvider="{elevations}"/>
</mx:series>
</mx:ColumnChart>
−
<mx:Script>
import mx.charts.AreaChart;
import mx.charts.HitData;
import mx.charts.events.ChartItemEvent;
import com.google.maps.LatLng;
import com.google.maps.Map3D;
import com.google.maps.MapEvent;
import com.google.maps.MapOptions;
import com.google.maps.MapType;
import com.google.maps.View;
import com.google.maps.geom.Attitude;
import com.google.maps.MapMouseEvent;
import com.google.maps.overlays.Marker;
import com.google.maps.overlays.Polyline;
import com.google.maps.overlays.PolylineOptions;
import com.google.maps.services.Directions;
import com.google.maps.services.DirectionsEvent;
import com.google.maps.services.Elevation;
import com.google.maps.services.ElevationEvent;
import com.google.maps.services.ClientGeocoder;
import com.google.maps.services.GeocodingEvent;
import com.google.maps.overlays.MarkerOptions;
import com.google.maps.controls.MapTypeControl;
import com.google.maps.controls.NavigationControl;
import com.google.maps.services.Directions;
import com.google.maps.services.DirectionsOptions;
private var directionsService:Directions = null;
private var elevationService:Elevation = null;
private var geocodingService:ClientGeocoder = null;
private var rollOverMarker:Marker = null;
private var markers:Array = [];
private var polyline:Polyline = null;
private var zoom:int = 12;
[Bindable]
private var elevations:Array = null;
private var SAMPLES:int = 250;
private function onMapPreinitialize(event:MapEvent):void {
var myMapOptions:MapOptions = new MapOptions();
myMapOptions.zoom = zoom;
myMapOptions.center = new LatLng(40.756054, -73.986951);
myMapOptions.mapType = MapType.NORMAL_MAP_TYPE;
myMapOptions.viewMode = View.VIEWMODE_PERSPECTIVE;
myMapOptions.attitude = new Attitude(0,30,0);
map.setInitOptions(myMapOptions);
this.elevationService = new Elevation();
this.elevationService.addEventListener(ElevationEvent.ELEVATION_SUCCESS, plotElevation);
this.elevationService.addEventListener(ElevationEvent.ELEVATION_FAILURE, elevationError);
this.directionsService = new Directions();
this.directionsService.addEventListener(DirectionsEvent.DIRECTIONS_SUCCESS, getRouteElevation);
this.directionsService.addEventListener(DirectionsEvent.DIRECTIONS_FAILURE, directionsError);
this.geocodingService = new ClientGeocoder();
this.geocodingService.addEventListener(GeocodingEvent.GEOCODING_SUCCESS, addAddress);
this.geocodingService.addEventListener(GeocodingEvent.GEOCODING_FAILURE, geocodingError);
this.map.addEventListener(MapMouseEvent.CLICK, function(event:MapMouseEvent):void {
addMarker(event.latLng, true);
});
}
private function onMapReady(event:MapEvent):void {
map.addControl(new MapTypeControl());
map.addControl(new NavigationControl());
addMarker(new LatLng(37.80805,-122.426544), false);
addMarker(new LatLng(37.802116,-122.418884), false);
addMarker(new LatLng(37.800404,-122.409743), false);
addMarker(new LatLng(37.799844,-122.398907), true);
recenterMap();
}
private function addMarker(latLng:LatLng, doQuery:Boolean):void {
if (markers.length < 10) {
var marker:Marker = new Marker(latLng, new MarkerOptions({
draggable: true
}));
marker.addEventListener(MapMouseEvent.DRAG_END, function(event:MapMouseEvent):void {
updateElevation();
});
map.addOverlay(marker);
markers.push(marker);
if (doQuery) {
updateElevation();
}
if (markers.length == 10) {
address.enabled = false;
}
} else {
popup.title = "Points limit reached";
error.text = "No more than 10 points can be added.";
popup.visible = true;
}
}
private function addAddress(event:GeocodingEvent):void {
address.text = "";
var latlng:LatLng = event.response.placemarks[0].point;
addMarker(latlng, true);
recenterMap();
}
private function recenterMap():void {
if (markers.length > 0) {
zoom = 16;
var center:LatLng = markers[0].getLatLng();
var pitch:Number = map.getAttitude().pitch;
if (markers.length > 1) {
var bounds:LatLngBounds = new LatLngBounds();
for (var i:int = 0; i < markers.length; i++) {
bounds.extend(markers[i].getLatLng());
}
center = bounds.getCenter();
zoom = map.getBoundsZoomLevel(bounds);
}
map.setCenter(center, zoom);
map.setAttitude(new Attitude(0, pitch, 0));
}
}
private function updateElevation():void {
if (markers.length > 1) {
var latlngs:Array = [];
for (var i:int = 0; i < markers.length; i++) {
latlngs.push(markers[i].getLatLng())
}
if (mode.selectedIndex > 0) {
directionsService.setOptions(new DirectionsOptions({
travelMode: (mode.selectedIndex == 1 ?
DirectionsOptions.TRAVEL_MODE_DRIVING :
DirectionsOptions.TRAVEL_MODE_WALKING)
}));
directionsService.loadFromWaypoints(latlngs);
} else {
elevationService.loadElevationAlongPath(latlngs, SAMPLES);
}
}
}
private function getRouteElevation(event:DirectionsEvent):void {
elevationService.loadElevationAlongEncodedPath(event.directions.encodedPolylineData, SAMPLES);
}
private function plotElevation(event:ElevationEvent):void {
elevations = event.elevations;
var path:Array = [];
for (var i:int = 0; i < elevations.length; i++) {
path.push(elevations[i].location);
}
if (polyline) {
map.removeOverlay(polyline);
}
polyline = new Polyline(path, new PolylineOptions({
geodesic: true,
strokeStyle: {
color: 0x000000,
alpha: 0.9,
thickness: 3.0,
pixelHinting: true
}
}));
map.addOverlay(polyline);
}
private function chartRollOver(event:ChartItemEvent):void {
if (rollOverMarker == null) {
rollOverMarker = new Marker(event.hitData.item.location,
new MarkerOptions({
fillStyle: {
color: 0x00d000
}
}));
map.addOverlay(rollOverMarker);
} else {
rollOverMarker.visible = true;
}
var location:LatLng = event.hitData.item.location;
rollOverMarker.setLatLng(location);
var yaw:Number = getBearing(event.hitData.chartItem.index);
var pitch:Number = 45 + getGradient(event.hitData.chartItem.index);
map.cancelFlyTo();
map.flyTo(location, zoom + 2, new Attitude(yaw, pitch, 0.5));
}
private function chartRollOut(event:ChartItemEvent):void {
if (rollOverMarker != null) {
rollOverMarker.visible = false;
}
}
public function dtFunc(hd:HitData):String {
return "<B>Elevation: </B>" + Math.round(hd.item.elevation) + "m<br/>" +
"<B>Gradient: </B>" + Math.round(getGradient(hd.chartItem.index)) + "°";
}
private function reset():void {
map.clearOverlays();
polyline = null;
rollOverMarker = null;
markers = new Array();
elevations = new Array();
address.enabled = true;
}
private function getGradient(id:int):Number {
var id0:int = (id - 1 < 0 ? id : id - 1);
var id1:int = (id + 1 == elevations.length ? id : id + 1);
var location0:LatLng = elevations[id0].location;
var location1:LatLng = elevations[id1].location;
var locationDelta:Number = location0.distanceFrom(location1);
var elevation0:Number = elevations[id0].elevation;
var elevation1:Number = elevations[id1].elevation;
var elevationDelta:Number = elevation1 - elevation0;
var gradient:Number = Math.atan2(elevationDelta, locationDelta);
return deg(gradient);
}
private function geocodingError(event:GeocodingEvent):void {
popup.title = "Address lookup failed";
error.text = "Address not found.";
popup.visible = true;
}
private function directionsError(event:DirectionsEvent):void {
popup.title = "Address lookup failed";
error.text = "Could not generate a route between these points.";
popup.visible = true;
}
private function elevationError(event:ElevationEvent):void {
popup.title = "Elevation lookup failed";
error.text = "Could not obtain an elevation profile for this route.";
popup.visible = true;
elevations = new Array();
}
private function getBearing(id:int):Number {
var id0:int = (id - 1 < 0 ? id : id - 1);
var id1:int = (id + 1 == elevations.length ? id : id + 1);
var location0:LatLng = elevations[id0].location;
var location1:LatLng = elevations[id1].location;
return rhumbBearing(location0, location1);
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Based on the spherical geodesy formulae & scripts (c) Chris Veness 2002-2010 */
/* - www.movable-type.co.uk/scripts/latlong.html */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
private function rhumbBearing(location0:LatLng, location1:LatLng):Number {
var lat1:Number = rad(location0.lat()), lat2:Number = rad(location1.lat());
var dLng:Number = rad((location1.lng()-location0.lng()));
var dPhi:Number = Math.log(Math.tan(lat2/2+Math.PI/4)/Math.tan(lat1/2+Math.PI/4));
if (Math.abs(dLng) > Math.PI) dLng = dLng>0 ? -(2*Math.PI-dLng) : (2*Math.PI+dLng);
var brng:Number = Math.atan2(dLng, dPhi);
return (deg(brng)+360) % 360;
}
private function deg(r:Number):Number {
return r * 180 / Math.PI;
}
private function rad(d:Number):Number {
return d * Math.PI / 180;
}
</mx:Script>
<mx:TextInput x="61.5" y="398" id="address" enter="geocodingService.geocode(address.text)" width="113"/>
<mx:Text x="5.5" y="400" text="Address:" width="57"/>
<mx:Text x="182.5" y="400" text="Mode of transport:"/>
−
<mx:ComboBox x="299.5" y="398" id="mode" change="updateElevation()" selectedIndex="1" width="106">
−
<mx:ArrayCollection>
<mx:String>Direct</mx:String>
<mx:String>Driving</mx:String>
<mx:String>Walking</mx:String>
</mx:ArrayCollection>
</mx:ComboBox>
<mx:Button x="413.5" y="398" label="Clear points" id="clear" buttonDown="reset()"/>
−
<mx:TitleWindow x="195" y="176" width="250" height="124" layout="absolute" id="popup" visible="false" backgroundColor="#FFFFFF">
<mx:TextArea x="10" y="10" height="35" width="210" id="error" borderThickness="0" borderStyle="none"/>
<mx:Button x="93.5" y="52" label="OK" buttonDown="popup.visible=false"/>
</mx:TitleWindow>
<mx:HRule x="0" y="389" width="512"/>
</mx:Application>