ThinkGeo.com    |     Documentation    |     Premium Support

WPF GeoTiff Example

Hi Mohamad,

Here is our sample for projection:

You can set the epsg id of Gdm2000 here.
When we assign projection to layer, the InternalProjectionParametersString should be data projection, and the ExternalProjectionParametersString should be which projection you want it convert to, you can think it’s map projection.

        Proj4Projection proj4Projection = new Proj4Projection();
        proj4Projection.InternalProjectionParametersString = Proj4Projection.GetEpsgParametersString(4326);
        proj4Projection.ExternalProjectionParametersString = Proj4Projection.GetEpsgParametersString(2163);

Wish that’s helpful.

Regards,

Ethan

Hai Ethan,

sorry i still confuse in this map projection. The number 4326 is being replaced by the epsg id for Gdm2000 that is 4742 right? the number 2163 is id for what epsg?

Proj4Projection proj4Projection = new Proj4Projection();
proj4Projection.InternalProjectionParametersString = Proj4Projection.GetEpsgParametersString(4326);
proj4Projection.ExternalProjectionParametersString = Proj4Projection.GetEpsgParametersString(2163);

Hi Mohamad,

The code is come from the sample. and the 2163 is the projection in the sample, please just ignore it.

I think your target is convert your Gdm2000 to decimal degree right?

4326 is for decimal degree, 3857 is for Google, Bing etc(meter).

So if you convert Gdm2000 to decimal degree, Internal = 4742, External = 4326.
if you convert decimal degree to Gdm2000, Internal = 4326, External = 4742.
if you convert Gdm2000 to Google Projection(meter), Internal = 4742, External = 3857.
if you convert Google Projection(meter) to Gdm2000, Internal = 3857, External = 4742.

Wish that’s helpful.

Regards,

Ethan

Hi Ethan,

Yes i want to apply the Gdm2000 projection into the Geotiff Raster Layer. Then i want to convert the meter to decimal degree. Below is my code , i try it but it throw me "ArgumentOutOfRangeException was unhandled to this code :

PointShape pointShape = ExtentHelper.ToWorldCoordinate(Map1.CurrentExtent, screenPointF, (float)Map1.Width, (float)Map1.Height);

