7

Summary:

I have 2 different image layers that looked fine with my old mapstraction/google maps based system. Using the same coordinates as bounds in openlayers results in a shift to the north by like 100 miles.

  • potentially most important is that this seems to be limited to the image layers only. For all of the vector-based layers I've looked at (vector based markers and vector based polylines), they all seem to be in the right spot when compared to the old system.
  • one image layer is an image of text where the original coordinates were chosen somewhat arbitrarily so the fact that it's shifted north is not a big deal (screenshot example: https://img.skitch.com/20110427-jj62ac75y8eihms3gxxfr15371.jpg)
  • the other image layer is weather radar and it's absolutely essential that the image overlay be in the correct place (screenshot example: http://img.skitch.com/20110426-dxwtj44q4g9su5e58p9gc85x2s.jpg)
  • this happens with Google Maps v3 base layers and OpenStreetMap base layers. I have not tested other base layers
  • the original question below was centered around the weather radar problem because that's where I originally noticed the image overlay problem, but it would appear that whatever I'm doing wrong for the weather radar image layer is also being done wrong for the text/image overlay.

I'm new to OpenLayers, so I'm hoping I'm missing something obvious.

I'm trying to transition my maps to OpenLayers from Mapstraction (and before that it was just the plain Google Maps v3 API). I'm having issues with one of the images not aligning properly (though all other types of layers seem to work just fine).

Specifically, I'm trying to overlay a weather radar image (http://radar.weather.gov/ridge/Conus/RadarImg/latest_radaronly.gif) but it's not putting it in the correct place. I've tried using both OSM and Google Maps v3 base layers, and it always appears to be too far north.

Screenshot explanation: img.skitch.com/20110426-dxwtj44q4g9su5e58p9gc85x2s.jpg

I originally got the coordinates through the KMZ file that you can download here: www.srh.noaa.gov/ridge/kmzgenerator.php. Click on "Lower 48 States" under the "National & regional mosaics" section to get the KMZ file. Alternatively, the KML contents are viewable here: gist.github.com/942730

I'm assuming I'm not specifying the bounds for the image layer properly:

# full code in the example links below this

proj4326 = new OpenLayers.Projection("EPSG:4326");

bounds = new OpenLayers.Bounds();
bounds.extend(new OpenLayers.LonLat(-127.620375523875420, 21.652538062803));
bounds.extend(new OpenLayers.LonLat(-66.517937876818, 50.406626367301044));
bounds.transform(proj4326, mapObject.getProjectionObject());
radar_overlay = new OpenLayers.Layer.Image('radar', 'http://radar.weather.gov/ridge/Conus/RadarImg/latest_radaronly.gif', bounds, new OpenLayers.Size(3400, 1600), {
  'isBaseLayer': false,
  'alwaysInRange': true
});

Full Examples:

http://jsfiddle.net/hayley/C4rue/ - (out of place) - simplified example with OL and google maps v3

beta.wickedwx.com/ - (out of place) more complete example - on this map, there's also an orange dot for the radar location at Wichita, Kansas where there's usually a blue blob (ground clutter on the radar), but the blue blob ends up being placed near Salina, Kansas (screenshot example: img.skitch.com/20110426-dxwtj44q4g9su5e58p9gc85x2s.jpg)

http://wickedwx.com/ - working example that uses mapstraction and google maps v3

2
  • You can declare bounds like this: new OpenLayers.Bounds(-127, 21, -66, 50), Commented Apr 27, 2011 at 12:53
  • I've tried declaring bounds in that way too with the same result (north shift). Example: jsfiddle.net/hayley/fvqDn/3
    – hayley
    Commented Apr 27, 2011 at 13:10

5 Answers 5

5

Hayley,

