WrapDateline hack, for tile maps

54 views
Skip to first unread message

Charlie Tennessen

unread,
May 1, 2014, 4:41:51 PM5/1/14
to opensca...@googlegroups.com
I have written a halfway decent hack to get OpenScales to draw a map across the dateline.  You will need to ask for the maps as though the Eastern Hemisphere goes beyond 180 degrees, eg, 200 degrees = -160 Lon.  This is how dateline wrapping works in OpenGIS, which is the last map server that I wrote a map client for.  So, here is a simple hack:

//here is an example of calling a map across the dateline
_map.zoomToExtent(new Bounds( 160, -10, 240, 70));

Make the following changes to location.as, grid.as, tile.as, and tms.as:


//add setter so lon can be changed from grid.as for dateline wrapping
public function set lon(value:Number):void 
{
_x = value;
}



//add this right before "stretchedWidth" is set in the loop
if (upRigth.lon < bottomLeft.lon) {
upRigth.lon += 360;
}

//we are going to be overriding function withinMapBounds() so we need to hack it a bit

private var _withinBounds:Boolean = false; //add this var

public function withinMapBounds():Boolean //rewrite existing function to look like this
{
if (_withinBounds) {
return true;
}else {
if(this.layer == null || !(this.layer is Grid))
return false;
if(!this.layer.maxExtent || !this.bounds.intersectsBounds(this.layer.maxExtent, false))
return false;
if(!this.bounds.intersectsBounds(this.layer.map.maxExtent, false))
return false;
if((this.layer as Grid).buffer == 0
//&& !this.bounds.intersectsBounds(this.layer.map.getExtentForResolution((this.layer as Grid).requestedResolution), false))
&& !this.bounds.intersectsBounds(this.layer.map.extent, false))
return false;
return true;
}
}

//add getters and setters

/**
 * Manual override for wrapping dateline
 */
public function get withinBounds():Boolean 
{
return _withinBounds;
}

/**
 * Manual override for wrapping dateline
 */
public function set withinBounds(value:Boolean):void 
{
_withinBounds = value;
}
}


//here is where the main hack is

override public function addTile(bounds:Bounds, position:Pixel):ImageTile { //rewrite existing function to look like this
var newBounds:Bounds = bounds.clone();

//re-working the bounds so that getURL returns a good url for the tiles we will be wrapping
if (maxExtent != null)
{
//shift right? 
while (newBounds.left < maxExtent.left && newBounds.right <= maxExtent.left)
{
newBounds = newBounds.add(maxExtent.width, 0);
}

//shift left? 
while (newBounds.left >= maxExtent.right && newBounds.right > maxExtent.right)
{
newBounds = newBounds.add( -maxExtent.width, 0);
}
}
var tl:ImageTile = new ImageTile(this, position, newBounds, this.getURL(newBounds), new Size(this.tileWidth, this.tileHeight));
if (!tl.withinMapBounds()) { //you can also just set every tl.withinBounds = true, but I'm trying to be efficient
var tmpB:Bounds = tl.bounds.clone();
tmpB = tmpB.reprojectTo("EPSG:4326"); //4326 is the only projection i understand!
if (tmpB.left + 360 < maxExtent.right) {
tl.withinBounds = true;
}
}

return tl;

}

I will not be dragging or wheeling in my application so I did not go very far on this.  You can drag and zoom a bit with this modification, but it crashes ("Error #2015: Invalid BitmapData.
") if you don't throttle the zoom and pan updates.  I would REALLY love it if someone wrote a genuine update so openscales would naturally pan across 180/-180!  This looks like a mostly dead forum but maybe someone will get this message in a bottle and move forward on this issue.  BTW I am using Bing maps.  Good luck and happy coding.
Reply all
Reply to author
Forward
0 new messages