ArcEngine 将管线属性表里面写入管点
现有管线数据,需要生成管点数据,然后在管线的属性表里面写入起始管点和终止管点。
思路:在ArcMap中用管线数据新建一个网络数据集就会自动生成管点数据,然后通过AE编程将每个管线(Polyline)的起始点(FromPoint)和终止点(ToPoint)通过缓冲区(Buffer)在管点图层中找到对应的点,然后将管点编号写入到管线的属性表中。
数据准备好后,现在开始写代码了:
这里的管线数据因为是CAD数据,数据质量不是很好,有的管线重复了,这样生成管点的时候也就有重复的,所以这里需要把管点图层中重复的管点删除掉
private void Bt_WritePoint_Click(object sender, EventArgs e) { WritePipeLine(); MessageBox.Show("写入成功!"); } private void WritePipeLine() { int a =0; try { ILayer pLayer = axMapControl1.get_Layer(1);//管线图层 IFeatureLayer pFeatureLayer = pLayer as IFeatureLayer; IFeatureClass pFeatureClass = pFeatureLayer.FeatureClass; IFeatureCursor pFeatureCursor = pFeatureClass.Search(null, false); IFeature pFeature = pFeatureCursor.NextFeature(); progressBar1.Maximum = pFeatureClass.FeatureCount(null)+100; while (pFeature != null) { a++; if (a % 10 == 0) //处理10条数据进度条显示一次 { progressBar1.Value += progressBar1.Step;//进度条提示 label1.Text = a.ToString(); Application.DoEvents(); } if (pFeature.Shape != null) { if (pFeature.Shape.GeometryType == esriGeometryType.esriGeometryPolyline) { WritePloyline(pFeature); } } pFeature = pFeatureCursor.NextFeature(); } } catch (Exception ex) { MessageBox.Show(ex.Message); MessageBox.Show(a.ToString()); } } private void WritePloyline(IFeature pFeature) { if (pFeature.Shape is Polyline) { IPolyline pPolyline = pFeature.Shape as IPolyline; DeleteRedLinePoint(pPolyline.FromPoint); DeleteRedLinePoint(pPolyline.ToPoint); } } //删除重复的管点 IFeatureClass pFeatureClass = null; private void DeleteRedLinePoint(IPoint pPoint) { ITopologicalOperator pTopologicalOperator = pPoint as ITopologicalOperator; IGeometry pGeometry = pTopologicalOperator.Buffer(0);//Distence是缓冲距离 pTopologicalOperator.Simplify(); ISpatialFilter pSpatialfilter = new SpatialFilterClass(); pSpatialfilter.Geometry = pGeometry; pSpatialfilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains; if (pFeatureClass == null) { ILayer pLayer = axMapControl1.get_Layer(0); string name = pLayer.Name; IFeatureLayer pFeatureLayer = pLayer as IFeatureLayer; pFeatureClass = pFeatureLayer.FeatureClass; } IFeatureCursor FeatureCursors = pFeatureClass.Search(pSpatialfilter, false); IFeature Feature = FeatureCursors.NextFeature(); // //删除重复要素 int a = 0;//查找的要素个数 while (Feature != null) { IPoint point = Feature.Shape as IPoint; if ( point.X == pPoint.X && point.Y==pPoint.Y) { a++; if (a > 1) { Feature.Delete(); FeatureCursors.Flush();//将缓存写入到数据库中 } } Feature = FeatureCursors.NextFeature(); } System.Runtime.InteropServices.Marshal.ReleaseComObject(FeatureCursors);//释放资源 }
管点数据处理完之后然后开始往管线属性表里面写入管点信息。
private void Bt_WritePoint_Click(object sender, EventArgs e) { WritePipeLine(); MessageBox.Show("写入成功!"); } private void WritePipeLine() { int a = 0; try { ILayer pLayer = axMapControl1.get_Layer(1);//管线图层 IFeatureLayer pFeatureLayer = pLayer as IFeatureLayer; IFeatureClass pFeatureClass = pFeatureLayer.FeatureClass; IFeatureCursor pFeatureCursor = pFeatureClass.Search(null, false); IFeature pFeature = pFeatureCursor.NextFeature(); progressBar1.Maximum = pFeatureClass.FeatureCount(null)+100; while (pFeature != null) { a++; if (pFeature.Shape.GeometryType == esriGeometryType.esriGeometryPolyline) { WritePloyline(pFeature); } pFeature.Store(); if (a % 20 == 0) //达到20个要素保存一次 { progressBar1.Value += progressBar1.Step;//执行步长 label1.Text = a.ToString(); Application.DoEvents(); } pFeature = pFeatureCursor.NextFeature(); } } catch (Exception ex) { MessageBox.Show(ex.Message); MessageBox.Show(a.ToString()); } } //写入起始管点和终止管点编号 private void WritePloyline(IFeature pFeature) { if (pFeature.Shape is Polyline) { IPolyline pPolyline = pFeature.Shape as IPolyline; string name = pFeature.OID.ToString(); string FNID1= ReturnLinePoint(pPolyline.FromPoint); if (FNID1 == "") { pFeature.set_Value(5, "-1"); } else { pFeature.set_Value(5, FNID1); } string FNID2= ReturnLinePoint(pPolyline.ToPoint); if (FNID2 == "") { pFeature.set_Value(6, "-1"); } else { pFeature.set_Value(6, FNID2); } } } //返回该节点最近的管点 IFeatureClass pFeatureClass = null; private string ReturnLinePoint(IPoint pPoint) { ITopologicalOperator pTopologicalOperator = pPoint as ITopologicalOperator; IGeometry pGeometry = pTopologicalOperator.Buffer(0);//Distence是缓冲距离 pTopologicalOperator.Simplify(); ISpatialFilter pSpatialfilter = new SpatialFilterClass(); pSpatialfilter.Geometry = pGeometry; pSpatialfilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains; if (pFeatureClass == null) { ILayer pLayer = axMapControl1.get_Layer(0); string name = pLayer.Name; IFeatureLayer pFeatureLayer = pLayer as IFeatureLayer; pFeatureClass = pFeatureLayer.FeatureClass; } IFeatureCursor FeatureCursors = pFeatureClass.Search(pSpatialfilter, false); IFeature Feature = FeatureCursors.NextFeature(); while (Feature != null) { IPoint point = Feature.Shape as IPoint; if (point.X == pPoint.X && point.Y ==pPoint.Y) { System.Runtime.InteropServices.Marshal.ReleaseComObject(FeatureCursors);//释放资源 return Feature.get_Value(2).ToString(); } Feature = FeatureCursors.NextFeature(); } System.Runtime.InteropServices.Marshal.ReleaseComObject(FeatureCursors);//释放资源 return ""; }
处理完数据之后如下图:

总结:
1、修改数据的时候,修改属性表保存用 pFeature.Store();修改要素的几何形状保存用FeatureCursors.Flush();Fush()使用的时候,如果一个游标里面的修改要素比较多,达到300个需要Flush一次。
2、在点缓冲查找同一坐标的点时给出过滤条件出现问题: pSpatialfilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelEnvelopeIntersects;这个是两个要素的包络线(Envelope)是否相交,而不是包含,所以查不到想要的管点,应该是 pSpatialfilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains;这个是包含关系。
3、在处理数据的时候,处理的很慢大概速度是1.5s/个。主要时间花在 IFeature Feature = FeatureCursors.NextFeature()。
4、打开游标的时候记得释放游标: System.Runtime.InteropServices.Marshal.ReleaseComObject(FeatureCursors)。
5、mdb数据库中的默认字段比shp文件里面的多一个Shape字段,在获取或修改要素的字段值时注意填入的索引。
6、之前在寻找相同点时候只有判断point.X == pPoint.X ,导致删除了很多有用的点,浪费了一晚上的时间(处理数据比较慢)。原因是管点的密集程度比较高,很多管点的X坐标是相同的,这会导致删除了其他有用的管点。所以应该加上point.Y ==pPoint.Y。
7、由于是CAD数据,数据的质量不高,有很多管线的长度为0,这个地方前期没有做处理,所以后期浪费了很多的处理时间。
posted on 2015-09-21 00:02 Geography爱好者 阅读(462) 评论(0) 收藏 举报
浙公网安备 33010602011771号