Arcengine开发效率优化(不定时更新)

1.修改要素效率对比

需要对图层的某个字段统一赋值

方法1:IFeature赋值

var dataset = layer as IDataset;
var workspaceEdit = dataset.Workspace as IWorkspaceEdit;
workspaceEdit.StartEditing(true);
workspaceEdit.StartEditOperation();
IQueryFilter filter = new QueryFilterClass();
filter.WhereClause = $"{GuidField} is null or {GuidField} = ' '";
var index = layer.FeatureClass.Fields.FindField(GuidField);
var cursor = layer.Search(filter, false);
IFeature feature = null;
while ((feature = cursor.NextFeature()) != null)
{
    feature.Value[index] = Guid.NewGuid().ToString();
    feature.Store();
}
Marshal.ReleaseComObject(cursor);
workspaceEdit.StartEditOperation();
workspaceEdit.StopEditing(true);
Marshal.ReleaseComObject(workspaceEdit);

该方法也是常用的一种方法,耗时112132ms

方法2 IRow赋值

var dataset = layer as IDataset;
var workspaceEdit = dataset.Workspace as IWorkspaceEdit;
workspaceEdit.StartEditing(true);
workspaceEdit.StartEditOperation();
IQueryFilter filter = new QueryFilterClass();
filter.WhereClause = $"{GuidField} is null or {GuidField} = ' '";
var index = layer.FeatureClass.Fields.FindField(GuidField);
ITable table = layer as ITable;
var cursor = table.Update(filter, false);
IRow row;
while((row = cursor.NextRow()) != null)
{
    row.set_Value(index,Guid.NewGuid().ToString());
    cursor.UpdateRow(row);
}
Marshal.ReleaseComObject(cursor);
workspaceEdit.StartEditOperation();
workspaceEdit.StopEditing(true);
Marshal.ReleaseComObject(workspaceEdit);

结论

方法时间
IFeature≤112132ms
IRow≤40808ms

方法1无疑是我们最常用的一种属性编辑方法,然而耗时大概是方法2的3倍。

2.新增要素效率对比(待补充)

3.删除要素效率对比(待补充)

4.遍历要素效率对比

4.1. 需多次遍历要素时

var layer = pLayer as IFeatureLayer;
 var cursor = layer.Search(null, false);
 IFeature feature;
 List<IFeature> features = new List<IFeature>();
 while ((feature = cursor.NextFeature()) != null)
 {
     features.Add(feature);
 }
 //1.Cursor遍历
 cursor = layer.Search(null, false);
 while ((feature = cursor.NextFeature()) != null)
 {
     
 }
 //2.list遍历
 foreach(var f in features)
 {

 }
 Marshal.ReleaseComObject(cursor);

在日常开发中有时需要对要素进行自身的一些对比,比如拓扑检查的时候,

方法时间
Cursor遍历≤17ms
List遍历≤1ms

实验表明,Cursor的遍历效率远远低于list

4.2.只需读取要素OID时

4.2.1.遍历IDS

IFeatureSelection selection = layer as IFeatureSelection;
selection.SelectFeatures(filter, esriSelectionResultEnum.esriSelectionResultNew, false);
var ids = selection.SelectionSet.IDs;
int id = -1;
while ((id = ids.Next()) != -1)
{
    result.Add(new ExecuteResult()
    {
        DataId = id.ToString(),
        DataSource = layerPathInfo.Path,
        DataType = type,
        ErrorInfo = $"{target}字段值为空!源要素:{layer.Name}(OID={id})"
    });
}
Marshal.ReleaseComObject(ids);
selection.Clear();

4.2.2.遍历Ifeature

var cursor = layer.Search(filter, false);
IFeature feature = null;
while ((feature = cursor.NextFeature()) != null)
{
    result.Add(new ExecuteResult()
    {
        DataId = feature.OID.ToString(),
        DataSource = layerPathInfo.Path,
        DataType = type,
        ErrorInfo = $"{target}字段值为空!源要素:{layer.Name}(OID={feature.OID})"
    });
    Marshal.ReleaseComObject(feature);
}
Marshal.ReleaseComObject(cursor);

