由于研究的需要,本人需要将一段曲线按等距离打断,分成固定长度的线段,并且按需要的长度绘制线段的中垂线。按照能不自己动手就坚决不动手的原则,我查阅了ARCGIS关于处理线要素的工具,发现只有等距离打断曲线的工具,但没有绘制线段中垂线的工具。哎,无奈之下,只能自己编写程序了。写程序前,先弄明白绘制中垂线的基本流程。实现工具:visual studio 2010+ARCGIS engine10.1 。数据:等距离打断的曲线图层。依据当前的工具和数据,我制定了完成任务的基本流程:
AE加载矢量数据的方法——获取线段的端点(有些线段可能是曲线,因此计算的是线段两点连线的中垂线,我是没想出其他好的方法。)——计算中垂线的两点(由于要求中垂线是定长的,我选择了以线段两点中点为准,求出定长中垂线上另一点)——要素编辑并存储——完成
看了下流程,难点在于计算中垂线的两点:本人选择了一种笨方法,方程求解。基本过程如下:1 利用已知线段的两个端点,求出线段中点的坐标,这个很简单。 2 求出线段端点连线的斜率,中垂线的斜率也就出来了,利用中点就可以求出中垂线的线性表达式,然后结合两点距离公式算出定长点的坐标(有两个点哦,我选择了这两个点来绘制中垂线的)
基本思路如上,下面就是贴代码时间了:首先贴出核心代码——计算中垂线的两点的函数
/// <summary>
/// 依据输入两点来计算输入两点的中位线的两点
/// </summary>
/// <param name="inpoint1"></param>
/// <param name="inpoint2"></param>
/// <param name="outpoint1"></param>
/// <param name="outpoint2"></param>
private void CaculateMiddleLinePoints(IPoint inpoint1,IPoint inpoint2,out IPoint outpoint1,out IPoint outpoint2)
{
//k
double k = (inpoint2.Y - inpoint1.Y) / (inpoint2.X - inpoint1.X);
//middle point for inpoint1 and inpoint2
IPoint middlePoint = new PointClass();
middlePoint.X = (inpoint1.X + inpoint2.X) / 2;
middlePoint.Y = (inpoint1.Y + inpoint2.Y) / 2;
double k01=-1/k;
double b01 = middlePoint.Y -k01 * middlePoint.X;
//caculate another point of middle line
//
double b1 =2*(-middlePoint.X + k01 * b01- k01 * middlePoint.Y);
double a1 = 1 + k01 * k01;
// 其中最后的一个数值5000代表的是中点到另一个点的距离,可以依据自己的需求来设置,我直接写成了5000m
double c1 = middlePoint.X * middlePoint.X + b01 * b01-2 * b01 * middlePoint.Y + middlePoint.Y * middlePoint.Y - 5000 * 5000;
//到中点距离为5000的有两个点,
IPoint p1 = new PointClass();
IPoint p2 = new PointClass();
//如果无解则退出
double delta=b1 * b1 - 4 * a1 * c1;
if (delta < 0)
{
outpoint1 = null;
outpoint2 = null;
return;
}
p1.X = (-b1 + Math.Sqrt(delta )) / (2 * a1);
p1.Y = k01 * p1.X + b01;
p2.X = (-b1 - Math.Sqrt(delta)) / (2 * a1);
p2.Y = k01 * p2.X + b01;
//
outpoint1 = p1;
outpoint2 = p2;
}
计算出了中垂线的两点,下面就简单了,就是添加要素的过程,具体如下:
private void button2_Click(object sender, EventArgs e)
{
button2.Enabled = false;
//获取存储中位线的shp存储文件
string targetLayerPath = @"d:\data\";
string filename = "MiddleLine.shp";
IWorkspaceFactory myWorkspacefac = new ShapefileWorkspaceFactoryClass();
IFeatureWorkspace myFeatureworkspace = (IFeatureWorkspace)myWorkspacefac.OpenFromFile(targetLayerPath, 0);
IFeatureClass targetFeatureclass = myFeatureworkspace.OpenFeatureClass(filename);
//启动编辑
IWorkspaceEdit workspaceEdit=(targetFeatureclass as IDataset ).Workspace as IWorkspaceEdit;
workspaceEdit.StartEditing(true);
workspaceEdit.StartEditOperation();
//快速查询数据
IQueryFilter mQueryFilter = new QueryFilterClass();
IFeatureCursor mFeatureCursor = lineLayer.Search(mQueryFilter, false);
IFeature feature = mFeatureCursor.NextFeature();
//提示处理进度
Form2 frmTip = new Form2();
frmTip.Show();
frmTip.TopMost = true;
System.Windows.Forms.Application.DoEvents();
int i = 0;
int featureCount = lineLayer.FeatureClass.FeatureCount(null);
while (feature != null)
{
IPolyline line = feature.Shape as IPolyline;
IPoint startPoint = line.FromPoint;
IPoint endPoint = line.ToPoint;
//计算中位线的两点坐标
IPoint sMiPoint=new PointClass();
IPoint eMIPoint=new PointClass();
CaculateMiddleLinePoints(startPoint, endPoint,out sMiPoint,out eMIPoint);
if (sMiPoint == null || eMIPoint == null)
{
string s=i.ToString();
MessageBox.Show(s);
return;
Application.Exit();
}
IPolyline miLine = new PolylineClass();
miLine.FromPoint = sMiPoint;
miLine.ToPoint = eMIPoint;
IFeature addFeature = targetFeatureclass.CreateFeature();
addFeature.Shape = miLine as IGeometry;
addFeature.Store();
//搜索下一要素
feature = mFeatureCursor.NextFeature();
//提示处理信息
i++;
double leftcount = featureCount - i;
frmTip.label1.Text = "请稍后,目前还剩 " + leftcount.ToString() + " 个要素未处理!";
}
//退出编辑状态
workspaceEdit.StopEditOperation();
workspaceEdit.StopEditing(true );
//处理完毕,退出提示
frmTip.Close();
frmTip.Dispose();
button2.Enabled = true;
}
哈哈,大功告成了!贴下我的结果图
可执行程序已经重新上传,有需要的可自行下载https://download.csdn.net/download/dingzhi816/12325081(刚上传,正审核,有需要可以联系邮箱:dingzhi816@163.com)