duheng
2024-06-06 ccc0d2319b71cc41f4d9d2f86dff28da918987da
WinfrmUI/Hydro.WinfrmUI.Browser/Viewer.cs
@@ -1,9 +1,4 @@

using Hydro.CommonBase;
using Hydro.MapView;
using Hydro.MapView.Common;
using Newtonsoft.Json;
using System;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
@@ -13,11 +8,15 @@
using System.Drawing;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Windows.Forms;
using static Hydro.MapView.MapViewEnum;
using Cursor = System.Windows.Forms.Cursor;
using System.Numerics;
using System.Text;
using System.Windows.Forms;
using static Hydro.MapView.MapViewEnum;
using Hydro.CommonBase;
using Hydro.MapView;
using Hydro.MapView.Common;
using Newtonsoft.Json;
using DevExpress.Utils;
namespace Hydro.WinfrmUI
{
@@ -25,19 +24,19 @@
    {
        public static bool LockSelect = false;
        public static bool ApplyFilter = false;
        #region 一、全局
        #region 初始化
        private bool _showToolBar = true;
        [DisplayName("显示工具栏")]
        private bool _showToolBar = true;
        [DisplayName("显示工具栏")]
        public bool showToolBar
        {
            get
            {
                return _showToolBar;// this.panel1==null?true:Visible;
                return _showToolBar;// this.panel1==null?true:Visible;
            }
            set
            {
@@ -46,26 +45,21 @@
            }
        }
        public ViewBrowser()
        public ViewBrowser()
        {
            this.showToolBar = false;
            InitializeComponent();
            MapCenter = PointF.Empty;
            zoom = 1.0f;
            SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            BackColor = Color.Transparent;
        }
        private void MapViewer_Load(object sender, EventArgs e)
        {
            this.panel1.Visible = _showToolBar;
            cb_Node_Colour.Items.Clear();
            cb_Link_Colour.Items.Clear();
@@ -85,26 +79,19 @@
                i++;
            }
            cb_Node_Colour.SelectedIndex = 0;
            cb_Link_Colour.SelectedIndex = 0;
            map.Init(TC,new DrawDelegate[] { Draw, Draw, DrawH },new MouseDelegate[] { mapMouseDown, mapMouseMove, mapMouseUp, mapMouseWheel });
            map.Init(TC, new DrawDelegate[] { Draw, Draw, DrawH }, new MouseDelegate[] { mapMouseDown, mapMouseMove, mapMouseUp, mapMouseWheel });
        }
        #endregion
        #endregion 初始化
        #region 对外开放,全局控制方法
        public bool LoadData(bool isDelCache = false)
        {
            if (_Template == null) return false;
            if (isDelCache || _Template.network == null)
            {
@@ -124,7 +111,6 @@
                    if (param == null)
                        param = new dict<string, dynamic>();
                    _Template.network.LoadRepeaters(_Template.MaxLevel, param, _ViewModel, !_IsEditMode);
                }
                else
                {
@@ -140,7 +126,6 @@
                    if (param == null)
                        param = new dict<string, dynamic>();
                    _Template.network.LoadRepeaters(_Template.MaxLevel, param, _ViewModel, !_IsEditMode);
                }
                else
                {
@@ -148,7 +133,6 @@
                        param = new dict<string, dynamic>();
                    _Template.network.LoadRepeaters(_Template.MaxLevel, param, null, !_IsEditMode);
                }
            }
            //if (GlobalObject.PropertyForm != null)
            //{
@@ -157,15 +141,14 @@
            //    //_Template.network.MapObjects.AddUndoRedoSupport(GlobalObject.PropertyForm.propertyGrid);
            //}
            SetStartEndPoint(_Template.Node1, _Template.Node2);
            ResumeLayout(false);
            return true;
        }
        private Dictionary<TemplateType, bool> _ViewModel = null;
        Dictionary<TemplateType, bool> _ViewModel = null;
        public void Clear()
        {
            _Template = null;
@@ -175,15 +158,15 @@
            RotationF = 90;
            SetMapInvalidate();
        }
        public void SetData(Template template, dict<string, dynamic> param = null, Dictionary<TemplateType, bool> viewMode = null)
        {
            this.param = param;
            bool reLoad = _Template == template;
            this._Template = template;
            this._ViewModel = viewMode;
            if (!LoadData()) return;
            if (!reLoad)
            {
@@ -199,8 +182,6 @@
                    SetMapInvalidate();
                }
            }
            刷新楼层ToolStripMenuItem_Click(1, new EventArgs());
            if (OnChangeViewCenter != null)
            {
@@ -210,15 +191,15 @@
            {
                OnChangeViewZoom.Invoke(zoom);
            }
            if(OnChangeViewRotation != null)
            if (OnChangeViewRotation != null)
            {
                OnChangeViewRotation.Invoke(Rotation, RotationF);
            }
        }
        public Action<PointF> OnChangeViewCenter = null;//
        public Action<PointF> OnChangeViewCenter = null;//改变视图中心的委托
        public Action<double> OnChangeViewZoom = null;//
        public Action<double,double> OnChangeViewRotation = null;//
        public Action<double, double> OnChangeViewRotation = null;//
        private void InitCenter()
        {
@@ -245,7 +226,6 @@
            Rotation = 0;
            RotationF = 90;
            if (_Nodes.Count > 0)
            {
                p.X /= _Nodes.Count;
@@ -256,13 +236,10 @@
        public void SetMapInvalidate()
        {
            _needPaintAll = true;
            PMin_Show = ScreenToMap(new PointF(0, this.map.Height));
            PMax_Show = ScreenToMap(new PointF(this.map.Width, 0));
            _timerDraw = true;
        }
        public void SetStartEndPoint(String node1, string node2)
@@ -271,6 +248,7 @@
            _EndPoint = node2;
            SetMapInvalidate();
        }
        public void Set3DView(bool is3Dview, double 俯视角度)
        {
@@ -279,23 +257,18 @@
            SetMapInvalidate();
        }
        public void SetRotation(double d)
        {
            this.Rotation = d;
            SetMapInvalidate();
        }
        #endregion
        #endregion 对外开放,全局控制方法
        #region 重绘函数
        bool _needPaintAll
        {
        private bool _needPaintAll
        {
            get
            {
                return __needpaintall;
@@ -305,6 +278,7 @@
                __needpaintall = value;
            }
        }
        //protected override void OnPaint(PaintEventArgs e)
        //{
        //    base.OnPaint(e);
@@ -320,10 +294,7 @@
        //    int heightOfBar = showToolBar ? 24 : 0;
        //    if (!showToolBar) heightOfBar = 0;
        //    if (e.ClipRectangle != new Rectangle(this.Left, heightOfBar, this.map.Width, this.map.Height - heightOfBar - statusStrip1.Height)) return;
        //    _needPaintAll = false;
        //    if (buffer == null || buffer.Width != Width || buffer.Height != Height)
@@ -355,14 +326,12 @@
        //        //BookMark    :绘制地图事件
        //        Draw(bufferG, _Template);
        //        if (_newTemplate?.network != null) Draw(bufferG, _newTemplate);
        //        var r = 2f / zoom;
        //        if (_isDragging && DragStartPos!=new PointF(0,0) && mousePosition!=new PointF(0,0))
        //        {
        //            label_center.Text = $"S:{DragStartPos.X}:{DragStartPos.Y} E:{mousePosition.X}:{mousePosition.Y}";
        //            label_center.Text = $"S:{DragStartPos.X}:{DragStartPos.Y} E:{mousePosition.X}:{mousePosition.Y}";
        //            var _lastMousePosition = DragStartPos;
        //            // 绘制矩形
        //            var start = new PointF((float)Math.Min(mousePosition.X, _lastMousePosition.X), (float)Math.Min(mousePosition.Y, _lastMousePosition.Y));
@@ -408,7 +377,6 @@
        //        }
        //        if (_isSettingBackGroundPictur)
        //        {
        //            var _lastMousePosition = DragStartPos;
        //            // 绘制矩形
        //            var start = new PointF((float)Math.Min(mousePosition.X, _lastMousePosition.X), (float)Math.Min(mousePosition.Y, _lastMousePosition.Y));
@@ -441,7 +409,7 @@
        //}
        PointF[] getCurclePoints(int num)
        private PointF[] getCurclePoints(int num)
        {
            PointF[] points = new PointF[num + 1];
            float angle = 0;
@@ -456,11 +424,6 @@
            return points;
        }
        private void timer_draw_Tick(object sender, EventArgs e)
        {
            _mouseHoverCheckFlag = true;
@@ -475,38 +438,32 @@
            // 当控件尺寸改变时,触发重绘
            this.SetMapInvalidate();
        }
        #endregion
        #endregion 重绘函数
        #region 鼠标事件
        void mapMouseDown(MouseEventArgs e)
        private void mapMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            _ClickStartPos = new PointF(e.X, e.Y);
            DragStartPos= ScreenToMap(new PointF(e.X, e.Y));
            DragStartPos = ScreenToMap(new PointF(e.X, e.Y));
            mousePosition = _MousePosition = ScreenToMap(new PointF(e.X, e.Y));
            if (e.Button == MouseButtons.Left && _isInsertingObject)
            {
            }
            else
            if (e.Button == MouseButtons.Middle || e.Button == MouseButtons.XButton2)
            {
                if (ModifierKeys == Keys.Control || ModifierKeys == Keys.Shift)//按下框选放大
                {
                    DragStartPos = ScreenToMap(new PointF(e.X, e.Y));
                    _isDragging = true;
                }
                else
                {
                    _lastCursor = this.Cursor;
                    this.Cursor = Cursors.SizeAll;
                    MapCenter0 = MapCenter;
@@ -516,8 +473,6 @@
            }
            else if (e.Button == MouseButtons.Left && _mouseState == MouseState.无)
            {
                if (ModifierKeys == Keys.Shift)
                {
                    var point = ScreenToMap(new PointF(e.X, e.Y));
@@ -545,14 +500,10 @@
                    List<NodeViewModel> nodes = selectedNodes;
                    foreach (NodeViewModel node in nodes)
                    {
                        PointF mapPos = WorldPointToMapPoint(node);
                        PointF currentPoint = MapToScreen(mapPos);
                        if (Get_dist(new PointF(e.X, e.Y), currentPoint) < 15f)
                        {
                            _NewNet.Nodes.AddRange(selectedNodes);
                            _NewNet.Links.AddRange(selectedLinks);
                            _isMovingObject = true;
@@ -563,15 +514,12 @@
                    }
                }
                if (!_isMovingObject)//拖拽选择
                {
                    DragStartPos = ScreenToMap(new PointF(e.X, e.Y));
                    _isDragging = true;
                }
            }
            else if (e.Button == MouseButtons.Left && _mouseState == MouseState.设置底图范围)
            {
                _mouseState = MouseState.无;
@@ -590,8 +538,8 @@
                mapOption0 = mapOption.Copy();
                _isRotating = true;
            }
        }
        private bool IsPointInPolygon(PointF point, List<PointF> polygon)
        {
            int count = polygon.Count;
@@ -622,9 +570,10 @@
            //if (_OperaNode == null) _OperaNode=_NewNet.Nodes[0];
        }
        bool controlDown = false;
        PointF _MousePosition = new PointF(0, 0);
        void mapMouseMove(MouseEventArgs e)
        private bool controlDown = false;
        private PointF _MousePosition = new PointF(0, 0);
        private void mapMouseMove(MouseEventArgs e)
        {
            //base.OnMouseMove(e);
            bool needInvalidate = false;
@@ -635,36 +584,30 @@
                var oldP = (PointF3D)_undoOldValue;
                if (!float.IsInfinity(p.X) && !float.IsInfinity(p.Y)) _newTemplate.OffSet = new PointF3D(p.X - oldP.X, p.Y - oldP.Y, 0); //_OperaNode.Position = p;
               // GlobalObject.PropertyForm.propertyGrid.Refresh();
                // GlobalObject.PropertyForm.propertyGrid.Refresh();
                needInvalidate = true;
            }
            else if (_isPainting)
            {
                needInvalidate = true;
            }
            else if (_isPanning)
            {
                var vector = GetRotateVector(new PointF(e.X, e.Y), new PointF(_lastMouseX, _lastMouseY));
                MapCenter = new PointF(MapCenter.X - vector.X / Zoom.X, MapCenter.Y - vector.Y / Zoom.Y);
                if (OnChangeViewCenter != null)
                {
                    OnChangeViewCenter.Invoke(MapCenter);
                }
                needInvalidate = true;
                needInvalidate = true;
            }
            else if (_isDragging || _isDrawingPolygon || _isSettingBackGroundPictur)
            {
                mousePosition = _MousePosition;
                // 绘制选择框
                // 绘制选择框
                // Rectangle selectionRect = new Rectangle(
                //    Math.Min((int)DragStartPos.X, (int)MP.X),
                //    Math.Min((int)DragStartPos.Y, (int)MP.Y),
@@ -672,7 +615,6 @@
                //    Math.Abs((int)DragStartPos.Y - (int)MP.Y));
                //DrawSelectionRect(selectionRect);
                needInvalidate = true;
            }
            else if (_isRotating)
            {
@@ -683,7 +625,6 @@
                if (RotationF > 90) RotationF = 90;
                if (RotationF < 0) RotationF = 0;
                needInvalidate = true;
            }
            else
@@ -695,8 +636,6 @@
                //GlobalObject.PropertyForm.propertyGrid.Refresh();
                needInvalidate = true;
            }
            //else
            /*判断是否触碰到对象*/
@@ -706,7 +645,7 @@
                // 遍历所有对象,找出范围内的对象
                PointF clickedPoint = new PointF(e.X, e.Y);  //ScreenToMap(new PointF(e.X, e.Y));
                var obj = GetObj_by_ScreenPoint(clickedPoint);
                if (hoveredObjs.Count > 0 && hoveredObjs[0] == obj || hoveredObjs.Count==0 && obj==null)
                if (hoveredObjs.Count > 0 && hoveredObjs[0] == obj || hoveredObjs.Count == 0 && obj == null)
                {
                    //needInvalidate = false;
                }
@@ -715,34 +654,28 @@
                    needInvalidate = true;
                    hoveredObjs.ForEach(o => o.Hovered = false);
                    hoveredObjs.Clear();
                    if (obj!=null)
                    if (obj != null)
                    {
                        obj.Hovered = true;
                        hoveredObjs.Add(obj);
                    }
                }
            }
            if (needInvalidate) this.SetMapInvalidate();
            if(OnChangeMonseClickPostion != null)
            if (OnChangeMonseClickPostion != null)
            {
                OnChangeMonseClickPostion(e.X, e.Y, _MousePosition);
            }
            _lastMouseX = e.X;
            _lastMouseY = e.Y;
        }
        public Action<int,int,PointF> OnChangeMonseClickPostion = null;
        bool RectangContain(RectangleF r, PointF p)
        public Action<int, int, PointF> OnChangeMonseClickPostion = null;
        private bool RectangContain(RectangleF r, PointF p)
        {
            var x = p.X; var y = p.Y;
            if (r.X <= x && x < r.X + r.Width && r.Y <= y)
            {
@@ -755,12 +688,14 @@
        /// <summary>
        /// 用于绘制管线
        /// </summary>
        NodeViewModel _select_junction1 = null;
        NodeViewModel _select_junction2 = null;
        DateTime _lastMouseUp = DateTime.Now;
        int doubleClick_Delay = 500;//毫秒
        bool recordView = false;
        void mapMouseUp(MouseEventArgs e)
        private NodeViewModel _select_junction1 = null;
        private NodeViewModel _select_junction2 = null;
        private DateTime _lastMouseUp = DateTime.Now;
        private int doubleClick_Delay = 500;//毫秒
        private bool recordView = false;
        private void mapMouseUp(MouseEventArgs e)
        {
            //BookMark    :鼠标抬起事件
            base.OnMouseUp(e);
@@ -805,7 +740,6 @@
                _isDragging = false;
                this.Cursor = _lastCursor;
                var _lastMousePosition = DragStartPos;
@@ -868,8 +802,6 @@
                NodeViewModel minNode = null;
                foreach (NodeViewModel node in nodes)
                {
                    PointF mapPos = WorldPointToMapPoint(node);
                    PointF currentPoint = MapToScreen(mapPos);
                    float currentDist = 0;
@@ -884,16 +816,12 @@
                if (ModifierKeys != Keys.Alt && minNode != null)
                {
                    var p1 = (PointF3D)_undoOldValue;
                    var p2 = minNode.Position3D;
                    var dd = _newTemplate.OffSet;
                    dx = p2.X - p1.X;
                    dy = p2.Y - p1.Y;
                    dz = p2.Z - p1.Z;
                }
                else
                {
@@ -909,9 +837,7 @@
                    dx = dd.X; //p2.X - p1.X;
                    dy = dd.Y;// p2.Y - p1.Y;
                    dz = dd.Z;// p2.Z - p1.Z;
                }
                net.Nodes.ForEach(n => { ((NodeViewModel)n).Position3D = new PointF3D(n.X + dx, n.Y + dy, n.Elev + dz); });
@@ -937,7 +863,7 @@
                //_OperaNode = null;
                //_Network.Nodes.AddRange(net.Nodes);
                //_Network.Links.AddRange(net.Links);
                SetMapInvalidate();
                return;
            }
@@ -964,7 +890,6 @@
                            n.Selected = true;
                        }
                    });
                }
                SetMapInvalidate();
                // 结束绘制多边形
