NAD83 (State Plane) projection to the WGS84 (Lat/Long)

Topics: SharpMap Project
Mar 7, 2013 at 5:43 PM
Howdy,
I am trying to remove my need for SpatiaLite outside of SharpMap layers. I do need to convert from the NAD83 (State Plane) projection to the WGS84 (Lat/Long) Projection. "CreateFromCoordinateSystems" says this is not supported. Any ideas?

using ProjNet.CoordinateSystems.Transformations;
using GeoAPI.CoordinateSystems.Transformations;
using GeoAPI.CoordinateSystems;
using ProjNet.CoordinateSystems;
  public static ICoordinateTransformation XForm2236toWG84
    {
        get
        {
            if (_2236toWG84 == null)
            {
                CoordinateSystemFactory csFac = new ProjNet.CoordinateSystems.CoordinateSystemFactory();
                CoordinateTransformationFactory ctFac = new CoordinateTransformationFactory();
                string wkt2236 = "PROJCS[\"NAD83 / Florida East (ftUS)\", GEOGCS [ \"NAD83\", DATUM [\"North American Datum 1983 (EPSG ID 6269)\", SPHEROID [\"GRS 1980 (EPSG ID 7019)\", 6378137, 298.257222101]], PRIMEM [ \"Greenwich\", 0.000000 ], UNIT [\"Decimal Degree\", 0.01745329251994328]], PROJECTION [\"SPCS83 Florida East zone (US Survey feet) (EPSG OP 15318)\"], PARAMETER [\"Latitude_Of_Origin\", 24.33333333333333333333333333333333333333], PARAMETER [\"Central_Meridian\", -80.9999999999999999999999999999999999999], PARAMETER [\"Scale_Factor\", 0.999941177], PARAMETER [\"False_Easting\", 656166.6669999999999999999999999999999999], PARAMETER [\"False_Northing\", 0], UNIT [\"U.S. Foot\", 0.3048006096012192024384048768097536195072]]";
                string wkt8307 = "GEOGCS [ \"WGS 84\", DATUM [\"World Geodetic System 1984 (EPSG ID 6326)\", SPHEROID [\"WGS 84 (EPSG ID 7030)\", 6378137, 298.257223563]], PRIMEM [ \"Greenwich\", 0.000000 ], UNIT [\"Decimal Degree\", 0.01745329251994328]]";
                ProjectedCoordinateSystem pcs = ProjNet.Converters.WellKnownText.CoordinateSystemWktReader.Parse(wkt2236) as ProjectedCoordinateSystem;
                GeographicCoordinateSystem gcs = ProjNet.Converters.WellKnownText.CoordinateSystemWktReader.Parse(wkt8307) as GeographicCoordinateSystem;

                _2236toWG84 = ctFac.CreateFromCoordinateSystems(pcs, gcs);
            }
            return _2236toWG84;
        }
    }
r,
dennis
Coordinator
Mar 7, 2013 at 6:58 PM
Unfortunatly the projection "SPCS83 Florida East zone (US Survey feet) (EPSG OP 15318)" is not implemented.
You can either
  • look up the projection in the EPSG registry and implement that yourself,
  • you compile SharpMap using the DotSpatialProjections configuration (though it should basically work, there might be a few adjustments to make. I have not tried that for a while)