2nd UPDATE: Played around some more and got the radar overlay to work with OpenLayers. What I and a few others have referred to holds true here. The Ridge Radar gifs are really meant to go into Google Earth (though they might also play nice in Google Maps too). However, in OpenLayers, one does have to ensure that raster images are transformed to spherical mercator in order to display in Google Maps and Open Street Maps via OpenLayers. In order to do that, you have to geo-reference the raster to ESPG 4326 and then transform it to spherical mercator. Now I used GDAL to do the geo-referencing and also warping to spherical mercator. Here are the commands I used:

gdal_translate -of PNG -a_srs EPSG:4326 -a_ullr -127.62 50.41 -66.42 21.61 radar.gif radartemp1.png

gdalwarp -t_srs '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs' radartemp1.png radartemp2.png

gdal_translate -of PNG -outsize 80% 80% radartemp2.png radartemp3.png

The first line geo-references the image to EPSG 4326 and also converts to a PNG. Just used to doing that but you should be able to keep GIFs (-of GIF).

The second line converts the image to EPSG 900913 via the proj.4 commands in single quotes. I had tried using 900913 and also 3785/3857 in gdalwarp but my version of GDAL didn't like those. Found the proj.4 commands worked. Key to this was the +nadgrids=@null option. I found that in our geo-referencing things worked fine with the transformation that we were using for our initial GM prototype. However, our images were "squished" when we tried to use them for OL. Discovered after a search and also in the reference that snapwire_org indicated that this is critical to getting the grid transformed into spherical mercator.

Now I found that in order to work with EPSG 900913 in OL, I had to use meters for the projection instead of the lat lon bounds and just transform everything between the two:

Declaring the map:

map = new OpenLayers.Map("map", {

    projection: new OpenLayers.Projection("EPSG:900913"),
    units: "m",
    maxResolution: 156543.0339,
    maxExtent: new OpenLayers.Bounds(
        -20037508, -20037508, 20037508, 20037508.34),
    displayProjection: new OpenLayers.Projection("EPSG:4326"),
    controls: [
        new OpenLayers.Control.Navigation(),
        new OpenLayers.Control.KeyboardDefaults(),
        new OpenLayers.Control.PanZoomBar(),
        new OpenLayers.Control.Scale(),
        new OpenLayers.Control.Attribution()
    ]

});

Now for the image overlay:

// create spherical mercator base layers

var googleLayer = new OpenLayers.Layer.Google("Google Physical", {type: google.maps.MapTypeId.TERRAIN, visibility: true});
var gstr = new OpenLayers.Layer.Google("Google Streets", {type: google.maps.MapTypeId.ROAD, visibility: true});
var osmLayer = new OpenLayers.Layer.OSM("OpenStreetMap");

NOW I've entered the correct numbers here after the 3rd GDAL transformation step above for your use in the new OpenLayers.Bounds line below

// create overlay with first image (GMoverlay is a global);

GMoverlay= new OpenLayers.Layer.Image("Radar Overlay","radartemp3.png",
     new OpenLayers.Bounds(-14206593.415,2465071.940,-7394741.764,6517585.728),   
     new OpenLayers.Size(847,484),
     {isBaseLayer: false, opacity: 0.4,
      projection: new OpenLayers.Projection("EPSG:900913")});

//add layers to map

map.addLayers([googleLayer, gstr,osmLayer, GMoverlay]); 

Again, you can see in the Bounds, we're using meters:

new OpenLayers.Bounds(-14206593.415,2465071.940,-7394741.764,6517585.728)

You would get that info by running

gdalinfo radartemp3.png

The lower left and upper right coordinates of the transformed image are displayed in this command's output and then entered in the part above when declaring the new OL Image.

In going back and forth between meters and standard Lat/Lon, you have to use OL transforms like this one for setting the initial center:

map.setCenter(new OpenLayers.LonLat(-80, 40).transform(
        new OpenLayers.Projection("EPSG:4326"),
        map.getProjectionObject()),5);

You need to be careful here using transform on geometries as I discovered when grabbing a point on the map. This is also discussed in that link on spherical mercator and here's the relevant statement:

"Because all transforms are in place, once you have added a geometry to a layer, you should not call transform on the geometry directly: instead, you should transform a clone of the geometry:"