@@ -977,8 +902,6 @@
                NodeViewModel minNode = null;
                foreach (NodeViewModel node in nodes)
                {
                    PointF mapPos = WorldPointToMapPoint(node);
                    PointF currentPoint = MapToScreen(mapPos);
                    float currentDist = 0;
@@ -989,7 +912,6 @@
                        break;
                    }
                }
                if (ModifierKeys != Keys.Alt && minNode != null)
                {
@@ -1056,21 +978,25 @@
                        n = _Network.AddJunction(p, z);
                        MapObjectExtensions.AddCommand(_Network, "Add", null, new List<IBaseViewModel>() { n });
                        break;
                    case MouseState.新建水表:
                        getPointAndHeight(e, out p, out z);
                        n = _Network.AddMeter(p);
                        MapObjectExtensions.AddCommand(_Network, "Add", null, new List<IBaseViewModel>() { n });
                        break;
                    case MouseState.新建水库:
                        getPointAndHeight(e, out p, out z);
                        n = _Network.AddReservoir(p);
                        MapObjectExtensions.AddCommand(_Network, "Add", null, new List<IBaseViewModel>() { n });
                        break;
                    case MouseState.新建水池:
                        getPointAndHeight(e, out p, out z);
                        n = _Network.AddTank(p);
                        MapObjectExtensions.AddCommand(_Network, "Add", null, new List<IBaseViewModel>() { n });
                        break;
                    case MouseState.新增管线:
                    case MouseState.新增立管:
                    case MouseState.新建水泵:
@@ -1078,7 +1004,7 @@
                    case MouseState.新建重复器:
                        if (_select_junction1 == null)
                        {
                            if (_mouseState==MouseState.新增立管)
                            if (_mouseState == MouseState.新增立管)
                            {
                                var m = ScreenToVMap(new PointF(e.X, e.Y));
                                z = m.Y;
@@ -1090,19 +1016,18 @@
                                getPointAndHeight(e, out p, out z);
                                Set_junction1(e);
                            }
                        }
                        else
                        {
                            if (_mouseState == MouseState.新增立管)
                            {
                                //需要把鼠标位置转换为立管的位置,获取鼠标位置的高程
                                var wPos = GetZZWorldPoint(_select_junction1.Position3D, _MousePosition, new Vector3(0, 0, 1));
                                //var m = ScreenToVMap(new PointF(e.X, e.Y));
                                //z = m.Y;
                                p = new PointF(wPos.X, wPos.Y);
                                var l = AddLink(new PointF( e.X,e.Y), true, p, wPos.Z);
                                var l = AddLink(new PointF(e.X, e.Y), true, p, wPos.Z);
                                if (l.Count > 0) MapObjectExtensions.AddCommand(_Network, "Add", null, l);
                            }
                            else
@@ -1110,9 +1035,7 @@
                                getPointAndHeight(e, _select_junction1, out p, out z);
                                var l = AddLink(new PointF(e.X, e.Y), isdoubleClick, p, z);
                                if (l.Count > 0) MapObjectExtensions.AddCommand(_Network, "Add", null, l);
                            }
                        }
                        break;
                }
