GIS

(ArcObject-C#) SDE 에서 Shapefile 로 만들때 - 특정 피쳐로 클립하여 컨버전(라이센스: Arc Engine)

조심이 2009. 10. 1. 11:45
반응형

SDE 데이터를 shpefile로 컨버전할때 특정 피쳐클래스를 기준으로 클립하여 shapefile로 컨버전.
엔진 라이센스라 Clip(info 에서 사용가능) 를 사용할 수 없으므로 토폴로지의 Envelope으로 짤라서 shapefile 을 생성한다.

예를 들어 SDE에 한국 지형, 시설물, 등등등..에대한 공간 정보가 있을때 서울시를 기준으로 하여 shapefile을 만들려고 한다.
서울시 피쳐클래스를 기준으로 짤라내어 shapefile을 만든다.

Convert API를 이용하지 않고 SDE에 공간 데이터를 커서로 읽어 shapefile 에 직접 넣는 방법이다.

- SDE, Shpefile 워크스페이스를 생성한다.

 /// <summary>
        /// SDE 워크스페이스 오픈
        /// </summary>
        /// <returns></returns>

        public IWorkspace openSDEWorkspace(String sServer, String sInstance, String sUser, String sPswd)
        {
            //IWorkspace pWS = null;
            try
            {
                IPropertySet pPropSet;

                pPropSet = new ESRI.ArcGIS.esriSystem.PropertySetClass();

                pPropSet.SetProperty("SERVER",   sServer.ToString());
                pPropSet.SetProperty("INSTANCE", sInstance.ToString());
                pPropSet.SetProperty("USER",     sUser.ToString());
                pPropSet.SetProperty("PASSWORD", sPswd.ToString());
                pPropSet.SetProperty("DATABASE", "");

                pPropSet.SetProperty("VERSION", "SDE.DEFAULT");

                IWorkspaceFactory2 workspaceFactory;
                workspaceFactory = (ESRI.ArcGIS.Geodatabase.IWorkspaceFactory2)new SdeWorkspaceFactoryClass();
               
                return workspaceFactory.Open(pPropSet, 0);
            }
            catch (Exception e)
            {
                MessageBox.Show("SDE에 연결할수 없습니다.\n 서버에 SDE서비스가 시작되어 있는지 확인하시기 바랍니다.");
                return null;
            }
        }


// <summary>
        /// SHAPE Workspace를 반환한다.
        /// </summary>
        /// <param name="sOutputPath"></param>
        /// <returns></returns>

        public IWorkspace OpenShpWorkspace(String sOutputPath)
        {
            try
            {
                IWorkspaceFactory pFact;
                IWorkspace pWorkspace;

                pFact = new ShapefileWorkspaceFactory();
                pWorkspace = pFact.OpenFromFile(sOutputPath, 0);

                return pWorkspace; ;
            }
            catch (Exception e)
            {
                MessageBox.Show("SHAPE FILE에 연결할 수 없습니다");
                return null;
            }

        }

-- 이제 SDE의 데이터를 Shapefile로 ...

    //내릴때 커서
        private IFeatureCursor copySourceCursor;
        private IFeatureCursor insertFeatureCursor;
        private IFeatureCursor pSearchFeatureCursor1;
        private IFeatureCursor featureCursor;



/// <summary>
        /// clip 해서 shapefile로 내리기
        /// sourceWorkspace : sde 워크스페이스
        /// targetworkspace : 쉐입(shapefile 워크스페이스)
        /// TargetName : 만들 쉐입파일
        /// SourceName ; SDE 피쳐클래스명
        /// clipFeatureNm : 짜르려고 하는 피쳐
        /// </summary>
        /// <returns></returns>
        //shape 파일로 내리기

        public bool FeatureClipToShapfile(IWorkspace sourceWorkspace, IWorkspace targetWorkspace, string TargetName, string SourceName, string clipFeatureNm)
        {
            bool result = true;
            try
            {
            
    
             IFeatureClass sourceFeatureClass = null;
             IFeatureClass targetFeatureClass = null;
             IFeatureClass clipFeatureClass   = null;


                 //원본 피쳐 클래스(SDE)
             IFeatureWorkspace sorceFW = sourceWorkspace as IFeatureWorkspace;
             sourceFeatureClass = sorceFW.OpenFeatureClass(SourceName);

                 //클립 피쳐 클래스(SDE 에 있는 짜르려고 하는 피쳐클래스-예:서울시)
             clipFeatureClass = sorceFW.OpenFeatureClass(clipFeatureNm);

          
        
             //쿼리필터로 피쳐구하기
             IQueryFilter pQueryFilter = new QueryFilter();
             pQueryFilter.WhereClause = "지역='서울시'";//쿼리필터: 지역 레이어에서 서울시만 골라내기 ..

            
             pSearchFeatureCursor1 = clipFeatureClass.Search(pQueryFilter, true);
             IFeature pFeature = pSearchFeatureCursor1.NextFeature();  //서울시경계피         
    /************************
             나중에..  여러개 피쳐가 피쳐클래스로 경계를 이룰 경우 여러개의 피쳐를 토폴로지 UNION하여 하나의 피쳐로 만들어 놓고 작업....
             ***********************/
             // define a spatial query filter
           

             //공간쿼리..
             SpatialFilter spatialFilter = new SpatialFilter();
         
             // 필드 제거전에 피쳐커서 만듦
            // IFeatureCursor interface provides access to a set of features in a feature class
            // get a cursor based on the spatial query

             featureCursor = sourceFeatureClass.Search(spatialFilter, true);

        

            //필드 제거전에 피쳐커서에 일단 담아서 쓰자
            IQueryFilter sQueryFilter = new QueryFilter();
             copySourceCursor = sourceFeatureClass.Search(sQueryFilter, true);
 
            /*
            //쉐입파일에 맞지 않는 필드제거
             * 필드를 제거하는 순간 전체 카운트도 달라 지므로 전체를 돌릴 필드와 실제 삭제되는 필드들을 분리
            IFeatureBuffer copySource = sourceFeatureClass.CreateFeatureBuffer();
             */

            IFields copyFields = copySourceCursor.Fields;
            IFieldsEdit eFieldEdit = copyFields as IFieldsEdit;
           
            IField field;
         
            for (int i = 0; i <  copySourceCursor.Fields.FieldCount; i++)
            {
           
                 field = copyFields.get_Field(i);
                 if (field.Type == ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeGlobalID && field.Type == ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeGeometry && field.Type == ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeOID && !field.Editable)
                 {
                     eFieldEdit.DeleteField(field);
                     if (i > 1)
                     { //필드 삭제 하는 순간 전체 카운트가 줄어듬
                         --i;
                     }
                  
                 }
                 if (field.Name.ToString().Trim().Equals("SHAPE.LEN"))
                 {
                     eFieldEdit.DeleteField(field);
                     if (i > 1)
                     {
                         --i;
                     }
                    
                 }
                 if (field.Name.ToString().Trim().Equals("SHAPE.AREA"))
                 {
                     eFieldEdit.DeleteField(field);
                     if (i > 1)
                     {
                         --i;
                     }
                 }
             }
    
            //쉐입 피쳐클래스 만들기
            IFeatureWorkspace targetFW = targetWorkspace as IFeatureWorkspace;
            targetFeatureClass = targetFW.CreateFeatureClass(TargetName, copyFields, sourceFeatureClass.CLSID, sourceFeatureClass.EXTCLSID, sourceFeatureClass.FeatureType, sourceFeatureClass.ShapeFieldName, "");

           
            // Loop through all the features and copy them over to the target shapefile.
            // We need to cast each feature to an ITopologicalOperator, since
            // this is where the clip method is, unfortunately.
          
            ITopologicalOperator geom;
            IFeatureBuffer FeaturBuffer;
            int valueIndex;

            IFeature feature = featureCursor.NextFeature();

         
                insertFeatureCursor = targetFeatureClass.Insert(true);
                FeaturBuffer = targetFeatureClass.CreateFeatureBuffer();
            

//짜르려고 하는 피쳐클래스의 토폴로지 envelope으로 짜름
                if (feature != null)
             {

                IFields flds = feature.Fields;
                int fieldCount = feature.Fields.FieldCount;

                IRowBuffer pRowBuffer;
                IFields pNewFields;

                int NewFieldIndex;

                //Copy the attributes of the orig feature the new feature
                pRowBuffer = FeaturBuffer;
                pNewFields = pRowBuffer.Fields;

                while (feature != null)
                {

                    IGeometry outgeom;

                    // get the shape and source to clip it
                    geom = feature.ShapeCopy as ITopologicalOperator;
                    geom.Clip(pFeature.Shape.Envelope);
                    geom.Buffer(0);

                    outgeom = geom as IGeometry;
                    FeaturBuffer.Shape = outgeom;

                    for (int i = 0; i < fieldCount; i++)
                    {

                        IField pField = flds.get_Field(i);

                        if (pField.Type != ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeGlobalID && pField.Type != ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeGeometry && pField.Type != ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeOID && pField.Editable)
                        {

                            if (!pField.Name.StartsWith("OBJECTID") && !pField.Name.StartsWith("SHAPE_LEN") && !pField.Name.Equals("SHAPE_AREA") && !pField.Name.Equals("SHAPE.LEN") && !pField.Name.Equals("SHAPE.AREA"))
                            {

                                valueIndex = flds.FindField(pField.Name);
                                NewFieldIndex = pNewFields.FindField(pField.Name);

                                if (NewFieldIndex != -1)
                                {
                            FeaturBuffer.set_Value(FeaturBuffer.Fields.FindField(pField.Name), (feature.get_Value(valueIndex)));
                                    
                                }
                            }
                        }
                    }

 

                    //피처커서에 인서트
                    insertFeatureCursor.InsertFeature(FeaturBuffer);

                    feature = featureCursor.NextFeature();

                }

 

                //커서 넣기
                try
                {
                    insertFeatureCursor.Flush();
                    //트랜젝션 커밋


                }
                catch (COMException comExc)
                {
             
                    result = false;
                }
                finally
                {

                    //커서해제
                    if (insertFeatureCursor != null)
                        System.Runtime.InteropServices.Marshal.ReleaseComObject(insertFeatureCursor);

                    if (pSearchFeatureCursor1 != null)
                        System.Runtime.InteropServices.Marshal.ReleaseComObject(pSearchFeatureCursor1);

                    if (copySourceCursor != null)
                        System.Runtime.InteropServices.Marshal.ReleaseComObject(copySourceCursor);

                    if (featureCursor != null)
                        System.Runtime.InteropServices.Marshal.ReleaseComObject(featureCursor);


                }
            }

        }
        catch (Exception ex)
        {   //커서해제
            if(insertFeatureCursor!=null)
            System.Runtime.InteropServices.Marshal.ReleaseComObject(insertFeatureCursor);
           
            if(pSearchFeatureCursor1!=null)
            System.Runtime.InteropServices.Marshal.ReleaseComObject(pSearchFeatureCursor1);
           
            if(copySourceCursor!=null)
            System.Runtime.InteropServices.Marshal.ReleaseComObject(copySourceCursor);
           
            if(featureCursor!=null)
            System.Runtime.InteropServices.Marshal.ReleaseComObject(featureCursor);


            result = false;
            return result;
         
        }
        finally
        {

            //커서해제
            if (insertFeatureCursor != null)
                System.Runtime.InteropServices.Marshal.ReleaseComObject(insertFeatureCursor);

            if (pSearchFeatureCursor1 != null)
                System.Runtime.InteropServices.Marshal.ReleaseComObject(pSearchFeatureCursor1);

            if (copySourceCursor != null)
                System.Runtime.InteropServices.Marshal.ReleaseComObject(copySourceCursor);

            if (featureCursor != null)
                System.Runtime.InteropServices.Marshal.ReleaseComObject(featureCursor);


        }

            return result;


        }

       

반응형