Changeset 629
- Timestamp:
- 07/22/08 12:49:17 (1 month ago)
- Files:
-
- branches/tom-tweenlite/lib/com/modestmaps/core/MarkerClip.as (modified) (7 diffs)
- branches/tom-tweenlite/lib/com/modestmaps/core/PolygonClip.as (added)
- branches/tom-tweenlite/lib/com/modestmaps/core/PolygonMarker.as (added)
- branches/tom-tweenlite/lib/com/modestmaps/core/Tile.as (modified) (2 diffs)
- branches/tom-tweenlite/lib/com/modestmaps/core/TileGrid.as (modified) (28 diffs)
- branches/tom-tweenlite/lib/com/modestmaps/events/MapEvent.as (modified) (1 diff)
- branches/tom-tweenlite/lib/com/modestmaps/extras/MapControls.as (modified) (1 diff)
- branches/tom-tweenlite/lib/com/modestmaps/extras/MapCopyright.as (modified) (5 diffs)
- branches/tom-tweenlite/lib/com/modestmaps/extras/README (added)
- branches/tom-tweenlite/lib/com/modestmaps/extras/ve_logo.png (added)
- branches/tom-tweenlite/lib/com/modestmaps/extras/VirtualEarthCopyright.as (added)
- branches/tom-tweenlite/lib/com/modestmaps/Map.as (modified) (1 diff)
- branches/tom-tweenlite/lib/com/modestmaps/mapproviders/microsoft/MicrosoftProvider.as (modified) (1 diff)
- branches/tom-tweenlite/samples/as3/ModestMapsSample.as (modified) (7 diffs)
- branches/tom-tweenlite/samples/flash/ModestMapsSample.as (modified) (4 diffs)
- branches/tom-tweenlite/swc/bin/ModestMapsSWC.swc (modified) (previous)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/tom-tweenlite/lib/com/modestmaps/core/MarkerClip.as
r609 r629 43 43 public var markerSortFunction:Function = sortMarkersByYPosition; 44 44 45 // setting this.dirty = true will re quest an Event.RENDER45 // setting this.dirty = true will redraw an MapEvent.RENDERED 46 46 protected var _dirty:Boolean; 47 47 … … 70 70 this.x = map.getWidth() / 2; 71 71 this.y = map.getHeight() / 2; 72 //map.addEventListener(MarkerEvent.ENTER, onMapMarkerEnters); 73 //map.addEventListener(MarkerEvent.LEAVE, onMapMarkerLeaves); 72 74 73 map.addEventListener(MapEvent.START_ZOOMING, onMapStartZooming); 75 74 map.addEventListener(MapEvent.STOP_ZOOMING, onMapStopZooming); … … 80 79 map.addEventListener(MapEvent.RESIZED, onMapResized); 81 80 map.addEventListener(MapEvent.EXTENT_CHANGED, onMapExtentChanged); 81 map.addEventListener(MapEvent.RENDERED, updateClips); 82 82 83 83 addEventListener(Event.ADDED_TO_STAGE, onAddedToStage); … … 96 96 protected function onAddedToStage(event:Event):void 97 97 { 98 //addEventListener(Event.RENDER, updateClips); 99 100 dirty = true; 101 updateClips(); 102 98 103 removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage); 99 addEventListener(Event.RENDER, updateClips); 100 addEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage); 101 } 104 addEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage); 105 } 106 102 107 protected function onRemovedFromStage(event:Event):void 103 108 { 104 removeEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage); 105 removeEventListener(Event.RENDER, updateClips); 109 //removeEventListener(Event.RENDER, updateClips); 110 111 removeEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage); 106 112 addEventListener(Event.ADDED_TO_STAGE, onAddedToStage); 107 113 } … … 109 115 public function attachMarker(marker:DisplayObject, location:Location):void 110 116 { 111 // TODO: optionally index markers and throw marker events? 112 //map.grid.putMarker(marker.name, map.getMapProvider().locationCoordinate(location), location); 113 114 locations[marker] = new Location(location.lat, location.lon); 117 locations[marker] = location.clone(); 115 118 coordinates[marker] = map.getMapProvider().locationCoordinate(location); 116 119 markersByName[marker.name] = marker; 117 120 markers.push(marker); 118 121 119 var point:Point = map.locationPoint(location, this); 120 marker.x = snapToPixels ? Math.round(point.x) : point.x; 121 marker.y = snapToPixels ? Math.round(point.y) : point.y; 122 123 var w:Number = map.getWidth() * 2; 124 var h:Number = map.getHeight() * 2; 125 if (markerInBounds(marker, w, h)) 126 { 127 addChild(marker); 128 sortMarkers(true); 129 } 122 // set dirty to true, so that the next call to updateClips will set the 123 // position and add the marker to the stage if it's visible 124 dirty = true; 130 125 } 131 126 … … 283 278 x = starting.x; 284 279 y = starting.y; 280 starting = null; 285 281 } 286 282 else { … … 289 285 y = map.getHeight() / 2; 290 286 } 291 /*292 * HACK: Apparently, in Safari the MouseEvent.MOUSE_UP event doesn't fire at the same293 * point in the render process that it does in other browsers. What ends up happening294 * is that when the pan stops and the stage is invalidated, an Event.RENDER isn't295 * dispatched until the next frame. This results in a single frame of incorrectly placed296 * markers.297 *298 * In order to get around this, we set _dirty to true and call updateClips() directly.299 * This should mean that updateClips() doesn't get called any more than it should, even300 * though calling it twice on a single frame shouldn't be much of a problem. --Shawn301 */302 287 dirty = true; 303 updateClips();288 //updateClips(); 304 289 } 305 290 branches/tom-tweenlite/lib/com/modestmaps/core/Tile.as
r621 r629 6 6 package com.modestmaps.core 7 7 { 8 import flash.display.Bitmap; 9 import flash.display.DisplayObject; 8 10 import flash.display.Loader; 9 11 import flash.display.Sprite; … … 41 43 { 42 44 while (numChildren > 0) { 43 var loader:Loader = removeChildAt(0) as Loader;44 if ( loader) {45 var child:DisplayObject = removeChildAt(0); 46 if (child is Loader) { 45 47 try { 46 loader.unload();48 Loader(child).unload(); 47 49 } 48 50 catch (error:Error) { branches/tom-tweenlite/lib/com/modestmaps/core/TileGrid.as
r628 r629 4 4 import com.modestmaps.mapproviders.IMapProvider; 5 5 6 import flash.display.Bitmap; 6 7 import flash.display.DisplayObject; 7 8 import flash.display.Loader; … … 23 24 public class TileGrid extends Sprite 24 25 { 25 // TILE_WIDTH and TILE_HEIGHT are now tileWidth and tileHeight 26 // this was needed for the NASA DailyPlanetProvider which has 512x512px tiles 27 // public static const TILE_WIDTH:Number = 256; 28 // public static const TILE_HEIGHT:Number = 256; 29 30 // read-only, kept up to date by calculateBounds() 31 protected var _minZoom:Number; 32 protected var _maxZoom:Number; 33 34 protected var minTx:Number, maxTx:Number, minTy:Number, maxTy:Number; 35 36 // read-only, convenience for tileWidth/Height 37 protected var _tileWidth:Number; 38 protected var _tileHeight:Number; 39 40 41 // pan and zoom etc are stored in here 42 // NB: this matrix is never applied to a DisplayObject's transform 43 // because it would require scaling tile positions to compensate 44 // instead, we adapt its values such that the current zoom level 45 // is approximately scale 1, and positions make sense in screen pixels 46 protected var worldMatrix:Matrix; 47 48 // this turns screen points into coordinates 49 protected var _invertedMatrix:Matrix; // use lazy getter for this 50 51 // the corners and center of the screen, in map coordinates 52 // (these also have lazy getters) 53 protected var _topLeftCoordinate:Coordinate; 54 protected var _bottomRightCoordinate:Coordinate; 55 protected var _centerCoordinate:Coordinate; 56 57 // where the tiles live: 58 protected var well:Sprite; 59 60 protected var provider:IMapProvider; 61 62 protected var tileQueue:TileQueue; 63 64 protected var tileCache:TileCache; 65 66 protected var tilePool:TilePool; 67 68 // per-tile, the array of images we're going to load, which can be empty 69 // TODO: document this in IMapProvider, so that provider implementers know 70 // they are free to check the bounds of their overlays and don't have to serve 71 // millions of 404s 72 protected var layersNeeded:Object = {}; 73 74 // keys we've recently seen 75 protected var recentlySeen:Array = []; 76 77 // open requests 78 protected var openRequests:Array = []; 79 80 // keeping track for dispatching MapEvent.ALL_TILES_LOADED and MapEvent.BEGIN_TILE_LOADING 81 protected var previousOpenRequests:int = 0; 82 83 // currently visible tiles 84 protected var visibleTiles:Array = []; 85 86 // number of tiles we're failing to show 87 protected var blankCount:int = 0; 88 89 // a textfield with lots of stats 90 public var debugField:TextField; 91 92 // for stats: 93 protected var lastFrameTime:Number; 94 protected var fps:Number = 30; 95 96 // what zoom level of tiles is 'correct'? 97 protected var _currentTileZoom:int; 98 // so we know if we're going in or out 99 protected var previousTileZoom:int; 100 101 // for sorting the queue: 102 protected var centerRow:Number; 103 protected var centerColumn:Number; 104 105 // for pan events 106 protected var startPan:Point; 107 public var panning:Boolean; 108 109 // for zoom events 110 protected var startZoom:Number = -1; 111 public var zooming:Boolean; 112 26 // OPTIONS 27 /////////////////////////////// 28 29 // TODO: split these out into a TileGridOptions class and allow mass setting/getting? 30 113 31 protected static const DEFAULT_MAX_PARENT_SEARCH:int = 5; 32 protected static const DEFAULT_MAX_PARENT_LOAD:int = 0; 114 33 protected static const DEFAULT_MAX_CHILD_SEARCH:int = 1; 115 protected static const DEFAULT_MAX_TILES_TO_KEEP:int = 256; 116 protected static const DEFAULT_TILE_BUFFER:int = 0;34 protected static const DEFAULT_MAX_TILES_TO_KEEP:int = 256; // 256*256*4bytes = 0.25MB ... so 256 tiles is 64MB of memory, minimum! 35 protected static const DEFAULT_TILE_BUFFER:int = 1; 117 36 protected static const DEFAULT_ENFORCE_BOUNDS:Boolean = true; 118 37 protected static const DEFAULT_MAX_OPEN_REQUESTS:int = 4; // TODO: should this be split into max-new-requests-per-frame, too? 119 38 protected static const DEFAULT_ROUND_POSITIONS:Boolean = true; 120 39 protected static const DEFAULT_ROUND_SCALES:Boolean = true; 40 protected static const DEFAULT_CACHE_LOADERS:Boolean = false; // !!! TODO: change to false :) 41 protected static const DEFAULT_MAX_LOADER_CACHE_SIZE:int = 0; // !!! TODO: change to 0 :) 121 42 122 43 /** if we don't have a tile at currentZoom, onRender will look for tiles up to 5 levels out. … … 129 50 * - it works, but you probably don't want to change this number :) */ 130 51 public var maxChildSearch:int = DEFAULT_MAX_CHILD_SEARCH; 131 132 public var maxTilesToKeep:int = DEFAULT_MAX_TILES_TO_KEEP; // 256*256*4bytes = 0.25MB ... so 256 tiles is 64MB of memory, minimum! 52 53 /** if maxParentSearch is enabled, setting maxParentLoad to between 1 and maxParentSearch will make requests for lower zoom levels first */ 54 public var maxParentLoad:int = DEFAULT_MAX_PARENT_LOAD; 55 56 /** this is the maximum size of tileCache (visible tiles will also be kept in the cache) */ 57 public var maxTilesToKeep:int = DEFAULT_MAX_TILES_TO_KEEP; 133 58 134 59 // 0 or 1, really: 2 will load *lots* of extra tiles … … 147 72 public var roundScalesEnabled:Boolean = DEFAULT_ROUND_SCALES; 148 73 149 public var mapWidth:Number; 150 public var mapHeight:Number; 74 /** with tile providers that you have crossdomain.xml support for, 75 * it's possible to avoid extra requests by reusing bitmapdata. enable cacheLoaders to try and do that */ 76 public static var cacheLoaders:Boolean = DEFAULT_CACHE_LOADERS; 77 public static var maxLoaderCacheSize:int = DEFAULT_MAX_LOADER_CACHE_SIZE; 78 protected static var loaderCache:Object = {}; 79 protected static var cachedUrls:Array = []; 80 81 /////////////////////////////// 82 // END OPTIONS 83 84 // TILE_WIDTH and TILE_HEIGHT are now tileWidth and tileHeight 85 // this was needed for the NASA DailyPlanetProvider which has 512x512px tiles 86 // public static const TILE_WIDTH:Number = 256; 87 // public static const TILE_HEIGHT:Number = 256; 88 89 // read-only, kept up to date by calculateBounds() 90 protected var _minZoom:Number; 91 protected var _maxZoom:Number; 92 93 protected var minTx:Number, maxTx:Number, minTy:Number, maxTy:Number; 94 95 // read-only, convenience for tileWidth/Height 96 protected var _tileWidth:Number; 97 protected var _tileHeight:Number; 98 99 // pan and zoom etc are stored in here 100 // NB: this matrix is never applied to a DisplayObject's transform 101 // because it would require scaling tile positions to compensate. 102 // Instead, we adapt its values such that the current zoom level 103 // is approximately scale 1, and positions make sense in screen pixels 104 protected var worldMatrix:Matrix; 105 106 // this turns screen points into coordinates 107 protected var _invertedMatrix:Matrix; // use lazy getter for this 108 109 // the corners and center of the screen, in map coordinates 110 // (these also have lazy getters) 111 protected var _topLeftCoordinate:Coordinate; 112 protected var _bottomRightCoordinate:Coordinate; 113 protected var _centerCoordinate:Coordinate; 114 115 // where the tiles live: 116 protected var well:Sprite; 117 118 protected var provider:IMapProvider; 119 120 protected var tileQueue:TileQueue; 121 122 protected var tileCache:TileCache; 123 124 protected var tilePool:TilePool; 125 126 // per-tile, the array of images we're going to load, which can be empty 127 // TODO: document this in IMapProvider, so that provider implementers know 128 // they are free to check the bounds of their overlays and don't have to serve 129 // millions of 404s 130 protected var layersNeeded:Object = {}; 131 132 // keys we've recently seen 133 protected var recentlySeen:Array = []; 134 135 // open requests 136 protected var openRequests:Array = []; 137 138 // keeping track for dispatching MapEvent.ALL_TILES_LOADED and MapEvent.BEGIN_TILE_LOADING 139 protected var previousOpenRequests:int = 0; 140 141 // currently visible tiles 142 protected var visibleTiles:Array = []; 143 144 // number of tiles we're failing to show 145 protected var blankCount:int = 0; 146 147 // a textfield with lots of stats 148 public var debugField:TextField; 149 150 // for stats: 151 protected var lastFrameTime:Number; 152 protected var fps:Number = 30; 153 154 // what zoom level of tiles is 'correct'? 155 protected var _currentTileZoom:int; 156 // so we know if we're going in or out 157 protected var previousTileZoom:int; 158 159 // for sorting the queue: 160 protected var centerRow:Number; 161 protected var centerColumn:Number; 162 163 // for pan events 164 protected var startPan:Point; 165 public var panning:Boolean; 166 167 // previous mouse position when dragging 168 protected var pmouse:Point; 169 170 // for zoom events 171 protected var startZoom:Number = -1; 172 public var zooming:Boolean; 173 174 protected var mapWidth:Number; 175 protected var mapHeight:Number; 151 176 152 177 protected var draggable:Boolean; … … 154 179 // setting this.dirty = true will request an Event.RENDER 155 180 protected var _dirty:Boolean; 156 157 // previous mouse position when dragging158 protected var pmouse:Point;159 181 160 182 public function TileGrid(w:Number, h:Number, draggable:Boolean, provider:IMapProvider) … … 289 311 { 290 312 if (!dirty || !stage) { 313 dispatchEvent(new MapEvent(MapEvent.RENDERED)); 291 314 return; 292 315 } … … 391 414 if (recentlySeen.length > maxRecentlySeen) { 392 415 416 // can we sort so that biggest zoom levels get removed first, without removing currently visible tiles? 417 /* var visibleKeys:Array = recentlySeen.slice(recentlySeen.length - visibleTiles.length, recentlySeen.length); 418 419 // take a look at everything else 420 recentlySeen = recentlySeen.slice(0, recentlySeen.length - visibleTiles.length); 421 recentlySeen = recentlySeen.sort(Array.DESCENDING); 422 recentlySeen = recentlySeen.concat(visibleKeys); */ 423 393 424 // throw away keys at the beginning of recentlySeen 394 425 recentlySeen = recentlySeen.slice(recentlySeen.length - maxRecentlySeen, recentlySeen.length); … … 404 435 centerColumn = center.column; 405 436 437 // listen out for this if you want to be sure map is in its final state before reprojecting markers etc. 438 dispatchEvent(new MapEvent(MapEvent.RENDERED)); 439 406 440 dirty = false; 407 441 } … … 419 453 // for use in loops etc. 420 454 var coord:Coordinate = new Coordinate(0,0,0); 421 455 422 456 // loop over currently visible tiles 423 457 for (var col:int = minCol; col <= maxCol; col++) { … … 427 461 var key:String = tileKey(col, row, currentTileZoom); 428 462 463 /* // see if we already have this tile in the well 464 var tile:Tile = well.getChildByName(key) as Tile; 465 466 // if not, see if we already have this tile in the cache 467 if (!tile) { 468 tile = ensureVisible(key); 469 } 470 471 // finally load it if we really don't have it 472 if (!tile) { 473 tile = requestLoad(col, row, currentTileZoom); 474 visibleTiles.push(tile); 475 } */ 476 429 477 // see if we already have this tile 430 478 var tile:Tile = well.getChildByName(key) as Tile; … … 436 484 tile = tilePool.getTile(col, row, currentTileZoom); 437 485 tile.name = key; 438 coord.row = tile.row;486 coord.row = tile.row; 439 487 coord.column = tile.column; 440 coord.zoom = tile.zoom; 488 coord.zoom = tile.zoom; 441 489 var urls:Array = provider.getTileUrls(coord); 442 490 if (urls && urls.length > 0) { … … 456 504 457 505 visibleTiles.push(tile); 458 506 459 507 var tileReady:Boolean = tile.isShowing() && (layersNeeded[tile.name] == null); 460 508 … … 504 552 } 505 553 506 var startZoomSearch:int = currentTileZoom - 1;507 508 if (currentTileZoom > previousTileZoom) {509 // we already looked for parent level 1, and didn't find it, so:510 startZoomSearch -= 1;511 }512 513 var endZoomSearch:int = Math.max(minZoom, currentTileZoom-maxParentSearch);514 515 554 var stillNeedsAnImage:Boolean = !foundParent && foundChildren < 4; 555 516 556 // if it still doesn't have an image yet, try more parent zooms 517 557 if (stillNeedsAnImage && maxParentSearch > 1 && currentTileZoom > minZoom) { 558 559 var startZoomSearch:int = currentTileZoom - 1; 560 561 if (currentTileZoom > previousTileZoom) { 562 // we already looked for parent level 1, and didn't find it, so: 563 startZoomSearch -= 1; 564 } 565 566 var endZoomSearch:int = Math.max(minZoom, currentTileZoom-maxParentSearch); 567 518 568 for (var pzoom:int = startZoomSearch; pzoom >= endZoomSearch; pzoom--) { 519 569 if (ensureVisible(parentKey(col, row, currentTileZoom, pzoom))) { 520 570 stillNeedsAnImage = false; 521 571 break; 572 } 573 else if (currentTileZoom - pzoom < maxParentLoad) { 574 trace("requesting parent tile at zoom", pzoom); 575 var pcoord:Array = parentCoord(col, row, currentTileZoom, pzoom); 576 visibleTiles.push(requestLoad(pcoord[0], pcoord[1], pzoom)); 522 577 } 523 578 } … … 532 587 } // for row 533 588 } // for col 589 590 trace("zoomLevel", zoomLevel, "currentTileZoom", currentTileZoom, "blankCount", blankCount); 534 591 535 592 } // repopulateVisibleTiles … … 560 617 } 561 618 619 //trace(); 620 //trace("tile.zoom, tile.alpha, tile.numChildren ? tile.getChildAt(0).alpha : '', tile.isShowing() && (layersNeeded[tile.name] == null), tileCache.containsKey(tile.name)"); 621 562 622 // apply the sorted depths, position all the tiles and also keep recentlySeen updated: 563 623 for each (var tile:Tile in visibleTiles) { … … 583 643 } 584 644 585 } 645 //trace(tile.zoom, tile.alpha, tile.numChildren ? tile.getChildAt(0).alpha : '', tile.isShowing() && (layersNeeded[tile.name] == null), tileCache.containsKey(tile.name)); 646 647 } 648 649 //trace(); 586 650 } 587 651 … … 602 666 // reuse visible tiles for the queue we'll be loading the same things over and over 603 667 604 // sort queue by distance from 'center' 605 tileQueue.sortTiles(centerDistanceCompare); 668 if (maxParentLoad == 0) { 669 // sort queue by distance from 'center' 670 tileQueue.sortTiles(centerDistanceCompare); 671 } 672 else { 673 tileQueue.sortTiles(zoomThenCenterCompare); 674 } 606 675 607 676 // process the queue … … 635 704 if (urls && urls.length > 0) { 636 705 var url:* = urls.shift(); 637 var tileLoader:Loader = new Loader(); 638 tileLoader.name = tile.name; 639 try { 640 tileLoader.load((url is URLRequest) ? url : new URLRequest(url)); 641 tileLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadEnd, false, 0, true); 642 tileLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onLoadError, false, 0, true); 643 openRequests.push(tileLoader); 644 } 645 catch(error:Error) { 646 tile.paintError(); 706 if (cacheLoaders && (url is String) && loaderCache[url]) { 707 var original:Bitmap = loaderCache[url] as Bitmap; 708 var bitmap:Bitmap = new Bitmap(original.bitmapData); 709 tile.addChild(bitmap); 710 loadNextURLForTile(tile); 711 } 712 else { 713 var tileLoader:Loader = new Loader(); 714 tileLoader.name = tile.name; 715 try { 716 tileLoader.load((url is URLRequest) ? url : new URLRequest(url)); 717 tileLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadEnd, false, 0, true); 718 tileLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onLoadError, false, 0, true); 719 openRequests.push(tileLoader); 720 } 721 catch(error:Error) { 722 tile.paintError(); 723 } 647 724 } 648 725 } … … 657 734 delete layersNeeded[tile.name]; 658 735 } 736 } 737 738 private function zoomThenCenterCompare(t1:Tile, t2:Tile):int 739 { 740 if (t1.zoom == t2.zoom) { 741 return centerDistanceCompare(t1, t2); 742 } 743 return t1.zoom < t2.zoom ? -1 : t1.zoom > t2.zoom ? 1 : 0; 659 744 } 660 745 … … 678 763 } 679 764 680 // makes sure th e tile with the given key is inthe well and added to visibleTiles681 // returns false if alreadySeen[key] does not exist682 private function ensureVisible(key:String): Boolean765 // makes sure that if a tile with the given key exists in the cache that it is added to the well and added to visibleTiles 766 // returns null if tile does not exist in cache 767 private function ensureVisible(key:String):Tile 683 768 { 684 769 if (tileCache.containsKey(key)) { … … 692 777 } 693 778 tile.showNow(); 694 return true; 695 } 696 return false; 697 } 698 779 return tile; 780 } 781 return null; 782 } 783 /* private function ensureVisible(key:String):Tile 784 { 785 var tile:Tile = null; 786 if (tileCache.containsKey(key)) { 787 tile = well.getChildByName(key) as Tile; 788 if (!tile) { 789 tile = tileCache.getTile(key); 790 well.addChildAt(tile,0); 791 } 792 if (tile.zoom == currentTileZoom) { 793 tile.show(); 794 } 795 else { 796 tile.showNow(); 797 } 798 } 799 if (tile) { 800 if (visibleTiles.indexOf(tile) < 0) { 801 visibleTiles.push(tile); // don't get rid of it yet! 802 } 803 else { 804 // we've already got this tile this frame 805 // (this happens quite a bit with parent tiles, 806 // since they cover more than one tile at the current zoom level) 807 } 808 } 809 return tile; 810 } */ 811 812 // for use in requestLoad 813 private var tempCoord:Coordinate = new Coordinate(0,0,0); 814 815 /** create a tile and add it to the queue - WARNING: this is buggy for the current zoom level, it's only used for parent zooms when maxParentLoad is > 0 */ 816 private function requestLoad(col:int, row:int, zoom:int):Tile 817 { 818 var key:String = tileKey(col, row, zoom); 819 if (tileCache.containsKey(key)) throw new Error("requested load for an already cached tile"); 820 var tile:Tile = well.getChildByName(key) as Tile; 821 if (!tile) { 822 tile = tilePool.getTile(col, row, zoom); 823 tile.name = key; 824 tempCoord.row = row; 825 tempCoord.column = col; 826 tempCoord.zoom = zoom; 827 var urls:Array = provider.getTileUrls(tempCoord); 828 if (urls && urls.length > 0) { 829 // keep a local copy of the URLs so we don't have to call this twice: 830 layersNeeded[tile.name] = urls; 831 tileQueue.push(tile); 832 } 833 else { 834 trace("no urls needed for that tile", tempCoord); 835 tile.show(); 836 } 837 well.addChild(tile); 838 } 839 return tile; 840 } 841 842 private static const zoomLetter:Array = "abcdefghijklmnopqrstuvwxyz".split(''); 843 844 /** zoom is translated into a letter so that keys can easily be sorted (alphanumerically) by zoom level */ 699 845 private function tileKey(col:int, row:int, zoom:int):String 700 { 701 return col+":"+row+":"+zoom;846 { 847 return zoomLetter[zoom]+":"+col+":"+row; 702 848 } 703 849 … … 710 856 return tileKey(pcol,prow,parentZoom); 711 857 } 858 859 // used when maxParentLoad is > 0 860 // TODO: check that this does the right thing with negative row/col? 861 private function parentCoord(col:int, row:int, zoom:int, parentZoom:int):Array 862 { 863 var scaleFactor:Number = Math.pow(2.0, zoom-parentZoom); 864 var pcol:int = Math.floor(Number(col) / scaleFactor); 865 var prow:int = Math.floor(Number(row) / scaleFactor); 866 return [ pcol, prow ]; 867 } 712 868 713 869 // TODO: check that this does the right thing with negative row/col