@@ -1135,11 +1058,10 @@
                    if (isJunction) _OperaNode = (NodeViewModel)obj;
                    mousePosition = new PointF(0, 0);
                    SetMapInvalidate();
                }
                else
                {
                   // GlobalObject.PropertyForm.SetObjs(new List<IBaseViewModel>() { });
                    // GlobalObject.PropertyForm.SetObjs(new List<IBaseViewModel>() { });
                    _OperaNode = null;
                    mousePosition = new PointF(0, 0);
                    SetMapInvalidate();
@@ -1160,7 +1082,6 @@
                var selectedObjs = new List<IBaseViewModel>();
                for (int i = 0; i < _Nodes.Count; i++)
                {
                    var node = _Nodes[i] as NodeViewModel;
                    if (!node.Visible) continue;
                    PointF p = WorldPointToMapPoint(node);
@@ -1168,7 +1089,6 @@
                    if (RectangContain(rectangle0, p))
                    {
                        selectedObjs.Add(node);
                    }
                }
@@ -1192,7 +1112,6 @@
            }
            if /*叠加框选*/(isMouseMoved && _mouseState == MouseState.无 && e.Button == MouseButtons.Left && ModifierKeys == Keys.Control)
            {
                _isDragging = false;
                Cursor = Cursors.Default;
@@ -1204,7 +1123,6 @@
                var rectangle0 = new RectangleF(start, size);
                for (int i = 0; i < _Nodes.Count; i++)
                {
                    var node = _Nodes[i] as NodeViewModel;
                    if (!node.Visible) continue;
                    PointF p = WorldPointToMapPoint(node);
@@ -1221,7 +1139,6 @@
                            node.Selected = true;
                            selectedObjs.Add(node);
                        }
                    }
                }
@@ -1314,11 +1231,8 @@
                    //    GlobalObject.PropertyForm.SetObjs(selectedObjs);
                    _OperaNode = null;
                    SetMapInvalidate();
                    mousePosition = new PointF(0, 0);
                }
                else
                {
@@ -1334,8 +1248,6 @@
                    SetMapInvalidate();
                }
                return;
            }
            if (/*叠加点选*/!isMouseMoved && _mouseState == MouseState.无 && e.Button == MouseButtons.Left && ModifierKeys == Keys.Control)
@@ -1389,13 +1301,13 @@
                }
            }
        }
        private void getPointAndHeight(MouseEventArgs e, out PointF p, out float z)
        {
            z = 0;
            if (RotationF != 0)
            {
                p = MapPointToWorldPoint(ScreenToMap(new PointF(e.X, e.Y), z));
            }
            else
            {
@@ -1404,13 +1316,13 @@
                p = new PointF(m.X, 0);
            }
        }
        private void getPointAndHeight(MouseEventArgs e, NodeViewModel j, out PointF p, out float z)
        {
            z = j.Elev;
            if (RotationF != 0)
            {
                p = MapPointToWorldPoint(ScreenToMap(new PointF(e.X, e.Y), j.Elev), j.Elev);
            }
            else
            {
@@ -1419,10 +1331,11 @@
                p = new PointF(j.X, j.Y);
            }
        }
        IBaseViewModel GetObj_by_ScreenPoint(PointF clickedPoint, float DistLimit = 15f)
        private IBaseViewModel GetObj_by_ScreenPoint(PointF clickedPoint, float DistLimit = 15f)
        {
            float minDist = float.MaxValue;
            int minIndex = -1;
            bool isJunction = true;
            IBaseViewModel obj = null;
@@ -1466,14 +1379,14 @@
            return obj;
        }
        List<IBaseViewModel> GetObjs_by_ScreenPoint(PointF clickedPoint, float DistLimit = 15f)
        private List<IBaseViewModel> GetObjs_by_ScreenPoint(PointF clickedPoint, float DistLimit = 15f)
        {
            float minDist = float.MaxValue;
            int minIndex = -1;
            IBaseViewModel obj = null;
            List < IBaseViewModel > objs = new List<IBaseViewModel>();
            List<IBaseViewModel> objs = new List<IBaseViewModel>();
            for (int i = 0; i < _Nodes.Count; i++)
            {
                var node = _Nodes[i] as NodeViewModel;
@@ -1502,8 +1415,6 @@
                //float dist = Get_dist(clickedPoint, currentPoint);
                if (dist < minDist && dist <= DistLimit)
                {
                    objs.Add(link);
                }
            }
@@ -1514,7 +1425,7 @@
        /// 鼠标滚轮事件
        /// </summary>
        /// <param name="e"></param>
        void mapMouseWheel(MouseEventArgs e)
        private void mapMouseWheel(MouseEventArgs e)
        {
            base.OnMouseWheel(e);
            mapOption0 = mapOption.Copy();
@@ -1528,14 +1439,15 @@
        private int _lastMouseX;
        private int _lastMouseY;
        #endregion
        #endregion 鼠标事件
        #endregion 一、全局
        #region 二、工具栏
        #region 视角工具
        // 显示点属性
        private void ShowProperties(IBaseViewModel obj)
        {
@@ -1548,9 +1460,11 @@
        private void label_center_Click(object sender, EventArgs e)
        {
          //  GlobalObject.PropertyForm.SetObj(MapCenter);
            //  GlobalObject.PropertyForm.SetObj(MapCenter);
        }
        double 俯视角度_bak = 45;
        private double 俯视角度_bak = 45;
        private void tool视角_ButtonClick(object sender, EventArgs e)
        {
            mapOption0 = mapOption.Copy();
@@ -1562,25 +1476,23 @@
            {
                俯视角度_bak = RotationF;
                RotationF = 90;
            }
            if (recordView) MapObjectExtensions.AddCommand(mapOption, "Map", mapOption0, mapOption);
            SetMapInvalidate();
        }
        private void tool设置俯视角度_Click(object sender, EventArgs e)
        public void tool设置俯视角度(string text)
        {
            mapOption0 = mapOption.Copy();
            double jiaodu = 45;
            var tool = sender as ToolStripItem;
            jiaodu = Convert.ToDouble(tool.Text);
            // var tool = sender as ToolStripItem;
            jiaodu = Convert.ToDouble(text);
            RotationF = jiaodu;
            if (recordView) MapObjectExtensions.AddCommand(mapOption, "Map", mapOption0, mapOption);
            SetMapInvalidate();
        }
        public void 重置视角ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 重置视角ToolStripMenu()
        {
            mapOption0 = mapOption.Copy();
@@ -1590,6 +1502,7 @@
            if (recordView) MapObjectExtensions.AddCommand(mapOption, "Map", mapOption0, mapOption);
            SetMapInvalidate();
        }
        private void 正视图ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mapOption0 = mapOption.Copy();
@@ -1598,6 +1511,7 @@
            SetMapInvalidate();
        }
        private void 俯视图ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mapOption0 = mapOption.Copy();
@@ -1606,12 +1520,11 @@
            SetMapInvalidate();
        }
        private void 默认视角ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mapOption0 = mapOption.Copy();
            InitCenter();
            RotationF = 45;
            Rotation = -45;
@@ -1619,6 +1532,7 @@
            SetMapInvalidate();
        }
        private void 设为隐藏ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            selectedObjs.ForEach(v =>
@@ -1628,11 +1542,11 @@
                    MapObjectExtensions.AddCommand(v, "Visible", v.Visible, false);
                    v.Visible = false;
                }
            });
            this.SetMapInvalidate();
        }
        private void 设置长度ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //double length = 0;
