前面输电线路的生成方式前提是实地勘测了杆塔点位,采集了杆塔的坐标,直接导入Excel生成shape文件。现在是做一个输电线路的选址,传统的规划选线作业采用失效性差的纸质地图,造成选线路径方案可行性差,准确性低。应用高分辨率卫星影像和数字高程模型建立三维选线平台以辅助选线并进行杆塔辅助规划,可有效提高线路路径规划的可行性和准确性,节省投资。
基础地理数据主要包括DEM、DOM、DLG,杆塔模型以及其他工程资料。这里条件所限,精度均达不到,只做测试,说明方案的可行性即可。
二维选址场景:
三维选线场景:
二三维交互进行选线,在调整路径平面的同时,可以实时显示纵断面图,并在三维场景下实时显示排位结果,以提高路线优化效率和精度。选线及纵断面图绘制参考前面的博文。二维选线结果:
线路纵断面图绘制结果如下图所示,包括杆塔分布、路线纵断面图以及架空线。架空线采用的是悬链线方程绘制(悬链线的绘制参考前面博文http://blog.csdn.net/giser_whu/article/details/21323807)。从纵断面图来看选线是较为合理的。
三维场景下实时显示排位结果:
通过二三维的交互选线可提高线路规划的效率以及方案的可行性,大大降低了人力劳动,节省了资金,是切实可行的。
下面是纵断面绘制的全部源码,仅供参考。需要说明的是,绘图是采用的Dev的chartcontrol控件,版本是11.1.4,安装见前面博文。
public partial class ProfileGraphicResult : DevComponents.DotNetBar.Office2007Form { #region 私有变量 private IFeatureLayer Linefeaturelayer = null; //输电线图层 private IFeatureLayer Pointfeaturelayer = null; //杆塔点位图层 private IRasterLayer elevationLayer = null; //DEM #endregion #region 构造函数 public ProfileGraphicResult(IFeatureLayer pLineFeaturelayer , IFeatureLayer pPointFeaturelayer , IRasterLayer rasterLayer) { Linefeaturelayer = new FeatureLayerClass(); Pointfeaturelayer = new FeatureLayerClass(); elevationLayer = new RasterLayerClass(); Linefeaturelayer = pLineFeaturelayer; Pointfeaturelayer = pPointFeaturelayer; elevationLayer = rasterLayer; InitializeComponent(); } #endregion #region load private void ProfileGraphic_Load(object sender , EventArgs e) { this.Text = Linefeaturelayer.Name + "纵断面图"; CreateProfileGraphic(); } #endregion #region 获取所有杆塔点位坐标 //获取杆塔点位 private static IPointCollection GetTowerPointCollection(IFeatureLayer featurelayer_towerpoint) { IPointCollection pointCollection = new MultipointClass(); int featureCount = featurelayer_towerpoint.FeatureClass.FeatureCount(null); object missing = Type.Missing; for (int i = 0;i < featureCount;i++) { IPoint point = new PointClass(); IFeature feature = featurelayer_towerpoint.FeatureClass.GetFeature(i); point = feature.ShapeCopy as IPoint; pointCollection.AddPoint(point , ref missing , ref missing); System.Runtime.InteropServices.Marshal.ReleaseComObject(point); System.Runtime.InteropServices.Marshal.ReleaseComObject(feature); } return pointCollection; } #endregion #region 纵断面内插点 private List<double> CreateProfileGraphicPointCollection() { List<double> List_towerElevation = new List<double>(); //高程值集 try { //获取所有杆塔点 IPointCollection ptCollection = new MultipointClass(); ptCollection = GetTowerPointCollection(Pointfeaturelayer); //获取高程内插点 for (int i = 0;i < ptCollection.PointCount - 1;i++) { IPoint point_start = new PointClass(); IPoint point_end = new PointClass(); IPoint point_temp = new PointClass(); (point_temp as IZAware).ZAware = true; IPolyline pLine = new PolylineClass(); point_start = ptCollection.get_Point(i); point_end = ptCollection.get_Point(i + 1); pLine.FromPoint = point_start; pLine.ToPoint = point_end; double pLength = OtherHelper.GetPlaneDistance(point_start , point_end); for (int j = 0; j < (int)pLength; j++) { pLine.QueryPoint(esriSegmentExtension.esriNoExtension , j , false , point_temp); double z = OtherHelper.GetValueByPoint(elevationLayer , point_temp); List_towerElevation.Add(z); } System.Runtime.InteropServices.Marshal.ReleaseComObject(pLine); System.Runtime.InteropServices.Marshal.ReleaseComObject(point_start); System.Runtime.InteropServices.Marshal.ReleaseComObject(point_end); System.Runtime.InteropServices.Marshal.ReleaseComObject(point_temp); } System.Runtime.InteropServices.Marshal.ReleaseComObject(ptCollection); } catch (System.Exception ex) { MessageBox.Show(ex.Message+" 纵断面插值点生成失败!"); } return List_towerElevation; } #endregion #region 悬链线内插点 private List<double> CreateTransmissionLinePtCollection(IFeatureLayer featurelayer_line) { List<double> List_TransmissionLineElevation = new List<double>(); //高程值集 try { //获取整条线要素 IFeature feature = featurelayer_line.FeatureClass.GetFeature(0); IPolyline polyline = new PolylineClass(); polyline = feature.ShapeCopy as IPolyline; //获取两个杆塔间的悬链线 int geometryCount = (polyline as IGeometryCollection).GeometryCount; for (int i = 0;i < geometryCount;i++) { IPath pLineBetweenTwoTower = new PathClass(); pLineBetweenTwoTower = (polyline as IGeometryCollection).get_Geometry(i) as IPath; IPoint point_start = new PointClass(); IPoint point_end = new PointClass(); point_start = pLineBetweenTwoTower.FromPoint; point_end = pLineBetweenTwoTower.ToPoint; double length = OtherHelper.GetPlaneDistance(point_start , point_end); //判断杆塔点位的前后关系 IFeature feature_pt = null; IFeatureCursor featureCursor = Pointfeaturelayer.FeatureClass.Search(null , false); int featureCount = Pointfeaturelayer.FeatureClass.FeatureCount(null); while ((feature_pt=featureCursor.NextFeature())!=null) { IPoint pt = new PointClass(); pt = feature_pt.ShapeCopy as IPoint; if (pt.Z == OtherHelper.GetValueByPoint(elevationLayer,point_start)) { point_start.ID = feature_pt.OID; } if (pt.Z == OtherHelper.GetValueByPoint(elevationLayer,point_end)) { point_end.ID = feature_pt.OID; } System.Runtime.InteropServices.Marshal.ReleaseComObject(pt); } if (point_start.ID>point_end.ID) { for (int j = 0;j <(int) length;j++) { IPoint point_temp = new PointClass(); (point_temp as IZAware).ZAware = true; pLineBetweenTwoTower.QueryPoint(esriSegmentExtension.esriNoExtension , length - j , false , point_temp); List_TransmissionLineElevation.Add(point_temp.Z); System.Runtime.InteropServices.Marshal.ReleaseComObject(point_temp); } } else { for (int j = 0;j < (int) length;j++) { IPoint point_temp = new PointClass(); (point_temp as IZAware).ZAware = true; pLineBetweenTwoTower.QueryPoint(esriSegmentExtension.esriNoExtension , j , false , point_temp); List_TransmissionLineElevation.Add(point_temp.Z); System.Runtime.InteropServices.Marshal.ReleaseComObject(point_temp); } } System.Runtime.InteropServices.Marshal.ReleaseComObject(pLineBetweenTwoTower); System.Runtime.InteropServices.Marshal.ReleaseComObject(point_start); System.Runtime.InteropServices.Marshal.ReleaseComObject(point_end); } System.Runtime.InteropServices.Marshal.ReleaseComObject(feature); System.Runtime.InteropServices.Marshal.ReleaseComObject(polyline); } catch (System.Exception ex) { MessageBox.Show(ex.Message+" 悬链线插值点生成失败!"); } return List_TransmissionLineElevation; } #endregion #region 每一段路线平面长度 private double[] GetLengthBetweenTwoTower() { IPointCollection ptCollection = new MultipointClass(); ptCollection = GetTowerPointCollection(Pointfeaturelayer); double[] lengthCollection = new double[ptCollection.PointCount - 1]; for (int i = 0;i < ptCollection.PointCount - 1;i++) { double length = OtherHelper.GetPlaneDistance(ptCollection.get_Point(i) , ptCollection.get_Point(i + 1)); lengthCollection[i] = length; } return lengthCollection; } #endregion #region 生成纵断面图(地形线、杆塔排位、悬链线) private void CreateProfileGraphic() { try { //杆塔点位图形 Series series_point = new Series(); series_point = CreateTowerPointSeries(); //纵断面曲线图形 Series series_line = new Series(); series_line = CreateProfileGraphicSeries(); //悬链线图形 Series series_Transmissionline = new Series(); series_Transmissionline = CreateTransmissionLineSeries(); #region 绘图环境参数设置 //定义标题 ChartTitle chartTitle = new ChartTitle() { Text = Linefeaturelayer.Name + "纵断面图" , Font = new Font(FontStyle.Bold.ToString() , 22) , TextColor = System.Drawing.Color.Brown , Dock = ChartTitleDockStyle.Top , Alignment = StringAlignment.Center }; chartControl_Profile.Titles.Add(chartTitle); //将曲线加入chartcontrol chartControl_Profile.Series.Add(series_line); chartControl_Profile.Series.Add(series_Transmissionline); chartControl_Profile.Series.Add(series_point); chartControl_Profile.Legend.Visible = true; //定义坐标轴标题 XYDiagram xydiagram = (XYDiagram) chartControl_Profile.Diagram; ((XYDiagram) chartControl_Profile.Diagram).AxisX.Title.Font = new Font("宋体", 10); ((XYDiagram) chartControl_Profile.Diagram).AxisX.Title.Alignment = StringAlignment.Far; ((XYDiagram) chartControl_Profile.Diagram).AxisX.Title.TextColor = System.Drawing.Color.Red; ((XYDiagram) chartControl_Profile.Diagram).AxisX.Title.Text = "输电线路长度/米"; ((XYDiagram) chartControl_Profile.Diagram).AxisX.Title.Visible = true; ((XYDiagram) chartControl_Profile.Diagram).AxisY.Title.Font = new Font("宋体" , 10); ((XYDiagram) chartControl_Profile.Diagram).AxisY.Title.Alignment = StringAlignment.Far; ((XYDiagram) chartControl_Profile.Diagram).AxisY.Title.TextColor = System.Drawing.Color.Red; ((XYDiagram) chartControl_Profile.Diagram).AxisY.Title.Text = "高程/米"; ((XYDiagram) chartControl_Profile.Diagram).AxisY.Title.Visible = true; #endregion } catch (System.Exception ex) { MessageBox.Show(ex.Message + " 创建纵断面失败!"); } } #endregion #region 创建杆塔点位图形 private Series CreateTowerPointSeries() { //图形属性设置 Series series_point = new Series("杆塔点位" , ViewType.Point) { ArgumentScaleType = ScaleType.Numerical }; series_point.Label.Visible = false; series_point.View.Color = System.Drawing.Color.Red; (series_point.View as PointSeriesView).PointMarkerOptions.Kind = MarkerKind.Star; (series_point.View as PointSeriesView).PointMarkerOptions.Size = 15; try { IPointCollection ptCollection = new MultipointClass(); ptCollection = GetTowerPointCollection(Pointfeaturelayer); //获取每一段路线长度集合 double[] lengthCollection = new double[ptCollection.PointCount - 1]; lengthCollection = GetLengthBetweenTwoTower(); //添加杆塔点 for (int i = 0;i < ptCollection.PointCount;i++) { if (i == 0) { double value = ptCollection.get_Point(i).Z; SeriesPoint seriesPt = new SeriesPoint(i + 1 , value); series_point.Points.Add(seriesPt); } else { //循环计算杆塔位置 double location = 0.0; for (int j = 0;j < i;j++) { double length = lengthCollection[j]; location += length; } double value = ptCollection.get_Point(i).Z; SeriesPoint seriesPt = new SeriesPoint(location , value); series_point.Points.Add(seriesPt); } } System.Runtime.InteropServices.Marshal.ReleaseComObject(ptCollection); } catch (System.Exception ex) { MessageBox.Show(ex.Message + "创建杆塔点位图形失败!!"); } return series_point; } #endregion #region 创建纵断面曲线图 private Series CreateProfileGraphicSeries() { //设置纵断面曲线属性 Series series_line = new Series(Linefeaturelayer.Name + "纵断面图" , ViewType.Spline) { ArgumentScaleType = ScaleType.Numerical }; series_line.Label.Visible = false; series_line.View.Color = System.Drawing.Color.Black; (series_line.View as SplineSeriesView).LineMarkerOptions.Kind = MarkerKind.Diamond; (series_line.View as SplineSeriesView).LineStyle.Thickness = 2; (series_line.View as SplineSeriesView).LineMarkerOptions.BorderVisible = false; (series_line.View as SplineSeriesView).LineMarkerOptions.Size = 1; (series_line.View as SplineSeriesView).LineStyle.DashStyle = DashStyle.Solid; //获取纵断面曲线插值点 List<double> point_ProfileGraphic = new List<double>(); point_ProfileGraphic = CreateProfileGraphicPointCollection(); for (int i = 1;i < point_ProfileGraphic.Count + 1;i++) { double value = point_ProfileGraphic[i - 1]; SeriesPoint seriesPoint = new SeriesPoint(i , value); series_line.Points.Add(seriesPoint); } return series_line; } #endregion #region 创建悬链线曲线图 private Series CreateTransmissionLineSeries() { //设置曲线属性 Series series_Transmissionline = new Series("架空线" , ViewType.Line) { ArgumentScaleType = ScaleType.Numerical }; series_Transmissionline.Label.Visible = false; series_Transmissionline.View.Color = SystemColors.HotTrack; (series_Transmissionline.View as LineSeriesView).LineMarkerOptions.Kind = MarkerKind.Diamond; (series_Transmissionline.View as LineSeriesView).LineStyle.Thickness = 2; (series_Transmissionline.View as LineSeriesView).LineMarkerOptions.BorderVisible = false; (series_Transmissionline.View as LineSeriesView).LineMarkerOptions.Size = 1; (series_Transmissionline.View as LineSeriesView).LineStyle.DashStyle = DashStyle.Dash; //获取悬链线插值点 List<double> point_TransmissionLine = new List<double>(); point_TransmissionLine = CreateTransmissionLinePtCollection(Linefeaturelayer); for (int i = 1;i < point_TransmissionLine.Count + 1;i++) { double value = point_TransmissionLine[i - 1]; SeriesPoint seriesPoint = new SeriesPoint(i , value); series_Transmissionline.Points.Add(seriesPoint); } return series_Transmissionline; } #endregion }欢迎留言交流!