##OverallCode ##

    private void Map_Loaded(object sender, RoutedEventArgs e)
    {
        Map1.MapUnit = GeographyUnit.Meter;
        LayerOverlay myOverlay = new LayerOverlay();
        Map1.Overlays.Add(myOverlay);
        myOverlay.TileCache = new FileBitmapTileCache(@"C:\Users\User\Documents\Visual Studio 2012\Projects\RasterMapViewer\RasterMapViewer\Cache\");

        string[] files = System.IO.Directory.GetFiles(@"C:\Users\User\Documents\Visual Studio 2012\Projects\RasterMapViewer\RasterMapViewer\Data\");
        foreach (string file in files)
        {
            GeoTiffRasterLayer tiffLayer = new GeoTiffRasterLayer(file);
            myOverlay.Layers.Add(tiffLayer);


           
        }
       
        myOverlay.Open();
        Map1.CurrentExtent = myOverlay.GetBoundingBox();
        myOverlay.Close();

        Proj4Projection proj4 = new Proj4Projection();
        Proj4Projection proj4Projection = new Proj4Projection();
           

        proj4Projection.InternalProjectionParametersString = Proj4Projection.GetEpsgParametersString(4920);
        proj4Projection.ExternalProjectionParametersString = Proj4Projection.GetEpsgParametersString(4326);

        Vertex projVertex = proj4.ConvertToExternalProjection(747032, 1297787);
         
    }       

    private void tetikusGerak_Loaded(object sender, MouseEventArgs e)
    {

        //Get the pointshape in world coordinates from screen coordinates.
        //Point currentPoint = e.GetPosition(Map1);
       // PointShape worldPoint = ExtentHelper.ToWorldCoordinate(Map1.CurrentExtent, new ScreenPointF((float)currentPoint.X, (float)currentPoint.Y), (float)Map1.ActualWidth, (float)Map1.ActualHeight);


        //string x = worldPoint.X.ToString("f6", CultureInfo.InvariantCulture);
        //string y = worldPoint.Y.ToString("f6", CultureInfo.InvariantCulture);
       // textBlockSatu.Text = string.Format("RSO_WEST(KERTAU) {0} , {1}", (worldPoint.X), (worldPoint.Y));



        Point point = e.MouseDevice.GetPosition(null);

        ScreenPointF screenPointF = new ScreenPointF((float)point.X, (float)point.Y);
        PointShape pointShape = ExtentHelper.ToWorldCoordinate(Map1.CurrentExtent, screenPointF, (float)Map1.Width, (float)Map1.Height);

        TextBoxSatu.Text = "X: " + DecimalDegreesHelper.GetDegreesMinutesSecondsStringFromDecimalDegree(pointShape.X) +
                      "  Y: " + DecimalDegreesHelper.GetDegreesMinutesSecondsStringFromDecimalDegree(pointShape.Y);


 
          }

    private RectangleShape GetFullExtent(GeoCollection<Layer> Layers)
    {
        Collection<BaseShape> rectangleShapes = new Collection<BaseShape>();

        foreach (Layer layer in Layers)
        {
            layer.Open();
            if (layer.HasBoundingBox == true) rectangleShapes.Add(layer.GetBoundingBox());
        }
        return ExtentHelper.GetBoundingBoxOfItems(rectangleShapes);

    }

Hi Mohamad,

Your exception is “Argument Out Of Range”, and it thrown in: PointShape pointShape = ExtentHelper.ToWorldCoordinate(Map1.CurrentExtent, screenPointF, (float)Map1.Width, (float)Map1.Height);

So it’s not related with projection.

I think one of your parameter is invalid, could you please list the 4 parameters value when it throw exception?

And I am not sure why you put the code in Loaded function, I think it should be placed in some other event for example MouseMove.

Regards,

Ethan

Hi Ethan,

I thought the projection code need to be inside the map loaded args. Below i try to change it inside the mouse move eventargs.

This list value for 4 parameter value when it throw exception

  1. Map1.CurrentExtent {436250.853344025,454911.16204289,713747.146655975,325090.83795711} ThinkGeo.MapSuite.Shapes.RectangleShape

    •    screenPointF	{X=717.6, Y=81.6}	ThinkGeo.MapSuite.Shapes.ScreenPointF
      
  2. (float)Map1.Width -float.Epsilon 1.401298E-45
    -float.MaxValue 3.40282347E+38
    -float.MinValue -3.40282347E+38
    -float.NaN NaN
    -float.NegativeInfinity -Infinity
    -float.PositiveInfinity Infinity

4.(float)Map1.Height) -float.Epsilon 1.401298E-45
-float.MaxValue 3.40282347E+38
-float.MinValue -3.40282347E+38
-float.NaN NaN
-float.NegativeInfinity -Infinity
-float.PositiveInfinity Infinity

private void Map_Loaded(object sender, RoutedEventArgs e)
{
Map1.MapUnit = GeographyUnit.Meter;
LayerOverlay myOverlay = new LayerOverlay();
Map1.Overlays.Add(myOverlay);
myOverlay.TileCache = new FileBitmapTileCache(@“C:\Users\User\Documents\Visual Studio 2012\Projects\RasterMapViewer\RasterMapViewer\Cache”);

        string[] files = System.IO.Directory.GetFiles(@"C:\Users\User\Documents\Visual Studio 2012\Projects\RasterMapViewer\RasterMapViewer\Data\");
        foreach (string file in files)
        {
            GeoTiffRasterLayer tiffLayer = new GeoTiffRasterLayer(file);
            myOverlay.Layers.Add(tiffLayer);


           
        }
       
        myOverlay.Open();
        Map1.CurrentExtent = myOverlay.GetBoundingBox();
        myOverlay.Close();

    }       

    private void tetikusGerak_Loaded(object sender, MouseEventArgs e)
    {

        Proj4Projection proj4Projection = new Proj4Projection();

        proj4Projection.InternalProjectionParametersString = Proj4Projection.GetEpsgParametersString(3375);
        proj4Projection.ExternalProjectionParametersString = Proj4Projection.GetEpsgParametersString(4326);

        proj4Projection.Open();
        Vertex projVertex = proj4Projection.ConvertToExternalProjection(747032, 1297787);
        proj4Projection.Close();

        Point point = e.MouseDevice.GetPosition(Map1);

        ScreenPointF screenPointF = new ScreenPointF((float)point.X, (float)point.Y);
        PointShape pointShape = ExtentHelper.ToWorldCoordinate(Map1.CurrentExtent, screenPointF, (float)Map1.Width, (float)Map1.Height);

       TextBoxSatu.Text = "X: " + DecimalDegreesHelper.GetDegreesMinutesSecondsStringFromDecimalDegree(pointShape.X) +
                      "  Y: " + DecimalDegreesHelper.GetDegreesMinutesSecondsStringFromDecimalDegree(pointShape.Y);

          }

}

    }

Hi Mohamad,

It looks the Map1.Width and Map1.Height is invalid.

Does the tetikusGerak_Loaded is the map loaded function?

