交通行业一个客户提出的需求:如下图,有高速公路中心线和很多设备点,这些设备点都没有在线上(由于地图缩小缘故看不太清),且设备点相对于线的偏移方向和距离没有规律,现在需要将这些点移动到线上。这里我基于Engine写了一段程序处理。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Display;
namespace pointBatchOffset
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//开始执行
private void button1_Click(object sender, EventArgs e)
{
//查询缓冲区图层
IFeatureLayer ptLayer = queryFeatureLayer("pointZ");
//得到指定图层上距point最近的feature上的最近点
IFeatureClass ptFeatClass = ptLayer.FeatureClass;
IFeatureCursor featureCursor = featureCursor = ptFeatClass.Search(null, false);
IFeature feature = featureCursor.NextFeature();
IPoint point = new PointClass();
while (feature != null)
{
point = feature.Shape as IPoint;
//查找离点最近的线
IFeature nearFea = GetNearestFeature(point, 1.2);
IPoint neaPoint = GetNearestPoint(point,nearFea);
neaPoint.Z = point.Z;
//移动点
MoveToNeaPoint(feature,point,neaPoint);
if (featureCursor == null || feature == null)
{
return;
}
feature = featureCursor.NextFeature();
}
MessageBox.Show("ok--");
}
//查询给定名称的图层
private IFeatureLayer queryFeatureLayer(string name)
{
for (int i = 0; i < axMapControl1.LayerCount; i++)
{
ILayer layer = axMapControl1.get_Layer(i);
if (layer.Name.Equals(name))
{
return (IFeatureLayer)layer;
}
}
return null;
}
////得到指定图层上距point最近的feature上的最近点
public IPoint GetNearestPoint(IPoint point, IFeature nearFea)
{
IProximityOperator Proximity = (IProximityOperator)point;
IFeatureLayer FeaLyr = queryFeatureLayer("MedianRoadZ");
IFeatureClass FeaCls = FeaLyr.FeatureClass;
IQueryFilter queryFilter = null;
ITopologicalOperator topoOper = (ITopologicalOperator)point;
IGeometry geo = topoOper.Buffer(1.2);
ISpatialFilter sf = new SpatialFilterClass();
sf.Geometry = geo;
sf.GeometryField = FeaCls.ShapeFieldName;
sf.SpatialRel = esriSpatialRelEnum.esriSpatialRelCrosses;
IFeatureCursor FeaCur = FeaCls.Search(queryFilter, false);
IFeature Fea = nearFea = FeaCur.NextFeature();
double minDistince, Distance;
if (Fea == null)
return null;
minDistince = Distance = Proximity.ReturnDistance((IGeometry)Fea.Shape); //最近的距离值
//保存距离最近的feature
Fea = FeaCur.NextFeature();
while (Fea != null)
{
Distance = Proximity.ReturnDistance((IGeometry)Fea.Shape);
if (Distance < minDistince)
{
minDistince = Distance;
nearFea = Fea;
}
Fea = FeaCur.NextFeature();
} //end while
Proximity = (IProximityOperator)nearFea.Shape;
return Proximity.ReturnNearestPoint(point, esriSegmentExtension.esriNoExtension);
}
//查找最近的线
public IFeature GetNearestFeature(IPoint p, double rongcha)
{
IFeature nearFea;
IProximityOperator Proximity = (IProximityOperator)p;
IFeatureLayer FeaLyr = queryFeatureLayer("MedianRoadZ");
IFeatureClass FeaCls = FeaLyr.FeatureClass;
IQueryFilter queryFilter = null;
IFeatureCursor FeaCur = FeaCls.Search(queryFilter, false);
IFeature Fea = nearFea = FeaCur.NextFeature();
double minDistince, Distance;
if (Fea == null)
return null;
minDistince = Distance = Proximity.ReturnDistance((IGeometry)Fea.Shape); //最近的距离值
//保存距离最近的feature
Fea = FeaCur.NextFeature();
while (Fea != null)
{
Distance = Proximity.ReturnDistance((IGeometry)Fea.Shape);
if (Distance < minDistince)
{
minDistince = Distance;
nearFea = Fea;
}
Fea = FeaCur.NextFeature();
} //end while
return nearFea;
}
private void MoveToNeaPoint(IFeature feature,IPoint point, IPoint neaPoint)
{
IGeometry toGeometry = null;
IPoint geomType = new PointClass();
feature.Shape = neaPoint as IGeometry;
feature.Store();
}
}
}