reproject featureclass

2899
6
Jump to solution
08-06-2015 05:22 PM
JohnMcGlynn
Occasional Contributor

I am trying to reproject a featureclass using the IGeometry.Project method.

When I use it to change a featureclass from Lambert to GDA94, nothing changes.

I may be making a fundamental error here as the finer points of reprojection have always exited my head after a cup of tea.

Can someone tell me what I'm doing wrong?

I am using a Windows 7 machine with ArcGIS 10.1. The application is a standalone .exe one.

My code is:

   public static string reProject(string sFromWorkspace, string sFromFC, string sToProjectionFile, ref ToolStripProgressBar pProgress)

        {

            // Reproject sFromFC using the projection in file sToProjectionFile

            string sError = "";

            IWorkspaceFactory pFromWSFactory = null;

            IWorkspace pFromWS = null;

            IFeatureWorkspace pFromFWS = null;

            IFeatureClass pFromFC = null;

            IFeatureCursor pFromFCur = null;

            IFeature pFromFeat = null;

            IGeometry pGeom;

            IQueryFilter pQ;

            ISpatialReference pSpRef;

            ISpatialReferenceFactory pSpRefFact = null;

            bool bProgress = false;

            int iCount;

            try

            {

                if (File.Exists(sToProjectionFile) == false)

                {

                    sError = "File: " + sToProjectionFile + " does not exist";

                    return sError;

                }

                bProgress = pProgress != null;

                // From Workspace

                pFromWSFactory = workspaceFactoryGet(sFromWorkspace, ref sError);

                if (sError.Length > 0)

                {

                    sError = "reProject\r\n" + sError;

                    return sError;

                }

                pFromWS = pFromWSFactory.OpenFromFile(sFromWorkspace, 0);

                pFromFWS = (IFeatureWorkspace)pFromWS;

             

                // Spatial reference

                Type factoryType = Type.GetTypeFromProgID("esriGeometry.SpatialReferenceEnvironment");

                System.Object obj = Activator.CreateInstance(factoryType);

                pSpRefFact = obj as ISpatialReferenceFactory;

                pSpRef = pSpRefFact.CreateESRISpatialReferenceFromPRJFile(sToProjectionFile);

                // Open the featureclass

                pFromFC = pFromFWS.OpenFeatureClass(sFromFC);

                iCount = pFromFC.FeatureCount(null);

                if (iCount == 0) return sError;

                if (bProgress == true)

                {

                    pProgress.Visible = true;

                    pProgress.Maximum = iCount;

                }

                iCount = 0;

           

                pFromFCur = pFromFC.Update(null, false);

                pFromFeat = pFromFCur.NextFeature();

                while (pFromFeat != null)

                {

                    pGeom = pFromFeat.ShapeCopy;

                    if (pGeom.IsEmpty == false)

                    {

                        pGeom.Project(pSpRef);

                     

                        pFromFeat.Shape = pGeom;

                        pFromFeat.Store();

                    }

                    Marshal.ReleaseComObject(pFromFeat);

                    pFromFeat = pFromFCur.NextFeature();

                    if (bProgress == true)

                    {

                        pProgress.Value = iCount;

                        iCount += 1;

                    }

                }

                return sError;

            }

            catch (Exception ex)

            {

                System.Diagnostics.StackTrace pStack = new System.Diagnostics.StackTrace(ex, true);

                System.Diagnostics.StackFrame pFrame = pStack.GetFrame(pStack.FrameCount - 1);

                int iLineNo = pFrame.GetFileLineNumber();

                sError = "Error: reProject; Line: " + iLineNo + " \r\n" + ex.Message;

                return sError;

            }

            finally

            {

                if (pFromFeat != null) Marshal.ReleaseComObject(pFromFeat);

                if (pFromFCur != null) Marshal.ReleaseComObject(pFromFCur);

                if (pFromFC != null) Marshal.ReleaseComObject(pFromFC);

                if (pFromWSFactory != null) pFromWSFactory = null;

                if (pFromWS != null) pFromWS = null;

                if (pFromFWS != null) pFromFWS = null;

                if (pSpRefFact != null) pSpRefFact = null;

                if (bProgress == true) pProgress.Visible = false;

            }

        }

Thanks,

John

0 Kudos
1 Solution

Accepted Solutions
JohnMcGlynn
Occasional Contributor

I think the problem is due to the fact that the spatial reference is stored in the shape field. When constructing a featureclass an IGeometryDef object is set with the Spatial Reference.

If you change the spatial reference of an instance of a geometry, ArcGIS refuses to store it because the new and the existing spatial refs don't match. You can change the coordinates to be the same as the reprojected geometry but the spatial reference cannot change. It also means looping through all the vertices of each geometry to change them.

To change the spatial reference of a featureclass would require removing the shape field and replacing it with one having the new spatial reference. By doing this you lose the original geometry.

It looks like the only way of doing a reproject is to create a new featureclass with the new spatial reference and then copy the old one to it with the geometry reprojected using the IGeometry.Project method.

View solution in original post

0 Kudos
6 Replies
DanPatterson_Retired
MVP Esteemed Contributor

how and where are you assessing differences?  If you are adding the results in ArcMap to a dataframe that contains the source file, it gets reprojected on-the-fly back.  If you want to visually see any difference, you need to add it to a new data frame.  Or are you comparing other values such coordinate values

0 Kudos
JohnMcGlynn
Occasional Contributor

The application is standalone. It takes the featureclass from a file geodatabase. When I look at the resulting featureclass in ArcCatalog it's source tab says Lambert, not GDA94.

0 Kudos
DanPatterson_Retired
MVP Esteemed Contributor

Ahhh that might explain why I don't see any specific spatial reference object You might try using a WKID for the SR that you need and code a check to ensure that it indeed does differ from that of the file you are trying to project.

0 Kudos
JohnMcGlynn
Occasional Contributor

Thanks for your help Dan,

The FeatureClass I am trying to reproject does indeed differ from the projection result.

The WKID is contained in the projection file (sToProjectionFile) read by the function:

GEOGCS["GCS_GDA_1994",DATUM["D_GDA_1994",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433],AUTHORITY["EPSG",4283]]

The Lambert coordinates (in metres) are of the order of 9,000,000 4,000,000. The GDA94 coordinates should be lat-long. Viewing the output featureclass in ArcCatalog shows that they are still Lambert coordinates.

The input and output featureclasses have the same datum (D_GDA_1994) so no transformation should be necessary. Despite that I tried using IGeometry2 to do the projection with a Null transformation but I got the same result.

0 Kudos
JohnMcGlynn
Occasional Contributor

I think the problem is due to the fact that the spatial reference is stored in the shape field. When constructing a featureclass an IGeometryDef object is set with the Spatial Reference.

If you change the spatial reference of an instance of a geometry, ArcGIS refuses to store it because the new and the existing spatial refs don't match. You can change the coordinates to be the same as the reprojected geometry but the spatial reference cannot change. It also means looping through all the vertices of each geometry to change them.

To change the spatial reference of a featureclass would require removing the shape field and replacing it with one having the new spatial reference. By doing this you lose the original geometry.

It looks like the only way of doing a reproject is to create a new featureclass with the new spatial reference and then copy the old one to it with the geometry reprojected using the IGeometry.Project method.

View solution in original post

0 Kudos
DanPatterson_Retired
MVP Esteemed Contributor

You should mark your answer as the accepted answer John, so that others will know that you have resolution on the issue

0 Kudos