@@ -1642,7 +1556,6 @@
            //{
            //    if (double.TryParse(input.ShowDialog(), out length))
            //    {
            //        var count1 = _Links.FindAll(ll => ll.Node1 == l.StartNode.ID || ll.Node2 == l.StartNode.ID).Count;
            //        var count2 = _Links.FindAll(ll => ll.Node1 == l.EndNode.ID || ll.Node2 == l.EndNode.ID).Count;
            //        if (count1 > 1 && count2 <= 1)
@@ -1664,15 +1577,11 @@
            //}
            //this.SetMapInvalidate();
        }
        void MovePointbyLength(NodeViewModel node1, NodeViewModel node2, float Length)
        {
        private void MovePointbyLength(NodeViewModel node1, NodeViewModel node2, float Length)
        {
            float distance = Vector3.Distance(new Vector3(node1.X, node1.Y, node1.Elev), new Vector3(node2.X, node2.Y, node2.Elev));
            if (distance > 0)
@@ -1698,6 +1607,7 @@
                //Console.WriteLine("移动后点 B 的坐标为 ({0}, {1}, {2})", x2, y2, z2);
            }
        }
        private void 全部显示ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            _Nodes.Select(n => (NodeViewModel)n).ToList().ForEach(v =>
@@ -1719,13 +1629,25 @@
            });
            this.SetMapInvalidate();
        }
        #endregion
        #endregion 视角工具
        #region 文件工具
        public void OpenFile(string filePath)
        {
            _Template = new Template();
            _Template.network = new MapViewNetWork();
            // 读取文件内容
            _Network.BuildFromInp(filePath);
            _Template.filePath = filePath;
            //_filePath = filePath;
            SetData(_Template);
        }
        private void tool打开_ButtonClick(object sender, EventArgs e)
        {
            // 创建打开文件对话框
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "INP Files (*.inp)|*.inp|All Files (*.*)|*.*";
@@ -1734,8 +1656,7 @@
            {
                _Template = new Template();
                _Template.network = new MapViewNetWork();
                //_Template.network.use_old = false;
                // 获取选中文件的文件路径
                string filePath = openFileDialog.FileName;
@@ -1748,58 +1669,26 @@
                }
            }
        }
        public void OpenFile(string filePath)
        {
            _Template = new Template();
            _Template.network = new MapViewNetWork();
        //private void 旧版打开ToolStripMenuItem_Click(object sender, EventArgs e)
        //{
        //    // 创建打开文件对话框
            {
                // 读取文件内容
                _Network.BuildFromInp(filePath);
                _Template.filePath = filePath;
                //_filePath = filePath;
                SetData(_Template);
            }
        }
        private void 旧版打开ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // 创建打开文件对话框
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "INP Files (*.inp)|*.inp|All Files (*.*)|*.*";
        //        _Template = new Template();
        //        _Template.network = new MapViewNetWork();
        //        //_Template.network.use_old = true;
        //        // 获取选中文件的文件路径
        //        string filePath = openFileDialog.FileName;
        //        {
        //            // 读取文件内容
        //            _Network.BuildFromInp(filePath);
        //            _Template.filePath = filePath;
        //            //_filePath = filePath;
        //            SetData(_Template);
        //        }
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                _Template = new Template();
                _Template.network = new MapViewNetWork();
                //_Template.network.use_old = true;
                // 获取选中文件的文件路径
                string filePath = openFileDialog.FileName;
                {
                    // 读取文件内容
                    _Network.BuildFromInp(filePath);
                    _Template.filePath = filePath;
                    //_filePath = filePath;
                    SetData(_Template);
                }
            }
        }
        //}
        private void 打开文件位置ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (_filePath == null) return;
            FileInfo fi = new FileInfo(_filePath);
            Process.Start("explorer.exe", $"/select,\"{_filePath}\"");
            //System.Diagnostics.Process.Start("explorer.exe", fi.Directory.FullName);
        }
        private void EPA中打开ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (_filePath == null) return;
            Process.Start(@"epanetH\Epanet2wH.exe", _filePath);
        }
        private void 保存ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (!_IsEditMode)
@@ -1807,7 +1696,6 @@
                if (message.show("提醒", "浏览模式无法保存,是否恢复为编辑模式"))
                {
                    _IsEditMode = true;
                }
                else
                    return;
@@ -1818,52 +1706,43 @@
        private void toolStripButton_save_Click(object sender, EventArgs e)
        {
        }
        private void 另存ToolStripMenuItem_Click(object sender, EventArgs e)
        {
        }
        private void 导出形状ToolStripMenuItem_Click(object sender, EventArgs e)
        {
        }
        #endregion
        #endregion 文件工具
        #region 绘图工具
        public void toolStripButton_新建节点_Click(object sender, EventArgs e)
        public void NewNode()
        {
            _mouseState = MouseState.新增节点;
            Cursor = Cursors.Cross;
        }
        public void toolStripButton_普通_Click(object sender, EventArgs e)
        {
            _mouseState = MouseState.无;
            Cursor = Cursors.Default;
        }
        public void toolStripButton_新建管线_Click(object sender, EventArgs e)
        public void NewLink()
        {
            _mouseState = MouseState.新增管线;
            Cursor = Cursors.Cross;
        }
        public void toolStripButton_新建立管_Click(object sender,EventArgs e)
        public void NewVerticalLink()
        {
            _mouseState = MouseState.新增立管;
            Cursor = Cursors.Cross;
        }
        public void ResetOperateStatus()
        {
            _mouseState = MouseState.无;
            Cursor = Cursors.Cross;
        }
        private List<IBaseViewModel> AddLink(PointF e, bool isdoubleClick, PointF p, float z)
        {
@@ -1881,7 +1760,7 @@
                    l.Add(_select_junction2);
                }
                if (_mouseState == MouseState.新增管线 || _mouseState==MouseState.新增立管)
                if (_mouseState == MouseState.新增管线 || _mouseState == MouseState.新增立管)
                    l.Add(_Network.AddPipe(_select_junction1, _select_junction2));
                else if (_mouseState == MouseState.新建阀门)
                    l.Add(_Network.AddValve(_select_junction1, _select_junction2));
@@ -1893,8 +1772,6 @@
                _select_junction1 = null;
                _select_junction2 = null;
                _isPainting = false;
            }
            return l;
        }
