Help with GdiImageLayer and Worldfile

Topics: General Topics
Feb 22 at 12:33 PM
I am working on a project to overlay the National Weather Service Doppler radar images over a map. The map I am working on is a projected coordinate system NAD83 15N. I am using SharpMap 1.0 libraries.

I am using a KMZ file provided by the Weather Service to get the link to the radar image. The link is. http://radar.weather.gov/ridge/RadarImg/NCR/MVX_NCR_0.gif
The image is 660x550

I realize that gif files don't work with GdiImageLayer so for now I have just converted it to .png using Gimp for testing. Once working I would develop the code to convert it on the fly.

For now I am manually creating the world file using coordinates retrieved from the doc.kml file extracted from the kmz. The weather service image has the following lat/lon box coordinates.

<north>50.4520865145597</north>
<south>44.593260830966</south>
<east>-94.123947642933</east>
<west>-100.515393843217</west>

I convert these coordinates from WGS84 to NAD8315N to get
North - 5281933
South - 4662024
East - 686592
West - 229292

Here is where I'm not sure on what I'm doing. I have read and re-read the wiki on how to setup the world files and what I calculate for x scale and y scale in the world file do not properly scale the image over the NAD83 coordinates - the image is not "stretched" enough.
The X delta is 457300 meters
The Y delta is -619908 meters
One pixel on my map = 1474 meters

I'm not sure how the size of the gif image enters into the equation. Originally I thought I would just take the deltas of the x and y coordinates and divide by the map pixel size but that doesn't scale properly.

By trial and error I have come up with a world file that works but would like to develop the equation because I have other radar images that I wish to use. Here is what works.

760
0
0
-1130
229292
5281933
Feb 23 at 7:59 PM
I had a link to the wrong radar image not that it matters. Here is the correct one.

http://radar.weather.gov/ridge/RadarImg/NCR/MPX_NCR_0.gif
Coordinator
Feb 24 at 6:59 AM
Could you post a link to the kml/kmz file, too?
Feb 24 at 3:30 PM
I couldn't post a link to the KMZ because it is generated based on radar selections that you make on their webpage. Here is the contents of the doc.kml.
I think I figured out the math as follows but there still appears to be some issues.

I believe the x-scale should be the x-coordinates delta divided by the images x pixels as follows
457300/660 = 630
y-scale would then be 619908/550 = 1127
My understanding is that this scales the images pixel size to the pixel size needed on the map. I will post a screenshot if I can.


<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.0">
<Document>
    <name>NWS Radar Images</name>
    <open>1</open>
    <Folder>  
        <name>National Weather Service</name>
         <ScreenOverlay>
             <name>National Weather Service</name>
             <description>National Weather Service Doppler Radar RIDGE Imagery http://radar.weather.gov</description>
             <visibility>1</visibility> 
             <Icon>  <href>http://radar.weather.gov/ridge/graphics/nws_google.gif</href>  </Icon>
             <overlayXY x="0" y="1" xunits="fraction" yunits="fraction" />
             <screenXY x="0" y="1" xunits="fraction" yunits="fraction" />  
             <rotationXY x="0" y="0" xunits="fraction" yunits="fraction" />
             <size x="0" y="0" xunits="fraction" yunits="fraction" />  
         </ScreenOverlay>
         <ScreenOverlay>  
             <name>NOAA</name>   
             <description>National Oceanic and Atomospheric Administration  http://www.noaa.gov</description>
             <visibility>1</visibility> 
             <Icon>  <href>http://radar.weather.gov/ridge/graphics/noaa_google.gif</href>  </Icon>
             <overlayXY x=".2" y="1" xunits="fraction" yunits="fraction" />  
             <screenXY x=".2" y="1" xunits="fraction" yunits="fraction" />  
             <rotationXY x="0" y="0" xunits="fraction" yunits="fraction" />  
             <size x="0" y="0" xunits="fraction" yunits="fraction" />  
         </ScreenOverlay>
     </Folder>
     <Folder>
         <name>MPX</name>
         <Folder>
             <name>Composite Reflectivity</name>
             <ScreenOverlay>
                 <name>Legend</name>
                 <visibility>1</visibility>
                 <Icon><href>http://radar.weather.gov/ridge/kml/radarkeyimages/MPX_NCR_Legend_0.gif</href><refreshMode>onInterval</refreshMode><refreshInterval>120</refreshInterval></Icon>
                 <overlayXY x="1.0" y="0.5" xunits="fraction" yunits="fraction"/>
                 <screenXY x="1.0" y="0.5" xunits="fraction" yunits="fraction"/>
                 <rotationXY x="0" y="0" xunits="fraction" yunits="fraction"/>
             </ScreenOverlay>
             <GroundOverlay>
                 <name>Composite Reflectivity</name>
                 <Icon><href>http://radar.weather.gov/ridge/RadarImg/NCR/MPX_NCR_0.gif</href><refreshMode>onInterval</refreshMode><refreshInterval>120</refreshInterval></Icon>
                 <visibility>1</visibility>
                 <LatLonBox>
                     <north>47.6341556757147</north>
                     <south>42.053696080988</south>
                     <east>-90.516042244651</east>
                     <west>-96.6038163479892</west>
                 </LatLonBox>
             </GroundOverlay>
         </Folder>
         <Folder>
             <name>Warnings</name>
             <GroundOverlay>
                 <name>Warnings</name>
                 <Icon><href>http://radar.weather.gov/ridge/Warnings/Short/MPX_Warnings_0.gif</href><refreshMode>onInterval</refreshMode><refreshInterval>120</refreshInterval></Icon>
                 <visibility>0</visibility>
                 <LatLonBox>
                     <north>47.638801574707</north>
                     <south>42.059196472168</south>
                     <east>-90.521581476385</east>
                     <west>-96.6084234064276</west>
                 </LatLonBox>
             </GroundOverlay>
         </Folder>
     </Folder>
 </Document>