You can put the projection in it, but I think you should want to put the
PointShape pointShape = ExtentHelper.ToWorldCoordinate(Map1.CurrentExtent, screenPointF, (float)Map1.Width, (float)Map1.Height);

into the event like mouse move.

From your information we can know, when you call this line in loaded event, the map width and height cannot get the correct value, it looks the control hadn’t get initialized complete in this step.

If you want to put the code here, you should want to pass a actual value instead of it for example:
ExtentHelper.ToWorldCoordinate(Map1.CurrentExtent, screenPointF, 800, 600);

Regards,

Ethan

Hi Ethan,

tetikusGerak_Loaded is the mousemove_Loaded i will change the name function to mousemove_loaded. I will put all the projection code in the map loaded function. Supposedly the code for the : PointShape pointShape = ExtentHelper.ToWorldCoordinate(Map1.CurrentExtent, screenPointF, (float)Map1.Width, (float)Map1.Height);

into the mouse move function right?

I try it just now but it still throw the exception on the following code:
PointShape pointShape = ExtentHelper.ToWorldCoordinate(Map1.CurrentExtent, screenPointF, (float)Map1.Width, (float)Map1.Height);

This mean the map width and height can’t retrieve the correct value from the map loaded function right? The code for the longitude and latitude with mouse move function can’t be put on the map loaded ?

Overall Code

    private void Map_Loaded(object sender, RoutedEventArgs e)
    {
        Map1.MapUnit = GeographyUnit.Meter;
        LayerOverlay myOverlay = new LayerOverlay();
        Map1.Overlays.Add(myOverlay);
        myOverlay.TileCache = new FileBitmapTileCache(@"C:\Users\User\Documents\Visual Studio 2012\Projects\RasterMapViewer\RasterMapViewer\Cache\");

        string[] files = System.IO.Directory.GetFiles(@"C:\Users\User\Documents\Visual Studio 2012\Projects\RasterMapViewer\RasterMapViewer\Data\");
        foreach (string file in files)
        {
            GeoTiffRasterLayer tiffLayer = new GeoTiffRasterLayer(file);
            myOverlay.Layers.Add(tiffLayer);              
        }
       
        myOverlay.Open();
        Map1.CurrentExtent = myOverlay.GetBoundingBox();
        myOverlay.Close();

        Proj4Projection proj4Projection = new Proj4Projection();

        proj4Projection.InternalProjectionParametersString = Proj4Projection.GetEpsgParametersString(3375);
        proj4Projection.ExternalProjectionParametersString = Proj4Projection.GetEpsgParametersString(4326);

        proj4Projection.Open();
        Vertex projVertex = proj4Projection.ConvertToExternalProjection(747032, 1297787);
        proj4Projection.Close();

    }       

    private void mouseMove_Loaded(object sender, MouseEventArgs e)
    {

      
        Point point = e.MouseDevice.GetPosition(null);

        ScreenPointF screenPointF = new ScreenPointF((float)point.X, (float)point.Y);
        PointShape pointShape = ExtentHelper.ToWorldCoordinate(Map1.CurrentExtent, screenPointF, (float)Map1.Width, (float)Map1.Height);

        TextBoxSatu.Text = "X: " + DecimalDegreesHelper.GetDegreesMinutesSecondsStringFromDecimalDegree(pointShape.X) +
                      "  Y: " + DecimalDegreesHelper.GetDegreesMinutesSecondsStringFromDecimalDegree(pointShape.Y);

          }

}

Hi Mohamad,

I think you misunderstand, the MouseMove is an event for map, it should looks like: Map1_MouseMove

What’s the name is not important, it should be register on map like this:

<wpf:WpfMap x:Name="map" MouseMove="map_MouseMove"/>

I am not sure what’s the mouseMove_Loaded event on map.

Please try the MouseMove event and let me know whether the parameter is still invalid.

Regards,

Ethan

Hi Ethan,

I try it but the parameter still invalid

    <Wpf:WpfMap  x:Name="Map1" Height="auto" Width="auto" Loaded="Map_Loaded"   Margin="0,0,-0.4,16.2" MouseMove="Map1_MouseMove"/>

Overall Code

private void Map_Loaded(object sender, RoutedEventArgs e)
{
Map1.MapUnit = GeographyUnit.Meter;
LayerOverlay myOverlay = new LayerOverlay();
Map1.Overlays.Add(myOverlay);
myOverlay.TileCache = new FileBitmapTileCache(@“C:\Users\User\Documents\Visual Studio 2012\Projects\RasterMapViewer\RasterMapViewer\Cache”);

        string[] files = System.IO.Directory.GetFiles(@"C:\Users\User\Documents\Visual Studio 2012\Projects\RasterMapViewer\RasterMapViewer\Data\");
        foreach (string file in files)
        {
            GeoTiffRasterLayer tiffLayer = new GeoTiffRasterLayer(file);
            myOverlay.Layers.Add(tiffLayer);              
        }
       
        myOverlay.Open();
        Map1.CurrentExtent = myOverlay.GetBoundingBox();
        myOverlay.Close();

        Proj4Projection proj4Projection = new Proj4Projection();

        proj4Projection.InternalProjectionParametersString = Proj4Projection.GetEpsgParametersString(3375);
        proj4Projection.ExternalProjectionParametersString = Proj4Projection.GetEpsgParametersString(4326);

        proj4Projection.Open();
        Vertex projVertex = proj4Projection.ConvertToExternalProjection(747032, 1297787);
        proj4Projection.Close();
    }
         
    private void Map1_MouseMove(object sender, MouseEventArgs e)
    {
        Point point = e.MouseDevice.GetPosition(Map1);

        ScreenPointF screenPointF = new ScreenPointF((float)point.X, (float)point.Y);
        PointShape pointShape = ExtentHelper.ToWorldCoordinate(Map1.CurrentExtent, screenPointF, (float)Map1.Width, (float)Map1.Height);

        TextBoxSatu.Text = "X: " + DecimalDegreesHelper.GetDegreesMinutesSecondsStringFromDecimalDegree(pointShape.X) +
                      "  Y: " + DecimalDegreesHelper.GetDegreesMinutesSecondsStringFromDecimalDegree(pointShape.Y);
    }

        }
    }