The referenced link that snapwire_org mentioned has a good deal of what I refer to here.

Also note that the size of the image is about a quarter the size of radartemp3.png. That's because you have to reduce the size number the farther out you zoom. So, you can't use 3700 x 1600 of the original image.

This really should be the answer you're looking for. I checked it myself in a test OL app with much of the pieces above and it projected spot on to what was being displayed at weather.gov. You still will have to do the geo-referencing and transformations. But GDAL is also open source and easy to install.

Tell you, it took a while to find that proj.4 option for our transformations. Then I pieced together several references which set up the map and image overlay in meters (including the one from snapwire_org) and then did transformations for points between 4326 and 900913. Worked like a charm then.

Good luck!

2
  • Wow! Thank you for the incredibly detailed response. It sounds like this has definitely moved into the realm where it's going to be less of a hassle to figure out how to get radar from a TMS/WMS service than to go through all of the necessary translations to make this specific radar image work with OL. Thanks for all your hard work!
    – hayley
    Commented May 6, 2011 at 14:38
  • Speaking of TMS, I recently found that Iowa State has a good TMS that projects radar data in spherical mercator! So in OL, I tried this out: var n0q = new OpenLayers.Layer.TMS( 'NEXRAD Base Reflectivity', 'mesonet.agron.iastate.edu/cache/tile.py', {layername : 'nexrad-n0q-900913', service : '1.0.0', type : 'png', visibility : false, opacity : 0.7, getURL : get_my_url, isBaseLayer : false} ); Then there's a function for get_my_url that adjusts the image accordingly. Go their main site for info. Commented May 11, 2011 at 14:50
4

Sounds like you're having the same problem I had: How to overlay lat/lon points on a Google layer in OpenLayers 2?

You basically have to enable re-projections using "sphericalMercator: true" option and then perform the necessary re-projections.

3
  • 1
    Hey, thanks for the suggestion but I think we're having different problems. Were you using Google Maps V2 or V3, because my understanding (per this openlayers blog post ) is that the sphericalMercator: true is only necessary for V2 whereas V3 has it baked in. Also, everything except the image layer seems to be working properly (e.g. vector coordinates all seem to end up in the right location when compared to the live (mapstraction-based) site).
    – hayley
    Commented Apr 26, 2011 at 19:18
  • I made a new fiddle with the sphericalMercator option set and it doesn't seem to have made a difference: jsfiddle.net/hayley/fvqDn/1 The radar is still showing up too far north. Thanks though!
    – hayley
    Commented Apr 26, 2011 at 19:30
  • @hayley: Thanks for the link to the openlayers blog.
    – underdark
    Commented Apr 27, 2011 at 6:33
3

OpenLayers won't be able to reproject an image on the fly.

Update:

Maybe try the following code to check the tranformation is working correctly. If it is still out of place then there is likely to be an issue with your original coordinates:

  var bounds = new OpenLayers.Bounds(-127.620375523875420, 21.652538062803, -66.517937876818, 50.406626367301044);

   bounds = bounds.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913"));
5
  • As far as I know, I'm not asking it to. The image is already in a format that has worked just fine for vanilla Google Maps v3 API, Mapstraction/Google Maps v3, and Google Earth, which means that the image itself shouldn't need reprojecting, right?
    – hayley
    Commented Apr 27, 2011 at 13:15
  • So the original image is in web mercator? Can't you also get the original reference coordinates in web mercator? Commented Apr 27, 2011 at 13:21
  • I'm still sort of fuzzy on projection systems right now, so I'm not sure if this is web mercator or not, but this is what's in the KML that you can download from the National Weather Service that will work in Google Earth: <LatLonBox><north>50.406626367301044</north><south>21.652538062803</south><east>-66.517937876818</east><west>-127.620375523875420</west>
    – hayley
    Commented Apr 27, 2011 at 13:26
  • Also, on the more arbitrary image layer here (mapstraction): wickedwx.com/2011/04/29 and here (openlayers): beta.wickedwx.com/2011/04/29 there is also a north shift (you have to zoom in to a corner of the text to really notice it). I could live with this one being shifted since the coordinates were chosen arbitrarily, but it seems to indicate that whatever I'm doing wrong with the radar, is also being done wrong for this image layer.
    – hayley
    Commented Apr 27, 2011 at 13:32
  • Per your update, I previously had proj4326 = new OpenLayers.Projection("EPSG:4326"); bounds.transform(proj4326, mapObject.getProjectionObject()) and tried the more explicit bounds = bounds.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913")) but it's the same north shift.
    – hayley
    Commented Apr 27, 2011 at 13:40
