지오데이터베이스(GeoDatabase - personal geodatabase, file geodatabase, ArcSDE)에서 9.2 버전부터 high-precision spatial reference를 default로 사용한다.
9.2 이전 버전의 low-precision spatial reference를 사용하는 지오데이터베이스 피쳐클래스의 spatial reference 정보를 이용하여 high-precision 지오데이터베이스에 FeaureClass를 생성하는 경우에 다음과 같은 오류가 발생하는 경우가 있다.
<Cannot create a low precision dataset in a high precision database> 또는<The XY domain on the spatial reference is not set or invalid>
다음은 이 오류를 해결하는 방법을 설명하며, 전체 코드는 마지막 ④ 해결을 위한 전체 코드를 참고하면 된다.
① 현재 접속한 Workspace가 High-Precision Workspace인지를 판별하는 방법다음 코드는 현재 접속한 Workspace가 high-precision을 사용하는 workspace인지를 판별하는 코드이다.
[code c#]
private bool IsHighPrecisionWorkspace(IWorkspace Workspace)
{
bool isHighPrecision = false;
if (Workspace is IWorkspaceProperties)
{
IWorkspaceProperties ipWsProps = (IWorkspaceProperties)Workspace;
IWorkspaceProperty ipProp = ipWsProps.get_Property(
esriWorkspacePropertyGroupType.esriWorkspacePropertyGroup,
(int)esriWorkspacePropertyType.esriWorkspacePropSupportsHighPrecisionStorage);
if (ipProp.IsSupported)
{
isHighPrecision = Convert.ToBoolean(ipProp.PropertyValue);
}
}
return isHighPrecision;
}
[/code]
② How to construct a high- or low-precision spatial reference
출처 : http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/0682A7EC-2C4D-4e93-B664-957A1AE7185A.htm
다음 코드는 high-precision spatial reference와 low-precision spatial reference를 생성하며, 각 precision에 맞는 default resolution and default
tolerance를 설정하는 코드이다.
펼쳐두기..
[code c#]
private void ConstructCoordinateSystem(bool highPrecision)
{
ISpatialReferenceFactory3 spatialReferenceFactory = new
SpatialReferenceEnvironmentClass();
ISpatialReference3 spatialReference =
spatialReferenceFactory.CreateESRISpatialReferenceFromPRJFile(
"C:\\Program Files\\ArcGIS\\Coordinate Systems\\Geographic Coordinate Systems\\World\\WGS 1984.prj")as ISpatialReference3;
IControlPrecision2 controlPrecision = spatialReference as IControlPrecision2;
//Determines whether you are constructing a high- or low-precision spatial reference.
controlPrecision.IsHighPrecision = highPrecision;
ISpatialReferenceResolution spatialReferenceResolution = spatialReference as
ISpatialReferenceResolution;
//These three methods are the keys; construct horizon, then set the default x,y resolution and tolerance.
spatialReferenceResolution.ConstructFromHorizon();
//Set the default x,y resolution value.
spatialReferenceResolution.SetDefaultXYResolution();
//Set the default x,y tolerance value.
ISpatialReferenceTolerance spatialReferenceTolerance = spatialReference as
ISpatialReferenceTolerance;
spatialReferenceTolerance.SetDefaultXYTolerance();
double xMin;
double xMax;
double yMin;
double yMax;
spatialReference.GetDomain(out xMin, out xMax, out yMin, out yMax);
System.Windows.Forms.MessageBox.Show("Domain : " + xMin + ", " + xMax + ", "
+ yMin + ", " + yMax);
}
[/code]
③ How to convert between high and low precision spatial references
출처 : http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/A98B72CF-A833-4dc8-A4D3-48F5044210FF.htm
이 문서 및 샘플 코드는 low-precision spatial reference
(pre-9.2)를 high-precision spatial reference로 변환하는 예이다.
펼쳐두기..
[code c#]
private void LowHighConversion_Example(IFeatureClass pre92FeatureClass)
{
IGeoDataset pre92GeoDataset = pre92FeatureClass as IGeoDataset;
ISpatialReference pre92SpatialReference = pre92GeoDataset.SpatialReference;
double falseX;
double falseY;
double xyUnits;
pre92SpatialReference.GetFalseOriginAndUnits(out falseX, out falseY, out
xyUnits);
System.Windows.Forms.MessageBox.Show(
"Low precision coordinate grid definition:\n" + "false x: " + falseX +
", false y: " + falseY + ", scale factor: " + xyUnits);
ISpatialReferenceFactory3 spatialReferenceFactory = new
SpatialReferenceEnvironmentClass();
ISpatialReference spatialReference92 =
spatialReferenceFactory.ConstructHighPrecisionSpatialReference
(pre92SpatialReference, - 1, - 1, - 1);
spatialReference92.GetFalseOriginAndUnits(out falseX, out falseY, out xyUnits)
;
System.Windows.Forms.MessageBox.Show(
"high precision coordinate grid definition:\n" + "false x: " + falseX +
", false y: " + falseY + ", scale factor: " + xyUnits);
}
[/code]
④ 오류 해결을 위한 전체 코드다음 코드는 low-precision spatial reference를 사용하는 FeatureClass와 동일한 필드 및 spatial reference를 사용하는 FeatureClass를 high-precision Workspace에 생성하는 코드이다.
IsHighPrecision, ConstructFromHorizon, SetDefaultXYResolution, SetDefaultXYTolerance가 이 코드의 핵심이다.
펼쳐두기..
[code c#]
private void CreateFeatureClass_Sample()
{
IWorkspace pre92Workspace, highPrecisionWs;
IFeatureClass pre92Fc, highPrecisionFc;
pre92Workspace = OpenPre92AccessWorkspace();
pre92Fc = OpenPre92FeatureClass(pre92Workspace, "클래스명");
highPrecisionWs = OpenHighPrecisionWorkspace();
IFeatureWorkspace highPrecisionFWs = (IFeatureWorkspace)highPrecisionWs;
//0. clone fields
IFields newFields = (IFields)((IClone)pre92Fc.Fields).Clone();
//1. low-precision spatialreference를 그대로 사용하면 오류 발생
//highPrecisionFc =
highPrecisionFWs.CreateFeatureClass("HIGH_PRE_FC", newFields, null,
null, esriFeatureType.esriFTSimple, pre92Fc.ShapeFieldName,
string.Empty);
//2. High-precision으로 전환 후 필드에 적용
//check high-precision workspace
bool isHighPrecisionWorkspace = this.IsHighPrecisionWorkspace(highPrecisionWs);
//get geometry field
IField geometryField = null;
for (int k = 0; k < newFields.FieldCount; k++)
{
if (newFields.get_Field(k).Type == esriFieldType.esriFieldTypeGeometry)
{
geometryField = newFields.get_Field(k);
break;
}
}
//modify spatialreference
IGeometryDefEdit geomDefEdit = (IGeometryDefEdit)geometryField.GeometryDef;
ISpatialReference pre92Sr = geomDefEdit.SpatialReference;
IControlPrecision2 controlPrecision = (IControlPrecision2)pre92Sr;
if (isHighPrecisionWorkspace && !controlPrecision.IsHighPrecision)
{
controlPrecision.IsHighPrecision = isHighPrecisionWorkspace;
}
//construct horizon, then set the default x,y resolution and tolerance.
ISpatialReferenceResolution srResolution = (ISpatialReferenceResolution)pre92Sr;
ISpatialReferenceTolerance srTolerance = (ISpatialReferenceTolerance)pre92Sr;
srResolution.ConstructFromHorizon();
srResolution.SetDefaultXYResolution();
srTolerance.SetDefaultXYTolerance();
//check z, m
if (geomDefEdit.HasZ || geomDefEdit.HasM)
{
srResolution.SetDefaultZResolution();
srResolution.SetDefaultMResolution();
srTolerance.SetDefaultZTolerance();
srTolerance.SetMinimumMTolerance();
}
//3. create featureclass
highPrecisionFc = highPrecisionFWs.CreateFeatureClass("HIGH_PRE_FC",
newFields, null, null, esriFeatureType.esriFTSimple,
pre92Fc.ShapeFieldName, string.Empty);
System.Diagnostics.Debug.WriteLine("OK");
}
private bool IsHighPrecisionWorkspace(IWorkspace Workspace)
{
bool isHighPrecision = false;
if (Workspace is IWorkspaceProperties)
{
IWorkspaceProperties ipWsProps = (IWorkspaceProperties)Workspace;
IWorkspaceProperty ipProp = ipWsProps.get_Property(
esriWorkspacePropertyGroupType.esriWorkspacePropertyGroup,
(int)esriWorkspacePropertyType.esriWorkspacePropSupportsHighPrecisionStorage);
if (ipProp.IsSupported)
{
isHighPrecision = Convert.ToBoolean(ipProp.PropertyValue);
}
}
return isHighPrecision;
}
[/code]
댓글 없음:
댓글 쓰기