ArcEngine下輸電線路二三維交互選線

前面輸電線路的生成方式前提是實地勘測了杆塔點位,採集了杆塔的座標,直接導入Excel生成shape文件。如今是作一個輸電線路的選址,傳統的規劃選線做業採用失效性差的紙質地圖,形成選線路徑方案可行性差,準確性低。應用高分辨率衛星影像和數字高程模型創建三維選線平臺以輔助選線並進行杆塔輔助規劃,可有效提升線路路徑規劃的可行性和準確性,節省投資。函數

基礎地理數據主要包括DEM、DOM、DLG,杆塔模型以及其餘工程資料。這裏條件所限,精度均達不到,只作測試,說明方案的可行性便可。測試

二維選址場景:優化


三維選線場景:this


二三維交互進行選線,在調整路徑平面的同時,能夠實時顯示縱斷面圖,並在三維場景下實時顯示排位結果,以提升路線優化效率和精度。選線及縱斷面圖繪製參考前面的博文。二維選線結果:spa



線路縱斷面圖繪製結果以下圖所示,包括杆塔分佈、路線縱斷面圖以及架空線。架空線採用的是懸鏈線方程繪製(懸鏈線的繪製參考前面博文http://blog.csdn.net/giser_whu/article/details/21323807)。從縱斷面圖來看選線是較爲合理的。.net

三維場景下實時顯示排位結果:code

經過二三維的交互選線可提升線路規劃的效率以及方案的可行性,大大下降了人力勞動,節省了資金,是切實可行的。orm

下面是縱斷面繪製的所有源碼,僅供參考。須要說明的是,繪圖是採用的Dev的chartcontrol控件,版本是11.1.4,安裝見前面博文。blog

 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



    }
歡迎留言交流!