Converting Spatial Coordinates with Proj.NET

In my previous article I expressed some disappointment in the usefulness of the Map Projections in SQL Spatial Tools on CodePlex. There's not much you can do with these in a real-life application. Fortunately there's also Proj.NET on CodePlex, a flexible advanced point-to-point coordinate conversion engine that is used internally by a lot of open source GIS projects.

Here's a small fraction of its object model:

Geographic Coordinate Systems 

The only predefined geographic coordinate system is WGS84:

ICoordinateSystem gcs_WGS84 = GeographicCoordinateSystem.WGS84;


But you can easily create your own, from Well-Known Text (WKT) or through the object model:

string wkt_WGS84 =

    "GEOGCS[\"GCS_WGS_1984\"," +

         "DATUM[\"D_WGS_1984\",SPHEROID[\"WGS_1984\",6378137,298.257223563]]," +

         "PRIMEM[\"Greenwich\",0]," +

         "UNIT[\"Degree\",0.0174532925199433]" +


ICoordinateSystem gcs_WGS84 = CoordinateSystemWktReader.Parse(wkt_WGS84) as ICoordinateSystem

Projected Coordinate Systems

The only predefined projected coordinate system is UTM:

IProjectedCoordinateSystem pcs_UTM31N = ProjectedCoordinateSystem.WGS84_UTM(31, true);


But again, you can easily create your own, from WKT or through an object model. Here's how Lambert 2008 -a local Belgian projection- looks like:

string wkt_Lam08 =

    "PROJCS[\"ETRS89 / Belgian Lambert 2008\"," +

        "GEOGCS[\"ETRS89\"," +

            "DATUM[\"European Terrestrial Reference System 1989\"," +

                "SPHEROID[\"GRS 1980\",6378137.0,298.257222101," +

                    "AUTHORITY[\"EPSG\",\"7019\"]]," +

                "TOWGS84[0.0,0.0,0.0,0.0,0.0,0.0,0.0]," +

                "AUTHORITY[\"EPSG\",\"6258\"]]," +

            "PRIMEM[\"Greenwich\",0.0," +

                "AUTHORITY[\"EPSG\",\"8901\"]]," +

            "UNIT[\"degree\",0.017453292519943295]," +

            "AXIS[\"Geodetic latitude\",NORTH]," +

            "AXIS[\"Geodetic longitude\",EAST]," +

            "AUTHORITY[\"EPSG\",\"4258\"]]," +

        "PROJECTION[\"Lambert Conic Conformal (2SP)\"]," +

        "PARAMETER[\"central_meridian\",4.359215833333335]," +

        "PARAMETER[\"latitude_of_origin\",50.79781500000001]," +

        "PARAMETER[\"standard_parallel_1\",49.833333333333336]," +

        "PARAMETER[\"false_easting\",649328.0]," +

        "PARAMETER[\"false_northing\",665262.0]," +

        "PARAMETER[\"standard_parallel_2\",51.16666666666667]," +

        "UNIT[\"m\",1.0]," +

        "AXIS[\"Easting\",EAST]," +

        "AXIS[\"Northing\",NORTH]," +


IProjectedCoordinateSystem pcs_Lam08 =

    CoordinateSystemWktReader.Parse(wkt_Lam08) as IProjectedCoordinateSystem;


The list of supported projections includes Mercator, Transverse Mercator, Albers, Lambert Conformal, and Krovak.

If you download the project's source code, you'll also discover an SRIDReader class that allows you to instantiate a coordinate system from nothing more than its Spatial Reference ID.


A coordinate conversion can be defined and called through the API as follows:

CoordinateTransformationFactory ctfac = new CoordinateTransformationFactory();

ICoordinateTransformation trans = ctfac.CreateFromCoordinateSystems(gcs_WGS84, pcs_UTM31N);

double[] fromPoint = new double[] { 4.296545, 50.880324 };  // U2U Consult Head Office, in degrees

double[] toPoint = trans.MathTransform.Transform(fromPoint);


If you're lucky, then you also get the inverse transformation, but it's not always implemented.



    IMathTransform inversedTransform = trans.MathTransform.Inverse();

    double[] point = inversedTransform.Transform(toPoint);


catch (NotImplementedException ex)


    // Your exception handling here...


 Test Client

Here are U2U Consult's Headquarter's coordinates:

I built a small test client that applies some transformations on these (WGS 84 - UTM - Lambert 1972 - Lambert 2008). Here's how the result looks like:

For the sake of completeness: here's the full source code: (38,93 kb)