Hth FObermaier
Coordinator
Mar 7, 2013 at 7:36 PM
Edited Mar 7, 2013 at 7:39 PM
I did some more investigation. The projection with the fancy name turns out to be Transverse Mercator. Mercator had is 501th birthday this week, by the way :). Anyway, this should work:
    private static System.Type ReflectType(string typeName)
    {
        var asm = Assembly.GetAssembly(typeof (ProjNet.CoordinateSystems.Projections.MapProjection));
        var res = asm.GetType(typeName);
        return res;
    }

    public static ICoordinateTransformation XForm2236toWG84
    {
        get
        {
            if (_2236toWG84 == null)
            {
                CoordinateSystemFactory csFac = new ProjNet.CoordinateSystems.CoordinateSystemFactory();
                CoordinateTransformationFactory ctFac = new CoordinateTransformationFactory();
                string wkt2236 = "PROJCS[\"NAD83 / Florida East (ftUS)\", GEOGCS [ \"NAD83\", DATUM [\"North American Datum 1983 (EPSG ID 6269)\", SPHEROID [\"GRS 1980 (EPSG ID 7019)\", 6378137, 298.257222101]], PRIMEM [ \"Greenwich\", 0.000000 ], UNIT [\"Decimal Degree\", 0.01745329251994328]], PROJECTION [\"SPCS83 Florida East zone (US Survey feet) (EPSG OP 15318)\"], PARAMETER [\"Latitude_Of_Origin\", 24.33333333333333333333333333333333333333], PARAMETER [\"Central_Meridian\", -80.9999999999999999999999999999999999999], PARAMETER [\"Scale_Factor\", 0.999941177], PARAMETER [\"False_Easting\", 656166.6669999999999999999999999999999999], PARAMETER [\"False_Northing\", 0], UNIT [\"U.S. Foot\", 0.3048006096012192024384048768097536195072]]";
                string wkt8307 = "GEOGCS [ \"WGS 84\", DATUM [\"World Geodetic System 1984 (EPSG ID 6326)\", SPHEROID [\"WGS 84 (EPSG ID 7030)\", 6378137, 298.257223563]], PRIMEM [ \"Greenwich\", 0.000000 ], UNIT [\"Decimal Degree\", 0.01745329251994328]]";
                ProjectedCoordinateSystem pcs = ProjNet.Converters.WellKnownText.CoordinateSystemWktReader.Parse(wkt2236) as ProjectedCoordinateSystem;
                GeographicCoordinateSystem gcs = ProjNet.Converters.WellKnownText.CoordinateSystemWktReader.Parse(wkt8307) as GeographicCoordinateSystem;

                ProjNet.CoordinateSystems.Projections.ProjectionsRegistry.Register("SPCS83 Florida East zone (US Survey feet) (EPSG OP 15318)", 
                      ReflectType("ProjNet.CoordinateSystems.Projections.TransverseMercator"));
                _2236toWG84 = ctFac.CreateFromCoordinateSystems(pcs, gcs);
            }
            return _2236toWG84;
        }
    }
Are you sure you dont want EPSG:4326 as WGS84? You can get that using
ProjNet.CoordinateSystems.GeographicCoordinateSystem.WGS84
Coordinator
Mar 7, 2013 at 7:41 PM
And if you want it really simple, replace the projection name with "Transverse_Mercator"
Mar 7, 2013 at 7:42 PM
FObermaier,

Thank you. Since I need not re-project entire layers. All I had to do was reference DotSpatial.Projections
    public string GetLonLatTransformedGeometry(string pointstring)
    {
        string rtnval = null;
        NetTopologySuite.IO.WKTReader r = new NetTopologySuite.IO.WKTReader(NTSGeometryFactory);
        IGeometry g = r.Read(pointstring);
        ProjectionInfo _2236 = KnownCoordinateSystems.Projected.StatePlaneNad1983Feet.NAD1983StatePlaneFloridaEastFIPS0901Feet;
        ProjectionInfo _wg83 = KnownCoordinateSystems.Geographic.World.WGS1984;
        GeoPoint p = g.Coordinates[0];
        double[] xy = new double[] { p.X, p.Y };
        Reproject.ReprojectPoints(xy, new double[] { 0 }, _2236, _wg83, 0, 1);
        rtnval = xy[0].ToString() + " " + xy[1].ToString();
        return rtnval;
    }
Thanks again.
r,
dennis
Coordinator
Mar 7, 2013 at 8:17 PM
Was fun, though
Mar 7, 2013 at 11:46 PM
FObermaier,
YES... your stuff is fun.
I will check out your solution tomorrow.
By the way, I really do enjoy this framework. For the last 7 years I have written a ton of code against Autodesk's .NET API and it is good stuff but very, very complex. I have also done a bunch with MapGuide Open Source Version 1.1 - 2.2 not so complex but it's all about the web. I have just heard from an old acquaintance who has ported OSgeo FDO to C#. I have not had a chance to browse the API(just got it Monday or so) but that would be awesome. Your stuff lets me work with my 1.5 million geometries without an issue of speed or accessibility. Yes, this is powerful stuff... I am now on generation 2 of a series of desktop applications, with Infragistics Winforms controls and your maps these apps really rock. I have been able to actually SIMPLIFY the entire GIS concept and process for the users...without your tool this would not have been possible.
IMHO, not WAS ... IS fun.
r,
dennis