# How to convert PCS based point X/Y into GCS Lat/Lon using ArcObjects

There are so many permutations of questions I've tried to find the answer to my question from various sources, but I have yet to actually find an answer the way that makes sense to me (and works).

I'm using ArcObjects in a ArcMap add-in, and I have shape file loaded with sample data that comes in a Projected Coordinate System.

I want to convert a feature's points (IPoint) which are X/Y coordinates, into it's BASE GCS Lat/Lon values.

For example:

The Data Source in the Shape File shows (Custom since Factory Code shows ZERO):

Projected Coordinate System: NAD27_BLM_3N_ftUS Projection: Transverse_Mercator false_easting: 1640416.67000000 false_northing: 0.00000000 central_meridian: -165.00000000 scale_factor: 0.99960000 latitude_of_origin: 0.00000000 Linear Unit: Foot_US

Geographic Coordinate System: GCS_North_American_1927 Datum: D_North_American_1927 Prime Meridian: Greenwich Angular Unit: Degree

And I want to convert the X/Y coordinates to be Lat/Lon instead with GCS NAD 27.

There is no transformation, it's the same Datum.

I have tried to use the following code:

``````IPoint geographicPoint = new Point();
geographicPoint.X = _pcsX;
geographicPoint.Y = _pcsY;
geographicPoint.Z = _z;
geographicPoint.M = _m;
geographicPoint.SpatialReference = _inputSpatialReference; // PCS

ISpatialReference outputSpatialReference = SpatialReference.GenerateSpatialReference(outputCoordinateSystemWKID, false); // GCS

((IGeometry2)geographicPoint).ProjectEx(outputSpatialReference, esriTransformDirection.esriTransformReverse, null, false, 0, 0);

_gcsLat = geographicPoint.Y;
_gcsLong = geographicPoint.X;
``````

I have also tried to use the Project() method as well instead of ProjectEx:

``````((IGeometry2)geographicPoint).Project(outputSpatialReference);
``````

however, in both cases, I just get the exact same X/Y coordinates in the X/Y values of the geographicPoint, when I am expecting the X/Y values to now be the Long/Lat as I have requested the output coordinate system that is a Geographic Coordinate System.

Source Point:

X: 2440016.02472701 Y: 25980973.0785536

After Projection to 4267:

LAT: 25980973.0785536 LON: 2440016.02472701

Can anyone help?

As Requested: the PRJ file of the input document: PROJCS["NAD27_BLM_3N_ftUS",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Transverse_Mercator"],PARAMETER["false_easting",1640416.67],PARAMETER["false_northing",0],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",-165],PARAMETER["scale_factor",0.9996],UNIT["Foot_US",0.30480060960121924]]

• what are your input and output coordinate systems? You say they are the same datum, which sounds great, but are they EPSG coordinate systems? I can't tell by your code... If a coordinate system is defied textually it may be identical to an EPSG spatial reference but still be considered custom, thus requiring a transformation. Aug 18, 2014 at 21:45
• I think the input values are in feet, not meters. Depending on which version you have, see if there's a NAD27 BLM 3 coordinate system available. It uses US survey feet for the units. Aug 18, 2014 at 23:51
• The input coordinate system comes from whatever Shape File is loaded. So they could be GCS or PCS or they could be Custom coordinate systems defined by the company. There is many inputs. The outputs are whatever coordinate systems are defined by ESRI within it's enumerations. All referenced by the Well Known ID. The point data, comes from the Shape Files. Aug 19, 2014 at 13:43

Here's some revised code that I tested successfully:

``````x -165.997618623476, y 72.0016465340226
``````

Here's the prj file contents:

``````PROJCS["NAD27_BLM_3N_ftUS",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",-165],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",1640416.67],PARAMETER["false_northing",0],UNIT["Foot_US",0.30480060960121924]]
``````

Here's the code:

``````public static void TestProjectToGCS()
{
string prjFile = @"D:\projects\blm3n.prj";

var t = Type.GetTypeFromProgID("esriGeometry.SpatialReferenceEnvironment");
var srf = Activator.CreateInstance(t) as ISpatialReferenceFactory2;
var sr = srf.CreateESRISpatialReferenceFromPRJFile(prjFile);
IPoint p = new PointClass();
p.PutCoords(1527538.32, 26211344.31);
p.SpatialReference = sr;
var p2 = (IPoint)ProjectToGCS(p);
Debug.Print("x {0}, y {1}", p2.X, p2.Y);
}
public static IGeometry ProjectToGCS(IGeometry inGeom)
{
if (!(inGeom.SpatialReference is IProjectedCoordinateSystem5))
throw new Exception("geometry is not in a projected coordinate system");

var outGeom = ((IClone)inGeom).Clone() as IGeometry;
var outSR = ((IProjectedCoordinateSystem5)outGeom.SpatialReference).GeographicCoordinateSystem as ISpatialReference;
outGeom.Project(outSR);
return outGeom;
}
``````
• I do not believe there is any new code here. as it is still using the same Project() call on the Geometry, and it still uses the same projected coordinate system, and geographic coordinate system. The code is identical to the Question above. Alas, this code does not work for the situation I am faced with. I believe there is a problem using the Custom Projected Coordinate System. I have updated the Question with the details of the Projected Coordinate System information from the Data Source. Aug 19, 2014 at 14:13
• The code I posted doesn't use GenerateSpatialReference, but your code does. What are IPoint.X & Y after calling ProjectToGCS? Aug 19, 2014 at 14:16
• The call to "GenerateSpatialReference" Is just a helper class that uses the ISpatialReferenceFactory2 to call "CreateSpatialReference" ultimately. I have just tried yours and I get the exact same results: Input X: 1527538.32, Input Y: 26211344.31 > (To: 4267) LAT: 26211344.31, LON: 1527178.32 Aug 19, 2014 at 14:29
• @Draek Maybe open the .prj file in notepad, then copy and paste the contents into the body of your question. Aug 19, 2014 at 15:14
• @Draek see revised test results Aug 19, 2014 at 17:04