Hi Mohamad,

I build a sample based on your code, wish that’s helpful.

Test2.zip (10.6 KB)

Regards,

Ethan

Hi Ethan

Thank you for the sample. I already try it, it work. But why the longitude and latitude are wrong. Supposedly it will display the lat long for the Pekan, Pahang at my country Malaysia. But when I check the lat long that display on map at the google map it goes to Thailand. Did you know what cause this ? Is this because of the projection?

Thank you and best regards

Hi Mohamad,

In my sample, the projection is from 3857 to 4326, that’s why you found the position is incorrect.

Today I research your scenario again and found some problem:

  1. Your projection shouldn’t be 4742, because the unit of 4742 is decimal degree, but it looks your data is under meter.

  2. I guess your projection is 4920 or 4921, but they cannot works with our Proj4Projection. The solution is add new package ThinkGeo.MapSuite.Shapes.UnmanagedProj4Projection, and then use the code as below:

         uprj4 = new UnmanagedProj4Projection();
         uprj4.InternalProjectionParametersString = "+proj=geocent +ellps=GRS80 +units=m +no_defs"; // epsg 9420
         uprj4.ExternalProjectionParametersString = UnmanagedProj4Projection.GetEpsgParametersString(4326);
         uprj4.Open();
    
  3. The projection 9420 is limited in target area:

I tested a point in it:

            PointShape p1 = new PointShape(108.81500000, 4.33000000);
        PointShape p2 = uprj4.ConvertToInternalProjection(p1) as PointShape;

It looks the result is correct, so the uprj4 should works to convert between 4326 and 9420 now.
4. After that I found the mouse move coordinate still incorrect because the Y value is keep equal 0. I check the bouding box of my test data 4257.tif and found it’s not in target area. So if you want to make this function works, please make sure your data is in target area of your projection.

General, I think 9420 is your projection, but I think double check it with your data provider is better. And please make sure your data is contained by the valid area, or else this function won’t works well.

Regards,

Ethan

Hai Ethan,

I just check the raster map sample projection using global mapper software. The projection is KERTAU projection (epsg 3168) the map unit in meter. I try use the proj4projection and unmanageproj4projection to project to epsg 4326 also still the lat long (decimal degree) is incorrect. But the RSO coordinate (in meter) is correct. This code sample i try to make the map display both the lat long in meter and decimal degree in mouse pointer. Did epsg 4326 the only projection use to convert to decimal degree?

