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
Solved! Go to Solution.
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.
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
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.
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.
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.
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.
You should mark your answer as the accepted answer John, so that others will know that you have resolution on the issue