0

I'm writing Windows WPF application using ESRI's axMapControl, and I need to display points on the map, where the points are in lat/lon (WGS 1984), and the map projection is determined by the user. (User selects which .mxd to display, and I cannot mandate which projection it uses.)

I've been searching around the web, looking for examples of how to project lat/lon, and this is what I've found:

double lon = -3.159875;
double lat = 51.465615;

var srf = Activator.CreateInstance(Type.GetTypeFromProgID("esriGeometry.SpatialReferenceEnvironment")) as ISpatialReferenceFactory3;

// Create Transformation from WGS84 to OSGB86
var geoTrans = srf.CreateGeoTransformation((int)esriSRGeoTransformationType.esriSRGeoTransformation_OSGB1936_To_WGS1984Petrol) as IGeoTransformation;

var wgs84GCS = srf.CreateGeographicCoordinateSystem((int)esriSRGeoCSType.esriSRGeoCS_WGS1984);
var bngPCS = srf.CreateProjectedCoordinateSystem((int)esriSRProjCSType.esriSRProjCS_BritishNationalGrid);

IPoint point = new Point();
point.PutCoords(lon, lat);

var geometry = point as IGeometry5;
geometry.SpatialReference = wgs84GCS;

geometry.ProjectEx(bngPCS, esriTransformDirection.esriTransformReverse, geoTrans, false, 0.0, 0.0);
point = geometry as IPoint;

double x = point.X;
double y = point.Y;

The above works fine for converting from WGS84 to OSGB86. My problem is that it depends upon a particular predefined geographic transformation, and there's no way for me to know which one to use. I'll know that I'm converting from WGS84, but I'll want to convert to the coordinate system of the map.

In digging through the ESRI docs, I've found reference to IGeometry5 .Project(), which takes only a target spatial reference, which would seem to be what I need, except that it doesn't return the same values as ProjectEx(), in the example above, and the gives me this warning:

A geometry is not densified before it is projected. This can lead to the output geometries not reflecting the 'true' shape in the new coordinate system. A straight line in one coordinate system is not necessarily a straight line in a different coordinate system. Use IGeometry2::ProjectEx if you want to densify the geometries while they are projected.

So, assuming I want to use ProjectEx(), instead of Project(), is there some way of finding the appropriate geographic transformation, given WGS84, and the spatial reference of a map?

Or is there some other way of projecting a geometry, that does densify, and can work with just the two spatial references, instead of a predefined geographic transform?

  • 1
    You need to code the ones you are likely to get and return an error message if the users' spatial reference is outside of your defined values... how many spatial reference transformations are you likely to get? I would use IGeometry5.ProjectEx5() to perform the projection if you're going to need a transformation. Note transformations only apply if you're changing datums, WGS84 to UTM Zone XX(n/s) doesn't need a transformation. – Michael Stimson Jul 6 '16 at 22:27
  • 1
    With ProjectEx5, maybe try setting the esriProjectionHint to 4 (esriProjectionHintFindGeoTransformation). – mkennedy Jul 6 '16 at 22:30
  • We have close to 1000 customers in 47 states and a number of Canadian provinces. Figuring out what projections they might use is essentially impossible. – Jeff Dege Jul 7 '16 at 6:17
1

For what it's worth, I've not found a method of creating a GeoTransformation using nothing but the information in a Map, so I've not been able to get ProjectEx() to work.

Using Project(), on the other hand, is simple:

double x;
double y;

var success = this.projectLonLat(this.axMapControl1.SpatialReference,
    -84.3880, 33.7490, out x, out y);
if (success)
    this.addTextElement(this.axMapControl1.Map, x, y);


private bool projectLonLat(ISpatialReference mapSpatialReference, 
    double lon, double lat, out double x, out double y)
{
    x = 0.0;
    y = 0.0;

    var point = new Point();
    point.PutCoords(lon, lat);

    var geometry = point as IGeometry5;
    Debug.Assert(geometry != null, "geometry != null");

    geometry.SpatialReference = this.wgs84GCS;
    geometry.Project(mapSpatialReference);

    var newPoint = geometry as IPoint;
    Debug.Assert(newPoint != null, "newPoint != null");

    x = newPoint.X;
    y = newPoint.Y;

    return true;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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