Newer
Older
GHFX_REFACTOR / FrmCompareFeature.cs
xiaowei on 15 Nov 2016 20 KB 修改双屏,替换模型库
using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using DevComponents.DotNetBar;
using GeoScene.Data;
using GeoScene.Globe;

namespace Cyberpipe
{
    public partial class FrmCompareFeature : Office2007Form
    {
        GSOFeature srcFeature;
        GSOFeature dscFeature;
        GSOGlobeControl globeControl1;
        GSOGlobeControl globeControl2;
        bool isSamePolyline;

        GSOLayer layerTemp;
        GSOLayer layerTemp2;
        GSOFeature new_feat;
        GSOGeoPolygon3D resPolygon;

        static FrmCompareFeature frm;

        public static void ShowForm(GSOGlobeControl _globeControl1, GSOGlobeControl _globeControl2,
            GSOLayer _layerTemp, GSOLayer _layerTemp2, int width)
        {
            if (frm == null)
            {
                frm = new FrmCompareFeature(_globeControl1, _globeControl2, _layerTemp, _layerTemp2);

                frm.Location = new Point((width - frm.Width)/2, 50);
                frm.Show(_globeControl1.Parent);
            }
            else
            {
                if (frm.WindowState == FormWindowState.Minimized)
                    frm.WindowState = FormWindowState.Normal;
            }
        }

        public FrmCompareFeature(GSOGlobeControl _globeControl1, GSOGlobeControl _globeControl2,
            GSOLayer _layerTemp, GSOLayer _layerTemp2)
        {
            globeControl1 = _globeControl1;
            globeControl2 = _globeControl2;
            InitializeComponent();

            globeControl1.Globe.Action = EnumAction3D.SelectObject;
            globeControl2.Globe.Action = EnumAction3D.SelectObject;
            layerTemp = _layerTemp;
            layerTemp2 = _layerTemp2;

            globeControl1.MouseClick += globeControl1_MouseClick;
            globeControl2.MouseClick += globeControl2_MouseClick;
        }

        private void buttonAnalysis_Click(object sender, EventArgs e)
        {
            dataGridViewX1.DataSource = null;

            double bufferWidth = Convert.ToDouble(textBox1.Text);

            if (srcFeature == null || dscFeature == null)
                MessageBox.Show("请选择要对比的管段!", "提示");
            else
            {
                if (srcFeature.Geometry.Type != dscFeature.Geometry.Type)
                    MessageBox.Show("请选择同种类型图层!");
                else if (srcFeature.Geometry.Type == dscFeature.Geometry.Type &&
                         srcFeature.Geometry.Type == EnumGeometryType.GeoPolyline3D)
                {
                    lineLayerCompare(srcFeature, dscFeature, bufferWidth);
                    if (!isSamePolyline)
                        MessageBox.Show("实测管段与施工管段非同一条管段,请选择同一管段进行比较!", "提示");
                    else
                    {
                        lineFeatureCompare(srcFeature, dscFeature);
                        globeControl1.Globe.Action = EnumAction3D.ActionNull;
                        globeControl2.Globe.Action = EnumAction3D.ActionNull;
                    }
                }
                else
                    MessageBox.Show("无法处理该类型图层!");
            }
        }

