Skip to content

Instantly share code, notes, and snippets.

@RandomEtc
Created August 11, 2010 00:14
Show Gist options
  • Save RandomEtc/518261 to your computer and use it in GitHub Desktop.
Save RandomEtc/518261 to your computer and use it in GitHub Desktop.
experimental Modest Maps provider for the Bing REST API
package com.modestmaps.mapproviders.microsoft
{
import com.modestmaps.core.Coordinate;
import com.modestmaps.mapproviders.AbstractMapProvider;
import com.modestmaps.mapproviders.IMapProvider;
import com.modestmaps.util.BinaryUtil;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.net.URLVariables;
public class BingMapsProvider extends AbstractMapProvider implements IMapProvider, IEventDispatcher
{
public static const ROAD:String = 'Road';
public static const AERIAL:String = 'Aerial';
public static const HYBRID:String = 'AerialWithLabels';
public static const AERIAL_WITH_LABELS:String = 'AerialWithLabels';
private var dispatcher:EventDispatcher;
private var key:String;
private var type:String;
private var imageURL:String = null;
private var subDomains:Array = [];
private var serverSalt:int = 0;
public var copyright:String = null;
public var logo:String = null;
public function BingMapsProvider(key:String, type:String='Road', API:String='http://dev.virtualearth.net/REST/V1/Imagery/Metadata/')
{
super();
this.key = key;
this.type = type;
this.dispatcher = new EventDispatcher(this);
var data:URLVariables = new URLVariables();
data.key = key;
data.output = 'xml';
var request:URLRequest = new URLRequest(API + type);
request.data = data;
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, onLoadComplete);
loader.load(request);
}
private function onLoadComplete(event:Event):void
{
var response:XML = XML(event.target.data);
default xml namespace = new Namespace('http://schemas.microsoft.com/search/local/ws/rest/v1');
this.logo = response.BrandLogoUri[0].text().toString();
this.copyright = response.Copyright[0].text().toString();
var metadata:XML = response.ResourceSets[0].ResourceSet[0].Resources[0].ImageryMetadata[0];
this.imageURL = metadata.ImageUrl[0].text().toString();
for each (var string:XML in metadata.ImageUrlSubdomains[0].string) {
this.subDomains.push(string.text().toString());
}
serverSalt = int(Math.random() * this.subDomains.length);
// TODO: deal with ImageWidth/ImageHeight?
var zoomMin:int = parseInt(metadata.ZoomMin[0].text(),10);
var zoomMax:int = parseInt(metadata.ZoomMax[0].text(),10);
__bottomRightInLimit = __bottomRightInLimit.zoomTo(zoomMax);
__topLeftOutLimit = __topLeftOutLimit.zoomTo(zoomMin);
dispatchEvent(new Event(Event.COMPLETE));
}
////////// microsoft
protected function quadKey(coord:Coordinate):String
{
var sourceCoord:Coordinate = sourceCoordinate(coord);
// convert row + col to zoom string
// padded with zeroes so we end up with zoom digits after slicing:
var rowBinaryString:String = BinaryUtil.convertToBinary(sourceCoord.row);
rowBinaryString = rowBinaryString.slice(-sourceCoord.zoom);
var colBinaryString:String = BinaryUtil.convertToBinary(sourceCoord.column);
colBinaryString = colBinaryString.slice(-sourceCoord.zoom);
// generate zoom string by combining strings
var zoomString:String = "";
for(var i:Number = 0; i < sourceCoord.zoom; i += 1) {
zoomString += BinaryUtil.convertToDecimal(rowBinaryString.charAt( i ) + colBinaryString.charAt( i ));
}
return zoomString;
}
////////// map provider
public function getTileUrls(coord:Coordinate):Array
{
var size:int = Math.pow(2,coord.zoom);
if (coord.row < 0 || coord.row >= size) {
return [];
}
var subdomain:String = subDomains[Math.abs(serverSalt + coord.row + coord.column + coord.zoom) % 4];
var quadkey:String = quadKey(coord);
return [ imageURL.replace('{subdomain}',subdomain).replace('{quadkey}',quadkey) + '&stl=h' ];
}
public function toString():String
{
return 'BING_'+type.toUpperCase();
}
////////// events
public function willTrigger(type:String):Boolean
{
return dispatcher.willTrigger(type);
}
public function dispatchEvent(event:Event):Boolean
{
return dispatcher.dispatchEvent(event);
}
public function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false):void
{
dispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference);
}
public function hasEventListener(type:String):Boolean
{
return dispatcher.hasEventListener(type);
}
public function removeEventListener(type:String, listener:Function, useCapture:Boolean=false):void
{
dispatcher.removeEventListener(type, listener, useCapture);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment