Changeset 67

Show
Ignore:
Timestamp:
01/22/07 22:41:36 (2 years ago)
Author:
migurski
Message:

Merged branch "darren tile painting" on to trunk

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/as2/lib/com/modestmaps/core/Coordinate.as

    r42 r67  
    1515    { 
    1616        return '(' + row + ',' + column + ' @' + zoom + ')'; 
     17    } 
     18     
     19    public function copy():Coordinate 
     20    { 
     21        return new Coordinate(row, column, zoom); 
    1722    } 
    1823     
     
    6570        return new Coordinate(row, column - (distance ? distance : 1), zoom); 
    6671    } 
     72     
     73    /* 
     74     * Returns true if the the two coordinates refer to the same Tile location. 
     75     */ 
     76    public function equalTo( coord : Coordinate ) : Boolean 
     77    { 
     78        return coord.row == this.row && coord.column == this.column && coord.zoom == this.zoom; 
     79    } 
    6780} 
  • trunk/as2/lib/com/modestmaps/core/mapproviders/AbstractMapProvider.as

    r44 r67  
     1import mx.events.EventDispatcher; 
     2 
    13import com.modestmaps.core.mapproviders.IMapProvider; 
    24import com.modestmaps.io.RequestThrottler; 
    35import com.modestmaps.core.Coordinate; 
     6import com.modestmaps.events.IDispatchable; 
     7import com.modestmaps.geo.IProjection; 
     8import com.modestmaps.geo.LinearProjection; 
     9import com.modestmaps.geo.Transformation; 
     10import com.modestmaps.geo.Location; 
    411 
    512/** 
     
    714 */ 
    815class com.modestmaps.core.mapproviders.AbstractMapProvider   
     16implements IDispatchable 
    917{ 
     18        // Event Types 
     19        public static var EVENT_PAINT_COMPLETE : String = "onPaintComplete"; 
     20         
    1021        private var __requestThrottler : RequestThrottler; 
     22        private var __projection:IProjection; 
    1123 
     24        // tracks if we're set up to broadcast events 
     25        private static var _dispatcherInited : Boolean = false; 
     26 
     27        /* 
     28         * Constructor. 
     29         */ 
    1230        private function AbstractMapProvider() 
    1331        { 
    14                 __requestThrottler = RequestThrottler.getInstance();     
     32                // only set up broadcasting once, in the prototype 
     33                if ( !_dispatcherInited ) 
     34                {                
     35                        EventDispatcher.initialize( this.__proto__ ); 
     36                        _dispatcherInited = true; 
     37                } 
     38 
     39                __requestThrottler = RequestThrottler.getInstance(); 
     40 
     41            var t:Transformation = new Transformation(1, 0, 0, 0, 1, 0); 
     42        __projection = new LinearProjection(Coordinate.MAX_ZOOM, t); 
    1543        } 
    1644 
     
    2250        public function createLabel( clip : MovieClip, label : String ) : Void 
    2351        { 
     52                clip["labelTF"].removeTextField(); 
     53                 
    2454                clip.createTextField('labelTF', 1, 0, 0, 1, 1); 
    2555            var tf : TextField = clip["labelTF"]; 
     
    2959                tf.text = label;         
    3060        } 
     61         
     62        // Private Methods 
     63         
     64        private function raisePaintComplete( clip : MovieClip, coord : Coordinate ) : Void 
     65        { 
     66                var eventObj : Object = 
     67                { 
     68                        target : this, 
     69                        type : EVENT_PAINT_COMPLETE, 
     70                        clip : clip, 
     71                        coord : coord 
     72                }; 
     73                dispatchEvent( eventObj ); 
     74        } 
     75 
     76        // IDispatchable 
     77        public function addEventListener( type : String, handler ) : Void 
     78        { 
     79                super.addEventListener( type, handler ); 
     80        } 
     81         
     82        public function removeEventListener( type : String, handler ) : Void 
     83        { 
     84                super.removeEventListener( type, handler ); 
     85        } 
     86         
     87        public function dispatchEvent( eventObj : Object ) : Void 
     88        { 
     89                super.dispatchEvent( eventObj ); 
     90        } 
     91     
     92   /* 
     93    * Return projected and transformed coordinate for a location. 
     94    */ 
     95    public function locationCoordinate(location:Location):Coordinate 
     96    { 
     97        return __projection.locationCoordinate(location); 
     98    } 
     99     
     100   /* 
     101    * Return untransformed and unprojected location for a coordinate. 
     102    */ 
     103    public function coordinateLocation(coordinate:Coordinate):Location 
     104    { 
     105        return __projection.coordinateLocation(coordinate); 
     106    } 
    31107} 
  • trunk/as2/lib/com/modestmaps/core/mapproviders/AbstractMicrosoftMapProvider.as

    r44 r67  
    22import com.modestmaps.core.Coordinate; 
    33import com.modestmaps.util.BinaryUtil; 
     4import com.modestmaps.io.LoadMovieThrottledRequest; 
     5import mx.utils.Delegate; 
     6import com.modestmaps.geo.MercatorProjection; 
     7import com.modestmaps.geo.Transformation; 
    48 
    59/** 
     
    1014{ 
    1115        public static var BASE_URL : String; 
     16        public static var ASSET_EXTENSION : String; 
    1217         
    1318        function AbstractMicrosoftMapProvider()  
    1419        { 
    1520                super(); 
     21 
     22            // see: http://track.stamen.com/modestmap/wiki/TileCoordinateComparisons#TileGeolocations 
     23            var t:Transformation = new Transformation(1.068070779e7, 0, 3.355443185e7, 
     24                                                          0, -1.068070890e7, 3.355443057e7); 
     25                                                           
     26        __projection = new MercatorProjection(26, t); 
    1627        } 
    1728         
     
    2031                super.paint( clip, coord ); 
    2132                 
    22                 __requestThrottler.enqueue( clip.image, getTileUrl( coord ) ); 
     33                var request : LoadMovieThrottledRequest = new LoadMovieThrottledRequest( clip.image, getTileUrl( coord ) ); 
     34                request.addEventListener( LoadMovieThrottledRequest.EVENT_REQUEST_ERROR, Delegate.create( this, this.onRequestError )); 
     35                request.addEventListener( LoadMovieThrottledRequest.EVENT_RESPONSE_COMPLETE, Delegate.create( this, this.onResponseComplete )); 
     36                request.addEventListener( LoadMovieThrottledRequest.EVENT_RESPONSE_ERROR, Delegate.create( this, this.onResponseError )); 
     37                request.send(); 
    2338                 
    2439                createLabel( clip, coord.toString() ); 
     
    2641         
    2742        /* 
    28          * Abstract method, implemented by concrete subclass. 
     43         * Returns the value of BASE_URL for the class. 
     44         */ 
     45        public function get baseUrl() : String 
     46        { 
     47                throw new Error( "Abstract method not implemented by subclass." );       
     48                return null; 
     49        } 
     50 
     51        /* 
     52         * Returns the value of ASSET_EXTENSION for the class. 
     53         */ 
     54        public function get assetExtension() : String 
     55        { 
     56                throw new Error( "Abstract method not implemented by subclass." );       
     57                return null;     
     58        } 
     59         
     60        /* 
     61         * Returns the url needed to get the tile image.  
    2962         */ 
    3063        private function getTileUrl( coord : Coordinate ) : String 
    3164        { 
     65                throw new Error( "Abstract method not implemented by subclass." );       
    3266                return null; 
    3367        } 
     
    5185                return zoomString;  
    5286        } 
     87         
     88        /* 
     89         * Given a URL, returns the coordinates that the URL refers to. 
     90         */ 
     91        private function getCoordinateFromURL( url : String ) : Coordinate 
     92        { 
     93                var row, col, zoom : Number; 
     94                 
     95                // first locate the meaty bits (i.e. the zoomString). 
     96                var zoomString : String = url.substring( baseUrl.length ); 
     97                zoomString = zoomString.substring( 0, zoomString.indexOf( assetExtension ) ); 
     98 
     99                // now work backwards to determine row and col 
     100                zoom = zoomString.length; 
     101         
     102                var rowStr : String = ""; 
     103                var colStr : String = ""; 
     104                var tempStr : String = ""; 
     105                 
     106                for ( var i : Number = 0; i < zoom; i++ ) 
     107                { 
     108                        tempStr = BinaryUtil.convertToBinary( parseInt( zoomString.charAt( i ) ) ); 
     109                        colStr += tempStr.charAt( tempStr.length-1 ); 
     110                        rowStr += tempStr.charAt( tempStr.length-2 ); 
     111                } 
     112                                 
     113                row = BinaryUtil.convertToDecimal( rowStr ); 
     114                col = BinaryUtil.convertToDecimal( colStr ); 
     115                 
     116                var coord : Coordinate = new Coordinate( row, col, zoom ); 
     117                return coord; 
     118        } 
     119         
     120        // Event Handlers 
     121 
     122        private function onRequestError( eventObj : Object ) : Void 
     123        { 
     124        } 
     125         
     126        private function onResponseComplete( eventObj : Object ) : Void 
     127        { 
     128                var clip : MovieClip = MovieClip( eventObj.clip ); 
     129                var url : String = String( eventObj.url ); 
     130                 
     131                raisePaintComplete( clip, getCoordinateFromURL( url ) ); 
     132        } 
     133         
     134        private function onResponseError( eventObj : Object ) : Void 
     135        { 
     136        }        
    53137} 
  • trunk/as2/lib/com/modestmaps/core/mapproviders/IMapProvider.as

    r44 r67  
    33 */ 
    44import com.modestmaps.core.Coordinate;  
     5import com.modestmaps.geo.Location; 
    56  
    67interface com.modestmaps.core.mapproviders.IMapProvider  
    78{ 
    89        public function paint( clip : MovieClip, coord : Coordinate ) : Void; 
     10     
     11   /* 
     12    * Return projected and transformed coordinate for a location. 
     13    */ 
     14    public function locationCoordinate(location:Location):Coordinate; 
     15     
     16   /* 
     17    * Return untransformed and unprojected location for a coordinate. 
     18    */ 
     19    public function coordinateLocation(coordinate:Coordinate):Location; 
    920} 
  • trunk/as2/lib/com/modestmaps/core/mapproviders/MapProviderFactory.as

    r43 r67  
    5454 
    5555                        case MapProviders.MICROSOFT_HYBRID : 
    56                                 return new MicrosoftAerialMapProvider(); 
     56                                return new MicrosoftHybridMapProvider(); 
    5757                                 
    5858                        case MapProviders.MICROSOFT_DELAYED : 
  • trunk/as2/lib/com/modestmaps/core/mapproviders/MicrosoftAerialMapProvider.as

    r44 r67  
    33import com.modestmaps.core.Coordinate; 
    44import com.modestmaps.util.BinaryUtil; 
     5import com.modestmaps.events.IDispatchable; 
    56 
    67/** 
     
    1011class com.modestmaps.core.mapproviders.MicrosoftAerialMapProvider  
    1112extends AbstractMicrosoftMapProvider 
    12 implements IMapProvider  
     13implements IMapProvider, IDispatchable 
    1314{ 
    1415        private static var BASE_URL : String = "http://a0.ortho.tiles.virtualearth.net/tiles/a"; 
     16        private static var ASSET_EXTENSION : String = ".jpeg"; 
    1517                 
    1618        public function toString() : String 
     
    1921        } 
    2022         
     23        public function get baseUrl() : String 
     24        { 
     25                return BASE_URL;         
     26        } 
     27         
     28        public function get assetExtension() : String 
     29        { 
     30                return ASSET_EXTENSION;  
     31        } 
     32                 
    2133        private function getTileUrl( coord : Coordinate ) : String 
    2234        {                
    23                 var url : String = BASE_URL + getZoomString( coord ) + ".jpeg?g=45"; 
     35                var url : String = BASE_URL + getZoomString( coord ) + ASSET_EXTENSION + "?g=45"; 
    2436                 
    2537                //trace (this + ": Mapped " + coord.toString() + " to URL: " + url); 
  • trunk/as2/lib/com/modestmaps/core/mapproviders/MicrosoftDelayedAerialMapProvider.as

    r44 r67  
    33import com.modestmaps.core.Coordinate; 
    44import com.modestmaps.util.BinaryUtil; 
     5import com.modestmaps.events.IDispatchable; 
    56 
    67/** 
     
    1011class com.modestmaps.core.mapproviders.MicrosoftDelayedAerialMapProvider  
    1112extends AbstractMicrosoftMapProvider 
    12 implements IMapProvider  
     13implements IMapProvider, IDispatchable 
    1314{ 
    1415        private static var BASE_URL : String = "http://modestmap.com/proxy/index.php/a"; 
     16        private static var ASSET_EXTENSION : String = ".jpeg"; 
    1517                 
    1618        public function toString() : String 
     
    1921        } 
    2022         
     23        public function get baseUrl() : String 
     24        { 
     25                return BASE_URL;         
     26        } 
     27 
     28        public function get assetExtension() : String 
     29        { 
     30                return ASSET_EXTENSION;  
     31        } 
     32                         
    2133        private function getTileUrl( coord : Coordinate ) : String 
    2234        {                
    23                 var url : String = BASE_URL + getZoomString( coord ) + ".jpeg?g=45"; 
     35                var url : String = BASE_URL + getZoomString( coord ) + ASSET_EXTENSION + "?g=45";               
    2436                 
    2537                //trace (this + ": Mapped " + tile.toString() + " to URL: " + url); 
  • trunk/as2/lib/com/modestmaps/core/mapproviders/MicrosoftHybridMapProvider.as

    r44 r67  
    33import com.modestmaps.core.Coordinate; 
    44import com.modestmaps.util.BinaryUtil; 
     5import com.modestmaps.events.IDispatchable; 
    56 
    67/** 
     
    1011class com.modestmaps.core.mapproviders.MicrosoftHybridMapProvider  
    1112extends AbstractMicrosoftMapProvider 
    12 implements IMapProvider  
     13implements IMapProvider, IDispatchable 
    1314{ 
    1415        private static var BASE_URL : String = "http://h1.ortho.tiles.virtualearth.net/tiles/h"; 
     16        private static var ASSET_EXTENSION : String = ".jpeg"; 
    1517         
    1618        public function toString() : String 
     
    1921        } 
    2022         
     23        public function get baseUrl() : String 
     24        { 
     25                return BASE_URL;         
     26        } 
     27 
     28        public function get assetExtension() : String 
     29        { 
     30                return ASSET_EXTENSION;  
     31        } 
     32                 
    2133        private function getTileUrl( coord : Coordinate ) : String 
    2234        {                
    23                 var url : String = BASE_URL + getZoomString( coord ) + ".jpeg?g=45"; 
    24                  
    25                 //trace (this + ": Mapped " + tile.toString() + " to URL: " + url); 
    26                  
     35                var url : String = BASE_URL + getZoomString( coord ) + ASSET_EXTENSION + "?g=45";                
    2736                return url;  
    2837        } 
  • trunk/as2/lib/com/modestmaps/core/mapproviders/MicrosoftRoadMapProvider.as

    r44 r67  
    22import com.modestmaps.core.mapproviders.AbstractMicrosoftMapProvider; 
    33import com.modestmaps.core.Coordinate; 
     4import com.modestmaps.events.IDispatchable; 
    45 
    56 
     
    1011class com.modestmaps.core.mapproviders.MicrosoftRoadMapProvider  
    1112extends AbstractMicrosoftMapProvider 
    12 implements IMapProvider  
     13implements IMapProvider, IDispatchable 
    1314{ 
    1415        private static var BASE_URL : String = "http://r3.ortho.tiles.virtualearth.net/tiles/r"; 
     16        private static var ASSET_EXTENSION : String = ".png"; 
    1517                 
    1618        public function toString() : String 
     
    1921        } 
    2022         
     23        public function get baseUrl() : String 
     24        { 
     25                return BASE_URL;         
     26        } 
     27 
     28        public function get assetExtension() : String 
     29        { 
     30                return ASSET_EXTENSION;  
     31        } 
     32                         
    2133        private function getTileUrl( coord : Coordinate ) : String 
    2234        {                
    23                 var url : String = BASE_URL + getZoomString( coord ) + ".png?g=45"; 
     35                var url : String = BASE_URL + getZoomString( coord ) + ASSET_EXTENSION + "?g=45"; 
    2436                 
    2537                //trace (this + ": Mapped " + tile.toString() + " to URL: " + url); 
  • trunk/as2/lib/com/modestmaps/core/mapproviders/VanillaMapProvider.as

    r44 r67  
    66import com.modestmaps.core.mapproviders.AbstractMapProvider; 
    77import com.modestmaps.core.Coordinate; 
     8import com.modestmaps.events.IDispatchable; 
    89 
    910class com.modestmaps.core.mapproviders.VanillaMapProvider  
    1011extends AbstractMapProvider 
    11 implements IMapProvider  
     12implements IMapProvider, IDispatchable 
    1213{ 
    1314        public function paintTile( clip : MovieClip, coord : Coordinate ) : Void  
  • trunk/as2/lib/com/modestmaps/core/Tile.as

    r44 r67  
    55import com.modestmaps.core.TileGrid; 
    66import com.modestmaps.core.mapproviders.IMapProvider; 
     7import com.modestmaps.core.mapproviders.AbstractMapProvider; 
     8import mx.utils.Delegate; 
     9import com.modestmaps.events.IDispatchable; 
    710 
    811class com.modestmaps.core.Tile  
     
    1114    public var grid:TileGrid; 
    1215 
    13     public var coord:Coordinate; 
     16    private var __coord : Coordinate; 
    1417     
    15     /* 
    16     public var row:Number = 0; 
    17     public var column:Number = 0; 
    18     public var zoom:Number = 0; 
    19     */ 
    20  
    2118    public var width:Number; 
    2219    public var height:Number; 
     
    2522    public var origin:Boolean; 
    2623 
    27         public var displayClip : MovieClip; 
     24        // Keeps track of all clips awaiting painting. 
     25        private var __displayClips : Array; 
     26 
     27        private var __paintCompleteDelegate : Function; 
    2828 
    2929    public static var symbolName:String = '__Packages.com.modestmaps.core.Tile'; 
     
    3434    { 
    3535        super(); 
     36         
     37        __displayClips = new Array(); 
     38         
     39        __paintCompleteDelegate = Delegate.create( this, this.onPaintComplete );         
    3640    } 
    37      
     41    
     42    public function get coord() : Coordinate 
     43    { 
     44        return __coord;  
     45    } 
     46    public function set coord( coord : Coordinate ) : Void 
     47    { 
     48        __coord = coord; 
     49        redraw();        
     50    } 
     51         
    3852    public function center():Point 
    3953    { 
     
    4458    { 
    4559        coord = new Coordinate(Math.floor(coord.row / 2), Math.floor(coord.column / 2), coord.zoom + 1); 
    46         redraw(); 
    4760    } 
    4861 
     
    5063    { 
    5164        coord = new Coordinate(coord.row * 2, coord.column * 2, coord.zoom - 1); 
    52         redraw(); 
    5365    } 
    5466 
     
    5668    { 
    5769        coord = new Coordinate(coord.row * 2, coord.column * 2 + 1, coord.zoom - 1); 
    58         redraw(); 
    5970    } 
    6071 
     
    6273    { 
    6374        coord = new Coordinate(coord.row * 2 + 1, coord.column * 2, coord.zoom - 1); 
    64         redraw(); 
    6575    } 
    6676 
     
    6878    { 
    6979        coord = new Coordinate(coord.row * 2 + 1, coord.column * 2 + 1, coord.zoom - 1); 
    70         redraw(); 
    7180    } 
    7281 
     
    7483    { 
    7584        coord = coord.up(distance); 
    76         redraw(); 
    7785    } 
    7886 
     
    8088    { 
    8189        coord = coord.right(distance); 
    82         redraw(); 
    8390    } 
    8491 
     
    8693    { 
    8794        coord = coord.down(distance); 
    88         redraw(); 
    8995    } 
    9096 
     
    9298    { 
    9399        coord = coord.left(distance); 
    94         redraw(); 
    95100    } 
    96101 
     
    102107    public function redraw():Void 
    103108    { 
     109        _level0.tile.log("redraw: " + coord.toString()); 
     110         
     111        IDispatchable( grid.mapProvider ).addEventListener( AbstractMapProvider.EVENT_PAINT_COMPLETE, __paintCompleteDelegate ); 
    104112        paint( grid.mapProvider ); 
    105113         
     
    111119        // set up the proper clip to paint here 
    112120         
    113         var clip : MovieClip = this.createEmptyMovieClip( "display", this.getNextHighestDepth() ); 
     121        var clipId : Number = this.getNextHighestDepth(); 
     122        var clip : MovieClip = this.createEmptyMovieClip( "display" + clipId, clipId ); 
     123                 
     124                // hide all other displayClips to avoid weird "repaint" effect 
     125                var count : Number = __displayClips.length; 
     126                while ( count-- ) 
     127                { 
     128                        __displayClips[count].clip._visible = false; 
     129                } 
     130 
     131                __displayClips.push ( { clip : clip, coord : coord } ); 
    114132         
    115133        mapProvider.paint( clip, coord ); 
    116134    } 
    117135     
     136    // Event Handlers 
     137     
     138    private function onPaintComplete( eventObj : Object ) : Void 
     139    { 
     140        var coord : Coordinate = Coordinate( eventObj.coord ); 
     141         
     142        if ( this.coord.equalTo( coord ) ) 
     143        { 
     144                IDispatchable( grid.mapProvider ).removeEventListener( AbstractMapProvider.EVENT_PAINT_COMPLETE, __paintCompleteDelegate ); 
     145                 
     146                // remove all other displayClips /below/ this clip               
     147                var dcCoord : Coordinate; 
     148                for ( var i : Number = 0; i < __displayClips.length; i++ ) 
     149                { 
     150                        dcCoord = Coordinate( __displayClips[i].coord ); 
     151                        if ( dcCoord.equalTo( this.coord ) ) 
     152                                        break; 
     153                        else 
     154                        { 
     155                                __displayClips[i].clip.removeMovieClip(); 
     156                                __displayClips.splice( i, 1 ); 
     157                                i--; 
     158                        } 
     159                } 
     160        }        
     161    }    
    118162} 
  • trunk/as2/lib/com/modestmaps/core/TileGrid.as

    r44 r67  
    44import com.modestmaps.core.Tile; 
    55import com.modestmaps.core.mapproviders.IMapProvider; 
    6 import com.modestmaps.core.mapproviders.MapProviderFactory; 
    7 import com.modestmaps.core.mapproviders.MapProviders; 
    86 
    97import mx.utils.Delegate; 
     
    3836     
    3937    // For testing purposes. 
     38    public var labelContainer:MovieClip; 
    4039    public var label:TextField; 
    4140     
     
    4948 
    5049    // Who do we get our Map graphics from? 
    51     public var mapProviderType:Number; 
    52     public var mapProvider : IMapProvider; 
     50    public var mapProvider:IMapProvider; 
    5351 
    5452    public static var symbolName:String = '__Packages.com.modestmaps.core.TileGrid'; 
     
    5856    public function TileGrid() 
    5957    { 
    60         setMapProvider(mapProviderType); 
     58                this.createEmptyMovieClip( "labelContainer", getNextHighestDepth() ); 
     59        labelContainer.createTextField('label', 1, 10, 10, width-20, height-20); 
     60        label = labelContainer["label"]; 
     61        label.selectable = false; 
     62        label.textColor = 0xFF6600; 
     63                 
     64        log('FUCK YEAH '+width+'x'+height); 
    6165         
    6266        buildWell(); 
     
    8791         
    8892        allocateTiles(); 
    89         redraw(); 
    90          
    91         createTextField('label', getNextHighestDepth(), 10, 10, width-20, height-20); 
    92         label.selectable = false; 
    93          
    94         log('FUCK YEAH '+width+'x'+height); 
     93        redraw();    
     94         
     95        labelContainer.swapDepths( getNextHighestDepth() );     
    9596    } 
    9697     
     
    104105        well.onRelease = Delegate.create(this, this.stopWellDrag); 
    105106        well.onReleaseOutside = Delegate.create(this, this.stopWellDrag); 
     107         
     108        /* 
     109        // So the log is visible... 
     110        var c:Color = new Color(well); 
     111        var t:Object = c.getTransform(); 
     112        t.ra = 20; 
     113        t.rb = 204; 
     114        t.ga = 20; 
     115        t.gb = 204; 
     116        t.ba = 20; 
     117        t.bb = 204; 
     118        c.setTransform(t); 
     119        */ 
    106120    } 
    107121     
     
    142156    { 
    143157        label.text += msg + '\n'; 
     158        label.scroll = label.maxscroll; 
    144159    } 
    145160     
     
    147162    { 
    148163        label.text = ''; 
    149     } 
    150      
    151     private function setMapProvider( mapProviderType : Number ) : Void 
    152     { 
    153         this.mapProviderType = mapProviderType; 
    154         var mapProviderFactory : MapProviderFactory = MapProviderFactory.getInstance(); 
    155         mapProvider = MapProviderFactory.getInstance().getMapProvider( mapProviderType );  
    156164    } 
    157165     
     
    214222    } 
    215223     
    216     /* 
    217224    private function pointCoordinate(point:Point):Coordinate 
    218225    { 
     
    223230        // an arbitrary reference tile, zoomed to the maximum 
    224231        tile = tiles[0]; 
    225         tileCoord = new Coordinate(tile.row, tile.column, tile.zoom); 
    226         tileCoord.zoomTo(Coordinate.MAX_ZOOM); 
     232        tileCoord = tile.coord.copy(); 
     233        tileCoord = tileCoord.zoomTo(Coordinate.MAX_ZOOM); 
    227234         
    228235        // distance in tile widths from reference tile to point 
    229236        var xTiles:Number = (point.x - tile._x) / tileWidth; 
    230237        var yTiles:Number = (point.y - tile._y) / tileHeight; 
    231          
     238 
    232239        // distance in rows & columns at maximum zoom 
    233         var xDistance:Number = xTiles * Math.pow(2, (Coordinate.MAX_ZOOM - tile.zoom)); 
    234         var yDistance:Number = yTiles * Math.pow(2, (Coordinate.MAX_ZOOM - tile.zoom)); 
     240        var xDistance:Number = xTiles * Math.pow(2, (Coordinate.MAX_ZOOM - tile.coord.zoom)); 
     241        var yDistance:Number = yTiles * Math.pow(2, (Coordinate.MAX_ZOOM - tile.coord.zoom)); 
    235242         
    236243        // new point coordinate reflecting that distance 
     
    239246                                    tileCoord.zoom); 
    240247         
    241         return pointCoord; 
    242     } 
    243     */ 
     248        return pointCoord.zoomTo(tile.coord.zoom); 
     249    } 
     250     
     251    public function topLeftCoordinate():Coordinate 
     252    { 
     253        var point:Point = new Point(0, 0); 
     254         
     255        localToGlobal(point); 
     256        well.globalToLocal(point); 
     257         
     258        return pointCoordinate(point); 
     259    } 
     260     
     261    public function bottomRightCoordinate():Coordinate 
     262    { 
     263        var point:Point = new Point(width, height); 
     264         
     265        localToGlobal(point); 
     266        well.globalToLocal(point); 
     267         
     268        return pointCoordinate(point); 
     269    } 
    244270     
    245271   /* 
     
    263289        max.y = well._y - max.y; 
    264290         
    265         log('min/max for drag: '+min+', '+max+' ('+topLeftOutLimit+', '+bottomRightInLimit+')'); 
     291        //log('min/max for drag: '+min+', '+max+' ('+topLeftOutLimit+', '+bottomRightInLimit+')'); 
    266292         
    267293        // weird negative edge conditions, limit all movement on an axis 
     
    326352    } 
    327353     
    328     public function startZoomIn():Void 
     354    public function zoomIn(amount:Number):Void 
    329355    { 
    330356        if(zoomLevel >= bottomRightInLimit.zoom && Math.round(well._xscale) >= 100) 
    331357            return; 
    332358     
    333         well._xscale *= Math.pow(2, .25); 
    334         well._yscale *= Math.pow(2, .25); 
     359        well._xscale *= Math.pow(2, amount); 
     360        well._yscale *= Math.pow(2, amount); 
    335361         
    336362        normalizeWell(); 
     
    341367    } 
    342368     
    343     public function startZoomOut():Void 
     369    public function zoomOut(amount:Number):Void 
    344370    { 
    345371        if(zoomLevel <= topLeftOutLimit.zoom && Math.round(well._xscale) <= 100) 
    346372            return; 
    347373     
    348         well._xscale /= Math.pow(2, .25); 
    349         well._yscale /= Math.pow(2, .25); 
     374        well._xscale /= Math.pow(2, amount); 
     375        well._yscale /= Math.pow(2, amount); 
    350376         
    351377        normalizeWell(); 
     
    356382    } 
    357383 
    358    /* 
    359     * TODO: 
    360     * Size relative to stage is currently hard-coded, but shouldn't be. 
    361     */ 
    362     public function onResize():Void 
    363     { 
    364         width = Stage.width - 2 * _x; 
    365         height = Stage.height - 2 * _y; 
     384    public function resizeTo(bottomLeft:Point):Void 
     385    { 
     386        width = bottomLeft.x; 
     387        height = bottomLeft.y; 
    366388 
    367389        centerWell(false); 
     
    371393    } 
    372394     
    373     public function panEast( pixels : Number ) : Void 
    374     { 
    375        well._x -= pixels; 
    376        positionTiles(); 
    377        centerWell(true); 
     395    public function panRight(pixels:Number):Void 
     396    { 
     397        well._x -= pixels; 
     398        positionTiles(); 
     399        centerWell(true); 
    378400    } 
    379401  
    380     public function panWest( pixels : Number ) : Void 
    381     { 
    382        well._x += pixels; 
    383        positionTiles(); 
     402    public function panLeft(pixels:Number):Void 
     403    { 
     404        well._x += pixels; 
     405        positionTiles(); 
    384406        centerWell(true); 
    385407    }  
    386      
    387     public function panNorth( pixels : Number ) : Void 
    388     { 
    389         well._y -= pixels; 
    390         positionTiles(); 
    391         centerWell(true); 
    392     } 
    393408  
    394     public function panSouth( pixels : Number ) : Void 
    395     { 
    396        well._y += pixels; 
    397        positionTiles(); 
     409    public function panUp(pixels:Number):Void 
     410    { 
     411        well._y += pixels; 
     412        positionTiles(); 
    398413        centerWell(true); 
    399414    }       
     415     
     416    public function panDown(pixels:Number):Void 
     417    { 
     418        well._y -= pixels; 
     419        positionTiles(); 
     420        centerWell(true); 
     421    } 
     422 
     423   /** 
     424    * Find out whether a tile is at the grid's native zoom level. 
     425    */ 
     426    private function nativeZoom(tile:Tile):Boolean 
     427    { 
     428        return (tile.coord.zoom == zoomLevel); 
     429    } 
    400430 
    401431   /** 
     
    502532 
    503533            f