        /// <summary>
        /// 在容差范围内判断是否同一根管段
        /// </summary>
        /// <param name="srcFeature"></param>
        /// <param name="dscFeature"></param>
        /// <param name="bufferWidth"></param>
        /// <returns></returns>
        private bool lineLayerCompare(GSOFeature srcFeature, GSOFeature dscFeature, double bufferWidth)
        {
            isSamePolyline = false;

            GSOGeoPolyline3D srcLine = srcFeature.Geometry as GSOGeoPolyline3D;
            GSOGeoPolygon3D srcBufferPolygon = srcLine.CreateBuffer(bufferWidth * 2, true, 5, true, false);
            GSOLayer dsc = globeControl2.Globe.Layers.GetLayerByCaption(dscFeature.Dataset.Caption);

            if (srcBufferPolygon != null)
            {
                GSOFeatures featuresInSrcLayer = dsc.FindFeaturesInPolygon(srcBufferPolygon, true);

                if (featuresInSrcLayer != null && featuresInSrcLayer.Length > 0)
                {
                    for (int i = 0; i < featuresInSrcLayer.Length; i++)
                    {
                        if (featuresInSrcLayer[i].Name == dscFeature.Name)
                        {
                            isSamePolyline = true;
                            break;
                        }
                    }
                }
            }

            GSOGeoPolyline3D dscLine = dscFeature.Geometry as GSOGeoPolyline3D;
            GSOGeoPolygon3D dscBufferPolygon = dscLine.CreateBuffer(bufferWidth * 2, true, 5, true, false);
            GSOLayer src = globeControl1.Globe.Layers.GetLayerByCaption(srcFeature.Dataset.Caption);

            if (dscBufferPolygon != null)
            {
                GSOFeatures featuresInDscLayer = src.FindFeaturesInPolygon(dscBufferPolygon, true);

                if (featuresInDscLayer != null && featuresInDscLayer.Length > 0)
                {
                    for (int i = 0; i < featuresInDscLayer.Length; i++)
                    {
                        if (featuresInDscLayer[i].Name == srcFeature.Name)
                        {
                            isSamePolyline = true;
                            break;
                        }
                    }
                }
            }

            return isSamePolyline;
        }

        /// <summary>
        /// 分析两根管段的具体差异
        /// </summary>
        /// <param name="srcFeature"></param>
        /// <param name="dscFeature"></param>
        private void lineFeatureCompare(GSOFeature srcFeature, GSOFeature dscFeature)
        {
            GSOGeoPolyline3D srcLine = srcFeature.Geometry as GSOGeoPolyline3D;
            double srcLineLength = srcLine.GetSpaceLength(false, 6378137);

            GSOGeoPolyline3D dscLine = dscFeature.Geometry as GSOGeoPolyline3D;
            double dscLineLength = dscLine.GetSpaceLength(false, 6378137);

            double horizonDistance = calculateDistance(srcLine, dscLine,false);
            double verticalDistance = calculateDistance(srcLine, dscLine,true);

            DataTable dt = new DataTable();
            dt.Columns.Add("数据名称");
            dt.Columns.Add("图层名称");
            dt.Columns.Add("管段编号");
            dt.Columns.Add("管段长度");
            dt.Columns.Add("材质");
            dt.Columns.Add("水平距离/米");
            dt.Columns.Add("垂直距离/米");

            DataRow srcRow = dt.NewRow();
            srcRow[0] = "实测数据";
            srcRow[1] = srcFeature.Dataset.Caption;
            srcRow[2] = srcFeature.Name;
            srcRow[3] = srcLineLength.ToString("0.000");
            srcRow[4] = srcFeature.GetFieldAsString("材质");
            srcRow[5] = horizonDistance.ToString("0.000");
            srcRow[6] = verticalDistance.ToString("0.000");
            dt.Rows.Add(srcRow);

            DataRow dscRow = dt.NewRow();
            dscRow[0] = "施工数据";
            dscRow[1] = dscFeature.Dataset.Caption;
            dscRow[2] = dscFeature.Name;
            dscRow[3] = dscLineLength.ToString("0.000");
            dscRow[4] = dscFeature.GetFieldAsString("材质");
            dscRow[5] = horizonDistance.ToString("0.000");
            dscRow[6] = verticalDistance.ToString("0.000");
            dt.Rows.Add(dscRow);

            dataGridViewX1.DataSource = dt;
        }

        private void FrmCompareFeature_FormClosing(object sender, FormClosingEventArgs e)
        {
            globeControl1.Globe.Action = EnumAction3D.ActionNull;
            globeControl2.Globe.Action = EnumAction3D.ActionNull;
            frm = null;
        }

        private void addPologyToGlobeControl(GSOGeoPolyline3D line, double bufferWidth)
        {
            new_feat = new GSOFeature();
            resPolygon = line.CreateBuffer(bufferWidth*2, true, 0, false, false);
            resPolygon.AltitudeMode = EnumAltitudeMode.RelativeToGround;
            new_feat.Geometry = resPolygon;

            layerTemp.AddFeature(new_feat);
            layerTemp2.AddFeature(new_feat);
            globeControl1.Refresh();
            globeControl2.Refresh();
        }

        private GSOLayer getSameLayer(GSOFeature feature)
        {
            GSOLayer layer = null;
            if (!feature.Dataset.Caption.StartsWith("施工"))
            {
                layer = feature.Dataset.Caption == "供电管线"
                    ? globeControl2.Globe.Layers.GetLayerByCaption("施工电力管线")
                    : globeControl2.Globe.Layers.GetLayerByCaption("施工" + feature.Dataset.Caption);
            }
            else
            {
                layer = feature.Dataset.Caption == "施工电力管线"
                    ? globeControl1.Globe.Layers.GetLayerByCaption("供电管线")
                    : globeControl1.Globe.Layers.GetLayerByCaption(feature.Dataset.Caption.Replace("施工", ""));
            }

            return layer;
        }

        /// <summary>
        /// 地球1中点击地球2中同步添加缓冲区
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void globeControl1_MouseClick(object sender, MouseEventArgs e)
        {
            layerTemp.Visible = true;
            layerTemp2.Visible = true;
            GSOFeatures listFeatures = new GSOFeatures();
            double maxLength = 0;

            if (globeControl1.Globe.SelectedObject == null) return;
            else
            {
                clearFeatureHighLight(globeControl1, globeControl2);
                try
                {
                    double bufferWidth = Convert.ToDouble(textBox1.Text);
                    resPolygon = null;

                    if (globeControl1.Globe.Action == EnumAction3D.SelectObject &&
                        globeControl1.Globe.SelectedObject != null)
                    {
                        GSOGeoPolyline3D line = globeControl1.Globe.SelectedObject.Geometry as GSOGeoPolyline3D;
                        addPologyToGlobeControl(line, bufferWidth);
                    }

                    srcFeature = globeControl1.Globe.SelectedObject;
                    GSOLayer layers = getSameLayer(srcFeature);

                    GSOFeatures features = layers.FindFeaturesInPolygon(resPolygon, false);
                    GSOGeoPolyline3D scLine = srcFeature.Geometry as GSOGeoPolyline3D;

                    for (int i = 0; i < features.Length; i++)
                    {
                        lineLayerCompare(srcFeature, features[i], Convert.ToDouble(textBox1.Text));
                        if (isSamePolyline)
                            listFeatures.Add(features[i]);
                    }
                    calculate(out maxLength, out dscFeature, listFeatures, scLine);
                   
                }
                catch (Exception ex)
                {
                    LogError.PublishError(ex);
                }
            }
        }

        /// <summary>
        /// 地球2中点击地球1中同步添加缓冲区
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void globeControl2_MouseClick(object sender, MouseEventArgs e)
        {
            layerTemp.Visible = true;
            layerTemp2.Visible = true;
            GSOFeatures listFeatures = new GSOFeatures();
            double maxLength = 0;

            if (globeControl2.Globe.SelectedObject == null) return;
            else
            {
                clearFeatureHighLight(globeControl1, globeControl2);
                try
                {
                    double bufferWidth = Convert.ToDouble(textBox1.Text);
                    resPolygon = null;

                    if (globeControl2.Globe.Action != EnumAction3D.SelectObject ||
                        globeControl2.Globe.SelectedObject == null)
                        return;
                    else
                    {
                        GSOGeoPolyline3D line = globeControl2.Globe.SelectedObject.Geometry as GSOGeoPolyline3D;

                        addPologyToGlobeControl(line, bufferWidth);
                    }

                    dscFeature = globeControl2.Globe.SelectedObject;
                    //双屏同时选中同一管段
                    GSOLayer layers = getSameLayer(dscFeature);

                    GSOFeatures features = layers.FindFeaturesInPolygon(resPolygon, false);
                    GSOGeoPolyline3D scLine = dscFeature.Geometry as GSOGeoPolyline3D;

                    for (int i = 0; i < features.Length; i++)
                    {
                        lineLayerCompare(features[i], dscFeature, Convert.ToDouble(textBox1.Text));
                        if (isSamePolyline)
                        {
                            listFeatures.Add(features[i]);
                        }
                    }
                    calculate(out maxLength, out srcFeature, listFeatures, scLine);

                }
                catch (Exception ex)
                {
                    LogError.PublishError(ex);
                }
            }
        }