@@ -1910,43 +1787,70 @@
            }
        }
        public void toolStripButton_添加水表_Click(object sender, EventArgs e)
        public void NewWaterMeter()
        {
            _mouseState = MouseState.新建水表;
            Cursor = Cursors.Cross;
        }
        public void toolStripButton_添加阀门_Click(object sender, EventArgs e)
        {
            _mouseState = MouseState.新建阀门;
            Cursor = Cursors.Cross;
        }
        public void toolStripButton_添加水泵_Click(object sender, EventArgs e)
        {
            _mouseState = MouseState.新建水泵;
            Cursor = Cursors.Cross;
        }
        public void toolStripButton_添加水库_Click(object sender, EventArgs e)
        public void NewTask()
        {
            _mouseState = MouseState.新建水库;
            Cursor = Cursors.Cross;
        }
        public void toolStripButton_添加水池_Click(object sender, EventArgs e)
        public void NewPool()
        {
            _mouseState = MouseState.新建水池;
            Cursor = Cursors.Cross;
        }
        public void toolStripButton_重复器_Click(object sender, EventArgs e)
        public void NewPump()
        {
            _mouseState = MouseState.新建水泵;
            Cursor = Cursors.Cross;
        }
        public void NewValve()
        {
            _mouseState = MouseState.新建阀门;
            Cursor = Cursors.Cross;
        }
        public void NewRepeater()
        {
            _mouseState = MouseState.新建重复器;
            Cursor = Cursors.Cross;
        }
        bool Buzylock = false;
        public void toolStripButton_添加水表_Click(object sender, EventArgs e)
        {
        }
        public void toolStripButton_添加阀门_Click(object sender, EventArgs e)
        {
        }
        public void toolStripButton_添加水泵_Click(object sender, EventArgs e)
        {
        }
        public void toolStripButton_添加水库_Click(object sender, EventArgs e)
        {
        }
        public void toolStripButton_添加水池_Click(object sender, EventArgs e)
        {
        }
        public void toolStripButton_重复器_Click(object sender, EventArgs e)
        {
        }
        private bool Buzylock = false;
        private void MapViewer_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Escape)
            {
                Cursor = _lastCursor;
@@ -1996,11 +1900,7 @@
                    _Links.ForEach(o => ((LinkViewModel)o).Selected = false);
                    selectedObjs.Clear();
                    SetMapInvalidate();
                }
            }
            if (e.KeyCode == Keys.Delete)
            {
@@ -2016,33 +1916,30 @@
            if (e.KeyCode == Keys.C && e.Modifiers == Keys.Control)
            {
                复制ToolStripMenuItem_Click(1, new EventArgs());
                复制ToolStripMenuItem();
            }
            if (e.KeyCode == Keys.V && e.Modifiers == Keys.Control)
            {
                _ClickStartPos = Cursor.Position;
                粘贴ToolStripMenuItem1_Click(1, new EventArgs());
                粘贴ToolStripMenuItem();
            }
            if (e.KeyCode == Keys.D1 && e.Modifiers == Keys.Control)
            {
                南北对齐ToolStripMenuItem_Click(1, new EventArgs());
                南北对齐ToolStripMenuItem();
            }
            if (e.KeyCode == Keys.Oemtilde && e.Modifiers == Keys.Control)
            {
                东西对齐ToolStripMenuItem_Click(1, new EventArgs());
                东西对齐ToolStripMenuItem();
            }
            if (e.KeyCode == Keys.D2 && e.Modifiers == Keys.Control)
            {
                竖直对齐ToolStripMenuItem_Click(1, new EventArgs());
                竖直对齐ToolStripMenuItem();
            }
            if (e.KeyCode == Keys.D3 && e.Modifiers == Keys.Control)
            {
                自动对齐ToolStripMenuItem_Click(1, new EventArgs());
                自动对齐ToolStripMenuItem();
            }
        }
        private void MapViewer_KeyPress(object sender, KeyPressEventArgs e)
        {
@@ -2074,6 +1971,7 @@
                e.Handled = true;
            }
        }
        private void MapViewer_PreKeyPress(object sender, PreviewKeyDownEventArgs e)
        {
            if (e.Control && e.KeyCode == Keys.Z)
@@ -2081,23 +1979,21 @@
                ctrlPressed = true;
                // 防止默认操作
                e.IsInputKey = true;
            }
            if (e.Control && e.KeyCode == Keys.Y)
            {
                ctrlPressed = true;
                // 防止默认操作
                e.IsInputKey = true;
            }
            if (e.Control && e.KeyCode == Keys.R)
            {
                ctrlPressed = true;
                // 防止默认操作
                e.IsInputKey = true;
            }
        }
        public void setCenter(IBaseViewModel obj)
        {
            PointF position;
@@ -2113,12 +2009,11 @@
            MapCenter.Y - vector.Y / Zoom.Y);
        }
        bool ctrlPressed = false;
        #endregion
        private bool ctrlPressed = false;
        #endregion 绘图工具
        #region 右键菜单
        private void 转换ToolStripMenuItem_Click(object sender, EventArgs e)
        {
@@ -2143,6 +2038,7 @@
                        }
                        junc.ID = ID;
                        break;
                    case "基本节点":
                        junc = _Network.AddJunction(obj.Position, obj.Elev);
@@ -2155,6 +2051,7 @@
                        }
                        junc.ID = ID;
                        break;
                    case "水库":
                        junc = _Network.AddReservoir(obj.Position);
                        i = 0;
@@ -2166,6 +2063,7 @@
                        }
                        junc.ID = ID;
                        break;
                    case "水池":
                        junc = _Network.AddTank(obj.Position);
                        i = 0;
@@ -2184,14 +2082,12 @@
                junc.Elev = obj.Elev;
                junc.Demand = obj.Demand;
                junc.Selected = true;
                foreach (var p in _Links)
                {
                    if (p.StartNode == obj)
                    {
                        p.StartNode = junc;
                    }
                    else if (p.EndNode == obj)
                    {
@@ -2204,28 +2100,20 @@
                _Nodes.Remove(obj);
            }
            SetMapInvalidate();
        }
        public void 删除ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DeleteChoosedObj();
        }
        private void DeleteChoosedObj()
        public void DeleteChoosedObj()
        {
            var list = _Network.Remove(selectedObjs);
            MapObjectExtensions.AddCommand(_Network, "Remove", null, list);
            selectedObjs.Clear();
            SetMapInvalidate();
        }
        #endregion
        #endregion 右键菜单
        #region 编辑模式/浏览模式切换工具
        private void toolStripComboBox_expandRepeater_ButtonClick(object sender, EventArgs e)
        {
@@ -2241,7 +2129,8 @@
            //toolStripComboBox_浏览模式.Text = isEditMode ? "编辑模式" : "浏览模式";
            LoadData(true);
        }
        #endregion
        #endregion 编辑模式/浏览模式切换工具
        /// <summary>
        /// 工具栏可用
@@ -2277,13 +2166,12 @@
        #region 分析工具
        private void 水平旋转ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 水平旋转ToolStripMenuItem()
        {
            //var objs = GlobalObject.PropertyForm.selectionSet.selectedObjects;
            //var selectobjs = objs.FindAll(o => o is NodeViewModel); //GlobalObject.PropertyForm.listBox1.SelectedItems;
            //if (selectobjs.Count <= 0) return;
            //if (!(selectobjs[0] as IBaseViewModel).isNode())
            //{
            //    MessageBox.Show("围绕选中节点进行平面旋转,请在属性列表中选中一个节点类对象");
@@ -2304,7 +2192,6 @@
            //MapObjectExtensions.AddCommand(nodes, "Position", OldPositions, NewPositions);
            //SetMapInvalidate();
        }
        public List<PointF> GetRotatedPoints(List<PointF> points, PointF origin, float angle)
@@ -2338,7 +2225,6 @@
            return result;
        }
        public List<PointF3D> GetRotatedPoints(List<PointF3D> points, Vector3 line, float angle)
        {
@@ -2383,13 +2269,12 @@
            return result;
        }
        private void 缩放ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 缩放ToolStripMenuItem()
        {
            //var objs = GlobalObject.PropertyForm.selectionSet.selectedObjects;
            //var list = objs.FindAll(o => o is NodeViewModel); //GlobalObject.PropertyForm.listBox1.SelectedItems;
            //if (list.Count <= 0) return;
            //if (list.Count >= 1 && !list[0].isNode())
            //{
            //    MessageBox.Show("围绕选中节点进行三维缩放,请在属性列表中选中一个[节点类]缩放中心对象");
@@ -2452,20 +2337,15 @@
            return result;
        }
        public void toolStripButton_计算_Click(object sender, EventArgs e)
        {
            //LoadData();
            _Network.Calc(_Template.FullPath, GlobalPath.configPath+ "config_calc.wdb");
        }
        public void 关阀搜索ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 关阀搜索ToolStripMenuItem()
        {
            if (selectedObjs.Count > 0)//&& selectedObjs[0] is Link l
            {
                var objs = selectedObjs.ToList();
                var selectsValve = objs.FindAll(o => o is ValveViewModel);
                selectedObjs.ForEach(o => o.Selected = false);
@@ -2474,18 +2354,17 @@
                selectsValve.ForEach(o => o.Selected = false);
                this.SetMapInvalidate();
            }
        }
        /// <summary>
        /// 关阀分析(考虑水源的情况)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 关阀搜索考虑水源ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 关阀搜索考虑水源ToolStripMenuItem()
        {
            if (selectedObjs.Count > 0)//&& selectedObjs[0] is Link l
            {
                var objs = selectedObjs.ToList();
                var selectsValve = objs.FindAll(o => o is ValveViewModel);
                selectedObjs.ForEach(o => o.Selected = false);
@@ -2493,16 +2372,17 @@
                TraversePipeNetwork(objs, null);
                selectsValve.ForEach(o => o.Selected = false);
                this.SetMapInvalidate();
            }
        }
        //Queue<Link> queue2 = null;
        List<LinkViewModel> LinksToFindSource = null;
        Dictionary<LinkViewModel, List<IBaseViewModel>> Sets = null;
        Dictionary<LinkViewModel, bool> Sets_hasSource = null;
        private List<LinkViewModel> LinksToFindSource = null;
        private Dictionary<LinkViewModel, List<IBaseViewModel>> Sets = null;
        private Dictionary<LinkViewModel, bool> Sets_hasSource = null;
        private void TraversePipeNetwork(List<IBaseViewModel> startObjs, HashSet<NodeViewModel> visitedNodes = null, bool consider = true)
        {
            LinksToFindSource = new List<LinkViewModel>();
            if (visitedNodes == null)
@@ -2517,7 +2397,6 @@
                else if (o is NodeViewModel n)
                {
                    n.Links.Select(oo => oo as LinkViewModel).ToList().ForEach(link => TraversePipeNetwork(link, visitedNodes));
                }
            });
            if (!consider) return;
