1. 程式人生 > >ArcGis Engine 要素折點轉點的程式碼實現

ArcGis Engine 要素折點轉點的程式碼實現

ArcGIS中的GP工具要素折點轉點使用起來十分方便,速度也十分快,但是也存在一些問題,比如要求最高許可權,轉點時會對一些過近的點進行合併(待深入考察)。

程式碼如下:

 /// <summary>
        /// 要素節點轉點
        /// </summary>
        /// <param name="IN_Featureclass">要轉換的要素類</param>
        /// <param name="IN_FeatureDataset">要生成轉換後要素類的要素資料集</param>
        /// <returns>生成的點要素類</returns>
        private IFeatureClass PRV_FeatureVerticesToPoints(IFeatureClass IN_Featureclass, IFeatureDataset IN_FeatureDataset)
        {
            //建立要素類
            IFeatureClass Temp_VPFeatureClass = IN_FeatureDataset.CreateFeatureClass(IN_Featureclass.AliasName + "折點轉點", PRV_SetFields(IN_Featureclass), null, null, esriFeatureType.esriFTSimple, "Shape", "");
            //提取所有要素
            IFeatureCursor Temp_GetEachFeature = IN_Featureclass.Search(null, false);
            IFeature Temp_EachFeature = Temp_GetEachFeature.NextFeature();
            if (Temp_EachFeature != null)
            {
                //一般來需要新增下方的開啟工作空間編輯的命令,但是實際使用時卻發現會造成記憶體洩漏問題。
                //IWorkspaceEdit Temp_WorkspaceEdit = (IWorkspaceEdit)IN_FeatureDataset.Workspace;
                //Temp_WorkspaceEdit.StartEditing(true);
                //Temp_WorkspaceEdit.StartEditOperation();
                IFeatureBuffer Temp_FeatureBuffer = Temp_VPFeatureClass.CreateFeatureBuffer();
                IFeatureCursor Temp_FeatureCursor = Temp_VPFeatureClass.Insert(true);
                //儘量不在迴圈中建立變數
                IPointCollection Temp_Vertices;
                IPoint Each_Point = new PointClass();
                int i;
                //將點存入要素類
                while (Temp_EachFeature != null)
                {
                    //獲取要素的點集
                    Temp_Vertices = Temp_EachFeature.Shape as IPointCollection;
                    for (i= 0; i < Temp_Vertices.PointCount - 1; i++)
                    {
                        Temp_Vertices.QueryPoint(i,Each_Point);
                        //據說get_Point(i)方法回比QueryPoint(i,Each_Point)方法速度慢,但是實際使用沒感覺出來
                        //Each_Point = Temp_Vertices.get_Point(i);
                        Temp_FeatureBuffer.Shape = Each_Point;
                        Temp_FeatureCursor.InsertFeature(Temp_FeatureBuffer);
                    } Temp_EachFeature = Temp_GetEachFeature.NextFeature();
                }
                Temp_FeatureCursor.Flush();
                //清理資源並返回
                System.Runtime.InteropServices.Marshal.FinalReleaseComObject(Temp_GetEachFeature);
            }
            return Temp_VPFeatureClass;
        }

    private IFields PRV_SetFields(IFeatureClass IN_Featureclass)//設欄位的函式
        {
            //建立必要欄位
            IFeatureClassDescription Temp_FeatureClassDescription = new FeatureClassDescriptionClass();
            IObjectClassDescription Temp_ObjectClassDescription = (IObjectClassDescription)Temp_FeatureClassDescription;
            IFields Temp_Fields = Temp_ObjectClassDescription.RequiredFields;
            int Temp_ShapeFieldIndex = Temp_Fields.FindField(Temp_FeatureClassDescription.ShapeFieldName);
            IField Temp_RequiredField = Temp_Fields.get_Field(Temp_ShapeFieldIndex);
            //設定幾合欄位
            IGeometryDef Temp_GeometryDef = Temp_RequiredField.GeometryDef;
            IGeometryDefEdit Temp_GeometryDefEdit = (IGeometryDefEdit)Temp_GeometryDef;
            Temp_GeometryDefEdit.GeometryType_2 = esriGeometryType.esriGeometryPoint;
            ISpatialReferenceFactory Temp_SpatialRefFac = new SpatialReferenceEnvironmentClass();
            //以備用點為模板構建空間參考
            Temp_GeometryDefEdit.SpatialReference_2 = (IN_Featureclass as IGeoDataset).SpatialReference;
            //驗證欄位
            IFieldChecker Temp_FieldChecker = new FieldCheckerClass();
            IEnumFieldError Temp_FieldsError = null;
            IFields Temp_AllRightFields = null;//驗證無誤的欄位集
            Temp_FieldChecker.ValidateWorkspace = (IWorkspace)IN_Featureclass.FeatureDataset.Workspace;
            Temp_FieldChecker.Validate(Temp_Fields, out Temp_FieldsError, out Temp_AllRightFields);
            //本例新增"OriginClassOID"欄位
            IFieldsEdit Temp_FiledsEditor = Temp_AllRightFields as IFieldsEdit;
            IField Temp_OriginOIDFields = new FieldClass();
            IFieldEdit2 Temp_FiledEditor = Temp_OriginOIDFields as IFieldEdit2;
            Temp_FiledEditor.Type_2 = esriFieldType.esriFieldTypeInteger;
            Temp_FiledEditor.Name_2 = "OriginClassOID";
            Temp_FiledsEditor.AddField(Temp_OriginOIDFields);
            return Temp_AllRightFields;
        }

經過驗證,處理30000個地塊的時間需要192秒(i5-6400,8G)。

在插入feature時,如果開啟了工作空間編輯(IWorkSpaceEdit.StartEditing),因為要滿足對每次操作可以撤銷,工作空間並不會自動釋放儲存的改變資訊。隨著insert的要素越來越多而不store,記憶體就洩露了,因此會報錯。