        private void calculate(out double maxLength, out GSOFeature feature, GSOFeatures listFeatures,
            GSOGeoPolyline3D scLine)
        {
            maxLength = 0;
            feature=new GSOFeature();
            if (listFeatures.Length == 0)
                feature = null;
            else
            {
                if (listFeatures.Length == 1)
                {
                    feature = listFeatures[0];
                    listFeatures[0].HighLight = true;
                }
                else
                {
                    for (int m = 0; m < listFeatures.Length; m++)
                    {
                        GSOGeoPolyline3D tempSGLine = listFeatures[m].Geometry as GSOGeoPolyline3D;

                        double tempLength = tempSGLine.GetSpaceLength(false, 6378137);
                        double lengthAbs = Math.Abs(tempLength - scLine.GetSpaceLength(false, 6378137));
                        if (m == 0)
                        {
                            feature = listFeatures[0];
                            listFeatures[0].HighLight = true;
                            maxLength = lengthAbs;
                        }
                        else if (lengthAbs < maxLength)
                        {
                            feature = listFeatures[m];
                            listFeatures[m].HighLight = true;
                            maxLength = lengthAbs;
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 计算距离
        /// </summary>
        /// <param name="line1"></param>
        /// <param name="line2"></param>
        /// <returns></returns>
        double calculateDistance(GSOGeoPolyline3D line1, GSOGeoPolyline3D line2,bool isVertical)
        {
            GSOPoint3d pntIntersect1 = new GSOPoint3d();
            GSOPoint3d pntIntersect2 = new GSOPoint3d();
            GSOPoint3d pntProIntersect1 = new GSOPoint3d();
            GSOPoint3d pntProIntersect2 = new GSOPoint3d();
            double dDist = 0;
            if (isVertical)
            {
                dDist = globeControl1.Globe.Analysis3D.ComputeVerticalDistance(line1, line2,
                    out pntIntersect1, out pntIntersect2, out pntProIntersect1, out pntProIntersect2, false);

                LabelDistance(layerTemp, layerTemp2, pntProIntersect1, pntProIntersect2, dDist, true, "垂直");
            }
            else
            {
                dDist = globeControl1.Globe.Analysis3D.ComputeHorizonDistance(line1, line2,
                    out pntIntersect1, out pntIntersect2, out pntProIntersect1, out pntProIntersect2, false);

                LabelDistance(layerTemp, layerTemp2, pntProIntersect1, pntProIntersect2, dDist, true, "水平");
            }

            return dDist;
        }

        /// <summary>
        /// 清除所有高亮Feature
        /// </summary>
        /// <param name="glb"></param>
        private void clearFeatureHighLight(GSOGlobeControl glb1,GSOGlobeControl glb2)
        {
            layerTemp.RemoveAllFeature();
            layerTemp2.RemoveAllFeature();
            //清除gbl1中高亮
            for (int i = 0; i < glb1.Globe.Layers.Count; i++)
            {
                GSOLayer layer = glb1.Globe.Layers[i];
                if (!(layer is GSOFeatureLayer)) continue;
                GSOFeatures feats = layer.GetAllFeatures();
                for (int j = 0; j < feats.Length; j++)
                {
                    GSOFeature feat = feats[j];
                    feat.HighLight = false;
                }
            }
            //清除gbl2中高亮
            for (int i = 0; i < glb2.Globe.Layers.Count; i++)
            {
                GSOLayer layer = glb2.Globe.Layers[i];
                if (!(layer is GSOFeatureLayer)) continue;
                GSOFeatures feats = layer.GetAllFeatures();
                for (int j = 0; j < feats.Length; j++)
                {
                    GSOFeature feat = feats[j];
                    feat.HighLight = false;
                }
            }
        }

        /// <summary>
        /// 添加标注
        /// </summary>
        /// <param name="markerLayer"></param>
        /// <param name="pntIntersect1"></param>
        /// <param name="pntIntersect2"></param>
        /// <param name="distance"></param>
        /// <param name="markerVisible"></param>
        /// <returns></returns>
        private GSOPoint3d LabelDistance(GSOLayer markerLayer, GSOLayer markerLayer2, 
            GSOPoint3d pntIntersect1, GSOPoint3d pntIntersect2, double distance, bool markerVisible,string label)
        {
            if (pntIntersect1 == null || pntIntersect2 == null)
                return new GSOPoint3d();
            GSOGeoPolyline3D disline = new GSOGeoPolyline3D();
            GSOPoint3ds point3ds = new GSOPoint3ds();
            point3ds.Add(pntIntersect1);
            point3ds.Add(pntIntersect2);
            disline.AddPart(point3ds);
            
            GSOGeoMarker dismarker = new GSOGeoMarker();
            GSOFeature marker = null;
            GSOFeature line = null;
            createLineStyle(out marker, out line,disline, pntIntersect1, pntIntersect2, distance, label, dismarker);

            line.Visible = marker.Visible = markerVisible;
            markerLayer.AddFeature(line);
            markerLayer.AddFeature(marker);

            markerLayer2.AddFeature(line);
            markerLayer2.AddFeature(marker);

            return dismarker.Position;
        }
        /// <summary>
        /// 控制标注和字体的颜色
        /// </summary>
        /// <param name="marker"></param>
        /// <param name="line"></param>
        /// <param name="disline"></param>
        /// <param name="pntIntersect1"></param>
        /// <param name="pntIntersect2"></param>
        /// <param name="distance"></param>
        /// <param name="label"></param>
        /// <param name="dismarker"></param>
        private void createLineStyle(out GSOFeature marker,out GSOFeature line,GSOGeoPolyline3D disline,
            GSOPoint3d pntIntersect1,GSOPoint3d pntIntersect2, double distance, string label, GSOGeoMarker dismarker)
        {
            GSOSimpleLineStyle3D style = new GSOSimpleLineStyle3D(); //创建线的风格
            style.LineColor = Color.Red;
            style.LineWidth = 5;          //设置线的宽度为5
            style.VertexVisible = true; 	//显示线的节点
            disline.Style = style;          //把风格添加到线上
            disline.AltitudeMode = EnumAltitudeMode.Absolute;
            line=new GSOFeature();
            line.Geometry = disline;

            dismarker.X = pntIntersect1.X;
            dismarker.Y = pntIntersect1.Y;
            dismarker.Z = (pntIntersect1.Z + pntIntersect2.Z) / 2;
            dismarker.Text = label + distance.ToString("0.00") + "米";
            dismarker.AltitudeMode = EnumAltitudeMode.Absolute;

            GSOMarkerStyle3D styleMarker = new GSOMarkerStyle3D();
            GSOTextStyle styleText = new GSOTextStyle();
            styleText.IsSizeFixed = true;
            styleText.ForeColor = Color.Red;
            styleText.FontSize = 20;
            styleMarker.TextStyle = styleText;
            dismarker.Style = styleMarker;

            marker=new GSOFeature();
            marker.Geometry = dismarker;
        }

    }
}