@@ -2539,20 +2418,16 @@
                            o.Selected = true;
                            selectedObjs.Add(o);
                        }
                    });
                }
            }
            //if (GlobalObject.PropertyForm != null)
            //    GlobalObject.PropertyForm.SetObjs(selectedObjs);
        }
        private void TraversePipeNetwork(LinkViewModel startLink, HashSet<NodeViewModel> visitedNodes = null)
        {
            Queue<LinkViewModel> queue = new Queue<LinkViewModel>();
            queue.Enqueue(startLink);
            if (visitedNodes == null)
@@ -2581,35 +2456,24 @@
                                link.Selected = true;
                                selectedObjs.Add(link);
                                if (!(link is ValveViewModel))
                                {
                                    queue.Enqueue(link);
                                }
                                else
                                {
                                    LinksToFindSource.Add(link);
                                }
                            }
                        }
                    }
                }
            }
        }
        private void TraversePipeNetwork_Set(LinkViewModel startLink, HashSet<NodeViewModel> visitedNodes = null)
        {
            Queue<LinkViewModel> queue = new Queue<LinkViewModel>();
            queue.Enqueue(startLink);
            if (visitedNodes == null)
@@ -2661,19 +2525,13 @@
                        }
                    }
                }
            }
        }
        private bool FindSouce(LinkViewModel startLink, HashSet<LinkViewModel> visitedLinks, HashSet<LinkViewModel> visitedLinks2, Dictionary<IBaseViewModel, bool> hasSource = null)
        {
            foreach (var node in new NodeViewModel[] { startLink.StartNode, startLink.EndNode })
            {
                if (!hasSource.ContainsKey(node))
                {
                    //hasSource.Add(node, false);
@@ -2681,17 +2539,12 @@
                }
                if (hasSource[node] == true) return true;
            }
            return false;
        }
        private bool FindSouce(NodeViewModel startNode, HashSet<LinkViewModel> visitedLinks, HashSet<LinkViewModel> visitedLinks2, Dictionary<IBaseViewModel, bool> hasSource = null)
        {
            foreach (var link in startNode.ViewLinks)
            {
                if (hasSource.ContainsKey(link) && hasSource[link] == true) return true;
@@ -2703,43 +2556,30 @@
                    visitedLinks2.Add(link);
                if (!hasSource.ContainsKey(link))
                {
                    //hasSource.Add(link,false);
                    hasSource[link] = FindSouce(link, visitedLinks, visitedLinks2, hasSource);
                }
                if (hasSource[link] == true) return true;
            }
            return false;
        }
        //private void 联通性ToolStripMenuItem_Click(object sender, EventArgs e)
        //{
        //    if (selectedObjs.Count > 0)//&& selectedObjs[0] is Link l
        //    {
        //        var objs = selectedObjs.FindAll(o => o is LinkViewModel).Select(o => o as LinkViewModel).ToList();
        //        var visitedNodes = new HashSet<NodeViewModel>();
        //        objs.ForEach(o => TraversePipeNetworkALL(o, visitedNodes));
        //        this.SetInvalidated();
        //    }
        //}
        private void TraversePipeNetworkALL(LinkViewModel startLink, HashSet<NodeViewModel> visitedNodes = null,int direction=0)
        private void TraversePipeNetworkALL(LinkViewModel startLink, HashSet<NodeViewModel> visitedNodes = null, int direction = 0)
        {
            Queue<LinkViewModel> queue = new Queue<LinkViewModel>();
            queue.Enqueue(startLink);
            if (visitedNodes == null)
@@ -2770,96 +2610,48 @@
                                link.Selected = true;
                                selectedObjs.Add(link);
                                queue.Enqueue(link);
                            }
                        }
                    }
                }
            }
        }
        #endregion
        #endregion 分析工具
        #region 显示选项
        private void 显示节点ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 显示节点ToolStripMenuItem()
        {
            _ShowJunction = true;
            SetMapInvalidate();
        }
        private void 隐藏节点ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 隐藏节点ToolStripMenuItem()
        {
            _ShowJunction = false;
            SetMapInvalidate();
        }
        private void 大ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var item = sender as ToolStripItem;
            if (item.Text == "大")
            {
                junction_multiply = 1f;
            }
            else if (item.Text == "中")
            {
                junction_multiply = 0.6667f;
            }
            else
            {
                junction_multiply = 0.4f;
            }
            SetMapInvalidate();
        }
        private void 显示阀门ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 显示阀门ToolStripMenuItem()
        {
            _ShowValve = true;
            SetMapInvalidate();
        }
        private void 隐藏阀门ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 隐藏阀门ToolStripMenuItem()
        {
            _ShowValve = false;
            SetMapInvalidate();
        }
        private void 大ToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            var item = sender as ToolStripItem;
            if (item.Text == "大")
            {
                Link_multiply = 1f;
            }
            else if (item.Text == "中")
            {
                Link_multiply = 0.6667f;
            }
            else
            {
                Link_multiply = 0.4f;
            }
            SetMapInvalidate();
        }
        #endregion
        #endregion 显示选项
        #endregion 二、工具栏
        #region 方法
        private void 标高推测ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 标高推测ToolStripMenuItem()
        {
            int num = UpdateNodesEle();
            if (num > 0)
@@ -2869,9 +2661,9 @@
            else
            {
                MessageBox.Show($"没有需要更新的节点");
            }
        }
        public int UpdateNodesEle()
        {
            int num = 0;
@@ -2917,7 +2709,6 @@
                if (link.StartNode == node)
                {
                    neighbor = link.EndNode;
                }
                else
                {
@@ -2935,7 +2726,8 @@
                }
            }
        }
        private void 标高导出ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 标高导出ToolStripMenuItem()
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("ID");
@@ -2950,9 +2742,9 @@
                }
            }
            dtToSql(dt);
        }
        void dtToCsv(DataTable dt)
        private void dtToCsv(DataTable dt)
        {
            // 创建 SaveFileDialog 对象
            SaveFileDialog saveFileDialog = new SaveFileDialog();
@@ -2996,12 +2788,12 @@
                MessageBox.Show("文件保存成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
        void dtToSql(DataTable dt)
        private void dtToSql(DataTable dt)
        {
            // 创建 SaveFileDialog 对象
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.Filter = "Txt Files (*.txt)|*.txt";
            // 如果用户选择了保存位置和文件名,则执行保存操作
            if (saveFileDialog.ShowDialog() == DialogResult.OK)
@@ -3025,19 +2817,15 @@
    );
END
";
                // 构建 CSV 字符串
                StringBuilder csvContent = new StringBuilder();
                csvContent.AppendLine(tableString);
                //// 写入表头
                //foreach (DataColumn column in dt.Columns)
                //{
                //    csvContent.Append(column.ColumnName);
                //    csvContent.Append(",");
                //}
@@ -3047,7 +2835,6 @@
                int j = 0;
                while (i < dt.Rows.Count)
                {
                    if (j == 0) csvContent.AppendLine("INSERT INTO Elev (ID, Elev) VALUES");
                    // 写入数据行
@@ -3058,11 +2845,7 @@
                    i++;
                    j++;
                    if (j == 1000) j = 0;
                }
                // 将 CSV 内容写入文件
                File.WriteAllText(filePath, csvContent.ToString());
@@ -3087,18 +2870,29 @@
                LoadData();
            }
        }
        public void buttonUndo_Click(object sender, EventArgs e)
        public void Undo()
        {
            SetMapInvalidate();
            //GlobalObject.PropertyForm.propertyGrid.Refresh();
            MapObjectExtensions.Undo();
        }
        public void buttonRedo_Click(object sender, EventArgs e)
        public void Redo()
        {
            SetMapInvalidate();
            //GlobalObject.PropertyForm.propertyGrid.Refresh();
            MapObjectExtensions.Redo();
        }
        public void buttonUndo_Click(object sender, EventArgs e)
        {
        }
        public void buttonRedo_Click(object sender, EventArgs e)
        {
        }
        public void toolStripButton_save_ButtonClick(object sender, EventArgs e)
        {
            if (_Template == null) return;
@@ -3121,6 +2915,41 @@
        private void 以当前视角另存ToolStripMenuItem_Click(object sender, EventArgs e)
        {
        }
        private void 另存为ToolStripMenuItem_Click(object sender, EventArgs e)
        {
        }
        public void SaveAs(string filePath)
        {
            bool isReplace = false;
            _Network.BuildToInp(filePath, null, _filePath, isReplace);
        }
        public void Save()
        {
            if (_Template == null) return;
            if (!_IsEditMode)
            {
                if (message.show("提醒", "浏览模式无法保存,是否恢复为编辑模式"))
                {
                    _IsEditMode = true;
                }
                else
                    return;
            }
            else
            {
                bool isReplace = true;
                //isReplace = !message.show("模板选择", "使用模板新增/替换当前文件", MessageBoxButtons.YesNo);
                _Network.BuildToInp(_filePath, null, null, false);
            }
        }
        public void SaveAsByView(string filePath)
        {
            if (_Template == null) return;
            StringBuilder sb = new StringBuilder();
@@ -3130,86 +2959,51 @@
            {
                var p = WorldPointToMapPoint((NodeViewModel)n);
                sb.AppendLine($"{n.ID} {p.X} {p.Y}");
            });
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.Filter = "Inp Files (*.inp)|*.inp";
            saveFileDialog.InitialDirectory = Directory.GetCurrentDirectory() + $@"\template\";
            if (_filePath != null) saveFileDialog.FileName = _filePath;
            if (saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                string filePath = saveFileDialog.FileName;
                // 使用 filePath 变量来保存文件
                //temp.路径 = filePath;
                _Network.BuildToInp(filePath, sb.ToString(), _filePath);
                //_filePath = filePath;
            }
            _Network.BuildToInp(filePath, sb.ToString(), _filePath);
        }
        private void 另存为ToolStripMenuItem_Click(object sender, EventArgs e)
        public void Calc()
        {
            bool isReplace = false;
            //isReplace = !message.show("模板选择", "使用模板新增/替换当前文件", MessageBoxButtons.YesNo);
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.Filter = "Inp Files (*.inp)|*.inp";
            saveFileDialog.InitialDirectory = Directory.GetCurrentDirectory() + $@"\template\";
            if (_filePath != null) saveFileDialog.FileName = _filePath;
            if (saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                string filePath = saveFileDialog.FileName;
                // 使用 filePath 变量来保存文件
                //temp.路径 = filePath;
                _Network.BuildToInp(filePath, null, _filePath, isReplace);
                //_filePath = filePath;
            }
            _Network.Calc(_Template.FullPath, GlobalPath.configPath + "config_calc.wdb");
        }
        private void 连通性检查ToolStripMenuItem1_Click(object sender, EventArgs e)
        public void 连通性检查ToolStripMenuItem()
        {
            if (selectedObjs.Count > 0)//&& selectedObjs[0] is Link l
            {
                var objs = selectedObjs.FindAll(o => o is LinkViewModel).Select(o => o as LinkViewModel).ToList();
                if (objs.Count == 0) selectedObjs.FindAll(o => o is NodeViewModel).Select(o => o as NodeViewModel).ToList().ForEach(o=>objs.AddRange(o.Links.Select(l=>l as LinkViewModel).ToList()));
                if (objs.Count == 0) selectedObjs.FindAll(o => o is NodeViewModel).Select(o => o as NodeViewModel).ToList().ForEach(o => objs.AddRange(o.Links.Select(l => l as LinkViewModel).ToList()));
                //objs去掉重复的元素
                objs = objs.Distinct().ToList();
                var visitedNodes = new HashSet<NodeViewModel>();
                objs.ForEach(o => TraversePipeNetworkALL(o, visitedNodes));
                this.SetMapInvalidate();
            }
        }
        private void 下游连通性ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 下游连通性ToolStripMenuItem()
        {
            if (selectedObjs.Count > 0)//&& selectedObjs[0] is Link l
            {
                var objs = selectedObjs.FindAll(o => o is LinkViewModel).Select(o => o as LinkViewModel).ToList();
                if (objs.Count == 0) selectedObjs.FindAll(o => o is NodeViewModel).Select(o => o as NodeViewModel).ToList().ForEach(o =>
                if (objs.Count == 0) selectedObjs.FindAll(o => o is NodeViewModel).Select(o => o as NodeViewModel).ToList().ForEach(o =>
                {
                    objs.AddRange(o.Links.Select(oo => oo as LinkViewModel).ToList().FindAll(oo=>oo.StartNode==o?oo.EN_FLOW>0:oo.EN_FLOW<0));
                    objs.AddRange(o.Links.Select(oo => oo as LinkViewModel).ToList().FindAll(oo => oo.StartNode == o ? oo.EN_FLOW > 0 : oo.EN_FLOW < 0));
                });
                //objs去掉重复的元素
                objs = objs.Distinct().ToList();
                var visitedNodes = new HashSet<NodeViewModel>();
                objs.ForEach(o => TraversePipeNetworkALL(o, visitedNodes,1));
                objs.ForEach(o => TraversePipeNetworkALL(o, visitedNodes, 1));
                this.SetMapInvalidate();
            }
        }
        public void 复制ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 复制ToolStripMenuItem()
        {
            if(hoveredObjs.Count<=0 || !(hoveredObjs[0] is NodeViewModel))
            if (hoveredObjs.Count <= 0 || !(hoveredObjs[0] is NodeViewModel))
            {
                MessageBox.Show("请将鼠标悬停在一个节点对象上,作为基准点");
                return;
@@ -3219,7 +3013,7 @@
                MessageBox.Show("请选择要复制的对象");
                return;
            }
            _OperaNode = hoveredObjs[0] as NodeViewModel;
            MapViewNetWork net = new MapViewNetWork();
@@ -3236,12 +3030,10 @@
            catch
            {
                //提醒
            }
        }
        public void 粘贴ToolStripMenuItem1_Click(object sender, EventArgs e)
        public void 粘贴ToolStripMenuItem()
        {
            {
                var net = new MapViewNetWork();
@@ -3269,40 +3061,25 @@
                SetMapInvalidate();
            }
        }
        private void 增量保存ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (_Template == null) return;
            if (!_IsEditMode)
            {
                if (message.show("提醒", "浏览模式无法保存,是否恢复为编辑模式"))
                {
                    _IsEditMode = true;
                }
                else
                    return;
            }
            else
            {
                bool isReplace = true;
                //isReplace = !message.show("模板选择", "使用模板新增/替换当前文件", MessageBoxButtons.YesNo);
                _Network.BuildToInp(_filePath, null, null, false);
            }
        }
        private void 设为关闭ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            selectedObjs.ForEach(obj => { if (obj is LinkViewModel link) link.Status =Hydro.Core.ObjectEnum. StatusType.CLOSED; });
            selectedObjs.ForEach(obj => { if (obj is LinkViewModel link) link.Status = Hydro.Core.ObjectEnum.StatusType.CLOSED; });
            SetMapInvalidate();
        }
        private void 显示全部楼层ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 显示全部楼层ToolStripMenuItem()
        {
            //this.mapOption.ShowFloor = int.MinValue;
            _Network.MapObjects.ForEach(o => o.Visible = true);
            this.SetMapInvalidate();
        }
        private void 保存楼层视角ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 保存楼层视角ToolStripMenuItem()
        {
            //if (_Template?.Floors!=null)
            //{
@@ -3310,7 +3087,8 @@
            //    if (fl!=null)fl.MapView = this.mapOption.Copy();
            //}
        }
        public void 南北对齐ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 南北对齐ToolStripMenuItem()
        {
            if (selectedNodes.Count < 1) return;
            List<float> list = new List<float>();
@@ -3319,7 +3097,8 @@
            MapObjectExtensions.AddCommand(selectedNodes, "X", list, list1);
            this.SetMapInvalidate();
        }
        public void 东西对齐ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 东西对齐ToolStripMenuItem()
        {
            if (selectedNodes.Count < 1) return;
            List<float> list = new List<float>();
@@ -3328,7 +3107,8 @@
            MapObjectExtensions.AddCommand(selectedNodes, "Y", list, list1);
            this.SetMapInvalidate();
        }
        public void 竖直对齐ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 竖直对齐ToolStripMenuItem()
        {
            if (selectedNodes.Count < 1) return;
            List<PointF> list = new List<PointF>();
@@ -3337,7 +3117,8 @@
            MapObjectExtensions.AddCommand(selectedNodes, "Position", list, list1);
            this.SetMapInvalidate();
        }
        public void 自动对齐ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 自动对齐ToolStripMenuItem()
        {
            if (selectedNodes.Count < 3) return;
            List<PointF3D> OldPosition3Ds = selectedNodes.Select(n => n.Position3D).ToList();
@@ -3350,7 +3131,8 @@
            MapObjectExtensions.AddCommand(selectedNodes, "Position3D", OldPosition3Ds, NewPosition3Ds);
            this.SetMapInvalidate();
        }
        List<PointF3D> ProjectPointsToLine(List<PointF3D> points)
        private List<PointF3D> ProjectPointsToLine(List<PointF3D> points)
        {
            // 使用最小二乘法构造直线,并将点投影到直线上
@@ -3404,7 +3186,7 @@
            return projectedPoints;
        }
        public void 添加底图ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 添加底图ToolStripMenuItem()
        {
            if (_Template == null) return;
            OpenFileDialog openFileDialog = new OpenFileDialog();
@@ -3416,12 +3198,13 @@
                var backgroundImagePath = openFileDialog.FileName;
                Global.ClearFileReadOnly(_Template.BackGroundImg_FullPath);
                File.Copy(backgroundImagePath, _Template.BackGroundImg_FullPath, true);
                设置底图ToolStripMenuItem_Click(1, new EventArgs());
                设置底图ToolStripMenuItem();
            }
        }
        bool _isSettingBackGroundPictur = false;
        public void 设置底图ToolStripMenuItem_Click(object sender, EventArgs e)
        private bool _isSettingBackGroundPictur = false;
        public void 设置底图ToolStripMenuItem()
        {
            string inputValue = "0";// Prompt.ShowDialog("请输入底图标高", "");
            float BackGroundElev = 0;
@@ -3439,7 +3222,7 @@
            this.Cursor = Cursors.Cross;
        }
        public void 显示隐藏底图ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 显示隐藏底图ToolStripMenuItem()
        {
            mapOption.isShowPic = !mapOption.isShowPic;
            SetMapInvalidate();
@@ -3447,7 +3230,7 @@
        private dict<string, dynamic> param = null;
        public void 清除底图ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 清除底图ToolStripMenuItem()
        {
            mapOption.isShowPic = false;
            SetMapInvalidate();
@@ -3466,30 +3249,32 @@
            if (float.TryParse(inputValue, out float result))
            {
                zoom = result;
            }
        }
        private void label_file_DoubleClick(object sender, EventArgs e)
        {
            if (_filePath == null) return;
            FileInfo fi = new FileInfo(_filePath);
            Process.Start("explorer.exe", $"/select,\"{_filePath}\"");
        }
        private void label_file_Click(object sender, EventArgs e)
        {
            if (_filePath == null) return;
            FileInfo fi = new FileInfo(_filePath);
            Process.Start("explorer.exe", $"/select,\"{_filePath}\"");
        }
        private void 设为立管点ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (selectedNodes.Count == 1)
            {
                _Template.Node2 = _EndPoint = selectedNodes[0].ID;
            }
        }
        private void 显示水流ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 显示水流ToolStripMenuItem()
        {
            _Template.network.MapObjects.ForEach(o => o.Selected = false);
            selectedObjs.Clear();
@@ -3505,13 +3290,11 @@
                    node = link.EndNode;
                    node.Selected = true;
                    if (!selectedObjs.Contains(node)) selectedObjs.Add(node);
                }
            });
            this.SetMapInvalidate();
        }
        private void 全选ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            selectedObjs.Clear();
