ArcGIS修复几何错误

      几何错误常存在于shapefile以及存储在个人地理数据库或文件地理数据库的要素类,而当数据不满足ArcGIS的规范时,就会遇到各种无响应和奔溃。
     几何错误通常有:(查看原帮助文档
     1、短线段-有些线段短于与几何关联的控件参考的系统单位所允许的长度。
     2、空几何 - 该要素不具有几何或则SHAPE字段为空
     3、不正确的环走向-面的拓扑结构比较简单,但是面的环可能没有正确地定向(外环-顺时针,内环-逆时针)。
     4、不正确的线段走向-各条线段的定向不一致。线段i的“末”点应该与线段i+1的“始”点相接。
     5、自相交-面无法与自身相交
     6、非闭合环-环中最后一条线段的“末”点必须与第一条线段的“始”点相接。
     7、空的部分-几何具有多个部分,其中一个部分为空(没有几何)。
     8、重复折点-几何的两个或多个折点坐标相同
     9、不匹配的属性-某线段端点的Z坐标或M坐标与下一条线段中与之重合的端点的Z坐标或M坐标不匹配。
     10、不连续部分-几何的某部分由断开的或不连续的部分组成。
     11、空的Z值-几何的一个或多个折点Z值为空(例如,NaN)

     对与点要素,只会存在空几何问题。

检查几何错误:

     上述提到的几何错误都能使用ArcGIS自带的工具查找出来。位于“Data Management Tools ——要素——检查几何”。检查后要素的几何错误会以表的形式输出。那么几何错误检查出来了,下面就是如何修复几何。

修复几何错误:

执行ArcGIS工具“修复几何”就可以。

    位于“Data Management Tools ——要素——修复几何”。

执行Python脚本

# -*-coding:utf-8-*-
import arcpy
from arcpy import env
import time

# 实现功能:修复几何

try:
    source_path = "F:/GIS测试数据/测试.gdb"
    in_features = "NXF"
    start_time = time.time()

    env.workspace = source_path
    arcpy.RepairGeometry_management(in_features, "DELETE_NULL")
    arcpy.AddMessage("RepairGeometry Time:{0}s".format(time.time() - start_time))

except Exception, e:
    print e.message

AE实现,主要使用ITopologicalOperator2、IPolygon4、IPolyline5和IPolyline6接口

在执行修复几何之前要先查看 ITopologicalOperator::IsKnownSimple的值,如果为true则不进行修复。

1、ITopologicalOperator.Simplify方法:

描述
简化永久改变输入几何,使其定义在几何类型方面“拓扑合法:
   ①对于Points,Simplify什么都不做。点对其坐标值没有约束。
   ②对于Multipoints,Simplify将所有X,Y,Z和M坐标捕捉到相关空间参考的网格,然后删除相同的点。当两个点具有相同的X和Y坐标(捕捉后),并且当它知道的属性与另一个点知道的属性相同时,一个点与另一个点相同。例如,如果两个点都是Z识别的,则Z坐标值必须相同。
   ③对于折线,Simplify有两种变体:平面和非平面。默认情况下,不支持M的折线以平面方式简化:所有重叠的线段都缩小为单个线段,并且线段在交叉点处分割。为连接的段序列创建输出路径。尽可能保留输入段方向,但如有必要,将重新定向路径内部的段。M-aware的折线使用非平面简化:1、保留重叠和自交叉,但删除零长度段;2、
调整线段的走向,使线段i的“末”点应该与线段i+1的“始”点相接;3、当线段不连接时创建新的paths;4、当两个paths有共同线段时融合。
   ④对于多边形,Simplify用于多边形的内部和外部,然后修改多边形结构以与规定一致。处理内部和外部的默认方法是:1、删除所有悬挂的段序列;2、识别最大的合法环,将它们添加到多边形的输出形式,然后将其从当前形势中删除;3、重复。如果此方法最终为您的应用程序删除了太多段,请考虑使用IPolygon4 :: SimplifyEx并将XOR参数设置为TRUE。在简化结束时,没有环会重叠,不会发生自相交(除了在某些情况下),并且通常,任意点总是可以明确地分类为多边形的外部,边界或内部。

在简化折线和多边形时,会使用几何关联空间参考的XY容差。

                                                                  

2、IPolygon.SimplifyPreserveFromTo 方法:

   简化多边形并保留每个环的始末节点。
   SimplifyPreserveFromTo简化多边形的方式与ITopologicalOperator的Simplify方法一样,但是不会将环重定位。

                                             

3、IPolyline.SimplifyNetwork方法:

删除零长度段(2维中为零),合并有共享端点的部件,重新定位线段的方向。
执行Polyline的部分简化,以确保有效网络的必要一致性,但不是真正的拓扑简单性。SimplifyNetwork对基础折线执行以下更改:
   1)删除空和零长度段。
   2)删除空的部分。
   3)使段方向相互一致。确保连接段的以下FromPoints和前面的ToPoints相等。
   4)为具有不同属性的不连续段或段创建新零件。
   5)合并两个部分共享端点的部件。
   6)对于共享端点的部分中的一对段,使得一个段具有NaN属性而另一个段具有非NaN属性,将1的非NaN属性分配给另一个的相应NaN。

4、IPolyline6.SimplifyNonPlanar方法:

