simple, working WMS overlays (over commerical mapproviders)
hi, i've seen there are a number of questions on how to get WMS working. i've just got a simple means of doing so.
i've posted the code to do this here:
http://pastebin.ca/915930
it just sends an extra argument to YahooHybridMapProvider() that is the url:String of the WMS request except for the BBOX which is added as each tile is requested.
the projection should be in EPSG 54004 or 900913. to use lat/lon, one could just remove the toMercator() calls (but it wont line up perfectly).
right now, it's an ugly hack, but i hope if i post it, someone will clean it up (and share).
there's a live example here:
http://128.32.8.100/SOD/static/Modest...
where the green is a WMS layer of california parks.
the math is copied from john deck
http://johndeck.blogspot.com/2005/09/...
the gist of it is here:
#
private function toMercator(loc:Location):Location {
#
#
var sma:Number = 6378137.0;
#
var ecc:Number = 0.0818191913108718138;
#
#
var x:Number = loc.lon * sma * Math.PI / 180.;
#
var y:Number = loc.lat > 89.5 ? 89.5 :
#
(loc.lat < -89.5 ? -89.5 : loc.lat)
#
y *= Math.PI / 180.;
#
var l:Number = ecc * Math.sin(y);
#
#
y = sma * Math.log(Math.tan((y + Math.PI / 2 ) / 2) * Math.pow( ((1 - l) / (1 + l)) , (ecc/2)));
#
return new Location(y, x);
#
#
}
#
#
#
private function getWMSTileUrl(coord:Coordinate):String
#
{
#
var row:int = coord.row;
#
#
var up_left:Location = toMercator(coordinateLocation(sourceCoordinate(new Coordinate(row, coord.column, coord.zoom))));
#
#
var down_right:Location = toMercator(coordinateLocation(sourceCoordinate(new Coordinate(row + 1, coord.column + 1, coord.zoom))));
#
#
return __url + up_left.lon.toString() + "," + down_right.lat.toString() + ","
#
+ down_right.lon.toString() + "," + up_left.lat.toString();
#
#
}
-brent
i've posted the code to do this here:
http://pastebin.ca/915930
it just sends an extra argument to YahooHybridMapProvider() that is the url:String of the WMS request except for the BBOX which is added as each tile is requested.
the projection should be in EPSG 54004 or 900913. to use lat/lon, one could just remove the toMercator() calls (but it wont line up perfectly).
right now, it's an ugly hack, but i hope if i post it, someone will clean it up (and share).
there's a live example here:
http://128.32.8.100/SOD/static/Modest...
where the green is a WMS layer of california parks.
the math is copied from john deck
http://johndeck.blogspot.com/2005/09/...
the gist of it is here:
#
private function toMercator(loc:Location):Location {
#
#
var sma:Number = 6378137.0;
#
var ecc:Number = 0.0818191913108718138;
#
#
var x:Number = loc.lon * sma * Math.PI / 180.;
#
var y:Number = loc.lat > 89.5 ? 89.5 :
#
(loc.lat < -89.5 ? -89.5 : loc.lat)
#
y *= Math.PI / 180.;
#
var l:Number = ecc * Math.sin(y);
#
#
y = sma * Math.log(Math.tan((y + Math.PI / 2 ) / 2) * Math.pow( ((1 - l) / (1 + l)) , (ecc/2)));
#
return new Location(y, x);
#
#
}
#
#
#
private function getWMSTileUrl(coord:Coordinate):String
#
{
#
var row:int = coord.row;
#
#
var up_left:Location = toMercator(coordinateLocation(sourceCoordinate(new Coordinate(row, coord.column, coord.zoom))));
#
#
var down_right:Location = toMercator(coordinateLocation(sourceCoordinate(new Coordinate(row + 1, coord.column + 1, coord.zoom))));
#
#
return __url + up_left.lon.toString() + "," + down_right.lat.toString() + ","
#
+ down_right.lon.toString() + "," + up_left.lat.toString();
#
#
}
-brent
1
person likes this idea
I like this idea!
Tell me when this idea gets some attention.
The more people who like this idea, the more it gets noticed.
The more people who like this idea, the more it gets noticed.
Create a customer community for your own organization
Plans starting at $19/month
-
Inappropriate?Thanks, Brent!
You're not the first person to recommend making mmaps work with WMS, I'll see what I can do about rolling this into the samples area of the code.
I’m thankful
-
Inappropriate?hi, that'd be great!
thanks.
-b -
Inappropriate?Hi brentb, thanks for overaly wms sample code! I made similar map where I'm using Yahoo Road as "base" map, and WMS overlay on top of it.
Overlaying WMS tiles over Yahoo was very easy, just override paint method of AbstractImageBasedMapProvider class.
Well, I then took update from SVN and noticed that code base has changed quite a lot! There's no AbstractImageBasedMapProvider nor paint method to override :(
Do you have any idea how to overlay WMS tiles in current version of Modest Maps?
I would like to work with current code base since there are other nice features but I would love to see an example of overlaying wms tiles also.
Here's my paint method, notice that I also set WMS tile alpha to 0.7 which was also nice about older code base.
override public function paint(sprite:Sprite, coord:Coordinate):void
{
var request:MapProviderPaintThrottledRequest = null;
var bg:Sprite = new Sprite();
bg.name = "bg";
sprite.addChild(bg);
request = new MapProviderPaintThrottledRequest(bg, getYahooTileUrl( coord ), coord );
request.addEventListener(ThrottledRequestEvent.REQUEST_ERROR, onRequestError);
request.addEventListener(ThrottledRequestEvent.RESPONSE_COMPLETE, onResponseComplete);
request.addEventListener(ThrottledRequestEvent.RESPONSE_ERROR, onResponseError);
request.send();
bg.x = bg.y = -.5;
var wms:Sprite = new Sprite();
wms.name = "wms";
wms.alpha = 0.5;
sprite.addChild(wms);
request = new MapProviderPaintThrottledRequest(wms, getWMSTileUrl( coord ), coord );
request.addEventListener(ThrottledRequestEvent.REQUEST_ERROR, onRequestError);
request.addEventListener(ThrottledRequestEvent.RESPONSE_COMPLETE, onResponseComplete);
request.addEventListener(ThrottledRequestEvent.RESPONSE_ERROR, onResponseError);
request.send();
wms.x = wms.y = -.5;
createMask( sprite );
}
-
Inappropriate?Hi Opa,
Thanks for persevering with the new version, I understand it can be time-consuming and frustrating when software libraries change under your feet.
In the new version, the IMapProvider interface is much simpler to implement, and for maps using the Google-Yahoo-Microsoft-style mercator projection you can sub-class AbstractMapProvider. TileGrid handles loading and tile painting now (it's possible to draw onto tiles with code if you need to, but that's a discussion for another thread).
If you take a look at BlueMarbleMapProvider or similar, you can see there are only two methods you need to implement, and one of them is a simple toString().
The other function, getTileUrls(), now returns an array. If there is more than one URL in this array then TileGrid will stack up these images in the order you provide them.
So if you had a map with two layers, hosted at example.com/layer1 and example.com/layer2, your getTileUrls function would work like this:
public function getTileUrls(coord:Coordinate):Array
{
var sourced:Coordinate = sourceCoordinate(coord);
var img:String = source.zoom + '/' + sourced.row + '/' + sourced.column + '.jpg';
var url1:String = 'http://example.com/layer1/' + img;
var url2:String = 'http://example.com/layer2/' + img;
return [ url1, url2 ];
}
If you want the base url to come from Yahoo and the overlay to come from a WMS, you can subclass the Yahoo provider, add your getWMSTileUrl function in there and override the getTileUrls function to append the overlay URL, like so:
override public function getTileUrls(coord:Coordinate):Array
{
var urls:Array = super.getTileUrls(coord);
urls.push(getWMSTileUrl(coord););
return urls;
}
The downside to this simplicity is that it's tricky to manipulate the alpha of the overlay. If you need to manipulate each layer of your map separately, the best way to do this right now is to create two maps and synchonise them when they change. Hopefully I can post an example of how to do that soon, since it opens up a lot of potential for interesting effects.
Thanks again for your patience!
I’m hopeful!
-
Inappropriate?Hi Thanks for the reply RandomEtc,
Yes, I noticed that implementing custom mapprovider is now much easier and that's great. Setting tile alpha is not a problem, since I achieve that by letting mapserver to do that also.
Actually, I did try to do like you suggested, return two URL in array. There's a strange problem with aligning tiles, I'm using Yahoo road and ArcGis mapserver: when tiles are loading, sometimes some tiles are not aligned on top of each other properly, here's a screen shot

