ThinkGeo.com    |     Documentation    |     Premium Support

NTv2 Datum Support in ThinkGeo 14

I see this pop up every now and then over the years, but do we finally have the NTv2 Datum conversion support (Nad27 <-> Nad83).

We have it handled using our own hooks into the conversion pipeline (and feeding it to Proj4), but want to know if it is now supported in version 14 natively.

Hi Chris,

v14 is using the latest Gdal v3.9.1, which from the documentation, does support NTv2 Datum Conversions. However, I didn’t see it in the following test.

src: epsg:4267 (Nad27);
dest: 4269 (Nad83). The result is


which yields a different result compared to Transform coordinates - GPS online converter

We tried some different gsb files but didn’t get the expected result. We are still on it, once we figure out a way to do it on Gdal, we can also do it using GdalProjectionConverter in ThinkGeo v14.

Thanks,
Ben

Okay, here is what my tests found.

Grabbing the Gdal nuget package, and using the GdalProjectionConverter (an extension of the ProjectionConverter) I get the correct results, so long as I include the NTv2.gsb file we have from the Canadian government and we place that file in the projlib folder with the appropriate native version. This is not included in your package.

You should be able to do a search for this file on the internet and track down a download from the Canadian government site for free, but it is is licensed file.

Awesome! Glad you make it! Can you send me your test code (input point and expected output point)? We’ll see if we can make it easier for the users to integrate it in the future.

You need to get the ThinkGeo.Gdal nuget package (which includes the 3.9.1 version of GDAL)

Here is the button click that reads some values from a window, and converts them using the GDAL converter, as well as our current (well tested) Proj4 based converter.

    private void Convert_OnClick(object sender, RoutedEventArgs e)
    {
        // Get the Input Coordinate
        // This will be in the Source (Internal) coordinate system
        double originalX = double.Parse(XCoordinate.Text);
        double originalY = double.Parse(YCoordinate.Text);

        // Prepare these coordinates for use in the GDAL converter
        // They need to be stored in a Vertex array
        Vertex inputPoint = new Vertex(originalX, originalY);
        List<Vertex> vertices =
        [
            inputPoint
        ];

        // Get the GDAL Projection Converter
        // This is an extension of the ThinkGeo ProjectionConverter which is used (or a derivation of it)
        // for all the conversions and projections needed. GDAL seems to handle the Grid Conversions (like NTv2)
        // The big trick here was to obtain the NTv2.gsb file from Resources Canada, and drop it in the projlib folder
        // for the runtime for GDAL

        // To get the file
        // https://webapp.csrs-scrs.nrcan-rncan.gc.ca/geod/data-donnees/transformations.php
        // Sign in (or sign up) to register and accept the licence
        // Copy the NTv2.gsb file to
        // {application executable folder}\runtimes\win-x64\native\projlib

        // Suffice to say there are many other *.gsb files all around the world, just find the one you need and drop it in there.

        // Get the Input/Output reference identifiers
        int internalSrid = int.Parse(InputSrid.Text);
        int externalSrid = int.Parse(OutputSrid.Text);

        // Get me a converter that will handle the conversion
        GdalProjectionConverter gdalConverter = new GdalProjectionConverter(internalSrid, externalSrid);
        gdalConverter.Open();

        // Now the magic happens, convert it and display it
        Vertex outputVertex = gdalConverter.ConvertToExternalProjection(vertices).First();
        ThinkGeoX.Content = $"{outputVertex.X:F4}";
        ThinkGeoY.Content = $"{outputVertex.Y:F4}";

        // We have our own version of the Grid Conversions (Including the NTv2)
        // We can use this as a test

        // Our tool needs to know where the find the Grid Files,
        // this sets that directory for it (this is the key so it can find the NTv2.gsb file)
        string directory = Directory.GetCurrentDirectory();
        Proj4WrapperFactory.ResourceDirectory = $"{directory}\\nad\\";

        // Get a converter to handle our conversion
        IProj4Wrapper wrapper = Proj4WrapperFactory.CreateProjection(internalSrid, externalSrid);

        // Our wrapper works in tuples, it was easier for us
        Tuple<double, double>[] points = new Tuple<double, double>[1];
        points[0] = new Tuple<double, double>(originalX, originalY);

        // Do it, and show it
        Tuple<double, double>[] convertedPoints = wrapper.ConvertToExternalProjection(points);
        Proj4X.Content = $"{convertedPoints[0].Item1:F4}";
        Proj4Y.Content = $"{convertedPoints[0].Item2:F4}";

    }

Screenshot 2024-11-05 062853

And a UTM (Zone 12) conversion

Screenshot 2024-11-05 063130

They look pretty close to me.

To get this all to work I need the correct *.gsb files for Canada. To get the Grid File you have to go to…
Resource Canada Signup Page

And sign up and accept the license

Once you get the NTv2.gsb file from Resources Canada, you need to place it in the Runtime folder for the GDAL Libraries, in my case…

C:\Users\chris\Source\repos\ThinkGeoSaveState\ThinkGeoSaveState\bin\Debug\net8.0-windows\runtimes\win-x64\native\projlib for my debug. Your final executable folder may vary.

Chris,

YOU ROCK! Thanks for this super detailed explanation!

By the way, download the latest proj: https://download.osgeo.org/proj/proj-9.4.1.tar.gz, unzip it, copy the file “\proj-9.4.1\proj-9.4.1\data\tests\conus” to projlib folder will also make it work for my test case (my test point lat:36, lon:-116 is within Conus US)

Thanks,
Ben

Just trying to come up with an easy way to have it copy additional grid files into the correct projlib folder. I will let you know.

Thanks Chris for your input!

I got that conus file and dropped it into the projlib folder and your test and mine on that coordinate are the same. But, a test that I had that was in southern Ontario is now off. This says to me it uses the conus file instead of the ntv2_0.gsb file, I suspect because this point is south of the 49th!

Interesting, something for me to dig into further.

Good to know, thanks for sharing!