5

I am working with the ESRI Silverlight API. I found THIS post in the ESRI forums and THIS OTHER which show how to convert between WGS84 geographic coordinates and WebMercator coordinates. I want to do the same thing but from NAD27 Geographic coordinates to WebMercator. I found the spatial reference for NAD27 at the spatialreference website with the WKID 4267 and changed the code accordingly with the radius of 6378206.4 and degree 0.01745329251994328 respectively. I ended up with this function (in c#):

private MapPoint GeographicToWebMercator(MapPoint point)
{
        double a = point.Y * 0.01745329251994328;
        double y = (6378206.4/2) * Math.Log((1.0 + Math.Sin(a)) / (1.0 - Math.Sin(a)));

        double x = 6378206.4 * (point.X * 0.01745329251994328);
        return new MapPoint(x, y);
}

Unfortunately, my dots are displaced from where they should be. So, this is not working as intended. I was wondering if someone can take a look at it and tell me what is wrong... or if I can do this projection this way to begin with. The function, as is, is not checking for null "point" or any other data just yet. But, please, don't focus on that. I am just interested in the calculation per se. Thanks!

5
  • 3
    Displaced in what directions and by how much? How do you know where they "should" be? (It's possible the reference points are wrong, after all.) Please note that your equations are not correct for either WGS84 nor NAD27, both of which use ellipsoids with flattenings near 1/300: these equations are for a sphere only. (One way to tell that is to notice that the only parameter entering into the calculations is a radius; there is nothing indicating the flattening.)
    – whuber
    Commented Nov 27, 2012 at 22:28
  • Thanks for your comment. I know my markers are off because my reference layer has been thoroughly tested. We can also simply add a World Imagery layer to our map and see the physical locations we are referring on our own layer and the markers are off from those points. So, I don't think it gets any better than that to know we are off. How off are the markers, not much. I don't have them in front of me at the moment; but speculating I'd say anything between 200 and 500 meters and if I remember well, they all seem to be shifted in a north-west direction. Commented Nov 30, 2012 at 15:57
  • Also, if I were to add the flattening how would I do that? any ideas? Thanks! Commented Nov 30, 2012 at 15:58
  • 1
    The discrepancies due to confusing ellipsoidal and spherical datums will amount to tens of kilometers, typically, so that is not the explanation. The displacements you note are consistent with (although a bit large) for the shift between the NAD83 and NAD27 datums. This shift cannot be programmed with any simple formula, because it occurs irregularly throughout the US: you need to look up the amount of shift on a grid and interpolate. This is done with NADCON. If your area of interest is very small, a constant vector translation will do.
    – whuber
    Commented Nov 30, 2012 at 17:05
  • 1
    Re the flattening: it sounds like you don't need it, but for the record the y formula is corrected to y = (R/2) [log((1 + sin(phi)) / (1 - sin(phi))) - e log((1 + e sin(phi)) / (1 - e sin(phi)))] where e, the eccentricity, equals sqrt(2f-f^2) = 0.081819190842621 and R is the semi-major axis, 6378137.0 m. As before, phi is the (geodetic) latitude. The x formula uses the same value of R as the y formula.
    – whuber
    Commented Nov 30, 2012 at 17:14

2 Answers 2

2

If you don't mind making a round trip to the server, and you have a 10.1 geometry service available to you, you can use the Esri Rest API Project Geometries operation.

If Transformation is not specified, a search is made through a set of default GeoTransformations. Currently, the following default transformations are used when applicable:

esriSRGeoTransformation_NAD_1927_TO_NAD_1983_NADCON, forward and reverse, WKID=1241

esriSRGeoTransformation_NAD1983_To_WGS1984_1, forward and reverse, WKID=1188

esriSRGeoTransformation_NAD1927_To_WGS1984_4, forward and reverse, WKID=1173

1
  • Thanks for your reply! I tried this solution already and because of the amount of data our application handles dynamically (adds and deletes markers on the fly per user's demand) it is a little slow and (this may be something with our server) it seems to shut the operation after many continuous hits with 3000+ projections. That is why I like this solution doing the projections locally better. Commented Nov 30, 2012 at 16:01
2

I'd recommend you try the Proj.NET library (a Proj4 implementation for .Net) in your application and let Proj.NET do the coordinate transformations for you. It should be compatible with Silverlight by way of C#.

Here's a blog post with a C# example showing implementation.

I took a crack at it in a simple Windows Form app. Here's a screenshot of it..

enter image description here

And this is the C# code I used, of course you will need to have referenced the ProjNet.dll in your project..

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

//using ProjNet.Converters; // didn't need this one
using ProjNet.Converters.WellKnownText;
using ProjNet.CoordinateSystems;
using ProjNet.CoordinateSystems.Transformations;

namespace ProjNetTest
{
    public partial class projNetTestForm : Form
    {
        public projNetTestForm()
        {
            InitializeComponent();

            // BassPro, Springfield MO
            // long: -93.29592962, lat: 37.18069720
            xTB.Text = "-93.29592962";
            yTB.Text = "37.18069720";
        }

        private void convertButton_Click(object sender, EventArgs e)
        {
            // Get the NAD27 Point Coords as X(long) Y(Lat)..
            double fromX = Convert.ToDouble(xTB.Text);
            double fromY = Convert.ToDouble(yTB.Text);
            double[] nad27Point = new double[] { fromX, fromY };

            // To begin with, I tested against WGS84 coords.
            // Init the WGS84 rules..
            // ICoordinateSystem gcs_WGS84 = GeographicCoordinateSystem.WGS84;

            // Init the NAD27 rules..
            string epsg4267 = "GEOGCS[\"NAD27\",DATUM[\"North_American_Datum_1927\",SPHEROID[\"Clarke 1866\",6378206.4,294.9786982138982,AUTHORITY[\"EPSG\",\"7008\"]],AUTHORITY[\"EPSG\",\"6267\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4267\"]]";
            ICoordinateSystem gcs_NAD27 = CoordinateSystemWktReader.Parse(epsg4267) as ICoordinateSystem;

            // Init the WebMerc rules, and note the "gotchas!" at that link (this was eating me alive at first)..
            // READ THIS:
            // http://alastaira.wordpress.com/2011/01/23/the-google-maps-bing-maps-spherical-mercator-projection/
            string epsg3857_HACK = "PROJCS[\"Popular Visualisation CRS / Mercator\",GEOGCS[\"Popular Visualisation CRS\",DATUM[\"WGS84\",SPHEROID[\"WGS84\", 6378137.0, 298.257223563, AUTHORITY[\"EPSG\",\"7059\"]],AUTHORITY[\"EPSG\",\"6055\"]],PRIMEM[\"Greenwich\", 0, AUTHORITY[\"EPSG\", \"8901\"]],UNIT[\"degree\", 0.0174532925199433, AUTHORITY[\"EPSG\", \"9102\"]],AXIS[\"E\", EAST], AXIS[\"N\", NORTH], AUTHORITY[\"EPSG\",\"4055\"]],PROJECTION[\"Mercator\"],PARAMETER[\"semi_minor\",6378137],PARAMETER[\"False_Easting\", 0],PARAMETER[\"False_Northing\", 0],PARAMETER[\"Central_Meridian\", 0],PARAMETER[\"Latitude_of_origin\", 0],UNIT[\"metre\", 1, AUTHORITY[\"EPSG\", \"9001\"]],AXIS[\"East\", EAST], AXIS[\"North\", NORTH],AUTHORITY[\"EPSG\",\"3785\"]]";
            IProjectedCoordinateSystem gsc_WebMerc = CoordinateSystemWktReader.Parse(epsg3857_HACK) as IProjectedCoordinateSystem;

            // Perform the coordinate transformation between these systems.
            CoordinateTransformationFactory transformer = new CoordinateTransformationFactory();
            ICoordinateTransformation coordTransform = transformer.CreateFromCoordinateSystems(gcs_NAD27, gsc_WebMerc as ICoordinateSystem);

            double[] webMercPoint = coordTransform.MathTransform.Transform(nad27Point);

            double webMercX = (double)webMercPoint[0];
            double webMercY = (double)webMercPoint[1];

            resultTB.Text = "X: " + webMercX.ToString() + "\r\nY: " + webMercY.ToString();
        }
    }
}

And finally, here is where QGIS, with the Bing aerial (OpenLayers plugin) shows my point computation. I hovered my mouse over the position in question so it appears in the status area, below:

enter image description here

If you want to compare it with where Google places that Lat/Long, this is the link: http://maps.google.com/?ll=37.18069720,-93.29592962

8
  • thanks for all your efforts! this is awesome! I will try this and see how it works. Commented Nov 30, 2012 at 16:06
  • NP, Luis. Admittedly, I'm still curious whether or not this approach will side-step datum shift issues. I'll be interested to know the outcome.
    – elrobis
    Commented Nov 30, 2012 at 19:30
  • Thanks again. It does project; but south of the actual position. I measured the shift and they are off roughly 14 miles south from where they are supposed to be. So, I guess there is something going on with the 3857 projections that is not projecting the latitude correctly. I need to work on something else; but I will go back to this in a couple of days or so. Thanks for your help! Much appreciated. Commented Dec 3, 2012 at 18:58
  • Quick question, Is that application on the screen shot created with the ESRI toolkit? Or is it google maps? The reason I ask is because, in reading the ESRi documentation, I found that for 102100 they have a unit of ESRImeters... whatever that is. So, I guess they came up with their own unit for projections?? I may have misunderstood the documentation, so don't trust my statement completely. Commented Dec 3, 2012 at 19:07
  • Nope, my first screenshot is the little test form I created just to get a button that would run the routine---the second is QGIS showing Bing aerials projected to 3857. I just needed some way to test whether or no my C# code was converting coordinates and getting "in the ballpark". The part that should interest you the most is the convertButton_Click() function in the code sample, which is what you would want to implement into your silverlight client, and drive using some form of mouse_move event.
    – elrobis
    Commented Dec 3, 2012 at 19:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.