This is how I've done it previously (freqently) and had no problems whatsoever:

``````int NAD27_UTMzone4N = 26704; //http://spatialreference.org/ref/epsg/nad27-utm-zone-4n/

ISpatialReferenceFactory2 srFactory = new SpatialReferenceEnvironmentClass();

IPoint geographicPoint = new PointClass();
geographicPoint.X = _pcsX;
geographicPoint.Y = _pcsY;
geographicPoint.Z = _z;
geographicPoint.M = _m;
geographicPoint.SpatialReference = ProjectedSR;

geograhpicPoint.Project(GeographicSR);

_gcsLat = geographicPoint.Y;
_gcsLong = geographicPoint.X;
``````

I use the `Project()` method of the `IGeometry` which, provided no transformation need be supplied, works well. Refer IGeomertry.Project Method.

I use the `ISpatialReferenceFactory2` interface to generate the spatial reference from the EPSG code for well known coordinate systems, this works better than supplying text or prj file as there's no room for mistakes. Refer ISpatialReferenceFactory2.CreateSpatialReference Method.

It is possible that Z and M values are throwing the projection off, if these values aren't important don't set them. In this case a bad value is far worse than no value.

• According to Esri's sample for Creating a custom geotransformation, `SpatialReferenceEnvironmentClass` is a singleton. `Activator.CreateInstance` is the recommended way to create singletons. Aug 18, 2014 at 23:05
• @KirkKuykendall Refer help.arcgis.com/en/sdk/10.0/arcobjects_net/componenthelp/… specifically CoClasses that implement ISpatialReferenceFactory2. The aim is not to create a custom spatial reference but to create a well known spatial reference using the EPSG code. From the question it's obvious that the X and Y are NOT being transformed which is probably due to the in-out spatial reference. Aug 18, 2014 at 23:12
• Sorry, I didn't mean to suggest that a custom spatial reference is needed, only that Esri says to use `Activator` to create the `SpatialReferenceEnvironment` instance instead of `new`. Aug 18, 2014 at 23:17
• @KirkKuykendall if you would have a look at this sample help.arcgis.com/en/sdk/10.0/arcobjects_net/componenthelp/… (ctrl+F and search for Factory2).. you may be correct, my position is based on several years of using the new SpatialReferenceEnvironmentClass() - that doesn't necessarily make it better; many times I've been shown that there is a better way of doing things than the way I've been using for many years. Aug 18, 2014 at 23:45
• Many of the Projected Coordinate Systems may be custom, or have a FactoryCode of ZERO (0) so I cannot re-create the SpatialReference using a Well Known ID for these. The settings of the projection are defined in the pre-existing SpatialReference passed in through the points. Ultimately the code I see here, is literally the same as the code I presented above in my question. So there is nothing new there unfortunately. The only thing I ommited was the creation of the output spatial reference, which is a helper class, that does exactly what you are doing here to create the spatial reference. Aug 19, 2014 at 13:40

Unfortunately StackExchange broke my account causing me to not be able to comment on answers etc.

This is for Kirk Kuykendall, I appreciate your assistance with this very much. It's great to have people like you to come to when things just don't work right. I am excited to try the solution from the PRJ file, however, I will need to come up with some way to do this without the use of the actual PRJ file. Hopefully I can figure out how to get that projection definition from the ArcObjects in memory and somehow create the spatial reference that way without needing to have the user provide the PRJ file. Otherwise this will cause issues in the workflow being requested.

But I appreciate your help with this. I am having a ton of other issues I am now finding converting from known projections (not custom ones). Where I thought I was getting good values before, but now realize I am not getting good values at all.

For example, when I try the same code to convert from 32065 (Projected) to its base GCS (4267) it works, and then when I try and convert as well to WGS84 (4326) using a transformation NAD_1927_To_WGS_1984_1 I get invalid values! Which really surprizes me.

Projecting without transformation (From: 32065 PCS) (To: 4267 GCS)

Input X: 1545657.33157618, Y: 11654131.4567511

Output LAT: 32.1073377480588, LON: -93.3061315609481

Projecting using transformation NAD_1927_To_WGS_1984_1 (To: 4326)

Input X: 1545657.33157618, Y: 11654131.4567511

Output LAT: 32.1073377480588, LON: 91.2102941689212

Well that Output LAT LON is wrong, 91 is way off, if anything it should be -91, and even then if I check where that coordinate is, it's totally wrong!

I'm starting to get confused why you can't just choose input/output/transformation and use ProjectEx and get valid results :P