2010년 2월 22일 월요일

[ArcObjects]여러 Geometry를 하나로 합치기(Union)

Geometry 연산 중에서 여러 Geometry를 하나의 Geometry로 합치는 과정을 일반적으로 Union이라 부른다. Union은 다음 그림과 같이 서울시의 모든 시군구 폴리곤을 하나로 합쳐 서울시경계 폴리곤을 생성하기 위해 사용될 수 있다.

이 문서는 ITopologicalOperator 인터페이스를 활용하여 Geometry를 Union하는 예를 샘플코드와 함께 제공한다.

▣ ITopologicalOperator 사용시 주의사항
High-level Geometry(point, multipoint, polyline, polygon)에만 적용할 것
Union 대상 Geometry의 SpatialReference는 동일할 것

▣ 기본 사용법
 - 두 Geometry를 Union하는 방법
[code c#]
IGeometry geometryA = GetGeometryA();
IGeometry geometryB = GetGeometryB();

ITopologicalOperator2 topoOpt = (ITopologicalOperator2)geometryA;

IGeometry unionGeometry = topoOpt .Union(geometryB);
[/code]
▣ ITopologicalOperator의 Union Method를 반복적으로 사용
 - FeatureClass에서 검색된 Feature의 모든 Shape을 하나의 Geometry로 Union하며 Union 메쏘드를 반복적으로 수행하는 예이다. 피쳐 수가 많아지면 처리속도가 느려진다.
[code c#]
private IGeometry UnionGeometry(IFeatureClass featureClass, IQueryFilter queryFilter)
{
    ITopologicalOperator2 unionTopoOpt = null;
    esriGeometryType geometryType = featureClass.ShapeType;
   
    switch (geometryType)
    {
        case esriGeometryType.esriGeometryPoint:
            unionTopoOpt = new MultipointClass();
            break;
        case esriGeometryType.esriGeometryPolyline:
            unionTopoOpt = new PolylineClass();
            break;
        case esriGeometryType.esriGeometryPolygon:
            unionTopoOpt = new PolygonClass();
            break;
    }
   
    //Union
    IFeatureCursor featureCursor = featureClass.Search(queryFilter, true);
    IFeature feature = featureCursor.NextFeature();
    while (feature != null)
    {
        IGeometry sourceGeometry = feature.ShapeCopy;
   
        if (! sourceGeometry.IsEmpty)
        {
            unionTopoOpt = (ITopologicalOperator2)unionTopoOpt.Union(sourceGeometry);
        }
   
        feature = featureCursor.NextFeature();
    }
    System.Runtime.InteropServices.Marshal.ReleaseComObject(featureCursor);
   
    //Simplify
    unionTopoOpt.IsKnownSimple_2 = false;
    unionTopoOpt.Simplify();
   
    return (IGeometry)unionTopoOpt;
}
[/code]
▣ ITopologicalOperator의 ConstructUnion Method를 사용
 - FeatureClass에서 검색된 Feature의 모든 Shape을 하나의 Geometry로 Union하며 Union 메쏘드를 반복적으로 수행하는 예이다. Union 메쏘드를 개별적으로 호출하는 것보다 빠르다.
[code c#]
private static IGeometry ConstructUnionGeometry1(IFeatureClass featureClass, IQueryFilter queryFilter)
{
    IEnumGeometryBind geometryBind = new EnumFeatureGeometryClass();
    geometryBind.BindGeometrySource(queryFilter, featureClass);

    IGeometryFactory geometryFactory = new GeometryEnvironmentClass();
    IGeometryBag geometryBag = (IGeometryBag)geometryFactory.CreateGeometryFromEnumerator((IEnumGeometry)geometryBind);

    ITopologicalOperator2 unionTopoOpt = null;
    esriGeometryType geometryType = featureClass.ShapeType;

    switch (geometryType)
    {
        case esriGeometryType.esriGeometryPoint:
            unionTopoOpt = new MultipointClass();
            break;
        case esriGeometryType.esriGeometryPolyline:
            unionTopoOpt = new PolylineClass();
            break;
        case esriGeometryType.esriGeometryPolygon:
            unionTopoOpt = new PolygonClass();
            break;
    }

    unionTopoOpt.ConstructUnion((IEnumGeometry)geometryBag);

    return (IGeometry)unionTopoOpt;
}
[/code]
▣ ITopologicalOperator의 ConstructUnion Method를 사용
 - FeatureClass에서 검색된 Feature의 모든 Shape을 하나의 Geometry로 Union하며 Union 메쏘드를 반복적으로 수행하는 예이다. Union 메쏘드를 개별적으로 호출하는 것보다 빠르다.
[code c#]
private static IGeometry ConstructUnionGeometry2(IFeatureClass featureClass, IQueryFilter queryFilter)
{
    IGeometry geometryBag = new GeometryBagClass();
    geometryBag.SpatialReference = ((IGeoDataset)featureClass).SpatialReference;

    IGeometryCollection geometryCollection = (IGeometryCollection)geometryBag;

    object missingObj = Type.Missing;

    IFeatureCursor featureCursor = featureClass.Search(queryFilter, true);
    IFeature feature = featureCursor.NextFeature();
    while (feature != null)
    {
        geometryCollection.AddGeometry(feature.ShapeCopy, ref missingObj, ref missingObj);

        feature = featureCursor.NextFeature();
    }
    System.Runtime.InteropServices.Marshal.ReleaseComObject(featureCursor);
   
    ITopologicalOperator2 unionTopoOpt = null;
    esriGeometryType geometryType = featureClass.ShapeType;

    switch (geometryType)
    {
        case esriGeometryType.esriGeometryPoint:
            unionTopoOpt = new MultipointClass();
            break;
        case esriGeometryType.esriGeometryPolyline:
            unionTopoOpt = new PolylineClass();
            break;
        case esriGeometryType.esriGeometryPolygon:
            unionTopoOpt = new PolygonClass();
            break;
    }

    unionTopoOpt.ConstructUnion((IEnumGeometry)geometryBag);

    return (IGeometry)unionTopoOpt;
}
[/code]