4.2.3.遍历IRow

ITable table = layer as ITable;
var cursor = table.Search(filter, false);
IRow row = null;
 while ((row = cursor.NextRow()) != null)
 {
     result.Add(new ExecuteResult()
     {
         DataId = row.OID.ToString(),
         DataSource = layerPathInfo.Path,
         DataType = type,
         ErrorInfo = $"{target}字段值为空!源要素:{layer.Name}(OID={row.OID})"
     });
     Marshal.ReleaseComObject(row);
 }
 Marshal.ReleaseComObject(cursor);
方法时间
IDS≤13886ms
IFeature≤36424ms
IRow≤36491ms

实验表明,遍历Ids的效率是较高的

5. 计算点到目标几何的最短距离是否在容差范围内

5.1 esri方法

/// <summary>
 /// 求指定距离
 /// </summary>
 /// <param name="pGeometryA">目标几何</param>
 /// <param name="pGeometryB">点</param>
 /// <param name="torrance">容差</param>
 /// <returns></returns>
 private bool GetTwoGeometryDistance(IGeometry pGeometryA, IPoint pGeometryB,double torrance)
 {
     IProximityOperator pProOperator = pGeometryA as IProximityOperator;
     if (pGeometryA != null || pGeometryB != null)
     {
         double distance = pProOperator.ReturnDistance(pGeometryB);
         Marshal.ReleaseComObject(pProOperator);
         return distance<torrance;
     }
     else
     {
         return false;
     }

 }

5.2.数学方法

/// <summary>
/// 数学方法计算点到几何的最短距离
/// </summary>
/// <param name="point">点</param>
/// <param name="geo">目标几何</param>
/// <param name="torrance">容差</param>
/// <returns></returns>
private bool GetTwoGeometryDistanceByMath(IPoint point, IGeometry geo,double torrance)
{
   var segments = geo as ISegmentCollection;
   torrance = torrance * torrance;
   for(int i = 0; i < segments.SegmentCount; i++)
   {
       var line = segments.Segment[i];
       var dis = GetPointLineDis(line.FromPoint, line.ToPoint, point);
       if (dis < torrance)
           return true;
   }
   return false;
}
/// <summary>
/// 求点p到线段ab的最短距离的平方,避免过多开方运算
/// </summary>
/// <param name="pa"></param>
/// <param name="pb"></param>
/// <param name="p"></param>
/// <returns></returns>
private double GetPointLineDis(IPoint a,IPoint b,IPoint p)
{
   double dis = 0;
   //向量AB·向量Ap
   var abCrossAp = (b.X - a.X) * (p.X - a.X) + (b.Y - a.Y) * (p.Y - a.Y);
   //∠PAB为钝角,最短距离为PA
   if (abCrossAp <= 0)
       dis = (p.X - a.X) * (p.X - a.X) + (p.Y - a.Y) * (p.Y - a.Y);
   else
   {
       var ab2 = (b.X - a.X) * (b.X - a.X) + (b.Y - a.Y) * (b.Y - a.Y);
       //p的垂线相交于AB向量的延长线上,最短距离为PB
       if (abCrossAp >= ab2)
           dis = (p.X - b.X) * (p.X - b.X) + (p.Y - b.Y) * (p.Y - b.Y);
       //p的垂线相交于AB向量上(交点为D),最短距离为垂线的值
       else
       {
           var r = abCrossAp / ab2;
           var Dx = a.X + (b.X - a.X) * r;
           var Dy = a.Y + (b.Y - a.Y) * r;
           dis = (p.X - Dx) * (p.X - Dx) + (p.Y - Dy) * (p.Y - Dy);
       }
   }
   return dis;
}

结论

方法时间
Esri≤12ms
数学方法≤3ms

实验表明,使用数学方法计算效率大概是直接用esri方法的4倍

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShirmyMao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值