2

I know this might sound obvious for many people, but after several hours striving to get a well positioned Image.Layer over a GoogleMaps base map (instead of a distorted & misaligned one), we finally found that our layer was being affected by a not expected / 'non GIS' factor: Bootstrap CSS was aplying a max-width restriction over all images in the page. And that included the img rendered by OpenLayers to get an Image.Layer.

This was the fault: img {border: 0 none; height: auto; max-width: 100%; vertical-align: middle; }

We discovered it after some Firebug inspections and solved it with an overriding CSS style for the imgs inside the OpenLayers map. So my advice is to check CSS first, and then anything else.

1

The image isn't out of place, but vertically compressed. If you compare your original Mapstraction version and the Openlayers version of the map, you can notice that the images align perfectly on the northern bound. The basemap uses EPSG:900913, but the radar overlay is in EPSG:4326. As OpenLayers can only reproject vector data on the fly, you may have to either reproject the radar overlay externally (Mapserver, Geoserver, ...), find another radar overlay, or use a basemap which is also in EPSG:4326.

See also http://docs.openlayers.org/library/spherical_mercator.html (Quote: "One of the reasons that the Spherical Mercator projection is so important is that it is the only projection which will allow for overlaying image data on top of commercial layers like Google Maps correctly. [...]").

5
  • Thanks for looking! I managed to zoom in close enough that I could find some misalignment: img.skitch.com/20110429-nu6nkr1h83atast3kcnb8k1cs6.jpg So it appears that it is still somewhat north shifted up in Canada, but nowhere near as much. The math here is not precise, but it looks like up in Saskatchewan, it's about 16 miles shifted to the north whereas, in Kansas, it's off by about 90 miles. I'm not sure what this means yet, but it definitely adds helpful diagnostic info, so thanks!
    – hayley
    Commented Apr 29, 2011 at 14:03
  • Per your update, correct me if I'm wrong, but aren't 900913 and 4326 the same thing in terms of how they "stretch" the earth - it's just that one describes points in terms of lat/lon and the other in terms of X/Y? I don't think a reprojection of the radar is necessary. The overlay works fine via straight Google Maps API and mapstraction/gmaps. But it's out of alignment on openlayers. Aren't openlayers and google maps API using the same exact base layer tiles?
    – hayley
    Commented Apr 29, 2011 at 14:15
  • You can only compare points on the upper border of the overlay image, as the offset gets bigger when going further to the south. Here is a screenshot showing that there is zero offset on the upper border of the overlay: img215.imageshack.us/img215/7650/compareu.png Commented Apr 29, 2011 at 14:31
  • EPSG:900913 (or more officially EPSG:3785, as the former was "invented" as a temporary projection code number in Openlayers -> 900913 = google) and EPSG:4326 "stretch" the earth differently. Please have a look at docs.geotools.org/latest/userguide/tutorial/geometry/…, where you can also find some nice sample images to compare. Commented Apr 29, 2011 at 14:43
  • 1
    EPSG:3785 has been deprecated by EPSG. The current coordinate reference system is EPSG:3857. Std Disclaimer: I'm on the subcommittee that manages the EPSG Geodetic Parameter Dataset
    – mkennedy
    Commented Apr 29, 2011 at 22:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.