@@ -3522,14 +3305,12 @@
                    o.Selected = true;
                    selectedObjs.Add(o);
                }
            });
            this.SetMapInvalidate();
        }
        private void 反选ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            _Template.network.MapObjects.ForEach(o =>
            {
                if (o.Visible)
@@ -3544,39 +3325,36 @@
                        o.Selected = true;
                        selectedObjs.Add(o);
                    }
                }
            });
            this.SetMapInvalidate();
        }
        private void 显示状态ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 显示状态ToolStripMenuItem()
        {
            _Template.mapOption._ShowStatus = true;
            this.SetMapInvalidate();
        }
        private void 隐藏状态ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 隐藏状态ToolStripMenuItem()
        {
            _Template.mapOption._ShowStatus = false;
            this.SetMapInvalidate();
        }
        private void 显示流向ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 显示流向ToolStripMenuItem()
        {
            _Template.mapOption._ShowFlowDirection = true;
            this.SetMapInvalidate();
        }
        private void 隐藏流向ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 隐藏流向ToolStripMenuItem()
        {
            _Template.mapOption._ShowFlowDirection = false;
            this.SetMapInvalidate();
        }
        private void 方向修复ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 方向修复ToolStripMenuItem()
        {
            _Network.Links.ForEach(l =>
            {
@@ -3589,102 +3367,67 @@
                }
            });
        }
        private void 刷新楼层ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ToolStripMenuItem_Floor.DropDownItems.Clear();
            var mapobjects = _Network.MapObjects;
            TagList tags = new TagList();
            foreach (var item in mapobjects)
            {
                if (item.Tags != null)
                    tags.AddRange(item.Tags);
            }
            var t = tags.Distinct().ToList();
            tags.Clear();
            tags.AddRange(t);
            for (int i = -10; i < 1000; i++)
            {
                string tagstring = i.ToString() + "楼";
                if (tags.Contains(tagstring))
                {
                    var item=ToolStripMenuItem_Floor.DropDownItems.Add(i.ToString() + "楼");
                    item.Click += (oo, ee) =>
                    {
                        mapobjects.ForEach(o =>
                        {
                            if (o.Tags.Contains(tagstring))
                            {
                                o.Visible = true;
                            }
                            else
                            {
                                o.Visible = false;
                            }
                        });
                        this.SetMapInvalidate();
                    };
                }
            }
            this.SetMapInvalidate();
        }
        private void 显示所有隐藏内容ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 显示所有隐藏内容ToolStripMenuItem()
        {
            _Network.MapObjects.ForEach(o => o.Visible = true);
            this.SetMapInvalidate();
        }
        public void toolStripButton_CalcMiniLoss_Click(object sender, EventArgs e)
        {
        }
        private void toolStripButton_ClearMinor_Click(object sender, EventArgs e)
        {
        }
        private void 显示流向ToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            _isShowDirection = !_isShowDirection;
        }
        private bool _isShowDirection = false;
        public void 颜色分级管理ToolStripMenuItem()
        {
            //Form_Colour form_Colour = new Form_Colour(_Template.Colours);
            //form_Colour.Show(this);
        }
        private bool __needpaintall = false;
        public void CalcLinkMinorLoss()
        {
            _Network.SetNodeDemand();
            _Network.Calc(_Template.FullPath, GlobalPath.configPath + "config_calc.wdb");
            _Network.CalcLinkMinorLoss();
        }
        private void toolStripButton_ClearMinor_Click(object sender, EventArgs e)
        public void ClearMinorLoss()
        {
            _Network.ClearMinorLoss();
        }
        private void 显示流向ToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            _isShowDirection = !_isShowDirection;
        }
        bool _isShowDirection=false;
        private void 颜色分级管理ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //Form_Colour form_Colour = new Form_Colour(_Template.Colours);
            //form_Colour.Show(this);
        }
      private bool __needpaintall=false;
        private void cb_Link_Colour_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (_Template == null) return;
            var type = cb_Link_Colour.SelectedItem==null?ColourType.管线流量:(ColourType)cb_Link_Colour.SelectedItem;
            var type = cb_Link_Colour.SelectedItem == null ? ColourType.管线流量 : (ColourType)cb_Link_Colour.SelectedItem;
            mapOption.ColourLink = type;
            this.SetMapInvalidate();
        }
        private void cb_Node_Colour_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (_Template == null) return;
            var type = cb_Node_Colour.SelectedItem==null?ColourType.节点自由压力:(ColourType)cb_Node_Colour.SelectedItem;
            var type = cb_Node_Colour.SelectedItem == null ? ColourType.节点自由压力 : (ColourType)cb_Node_Colour.SelectedItem;
            mapOption.ColourNode = type;
            this.SetMapInvalidate();
        }
        private void label_ZZ_Click(object sender, EventArgs e)
        {
            //正交模式的全局变量开关
            _isOrtho = !_isOrtho;
        }
        private void 楼层管理ToolStripMenuItem_Click(object sender, EventArgs e)
        public void 楼层管理ToolStripMenuItem()
        {
            //if (_Template.Regions==null)
            //{
@@ -3694,9 +3437,10 @@
            //form_EditFloors.Show(this);
        }
        #endregion 方法
        #endregion
        private void 东西对齐ToolStripMenuItem1_Click(object sender, EventArgs e)
        {
        }
    }
}