Search code examples
c#geometrynettopologysuite

What sort of unit does NetTopologySuite return distances in, and how can I convert it to miles/km?


Whenever I use FreeMapTools to calculate the distance between myself and my friends postcode, it gives me the following:

  • 300.788 Miles
  • 484.072 KM

Screenshot from FreeMapTools showing 300.788 Miles Screenshot from FreeMapTools showing 484.072 KM

When I use NetTopologySuite, I get the value of 5.2174236612815 returned.

  • 5.2174236612815 times by 60 is 313.04541967689
  • 5.2174236612815 times by 100 is 521.74236612815

These values aren't too far away from the distances shown on FreeMapTools, but they are still way off.

My code is below:

using System;
using GeoAPI.Geometries;
using NetTopologySuite;

namespace TestingDistances
{
    class Program
    {
        static void Main(string[] args)
        {
            var geometryFactory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);

            // BT2 8HB
            var myPostcode = geometryFactory.CreatePoint(new Coordinate(-5.926223, 54.592395));

            // DT11 0DB
            var myMatesPostcode = geometryFactory.CreatePoint(new Coordinate(-2.314507, 50.827157));

            var distance = myPostcode.Distance(myMatesPostcode);
            Console.WriteLine(distance); // returns 5.2174236612815

            Console.WriteLine(distance * 60); //similar to miles (313.04541967689)
            Console.WriteLine(distance * 100); //similar to km (521.74236612815)

            Console.ReadLine();
        }
    }
}

How do I go about converting the value returned from NetTopologySuite accurately into miles/distances? Is this some form of GPS distancing unit I'm not aware off?

Thanks


Solution

  • As DavidG mentions correctly, NetTopologySuite assumes cartesian coordinates. Your coordinates are geographic (lat/lon). Thus the result you are getting is useless and cannot be translated into meter or miles.

    You have to perform a coordinate transformation prior to calling the distance method, e.g. using ProjNet:

    var csWgs84 = ProjNet.CoordinateSystems.GeographicCoordinateSystems.WGS84;
    const string epsg27700 = "..."; // see http://epsg.io/27700
    var cs27700 = ProjNet.Converters.WellKnownText.CoordinateSystemWktReader.Parse(epsg27700);
    var ctFactory = new ProjNet.CoordinateSystems.Transformations.CoordinateTransformationFactory();
    var ct = ctFactory.CreateFromCoordinateSystems(csWgs84, cs27700);
    var mt = ct.MathTransform;
    
    var gf = new NetTopologySuite.Geometries.GeometryFactory(27700);
    
    // BT2 8HB
    var myPostcode = gf.CreatePoint(mt.Transform(new Coordinate(-5.926223, 54.592395)));
    // DT11 0DB
    var myMatesPostcode = gf.CreatePoint(mt.Transform(new Coordinate(-2.314507, 50.827157)));
    
    double distance = myPostcode.Distance(myMatesPostcode);