</kml>
Feb 24 at 3:51 PM
Here is a screen shot of my map with the radar image on it. I have plotted the corners of the kml files lat/lon box and you can see that the image falls short. Here is the contents of the worldfile. I'm wondering if it could be that the image is overlaying such a large area that math rounding could be causing the issue?

630
0
0
-1127
229292.643162316
5281933.72223965

Image
Coordinator
Feb 25 at 1:01 PM
This approach seems to be ok:
(You may need to modify the Session related stuff)
public void TestWorldFileCalculation()
{
        //<LatLonBox>
        //    <north>47.6341556757147</north>
        //    <south>42.053696080988</south>
        //    <east>-90.516042244651</east>
        //    <west>-96.6038163479892</west>
        //</LatLonBox>
    var lt = new Coordinate(-90.516042244651, 47.6341556757147);
    var lb = new Coordinate(-90.516042244651, 42.053696080988);
    var rb = new Coordinate(-96.6038163479892, 42.053696080988);
    var rt = new Coordinate(-96.6038163479892, 47.6341556757147);

    var csSource = Session.Instance.CoordinateSystemServices.GetCoordinateSystem(4326);
    var csTarget = Session.Instance.CoordinateSystemServices.GetCoordinateSystem(26915);
    var ct = Session.Instance.CoordinateSystemServices.CreateTransformation(csSource, csTarget);
    var lt26915 = ct.MathTransform.Transform(lt);
    var lb26915 = ct.MathTransform.Transform(lb);
    var rb26915 = ct.MathTransform.Transform(rb);
    var rt26915 = ct.MathTransform.Transform(rt);

    var env26915 = new Envelope(lt26915, lb26915); 
    env26915.ExpandToInclude(rt26915);
    env26915.ExpandToInclude(rb26915);

    var tmpImg = Image.FromFile("D:\\GIS\\MPX_NCR_0.gif");

    var pixelSizeX = env26915.Width / tmpImg.Width;
    var pixelSizeY = env26915.Height / tmpImg.Height;

    Console.WriteLine(pixelSizeX.ToString(NumberFormatInfo.InvariantInfo));
    Console.WriteLine(0.ToString(NumberFormatInfo.InvariantInfo));
    Console.WriteLine(0.ToString(NumberFormatInfo.InvariantInfo));
    Console.WriteLine((-pixelSizeY).ToString(NumberFormatInfo.InvariantInfo));
    Console.WriteLine(env26915.MinX.ToString(NumberFormatInfo.InvariantInfo));
    Console.WriteLine(env26915.MaxY.ToString(NumberFormatInfo.InvariantInfo));

    using (var sw = new StreamWriter(File.Open("D:\\GIS\\MPX_NCR_0.gfw", FileMode.OpenOrCreate, FileAccess.Write)))
    {
        sw.WriteLine(pixelSizeX.ToString(NumberFormatInfo.InvariantInfo));
        sw.WriteLine(0.ToString(NumberFormatInfo.InvariantInfo));
        sw.WriteLine(0.ToString(NumberFormatInfo.InvariantInfo));
        sw.WriteLine((-pixelSizeY).ToString(NumberFormatInfo.InvariantInfo));
        sw.WriteLine(env26915.MinX.ToString(NumberFormatInfo.InvariantInfo));
        sw.WriteLine(env26915.MaxY.ToString(NumberFormatInfo.InvariantInfo));
    }

    var map = new SharpMap.Map(new Size(600,550));
    var gdi = new GdiImageLayer("MPX_NCR_0", "D:\\GIS\\MPX_NCR_0.gif");
    gdi.SRID = 26915;
    map.Layers.Add(gdi);
    var factory = Session.Instance.GeometryServices.CreateGeometryFactory(new PrecisionModel(PrecisionModels.Floating), 26915);
    var polygon = factory.CreatePolygon(factory.CreateLinearRing(new[]
    {
        lt26915, lb26915, rb26915, rt26915, lt26915
    }));
    var p = new GeometryProvider(polygon);
            
    map.Layers.Add(new VectorLayer("pkts", p));
    map.ZoomToExtents();
    using(var img = map.GetMap())
        img.Save("worldfiletest.png");
    map.Dispose();
}
Feb 26 at 2:29 PM
Cool Thanks FObermaier I will give it a try! Is the reason for creating the polygon near the end to prove that the image is indeed overlayed in the correct dimensions?
Feb 26 at 5:52 PM
Ok I must admit I don't know how you set the CoordinateSystemServicesProvider instance used in your "Sessions". If you could point me to an example or a give a brief example I would be truly grateful. I wasn't able to find an example in the source code.
Coordinator
Feb 27 at 6:22 PM
neutroz wrote:
Is the reason for creating the polygon near the end to prove that the image is indeed overlayed in the correct dimensions?
yes
Coordinator
Feb 27 at 6:28 PM
neutroz wrote:
Ok I must admit I don't know how you set the CoordinateSystemServicesProvider instance used in your "Sessions". If you could point me to an example or a give a brief example I would be truly grateful. I wasn't able to find an example in the source code.
This code is based on the current version in Branches/1.0 (github)
You cannot use it as is, you'll have to do it differently:
  • create a CoordinateSystemFactory
  • create the coordinate systems for wgs84 and NAD83/UTM15N
  • create a CoordinateTransformationFactory
  • create the coordinate transformation from WGS84 to NAD83/UTM15N
There are a lot of examples in the forum for doing that. There even is a tutorial in the Documentation
Feb 29 at 1:49 PM
Thank you so much for your prompt help. I was able to use other methods for the transformations.