Thank you and best regards.

    }

    private void Map_Loaded(object sender, RoutedEventArgs e)
    {
        Map1.MapUnit = GeographyUnit.Meter;
        LayerOverlay myOverlay = new LayerOverlay();
        Map1.Overlays.Add(myOverlay);

        myOverlay.TileCache = new FileBitmapTileCache(@"C:\Users\User\Documents\Visual Studio 2012\Projects\RasterMapViewer\RasterMapViewer\Cache\");

        string[] files = System.IO.Directory.GetFiles(@"C:\Users\User\Documents\Visual Studio 2012\Projects\RasterMapViewer\RasterMapViewer\Data\");
        foreach (string file in files)
        {
            GeoTiffRasterLayer tiffLayer = new GeoTiffRasterLayer(file);
            myOverlay.Layers.Add(tiffLayer);
        }

       // uprj4 = new UnmanagedProj4Projection();
      // uprj4.InternalProjectionParametersString = UnmanagedProj4Projection.GetEpsgParametersString(3168);
       //uprj4.ExternalProjectionParametersString = UnmanagedProj4Projection.GetEpsgParametersString(4326);
      //  uprj4.Open();
     
        //Apply the projection 
        proj4Projection = new Proj4Projection();
      proj4Projection.InternalProjectionParametersString = Proj4Projection.GetEpsgParametersString(3168);//Current Proj in meter
       proj4Projection.ExternalProjectionParametersString = Proj4Projection.GetEpsgParametersString(4326);//Change to the proj with decimal degree
       proj4Projection.Open();

 
        Map1.CurrentExtent = myOverlay.GetBoundingBox();

        Map1.Refresh();
 
    }

    private void Map1_MouseMove(object sender, MouseEventArgs e)
    {

        Point point = e.MouseDevice.GetPosition(Map1);

        ScreenPointF screenPointF = new ScreenPointF((float)point.X, (float)point.Y);
        PointShape pointShape = ExtentHelper.ToWorldCoordinate(Map1.CurrentExtent, screenPointF, (float)Map1.ActualWidth, (float)Map1.ActualHeight);


        string x = pointShape.X.ToString("f6", CultureInfo.InvariantCulture);
        string y = pointShape.Y.ToString("f6", CultureInfo.InvariantCulture);

        if(proj4Projection != null)
        {
            PointShape pointShape4326 = proj4Projection.ConvertToExternalProjection(pointShape) as PointShape;

        TextBoxSatu.Text ="RSO_WEST(KERTAU)" + "("+ (x) +","+ " "+ (y)+ ")"+ " "+ "Long: " + DecimalDegreesHelper.GetDegreesMinutesSecondsStringFromDecimalDegree(pointShape4326.X)+ " Lat: " + DecimalDegreesHelper.GetDegreesMinutesSecondsStringFromDecimalDegree(pointShape4326.Y);
    }

    }
}

}

Hi Ethan,

Can i know how i can add straight line on raster layer for routing? Act as ruler that can measure the distance from one point to other point.

Thank you and best regards,

Hi Mohamad,

Epsg 3168 and Epsg 4326 are different projection system. They use the specified map unit.
Epsg 3168 --> Meter: https://epsg.io/3168
Epsg 4326 --> Degree: https://epsg.io/4326

You convert Epsg 3168 to 4326, so the map unit should be decimal degree. When map unit is decimal degree, the map position is decimal degree point, so you don’t have to reprojection on MouseMove event handle.

Thanks,
Rex

Hi Mohamad,

The raster layer only render raster data. If you wan to display vector data, you can use feature layer to render. For example: InmemoryFeatuerLayer, ShapeFileFeatureLayer etc.

There is a Vechicle Tracking Sample, and you can refer it to implement your requirement.

We suggest you go through our ThinkGeo Wiki, and you can get a quick learning.

Thanks,
Rex

Hi Rex_Liu

Sorry i don’t understand still new in GIS and Map suite. What u mean i needn’t reprojection on MouseMove event handle? Which part i reproject it. You mean this line?

PointShape pointShape4326 = proj4Projection.ConvertToExternalProjection(pointShape) as PointShape;

    TextBoxSatu.Text ="RSO_WEST(KERTAU)" + "("+ (x) +","+ " "+ (y)+ ")"+ " "+ "Long: " + DecimalDegreesHelper.GetDegreesMinutesSecondsStringFromDecimalDegree(pointShape4326.X)+ " Lat: " + DecimalDegreesHelper.GetDegreesMinutesSecondsStringFromDecimalDegree(pointShape4326.Y);

Hi Mohamad,

You want to convert epsg 3169 to 4326, so map unit should be decimal degree. Because map unit is decimal degree, so map current extent is decimal degree format, and “ExtentHelper.ToWorldCoordinate(Map1.CurrentExtent, screenPointF, (float)Map1.ActualWidth, (float)Map1.ActualHeight);” method returns decimal degree point.

Here attached a Projection Demo (10.1 KB) , you can refer it.

If you have any questions, please feel free to contact us.

Thanks,
Rex

Hai Rex_Liu

Supposedly MapUnit follow the map that being apply right? The raster map that i share are in meter and epsg 3168. I try your sample but it seem the map does not display at all.

Thank you and best regards