how to use 3D map Actionscript class in mxml file for display map.

Posted by nemade-vipin on Stack Overflow See other posts from Stack Overflow or by nemade-vipin
Published on 2010-04-23T13:31:05Z Indexed on 2010/04/23 13:33 UTC
Read the original article Hit count: 450

Filed under:
|
|

hello friends, I have created the application in which I have to use 3D map Action Script class in mxml file to display a map in form. that is in tab navigator last tab.

My ActionScript 3D map class is(FlyingDirections):-

package src.SBTSCoreObject { import src.SBTSCoreObject.JSONDecoder; import com.google.maps.InfoWindowOptions; import com.google.maps.LatLng; import com.google.maps.LatLngBounds; import com.google.maps.Map3D; import com.google.maps.MapEvent; import com.google.maps.MapOptions; import com.google.maps.MapType; import com.google.maps.MapUtil; import com.google.maps.View; import com.google.maps.controls.NavigationControl; import com.google.maps.geom.Attitude; import com.google.maps.interfaces.IPolyline; import com.google.maps.overlays.Marker; import com.google.maps.overlays.MarkerOptions; import com.google.maps.services.Directions; import com.google.maps.services.DirectionsEvent; import com.google.maps.services.Route;

import flash.display.Bitmap; import flash.display.DisplayObject; import flash.display.DisplayObjectContainer; import flash.display.Loader; import flash.display.LoaderInfo; import flash.display.Sprite; import flash.events.Event; import flash.events.IOErrorEvent; import flash.events.MouseEvent; import flash.events.TimerEvent; import flash.filters.DropShadowFilter; import flash.geom.Point; import flash.net.URLLoader; import flash.net.URLRequest; import flash.net.navigateToURL; import flash.text.TextField; import flash.text.TextFieldAutoSize; import flash.text.TextFormat; import flash.utils.Timer; import flash.utils.getTimer;

public class FlyingDirections extends Map3D { /** * Panoramio home page. */ private static const PANORAMIO_HOME:String = "http://www.panoramio.com/";

/**
 * The icon for the car.
 */
[Embed("assets/car-icon-24px.png")]
private static const Car:Class;

/**
 * The Panoramio icon.
 */
[Embed("assets/iw_panoramio.png")]
private static const PanoramioIcon:Class;

/**
 * We animate a zoom in to the start the route before the car starts
 * to move. This constant sets the time in seconds over which this
 * zoom occurs.
 */
private static const LEAD_IN_DURATION:Number = 3;

/**
 * Duration of the trip in seconds.
 */
private static const TRIP_DURATION:Number = 40;

/**
 * Constants that define the geometry of the Panoramio image markers.
 */
private static const BORDER_T:Number = 3;
private static const BORDER_L:Number = 10;
private static const BORDER_R:Number = 10;
private static const BORDER_B:Number = 3;
private static const GAP_T:Number = 2;
private static const GAP_B:Number = 1;
private static const IMAGE_SCALE:Number = 1;

/**
 * Trajectory that the camera follows over time. Each element is an object
 * containing properties used to generate parameter values for flyTo(..).
 * fraction = 0 corresponds to the start of the trip; fraction = 1
 * correspondsto the end of the trip.
 */
private var FLY_TRAJECTORY:Array = [
    { fraction: 0, zoom: 6, attitude: new Attitude(0, 0, 0) },
    { fraction: 0.2, zoom: 8.5, attitude: new Attitude(30, 30, 0) },
    { fraction: 0.5, zoom: 9, attitude: new Attitude(30, 40, 0) },
    { fraction: 1, zoom: 8, attitude: new Attitude(50, 50, 0) },
    { fraction: 1.1, zoom: 8, attitude: new Attitude(130, 50, 0) },
    { fraction: 1.2, zoom: 8, attitude: new Attitude(220, 50, 0) },
];

/**
 * Number of panaramio photos for which we load data. We'll select a
 * subset of these approximately evenly spaced along the route.
 */
private static const NUM_GEOTAGGED_PHOTOS:int = 50;

/**
 * Number of panaramio photos that we actually show.
 */
private static const NUM_SHOWN_PHOTOS:int = 7;

/**
 * Scaling between real trip time and animation time.
 */
private static const SCALE_TIME:Number = 0.001;

/**
 * getTimer() value at the instant that we start the trip. If this is 0 then
 * we have not yet started the car moving.
 */
private var startTimer:int = 0;

/**
 * The current route.
 */
private var route:Route;

/**
 * The polyline for the route.
 */
private var polyline:IPolyline;

/**
 * The car marker.
 */
private var marker:Marker;

/**
 * The cumulative duration in seconds over each step in the route.
 * cumulativeStepDuration[0] is 0; cumulativeStepDuration[1] adds the
 * duration of step 0; cumulativeStepDuration[2] adds the duration
 * of step 1; etc.
 */
private var cumulativeStepDuration:/*Number*/Array = [];

/**
 * The cumulative distance in metres over each vertex in the route polyline.
 * cumulativeVertexDistance[0] is 0; cumulativeVertexDistance[1] adds the
 * distance to vertex 1; cumulativeVertexDistance[2] adds the distance to
 * vertex 2; etc.
 */
private var cumulativeVertexDistance:Array;

/**
 * Array of photos loaded from Panoramio. This array has the same format as
 * the 'photos' property within the JSON returned by the Panoramio API
 * (see http://www.panoramio.com/api/), with additional properties added to
 * individual photo elements to hold the loader structures that fetch
 * the actual images.
 */
private var photos:Array = [];

/**
 * Array of polyline vertices, where each element is in world coordinates.
 * Several computations can be faster if we can use world coordinates
 * instead of LatLng coordinates.
 */
private var worldPoly:/*Point*/Array;

/**
 * Whether the start button has been pressed.
 */
private var startButtonPressed:Boolean = false;

/**
 * Saved event from onDirectionsSuccess call.
 */
private var directionsSuccessEvent:DirectionsEvent = null;

/**
 * Start button.
 */
private var startButton:Sprite;

/**
 * Alpha value used for the Panoramio image markers.
 */
private var markerAlpha:Number = 0;

/**
 * Index of the current driving direction step. Used to update the
 * info window content each time we progress to a new step.
 */
private var currentStepIndex:int = -1;

/**
 * The fly directions map constructor.
 *
 * @constructor
 */
public function FlyingDirections() {
  key="ABQIAAAA7QUChpcnvnmXxsjC7s1fCxQGj0PqsCtxKvarsoS-iqLdqZSKfxTd7Xf-2rEc_PC9o8IsJde80Wnj4g";
  super();
  addEventListener(MapEvent.MAP_PREINITIALIZE, onMapPreinitialize);
  addEventListener(MapEvent.MAP_READY, onMapReady);
}

/**
 * Handles map preintialize. Initializes the map center and zoom level.
 *
 * @param event  The map event.
 */
private function onMapPreinitialize(event:MapEvent):void {

  setInitOptions(new MapOptions({
    center: new LatLng(-26.1, 135.1),
    zoom: 4,
    viewMode: View.VIEWMODE_PERSPECTIVE,
    mapType:MapType.PHYSICAL_MAP_TYPE
  }));
}

/**
 * Handles map ready and looks up directions.
 *
 * @param event  The map event.
 */
private function onMapReady(event:MapEvent):void {
  enableScrollWheelZoom();
  enableContinuousZoom();

  addControl(new NavigationControl());

  // The driving animation will be updated on every frame.
  addEventListener(Event.ENTER_FRAME, enterFrame);

  addStartButton();

  // We start the directions loading now, so that we're ready to go when
  // the user hits the start button.
  var directions:Directions = new Directions();
  directions.addEventListener(
      DirectionsEvent.DIRECTIONS_SUCCESS, onDirectionsSuccess);
  directions.addEventListener(
      DirectionsEvent.DIRECTIONS_FAILURE, onDirectionsFailure);
  directions.load("48 Pirrama Rd, Pyrmont, NSW to Byron Bay, NSW");
}

/**
 * Adds a big blue start button.
 */
private function addStartButton():void {
  startButton = new Sprite();
  startButton.buttonMode = true;
  startButton.addEventListener(MouseEvent.CLICK, onStartClick);

  startButton.graphics.beginFill(0x1871ce);
  startButton.graphics.drawRoundRect(0, 0, 150, 100, 10, 10);
  startButton.graphics.endFill();

  var startField:TextField = new TextField();
  startField.autoSize = TextFieldAutoSize.LEFT;
  startField.defaultTextFormat =
      new TextFormat("_sans", 20, 0xffffff, true);
  startField.text = "Start!";
  startButton.addChild(startField);
  startField.x = 0.5 * (startButton.width - startField.width);
  startField.y = 0.5 * (startButton.height - startField.height);

  startButton.filters = [ new DropShadowFilter() ];

  var container:DisplayObjectContainer =
      getDisplayObject() as DisplayObjectContainer;
  container.addChild(startButton);
  startButton.x = 0.5 * (container.width - startButton.width);
  startButton.y = 0.5 * (container.height - startButton.height);

  var panoField:TextField = new TextField();
  panoField.autoSize = TextFieldAutoSize.LEFT;
  panoField.defaultTextFormat =
      new TextFormat("_sans", 11, 0x000000, true);
  panoField.text = "Photos provided by Panoramio are under the copyright of their owners.";
  container.addChild(panoField);
  panoField.x = container.width - panoField.width - 5;
  panoField.y = 5;
}

/**
 * Handles directions success. Starts flying the route if everything
 * is ready.
 *
 * @param event  The directions event.
 */
private function onDirectionsSuccess(event:DirectionsEvent):void {
  directionsSuccessEvent = event;
  flyRouteIfReady();
}

/**
 * Handles click on the start button. Starts flying the route if everything
 * is ready.
 */
private function onStartClick(event:MouseEvent):void {
  startButton.removeEventListener(MouseEvent.CLICK, onStartClick);
  var container:DisplayObjectContainer =
      getDisplayObject() as DisplayObjectContainer;
  container.removeChild(startButton);
  startButtonPressed = true;
  flyRouteIfReady();
}

/**
 * If we have loaded the directions and the start button has been pressed
 * start flying the directions route.
 */
private function flyRouteIfReady():void {
  if (!directionsSuccessEvent || !startButtonPressed) {
    return;
  }

  var directions:Directions = directionsSuccessEvent.directions;

  // Extract the route.
  route = directions.getRoute(0);

  // Draws the polyline showing the route.
  polyline = directions.createPolyline();
  addOverlay(directions.createPolyline());

  // Creates a car marker that is moved along the route.
  var car:DisplayObject = new Car();
  marker = new Marker(route.startGeocode.point, new MarkerOptions({
    icon: car,
    iconOffset: new Point(-car.width / 2, -car.height)
  }));
  addOverlay(marker);

  transformPolyToWorld();
  createCumulativeArrays();

  // Load Panoramio data for the region covered by the route.
  loadPanoramioData(directions.bounds);

  var duration:Number = route.duration;
  // Start a timer that will trigger the car moving after the lead in time.
  var leadInTimer:Timer = new Timer(LEAD_IN_DURATION * 1000, 1);
  leadInTimer.addEventListener(TimerEvent.TIMER, onLeadInDone);
  leadInTimer.start();
  var flyTime:Number = -LEAD_IN_DURATION;

  // Set up the camera flight trajectory.
  for each (var flyStep:Object in FLY_TRAJECTORY) {
    var time:Number = flyStep.fraction * duration;
    var center:LatLng = latLngAt(time);
    var scaledTime:Number = time * SCALE_TIME;
    var zoom:Number = flyStep.zoom;
    var attitude:Attitude = flyStep.attitude;
    var elapsed:Number = scaledTime - flyTime;
    flyTime = scaledTime;
    flyTo(center, zoom, attitude, elapsed);
  }
}

/**
 * Loads Panoramio data for the route bounds. We load data about more photos
 * than we need, then select a subset lying along the route.
 * @param bounds Bounds within which to fetch images.
 */
private function loadPanoramioData(bounds:LatLngBounds):void {
  var params:Object = {
    order: "popularity",
    set: "full",
    from: "0",
    to: NUM_GEOTAGGED_PHOTOS.toString(10),
    size: "small",
    minx: bounds.getWest(),
    miny: bounds.getSouth(),
    maxx: bounds.getEast(),
    maxy: bounds.getNorth()
  };
  var loader:URLLoader = new URLLoader();
  var request:URLRequest = new URLRequest(
      "http://www.panoramio.com/map/get_panoramas.php?" +
      paramsToString(params));
  loader.addEventListener(Event.COMPLETE, onPanoramioDataLoaded);
  loader.addEventListener(IOErrorEvent.IO_ERROR, onPanoramioDataFailed);
  loader.load(request);
}

/**
 * Transforms the route polyline to world coordinates.
 */
private function transformPolyToWorld():void {
  var numVertices:int = polyline.getVertexCount();
  worldPoly = new Array(numVertices);
  for (var i:int = 0; i < numVertices; ++i) {
    var vertex:LatLng = polyline.getVertex(i);
    worldPoly[i] = fromLatLngToPoint(vertex, 0);
  }
}

/**
 * Returns the time at which the route approaches closest to the
 * given point.
 * @param world Point in world coordinates.
 * @return Route time at which the closest approach occurs.
 */
private function getTimeOfClosestApproach(world:Point):Number {
  var minDistSqr:Number = Number.MAX_VALUE;
  var numVertices:int = worldPoly.length;
  var x:Number = world.x;
  var y:Number = world.y;
  var minVertex:int = 0;
  for (var i:int = 0; i < numVertices; ++i) {
    var dx:Number = worldPoly[i].x - x;
    var dy:Number = worldPoly[i].y - y;
    var distSqr:Number = dx * dx + dy * dy;
    if (distSqr < minDistSqr) {
      minDistSqr = distSqr;
      minVertex = i;
    }
  }
  return cumulativeVertexDistance[minVertex];
}

/**
 * Returns the array index of the first element that compares greater than
 * the given value.
 * @param ordered Ordered array of elements.
 * @param value Value to use for comparison.
 * @return Array index of the first element that compares greater than
 *     the given value.
 */
private function upperBound(ordered:Array, value:Number,
                            first:int=0, last:int=-1):int {
  if (last < 0) {
    last = ordered.length;
  }
  var count:int = last - first;
  var index:int;
  while (count > 0) {
    var step:int = count >> 1;
    index = first + step;
    if (value >= ordered[index]) {
      first = index + 1;
      count -= step - 1;
    } else {
      count = step;
    }
  }
  return first;
}

/**
 * Selects up to a given number of photos approximately evenly spaced along
 * the route.
 * @param ordered Array of photos, each of which is an object with
 *     a property &apos;closestTime&apos;.
 * @param number Number of photos to select.
 */
private function selectEvenlySpacedPhotos(ordered:Array, number:int):Array {
  var start:Number = cumulativeVertexDistance[0];
  var end:Number =
      cumulativeVertexDistance[cumulativeVertexDistance.length - 2];

  var closestTimes:Array = [];
  for each (var photo:Object in ordered) {
    closestTimes.push(photo.closestTime);
  }

  var selectedPhotos:Array = [];
  for (var i:int = 0; i < number; ++i) {
    var idealTime:Number = start + ((end - start) * (i + 0.5) / number);

    var index:int = upperBound(closestTimes, idealTime);
    if (index < 1) {
      index = 0;
    } else if (index >= ordered.length) {
      index = ordered.length - 1;
    } else {
      var errorToPrev:Number =
          Math.abs(idealTime - closestTimes[index - 1]);
      var errorToNext:Number = Math.abs(idealTime - closestTimes[index]);
      if (errorToPrev < errorToNext) {
        --index;
      }
    }

    selectedPhotos.push(ordered[index]);
  }
  return selectedPhotos;
}

/**
 * Handles completion of loading the Panoramio index data. Selects from the
 * returned photo indices a subset of those that lie along the route and
 * initiates load of each of these.
 * @param event Load completion event.
 */
private function onPanoramioDataLoaded(event:Event):void {
  var loader:URLLoader = event.target as URLLoader;
  var decoder:JSONDecoder = new JSONDecoder(loader.data as String);
  var allPhotos:Array = decoder.getValue().photos;
  for each (var photo:Object in allPhotos) {
    var latLng:LatLng = new LatLng(photo.latitude, photo.longitude);
    photo.closestTime =
        getTimeOfClosestApproach(fromLatLngToPoint(latLng, 0));
  }
  allPhotos.sortOn("closestTime", Array.NUMERIC);

  photos = selectEvenlySpacedPhotos(allPhotos, NUM_SHOWN_PHOTOS);

  for each (photo in photos) {
      var photoLoader:Loader = new Loader();
      // The images aren&apos;t on panoramio.com: we can&apos;t acquire pixel access
      // using "new LoaderContext(true)".
      photoLoader.load(
          new URLRequest(photo.photo_file_url));
      photo.loader = photoLoader;
      // Save the loader info: we use this to find the original element when
      // the load completes.
      photo.loaderInfo = photoLoader.contentLoaderInfo;
      photoLoader.contentLoaderInfo.addEventListener(
          Event.COMPLETE, onPhotoLoaded);
  }
}

/**
 * Creates a MouseEvent listener function that will navigate to the given
 * URL in a new window.
 * @param url URL to which to navigate.
 */
private function createOnClickUrlOpener(url:String):Function {
  return function(event:MouseEvent):void {
    navigateToURL(new URLRequest(url));
  };
}

/**
 * Handles completion of loading an individual Panoramio image.
 * Adds a custom marker that displays the image. Initially this is made
 * invisible so that it can be faded in as needed.
 * @param event Load completion event.
 */
private function onPhotoLoaded(event:Event):void {
  var loaderInfo:LoaderInfo = event.target as LoaderInfo;
  // We need to find which photo element this image corresponds to.
  for each (var photo:Object in photos) {
    if (loaderInfo == photo.loaderInfo) {
      var imageMarker:Sprite = createImageMarker(photo.loader,
                                                 photo.owner_name,
                                                 photo.owner_url);
      var options:MarkerOptions = new MarkerOptions({
        icon: imageMarker,
        hasShadow: true,
        iconAlignment: MarkerOptions.ALIGN_BOTTOM | MarkerOptions.ALIGN_LEFT
      });
      var latLng:LatLng = new LatLng(photo.latitude, photo.longitude);
      var marker:Marker = new Marker(latLng, options);
      photo.marker = marker;
      addOverlay(marker);
      // A hack: we add the actual image after the overlay has been added,
      // which creates the shadow, so that the shadow is valid even if we
      // don&apos;t have security privileges to generate the shadow from the
      // image.
      marker.foreground.visible = false;
      marker.shadow.alpha = 0;
      var imageHolder:Sprite = new Sprite();
      imageHolder.addChild(photo.loader);
      imageHolder.buttonMode = true;
      imageHolder.addEventListener(
          MouseEvent.CLICK, createOnClickUrlOpener(photo.photo_url));
      imageMarker.addChild(imageHolder);
      return;
    }
  }
  trace("An image was loaded which could not be found in the photo array.");
}

/**
 * Creates a custom marker showing an image.
 */
private function createImageMarker(child:DisplayObject,
                                   ownerName:String,
                                   ownerUrl:String):Sprite {
  var content:Sprite = new Sprite();

  var panoramioIcon:Bitmap = new PanoramioIcon();
  var iconHolder:Sprite = new Sprite();
  iconHolder.addChild(panoramioIcon);
  iconHolder.buttonMode = true;
  iconHolder.addEventListener(MouseEvent.CLICK, onPanoramioIconClick);
  panoramioIcon.x = BORDER_L;
  panoramioIcon.y = BORDER_T;
  content.addChild(iconHolder);

  // NOTE: we add the image as a child only after we&apos;ve added the marker
  // to the map. Currently the API requires this if it&apos;s to generate the
  // shadow for unprivileged content.
  // Shrink the image, so that it doesn&apos;t obcure too much screen space.
  // Ideally, we&apos;d subsample, but we don&apos;t have pixel level access.
  child.scaleX = IMAGE_SCALE;
  child.scaleY = IMAGE_SCALE;
  var imageW:Number = child.width;
  var imageH:Number = child.height;
  child.x = BORDER_L + 30;
  child.y = BORDER_T + iconHolder.height + GAP_T;

  var authorField:TextField = new TextField();
  authorField.autoSize = TextFieldAutoSize.LEFT;
  authorField.defaultTextFormat = new TextFormat("_sans", 12);
  authorField.text = "author:";
  content.addChild(authorField);
  authorField.x = BORDER_L;
  authorField.y = BORDER_T + iconHolder.height + GAP_T + imageH + GAP_B;

  var ownerField:TextField = new TextField();
  ownerField.autoSize = TextFieldAutoSize.LEFT;
  var textFormat:TextFormat = new TextFormat("_sans", 14, 0x0e5f9a);
  ownerField.defaultTextFormat = textFormat;
  ownerField.htmlText =
      "<a href=\"" + ownerUrl + "\" target=\"_blank\">" +
      ownerName + "</a>";
  content.addChild(ownerField);
  ownerField.x = BORDER_L + authorField.width;
  ownerField.y = BORDER_T + iconHolder.height + GAP_T + imageH + GAP_B;

  var totalW:Number =
      BORDER_L + Math.max(imageW, ownerField.width + authorField.width) +
      BORDER_R;
  var totalH:Number =
      BORDER_T + iconHolder.height +
      GAP_T + imageH + GAP_B +
      ownerField.height +
      BORDER_B;
  content.graphics.beginFill(0xffffff);
  content.graphics.drawRoundRect(0, 0, totalW, totalH, 10, 10);
  content.graphics.endFill();

  var marker:Sprite = new Sprite();
  marker.addChild(content);
  content.x = 30;
  content.y = 0;

  marker.graphics.lineStyle();
  marker.graphics.beginFill(0xff0000);
  marker.graphics.drawCircle(0, totalH + 30, 3);
  marker.graphics.endFill();
  marker.graphics.lineStyle(2, 0xffffff);
  marker.graphics.moveTo(30 + 10, totalH - 10);
  marker.graphics.lineTo(0, totalH + 30);

  return marker;
}

/**
 * Handles click on the Panoramio icon.
 */
private function onPanoramioIconClick(event:MouseEvent):void {
  navigateToURL(new URLRequest(PANORAMIO_HOME));
}

/**
 * Handles failure of a Panoramio image load.
 */
private function onPanoramioDataFailed(event:IOErrorEvent):void {
  trace("Load of image failed: " + event);
}

/**
 * Returns a string containing cgi query parameters.
 * @param Associative array mapping query parameter key to value.
 * @return String containing cgi query parameters.
 */
private static function paramsToString(params:Object):String {
  var result:String = "";
  var separator:String = "";
  for (var key:String in params) {
    result += separator +
        encodeURIComponent(key) + "=" + encodeURIComponent(params[key]);
    separator = "&";
  }
  return result;
}

/**
 * Called once the lead-in flight is done. Starts the car driving along
 * the route and starts a timer to begin fade in of the Panoramio
 * images in 1.5 seconds.
 */
private function onLeadInDone(event:Event):void {
  // Set startTimer non-zero so that the car starts to move.
  startTimer = getTimer();

  // Start a timer that will fade in the Panoramio images.
  var fadeInTimer:Timer = new Timer(1500, 1);
  fadeInTimer.addEventListener(TimerEvent.TIMER, onFadeInTimer);
  fadeInTimer.start();
}

/**
 * Handles the fade in timer&apos;s TIMER event. Sets markerAlpha above zero
 * which causes the frame enter handler to fade in the markers.
 */
private function onFadeInTimer(event:Event):void {
  markerAlpha = 0.01;
}

/**
 * The end time of the flight.
 */
private function get endTime():Number {
  if (!cumulativeStepDuration || cumulativeStepDuration.length == 0) {
    return startTimer;
  }
  return startTimer +
      cumulativeStepDuration[cumulativeStepDuration.length - 1];
}

/**
 * Creates the cumulative arrays, cumulativeStepDuration and
 * cumulativeVertexDistance.
 */
private function createCumulativeArrays():void {
  cumulativeStepDuration = new Array(route.numSteps + 1);
  cumulativeVertexDistance = new Array(polyline.getVertexCount() + 1);
  var polylineTotal:Number = 0;
  var total:Number = 0;
  var numVertices:int = polyline.getVertexCount();
  for (var stepIndex:int = 0; stepIndex < route.numSteps; ++stepIndex) {
    cumulativeStepDuration[stepIndex] = total;
    total += route.getStep(stepIndex).duration;
    var startVertex:int = stepIndex >= 0 ?
        route.getStep(stepIndex).polylineIndex : 0;
    var endVertex:int = stepIndex < (route.numSteps - 1) ?
        route.getStep(stepIndex + 1).polylineIndex : numVertices;
    var duration:Number = route.getStep(stepIndex).duration;
    var stepVertices:int = endVertex - startVertex;

    var latLng:LatLng = polyline.getVertex(startVertex);
    for (var vertex:int = startVertex; vertex < endVertex; ++vertex) {
      cumulativeVertexDistance[vertex] = polylineTotal;
      if (vertex < numVertices - 1) {
        var nextLatLng:LatLng = polyline.getVertex(vertex + 1);
        polylineTotal += nextLatLng.distanceFrom(latLng);
      }
      latLng = nextLatLng;
    }
  }
  cumulativeStepDuration[stepIndex] = total;
}

/**
 * Opens the info window above the car icon that details the given
 * step of the driving directions.
 * @param stepIndex Index of the current step.
 */
private function openInfoForStep(stepIndex:int):void {
  // Sets the content of the info window.
  var content:String;
  if (stepIndex >= route.numSteps) {
    content = "<b>" + route.endGeocode.address + "</b>" +
              "<br /><br />" +
              route.summaryHtml;
  } else {
    content = "<b>" + stepIndex + ".</b> " +
        route.getStep(stepIndex).descriptionHtml;
  }
  marker.openInfoWindow(new InfoWindowOptions({ contentHTML: content }));
}

/**
 * Displays the driving directions step appropriate for the given time.
 * Opens the info window showing the step instructions each time we
 * progress to a new step.
 * @param time Time for which to display the step.
 */
private function displayStepAt(time:Number):void {
  var stepIndex:int = upperBound(cumulativeStepDuration, time) - 1;
  var minStepIndex:int = 0;
  var maxStepIndex:int = route.numSteps - 1;
  if (stepIndex >= 0 &&
      stepIndex <= maxStepIndex &&
      currentStepIndex != stepIndex) {
    openInfoForStep(stepIndex);
    currentStepIndex = stepIndex;
  }
}

/**
 * Returns the LatLng at which the car should be positioned at the given
 * time.
 * @param time Time for which LatLng should be found.
 * @return LatLng.
 */
private function latLngAt(time:Number):LatLng {
  var stepIndex:int = upperBound(cumulativeStepDuration, time) - 1;
  var minStepIndex:int = 0;
  var maxStepIndex:int = route.numSteps - 1;
  if (stepIndex < minStepIndex) {
    return route.startGeocode.point;
  } else if (stepIndex > maxStepIndex) {
    return route.endGeocode.point;
  }

  var stepStart:Number = cumulativeStepDuration[stepIndex];
  var stepEnd:Number = cumulativeStepDuration[stepIndex + 1];
  var stepFraction:Number = (time - stepStart) / (stepEnd - stepStart);

  var startVertex:int = route.getStep(stepIndex).polylineIndex;
  var endVertex:int = (stepIndex + 1) < route.numSteps ?
      route.getStep(stepIndex + 1).polylineIndex :
      polyline.getVertexCount();
  var stepVertices:int = endVertex - startVertex;

  var stepLeng

© Stack Overflow or respective owner

Related posts about flex3

Related posts about actionscript-3