What is more stranger, that small offset happens when I'm panning the map, and disappears again with just a small amount of pan. Here's same spot after a small panning, as you can see the gap is gone:

This must have something to do with my custom overaly, I tried to overlay Yahoo road and Yahoo aerial, and it worked fine.
I just have no idea what could cause this :)
Anyways, thanks for the great product, I'm really looking forward to see how Modest Map evolves! In my opinion MM is the best open source AS3 / Flex mapping framework at the moment!
I’m thankful
-
Inappropriate?Hmm... can you see if this happens with another base map provider, perhaps Microsoft, with your overlay?
I seem to remember Yahoo's tiles were 258px square at one point to account for Flash's handling of images. If that's the case then it will throw something off when TileGrid sets the scale of the tile (which contains both images).
Here's a sample image using a Modest Maps generated URL, which is 258px as I suspected:
http://us.maps2.yimg.com/us.png.maps....
Here's one I got from maps.yahoo.com just now, which is 256px:
http://us.maps1.yimg.com/us.tile.maps...
It looks like they've been updating a few things, including the zoom level numbering, but it also looks like it would be worth trying to generate URLs for the 256px tiles – I'd be happy to update the Yahoo providers in the source repository if you figure out a fix!
I’m concerned
-
Inappropriate?I tested wms overlay with Microsoft road, and tiles are perfectly aligned.
So it seems that Yahoo's 258px tiles are causing the problem. I'm able to use Yahoo as background if I change my wms request so that it will also return 258px sized tiles. So I'm happy with current Yahoo provider :)
Thanks for the tip!
I’m happy
-
Inappropriate?Hi again, one more question about using url array in getTIileUrls method.It seems that tile is not rendered until both urls are loaded. It would be very nice if urls are handled separately as own thread. I'm not sure if my explanation makes any sense, but here's example. As said earlier, I'm using Yahoo Road as base "background" map, and wms map on top of it. In my situation, wms tiles are mostly transparent and only some areas are rendered. My wms server happens to be a bit slow :) On these transparent areas it would be nice if Yahoo is first loaded and visible, and after that at some point wms tile is rendered on top of it. Now, Yahoo background is not rendered until wms tile is ready.
Cheers
Olli -
Inappropriate?Right now it's not possible to have the two layers load independently. The tile fading and reuse in TileGrid was quite tricky to debug, and if the layers faded in separately it would have made it even trickier, I think!
That said, you can get the effect you asking for by using two Map instances, I posted a quick example of this at http://gsfn.us/t/l7o
-
Inappropriate?Hi Modest Maps Community,
Could you please show an example of how to use an instance of the modestwms class.
I am trying it like this:
map.setMapProvider(new ModestWMS());
Error:
1067: Implicit coercion of a value of type Class to an unrelated type com.modestmaps.mapproviders:IMapProvider.
Background:
What I want to do is display a GeoServer mosaic which is in a non-standard lat/lon projection.
On top of the mosaic i would like to draw a bunch of markers in flash whose colour, size and shape are based on user selection. The coordinate info of the markers will come from a postgis db.
best regards
James
-
Inappropriate?There is currently no generalized support for WMS servers in the Modest Maps code base, sorry.
The ModestWMS class linked in the first post in this thread is not a Modest Maps map provider – it's a modification of a map provider that loads Yahoo tiles to also load WMS tiles on top. Even if you modified it to work with your WMS, you'd need to implement a new projection since the example above uses Mercator. -
Inappropriate?Why does it matter what projection the WMS layer is in if everything on the map is using the same projection in this case a custom lat/lon?
Doing projection conversions is costly and seems unnecessary in my case. -
Inappropriate?It depends. If you just want a tile viewer and you don't care about projections then you can ignore me. But if you want Modest Maps to be able to put map markers in the correct position on your map tiles for you then you'll need to specify a projection, and you'll need to specify your marker locations in lat/lon Locations using degrees.
Everything in Modest Maps is structured around turning Location objects that use lat/lon in degrees into tile Coordinates and/or on-screen Points. You can get by without a correct projection in some limited cases, but all the support classes (MarkerClip, etc) assume your data is positioned with lat/lon in degrees and won't work correctly with custom coordinates. The exception would be if your custom coordinates are within the +/- 90 +/- 180 ranges of lat/lon.
From the sounds of what you're describing, you'll probably have better luck with OpenLayers (www.openlayers.org) – I believe it has robust support for WMS built-in. -
Inappropriate?Thanks for your reply.
My coordinates are in lat/lon degrees so that should work fine in Modest Maps then, its just that they are not using one of EPSGs official projections - I had to define the projection parameters myself.
Re: OpenLayers
My application is currently running on OpenLayers but there are some limitations here.
Drawing 30,000 markers using javascript takes a very long time and its much faster with Flash.
Since the size, shape & colour of the marker will change depending on user selection - pre-creating these layers is not an option.
So to clarify:
I have 1 WMS raster tile layer served by GeoServer.
I will create a layer in flash on top of that with my "markers".
If anyone has some example or explanation how to do this that would be much appreciated. Whether it is using the class mentioned above or not doesn't really matter.
thanks
James
-
Inappropriate?Drawing 30,000 individual markers and having them all respond the the mouse interactively will be prohibitively slow, even in Flash. The built-in Modest Maps marker clip will start to seriously chug with more than a couple of thousand sprites to position.
You will probably want to look into the various bitmap drawing operations available, and draw all your graphics onto one layer. However this will mean you'll have to handle marker selection yourself, possibly with a quadtree or other spatial data structure if you want it to be fast.
Loading Profile...



EMPLOYEE

EMPLOYEE