删除零长度段(2维中为零),重新定位线段的方向。此方法类似于SimplifyNetwork,除了共享端点的部件不合并。

修复几何要素代码:只修复一次有时修复不完全

/// <summary>
/// 修复几何错误   
/// </summary>
/// <param name="geometry">几何对象</param>
public static void SimplifyGeometry(IGeometry geometry)
{
    if (geometry is ITopologicalOperator2 topoOp)
    {
        topoOp.IsKnownSimple_2 = false;   //设为false
        if (!topoOp.IsSimple)
        {
            switch (geometry.GeometryType)
            {
                case esriGeometryType.esriGeometryMultipoint:
                    {
                        topoOp.Simplify();
                    }
                    break;
                case esriGeometryType.esriGeometryPolygon:
                    {
                        ((IPolygon4)geometry).SimplifyPreserveFromTo();
                    }
                    break;
                case esriGeometryType.esriGeometryPolyline:
                    {
                        if (geometry is IPolyline6 polyline6)
                        {
                            polyline6.SimplifyNonPlanar();
                        }
                        else
                        {
                            ((IPolyline5)geometry).SimplifyNetwork();
                        }
                    }
                    break;
            }
        }
    }
}

要素类转换:

/// <summary>
/// 将源数据集符合条件的要素迁移至目标图层
/// </summary>
/// <param name="pTargetFClass">目标库数据集</param>
/// <param name="pSourceFClass">源数据集</param>
/// <param name="spatialFilter">筛选条件</param>
public static void FClassTransfer(IFeatureClass pTargetFClass, IFeatureClass pSourceFClass, ISpatialFilter spatialFilter)
{
    Dictionary<int, int> dicTargetSource =FieldsTargetSource(pTargetFClass, pSourceFClass); //获取字段对应关系
    long pCountToFlush = 1000;
    long n = 0; //当前记录

    判断目标图层是否有Z值
    //bool bHasZValue = false;
    //int iShapeFieldIndex = tarFClass.FindField(tarFClass.ShapeFieldName);
    //if (tarFClass.Fields.Field[iShapeFieldIndex].GeometryDef.HasZ)
    //{
    //    bHasZValue = true;
    //}

    using (ComReleaser comReleaser = new ComReleaser())
    {
        IFeatureCursor tcursor = pTargetFClass.Insert(true);
        comReleaser.ManageLifetime(tcursor);
        IFeatureBuffer pTargetFeatureBuffer = pTargetFClass.CreateFeatureBuffer();
        comReleaser.ManageLifetime(pTargetFeatureBuffer);
        IFeatureCursor scursor = pSourceFClass.Search(spatialFilter, true);
        comReleaser.ManageLifetime(scursor);
        IFeature pSourcFeature = null;

        IGeometry pSoureGeometry = null;
        //IZAware pZAware = null;
        while ((pSourcFeature = scursor.NextFeature()) != null)
        {
            //判断要素是否为注记,这在加载CAD文件时很重要
            //if (pSourceFClass.FeatureType == esriFeatureType.esriFTAnnotation)
            //{
            //    ESRI.ArcGIS.Carto.IAnnotationFeature pAF = pSourcFeature as ESRI.ArcGIS.Carto.IAnnotationFeature;
            //    IAnnotationFeature pNAF = pTargetFeatureBuffer as IAnnotationFeature;
            //    if (pAF.Annotation != null)
            //    {
            //        pNAF.Annotation = pAF.Annotation;
            //    }
            //}

            //if (bHasZValue || pTarGeometry == null || pTarGeometry.IsEmpty)
            //    featureBuffer.Shape = pTarGeometry;
            //else
            //{
            //    pZAware = pTarGeometry as IZAware;
            //    pZAware.ZAware = false;
            //    featureBuffer.Shape = pTarGeometry;
            //}
            pSoureGeometry = pSourcFeature.ShapeCopy;
            SimplifyGeometry(pSoureGeometry);  //只修复一次有时修复不完全
            SimplifyGeometry(pSoureGeometry);
            pTargetFeatureBuffer.Shape = pSoureGeometry;

            foreach (var it in dicTargetSource)
            {
                pTargetFeatureBuffer.Value[it.Key] = pSourcFeature.Value[it.Value];
            }
            tcursor.InsertFeature(pTargetFeatureBuffer);
            n = n + 1;
            if (n % pCountToFlush == 0)
            {
                tcursor.Flush();
                Console.WriteLine($"数量{n},时间{DateTime.Now}");
            }
        }
        tcursor.Flush();
    }
}
/// <summary>
/// 获取索引字典 key:targetField value:sourceField
/// </summary>
/// <param name="target">目标数据集</param>
/// <param name="source">源数据集</param>
/// <returns></returns>
public static Dictionary<int, int> FieldsTargetSource(IFeatureClass target, IFeatureClass source)
{
    Dictionary<int, int> targetsource = new Dictionary<int, int>();
    var fldName = string.Empty;
    for (int i = 0; i < target.Fields.FieldCount; i++)
    {
        IField tField = target.Fields.get_Field(i);
        //目标图层的字段必须为可编辑并且不是必须字段
        if (!tField.Required && tField.Editable)
        {
            fldName = tField.Name;
            int idx = source.Fields.FindField(fldName);
            if (idx > -1) //源要素类中该字段存在
                targetsource.Add(i, idx);
        }
    }
    return targetsource;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值