From b6a00e2fddcf2343b981c30be670aa00b87699dc Mon Sep 17 00:00:00 2001
From: ningshuxia <ningshuxia0927@outlook.com>
Date: 星期五, 28 三月 2025 14:07:50 +0800
Subject: [PATCH] 模拟计算

---
 WinFrmUI/PBS.WinFrmUI.Hydro/99-map-view/MapViewer.cs | 2125 +++++++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 1,570 insertions(+), 555 deletions(-)

diff --git a/WinFrmUI/PBS.WinFrmUI.Hydro/99-map-view/MapViewer.cs b/WinFrmUI/PBS.WinFrmUI.Hydro/99-map-view/MapViewer.cs
index 33074c0..d717823 100644
--- a/WinFrmUI/PBS.WinFrmUI.Hydro/99-map-view/MapViewer.cs
+++ b/WinFrmUI/PBS.WinFrmUI.Hydro/99-map-view/MapViewer.cs
@@ -1,42 +1,25 @@
-锘�
-using Newtonsoft.Json;
-using System.ComponentModel;
+锘縰sing Newtonsoft.Json;
+using PBS.WinFrmUI.Hydro;
 using System.Data;
-using System.IO;
 using System.Numerics;
 using System.Text;
-using static Hydro.MapViewEnum;
-using Cursor = System.Windows.Forms.Cursor;
 
-namespace Hydro
+namespace HydroUI
 {
-    public partial class MapViewer : UserControl
+    public partial class MapViewer : XtraUserControl
     {
 
-        #region 涓�銆佸叏灞�
+        #region View
+        #region 涓�銆佸叏灞� 
 
-
-        #region 鍒濆鍖�
-        //public MapViewer()
-        //{
-        //    InitializeComponent();
-        //    //_Template = new Template();
-        //    //toolStrip1.Visible = false;
-        //    MapCenter = PointF.Empty;
-        //    zoom = 1.0f;
-        //    DoubleBuffered = true;
-        //    SetStyle(ControlStyles.SupportsTransparentBackColor, true);
-        //    BackColor = Color.Transparent;
-
-        //}
+        #region 鍒濆鍖� 
         private bool _showToolBar = true;
         [DisplayName("鏄剧ず宸ュ叿鏍�")]
-
         public bool showToolBar
         {
             get
             {
-                return _showToolBar;// this.panel1==null?true:Visible; 
+                return _showToolBar; 
             }
             set
             {
@@ -60,36 +43,23 @@
                 if (this.statusStrip1 != null) this.statusStrip1.Visible = value;
             }
         }
-        //public MapViewer()
-        //{
-        //    this.showToolBar = false;
-        //    //this.showToolBar = false;
-        //    InitializeComponent();
 
-        //    MapCenter = PointF.Empty;
-        //    zoom = 1.0f;
-        //    DoubleBuffered = true;
-        //    SetStyle(ControlStyles.SupportsTransparentBackColor, true);
-        //    BackColor = Color.Transparent;
-
-
-        //}
-        public MapViewer(bool showToolBar = false)
+        private bool _showPropertyForm = true;
+        [DisplayName("鏄剧ず灞炴�ф爮")]
+        public bool ShowPropertyForm
         {
-
-            this.showToolBar = showToolBar;
-            InitializeComponent();
-            //var propertyForm = new PropertyForm();
-            //propertyForm.Dock = DockStyle.Right;
-            //this.Controls.Add(propertyForm);
-            MapCenter = PointF.Empty;
-            zoom = 1.0f;
-            DoubleBuffered = true;
-            SetStyle(ControlStyles.SupportsTransparentBackColor, true);
-            BackColor = Color.Transparent;
-
-            //if (!showToolBar) this.panel1.Visible = false;
+            get
+            {
+                return _showPropertyForm;// this.panel1==null?true:Visible; 
+            }
+            set
+            {
+                _showPropertyForm = value;
+                if (this.propertyForm != null) this.propertyForm.Visible = value;
+            }
         }
+
+
         public MapViewer()
         {
 
@@ -103,10 +73,7 @@
             BackColor = Color.Transparent;
 
         }
-        public void SetEditMode(bool isEditMode)
-        {
-            _IsEditMode = isEditMode;
-        }
+
         private void MapViewer_Load(object sender, EventArgs e)
         {
             GlobalObject.PropertyForm = this.propertyForm;
@@ -150,7 +117,7 @@
                 AreaViewModel area = new AreaViewModel();
                 area.ID = item.Key.ToString();
                 area.InnerNodes = new List<NodeViewModel>();
-                //area.Name= item.Key.ToString();
+                area.InnerNodes = new List<NodeViewModel>();
 
                 //6涓潰璁剧疆涓嶄竴鏍风殑棰滆壊
                 switch (item.Key)
@@ -255,7 +222,6 @@
             {
                 GlobalObject.PropertyForm.SetEnabled(_IsEditMode);
                 GlobalObject.PropertyForm.SetNet(_Template.network);
-                //_Template.network.MapObjects.AddUndoRedoSupport(GlobalObject.PropertyForm.propertyGrid);
             }
 
 
@@ -266,7 +232,7 @@
         }
 
 
-        Dictionary<TemplateType, bool> _ViewModel = null;
+        Dictionary<PBS.eModelTemplateType, bool> _ViewModel = null;
         public void Clear()
         {
             _Template = null;
@@ -276,7 +242,7 @@
             RotationF = 90;
             SetMapInvalidate();
         }
-        public void SetData(Template template, dict<string, dynamic> param = null, Dictionary<TemplateType, bool> viewMode = null)
+        public void SetData(Template template, dict<string, dynamic> param = null, Dictionary<PBS.eModelTemplateType, bool> viewMode = null)
         {
             this.param = param;
             bool reLoad = _Template == template;
@@ -284,7 +250,7 @@
             this._ViewModel = viewMode;
 
 
-   
+
             if (!LoadData()) return;
             if (!reLoad)
             {
@@ -301,7 +267,7 @@
             label_center.Text = $"center锛�({MapCenter.X.ToString("0.00")} 锛寋MapCenter.Y.ToString("0.00")}锛�";
             label_zoom.Text = $"Zoom锛歿zoom.ToString("0.000")}";
             toolStripStatusLabel_rotation.Text = $"Rotation锛�({Rotation.ToString("0")}锛寋RotationF.ToString("0")})";
-            //SetInvalidated();
+
         }
 
         private void InitCenter()
@@ -344,9 +310,7 @@
             _needPaintAll = true;
             PMin_Show = ScreenToMap(new PointF(0, this.map.Height));
             PMax_Show = ScreenToMap(new PointF(this.map.Width, 0));
-            _timerDraw = true;
-
-
+            _timerDraw = true;  
         }
 
         public void SetStartEndPoint(String node1, string node2)
@@ -425,11 +389,9 @@
 
         protected override void OnResize(EventArgs e)
         {
-            base.OnResize(e);
-
+            base.OnResize(e); 
             // 褰撴帶浠跺昂瀵告敼鍙樻椂锛岃Е鍙戦噸缁�
-            this.SetMapInvalidate();
-
+            this.SetMapInvalidate(); 
         }
 
         #endregion
@@ -572,116 +534,109 @@
             _isInsertingObject = true;
             _newTemplate = temp;
             _undoOldValue = new PointF3D(0, 0, 0);
-            _OperaNode = temp.network.Nodes.Find(node => node.ID == temp.Node1) as NodeViewModel;
-            //if (_OperaNode == null) _OperaNode=_NewNet.Nodes[0];
+            _OperaNode = temp.network.Nodes.Find(node => node.ID == temp.Node1);
         }
 
-        bool controlDown = false;
+    
         PointF _MousePosition = new PointF(0, 0);
         void mapMouseMove(MouseEventArgs e)
         {
-            //base.OnMouseMove(e);
-            bool needInvalidate = false;
+            bool flag = false;
             _MousePosition = ScreenToMap(new PointF(e.X, e.Y));
             if (_isMovingObject)
             {
-                var p = MapPointToWorldPoint(_MousePosition, _OperaNode.Elev);
-                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;
+                PointF pointF = MapPointToWorldPoint(_MousePosition, _OperaNode.Elev);
+                PointF3D pointF3D = (PointF3D)_undoOldValue;
+                if (!float.IsInfinity(pointF.X) && !float.IsInfinity(pointF.Y))
+                {
+                    _newTemplate.OffSet = new PointF3D(pointF.X - pointF3D.X, pointF.Y - pointF3D.Y, 0f);
+                }
 
-                GlobalObject.PropertyForm.propertyGrid.Refresh();
-
-                needInvalidate = true;
+                GlobalObject.PropertyForm.propertyGridControl1.Refresh();
+                flag = true;
             }
-
-
             else if (_isPainting)
             {
-                needInvalidate = true;
-
-
+                flag = 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);
-
-
-
-                label_center.Text = $"center锛�({MapCenter.X.ToString("0.000")} 锛寋MapCenter.Y.ToString("0.000")}锛�";
-                needInvalidate = true;
-
+                PointF rotateVector = GetRotateVector(new PointF(e.X, e.Y), new PointF(_lastMouseX, _lastMouseY));
+                MapCenter = new PointF(MapCenter.X - rotateVector.X / Zoom.X, MapCenter.Y - rotateVector.Y / Zoom.Y);
+                label_center.Text = "center锛�(" + MapCenter.X.ToString("0.000") + " 锛�" + MapCenter.Y.ToString("0.000") + "锛�";
+                flag = 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),
-                //    Math.Abs((int)DragStartPos.X - (int)MP.X),
-                //    Math.Abs((int)DragStartPos.Y - (int)MP.Y));
-                //DrawSelectionRect(selectionRect);
-                needInvalidate = true;
-
+                flag = true;
             }
             else if (_isRotating)
             {
                 mousePosition = _MousePosition;
-                bool is涓嬪崐灞忓箷 = RotaStartPos.Y >= this.map.Height / 2;
-                if (ModifierKeys != Keys.Alt) Rotation = Rotation0 + ((float)e.X - (float)RotaStartPos.X) * 180 * 2.5 / (float)this.map.Width * (is涓嬪崐灞忓箷 ? 1 : 1);
-                if (ModifierKeys != Keys.Shift) RotationF = 淇瑙掑害_start + ((float)e.Y - (float)RotaStartPos.Y) * 180 * 2.5 / (float)this.map.Height;
-                if (RotationF > 90) RotationF = 90;
-                if (RotationF < 0) RotationF = 0;
-                needInvalidate = true;
+                bool flag2 = RotaStartPos.Y >= (float)(map.Height / 2);
+                if (Control.ModifierKeys != Keys.Alt)
+                {
+                    Rotation = Rotation0 + (double)(((float)e.X - RotaStartPos.X) * 180f) * 2.5 / (double)(float)map.Width * (double)(flag2 ? 1 : 1);
+                }
 
+                if (Control.ModifierKeys != Keys.Shift)
+                {
+                    RotationF = 淇瑙掑害_start + (double)(((float)e.Y - RotaStartPos.Y) * 180f) * 2.5 / (double)(float)map.Height;
+                }
+
+                if (RotationF > 90.0)
+                {
+                    RotationF = 90.0;
+                }
+
+                if (RotationF < 0.0)
+                {
+                    RotationF = 0.0;
+                }
+
+                flag = true;
             }
-            else
-
-            if (_isInsertingObject)
+            else if (_isInsertingObject)
             {
-                var p = MapPointToWorldPoint(_MousePosition, _OperaNode.Elev);
-                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;
+                PointF pointF2 = MapPointToWorldPoint(_MousePosition, _OperaNode.Elev);
+                PointF3D pointF3D2 = (PointF3D)_undoOldValue;
+                if (!float.IsInfinity(pointF2.X) && !float.IsInfinity(pointF2.Y))
+                {
+                    _newTemplate.OffSet = new PointF3D(pointF2.X - pointF3D2.X, pointF2.Y - pointF3D2.Y, 0f);
+                }
 
-                GlobalObject.PropertyForm.propertyGrid.Refresh();
-                needInvalidate = true;
-
-
+                GlobalObject.PropertyForm.propertyGridControl1.Refresh();
+                flag = true;
             }
-            //else
-            /*鍒ゆ柇鏄惁瑙︾鍒板璞�*/
+
             if (_mouseHoverCheckFlag)
             {
                 _mouseHoverCheckFlag = false;
-                // 閬嶅巻鎵�鏈夊璞�,鎵惧嚭鑼冨洿鍐呯殑瀵硅薄
-                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)
+                PointF clickedPoint = new PointF(e.X, e.Y);
+                IBaseViewModel obj_by_ScreenPoint = GetObj_by_ScreenPoint(clickedPoint);
+                if ((hoveredObjs.Count <= 0 || hoveredObjs[0] != obj_by_ScreenPoint) && (hoveredObjs.Count != 0 || obj_by_ScreenPoint != null))
                 {
-                    //needInvalidate = false;
-                }
-                else
-                {
-                    needInvalidate = true;
-                    hoveredObjs.ForEach(o => o.Hovered = false);
-                    hoveredObjs.Clear();
-                    if (obj != null)
+                    flag = true;
+                    hoveredObjs.ForEach(delegate (IBaseViewModel o)
                     {
-                        obj.Hovered = true;
-                        hoveredObjs.Add(obj);
+                        o.Hovered = false;
+                    });
+                    hoveredObjs.Clear();
+                    if (obj_by_ScreenPoint != null)
+                    {
+                        obj_by_ScreenPoint.Hovered = true;
+                        hoveredObjs.Add(obj_by_ScreenPoint);
                     }
-
-
                 }
-
-
             }
 
+            if (flag)
+            {
+                SetMapInvalidate();
+            }
 
-
-            if (needInvalidate) this.SetMapInvalidate();
-            label_mouse.Text = $"X锛歿e.X.ToString("0")} Y锛歿e.Y.ToString("0")} [Map]X锛歿_MousePosition.X.ToString("0.00")} Y锛歿_MousePosition.Y.ToString("0.00")}";
+            label_mouse.Text = "X锛�" + e.X.ToString("0") + " Y锛�" + e.Y.ToString("0") + " [Map]X锛�" + _MousePosition.X.ToString("0.00") + " Y锛�" + _MousePosition.Y.ToString("0.00");
             _lastMouseX = e.X;
             _lastMouseY = e.Y;
         }
@@ -759,10 +714,8 @@
                 {
                     var node = _Nodes[i] as NodeViewModel;
                     PointF p = WorldPointToMapPoint(node);
-                    if (rectangle0.Contains(p.ToPoint()))
+                    if (rectangle0.Contains((int)p.X, (int)p.Y))
                     {
-                        //_Nodes[i].Selected = true;
-                        //selectedObjs.Add(_Nodes[i]);
                         objs.Add(node);
                     }
                 }
@@ -770,11 +723,8 @@
                 for (int i = 0; i < _Links.Count; i++)
                 {
                     var link = _Links[i] as LinkViewModel;
-                    //PointF p = GetPointF(Pipes[i]);
-                    if (rectangle0.Contains(link.Position.ToPoint()))
+                    if (rectangle0.Contains(new Point((int)link.Position.X, (int)link.Position.Y)))
                     {
-                        //_Links[i].Selected = true;
-                        //selectedObjs.Add(_Links[i]);
                         objs.Add(link);
                     }
                 }
@@ -804,20 +754,19 @@
             if  /*鎻掑叆缁撴瀯*/(e.Button == MouseButtons.Left && _isInsertingObject)
             {
                 var net = _newTemplate.network;//clone
-                var net0 = _newTemplate.network.DeepCopyByBin<MapViewNetWork>();
+                var net0 = _newTemplate.network.DeepCopy<MapViewNetWork>();
                 List<NodeViewModel> nodes = _Nodes.Select(node => (NodeViewModel)node).ToList();
                 float minDist = 100f;
                 NodeViewModel minNode = null;
                 foreach (NodeViewModel node in nodes)
                 {
-
-
                     PointF mapPos = WorldPointToMapPoint(node);
                     PointF currentPoint = MapToScreen(mapPos);
                     float currentDist = 0;
                     if (node != _OperaNode && (currentDist = Get_dist(new PointF(e.X, e.Y), currentPoint)) < 15f)
                     {
-                        if (currentDist < minDist) currentDist = minDist;
+                        if (currentDist < minDist)
+                            currentDist = minDist;
                         minNode = node;
                         break;
                     }
@@ -829,12 +778,9 @@
 
                     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
@@ -844,14 +790,6 @@
                     _isInsertingObject = false;
                     this.SetMapInvalidate();
                     return;
-
-                    var p1 = (PointF3D)_undoOldValue;
-                    var p2 = _OperaNode.Position3D;
-                    var dd = _newTemplate.OffSet;
-                    dx = dd.X; //p2.X - p1.X;
-                    dy = dd.Y;// p2.Y - p1.Y;
-                    dz = dd.Z;// p2.Z - p1.Z;
-
                 }
 
 
@@ -860,7 +798,6 @@
                 var list = _Network.Add(net);
 
                 var j = _Network.AddPipe(minNode, _OperaNode);
-                //j.Length = 0.0001f;
                 list.Add(j);
                 _OperaNode = null;
                 _NewNet.Clear();
@@ -874,7 +811,6 @@
                 selectedObjs.AddRange(list);
 
                 MapObjectExtensions.AddCommand(_Network, "Add", null, list);
-
 
 
                 _isInsertingObject = false;
@@ -984,13 +920,9 @@
                 var p1 = (PointF3D)_undoOldValue;
                 var p2 = _OperaNode.Position3D;
                 var dd = _newTemplate.OffSet;
-                var dx = dd.X; //p2.X - p1.X;
-                var dy = dd.Y;// p2.Y - p1.Y;
-                var dz = dd.Z;// p2.Z - p1.Z;
-                              //selectedNodes.ForEach(n => { n.Position3D = new PointF3D(n.X + dx, n.Y + dy, n.Elev + dz); });
-                              //List<PointF3D> newPositons = selectedNodes.Select(n => n.Position3D).ToList();
-                              //List<PointF3D> oldPositons = newPositons.Select(n => new PointF3D(n.X - dx, n.Y - dy, n.Z - dz)).ToList();
-                              //MapObjectExtensions.AddCommand(selectedNodes, "Position3D", oldPositons, newPositons);
+                var dx = dd.X; 
+                var dy = dd.Y; 
+                var dz = dd.Z;  
                 _OperaNode = null;
                 _NewNet.Clear();
                 return;
@@ -1051,8 +983,7 @@
                                 //闇�瑕佹妸榧犳爣浣嶇疆杞崲涓虹珛绠$殑浣嶇疆锛岃幏鍙栭紶鏍囦綅缃殑楂樼▼
 
                                 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), isdoubleClick, p, wPos.Z);
                                 if (l.Count > 0) MapObjectExtensions.AddCommand(_Network, "Add", null, l);
@@ -1062,7 +993,6 @@
                                 if (mapOption.IsOrtho)
                                 {
                                     var wPos = GetZZWorldPoint(_select_junction1.Position3D, _MousePosition, new Vector3(1, 1, 0));
-                                    //getPointAndHeight(e, _select_junction1, out p, out z);
                                     p = new PointF(wPos.X, wPos.Y);
                                     var l = AddLink(new PointF(e.X, e.Y), isdoubleClick, p, wPos.Z);
                                     if (l.Count > 0) MapObjectExtensions.AddCommand(_Network, "Add", null, l);
@@ -1089,7 +1019,7 @@
                 _isDragging = false;
 
                 // 閬嶅巻鎵�鏈夌偣锛屾壘鍑烘渶杩戠殑鐐�
-                PointF clickedPoint = new PointF(e.X, e.Y);  //ScreenToMap(new PointF(e.X, e.Y));
+                PointF clickedPoint = new PointF(e.X, e.Y);   
                 var obj = GetObj_by_ScreenPoint(clickedPoint);
                 bool isJunction = obj is NodeViewModel;
 
@@ -1285,8 +1215,7 @@
 
                 }
                 else
-                {
-                    //GlobalObject.LockSelect
+                { 
 
                     selectedObjs.ForEach(o => o.Selected = false);
                     selectedObjs.Clear();
@@ -1412,16 +1341,12 @@
             {
                 var link = _Links[i] as LinkViewModel;
                 if (!link.Visible) continue;
-                //float dist = (clickedPoint.X - Pipes[i].X) * (clickedPoint.X - Pipes[i].X) +
-                //    (clickedPoint.Y - Pipes[i].Y) * (clickedPoint.Y - Pipes[i].Y);
                 PointF mapPos1 = WorldPointToMapPoint(link.StartNode.Position, link.StartNode.Elev);
                 PointF currentPoint1 = MapToScreen(mapPos1);
                 PointF mapPos2 = WorldPointToMapPoint(link.EndNode.Position, link.EndNode.Elev);
                 PointF currentPoint2 = MapToScreen(mapPos2);
-                //鏍规嵁currentPoint1鍜宑urrentPoint2锛屽垽鏂璫lickedPoint绂荤嚎娈礳urrentPoint1鍜宑urrentPoint2鐨勮窛绂�
                 float dist = Get_dist(clickedPoint, currentPoint1, currentPoint2, DistLimit);
 
-                //float dist = Get_dist(clickedPoint, currentPoint);
                 if (dist < minDist && dist <= DistLimit)
                 {
                     minDist = dist;
@@ -1433,50 +1358,7 @@
             return obj;
         }
 
-        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>();
-            for (int i = 0; i < _Nodes.Count; i++)
-            {
-                var node = _Nodes[i] as NodeViewModel;
-                if (!node.Visible) continue;
-                PointF mapPos = WorldPointToMapPoint(node);
-                PointF currentPoint = MapToScreen(mapPos);
-                float dist = Get_dist(clickedPoint, currentPoint);
-                if (dist <= DistLimit)
-                {
-                    objs.Add(node);
-                }
-            }
-            for (int i = 0; i < _Links.Count; i++)
-            {
-                var link = _Links[i] as LinkViewModel;
-                if (!link.Visible) continue;
-                //float dist = (clickedPoint.X - Pipes[i].X) * (clickedPoint.X - Pipes[i].X) +
-                //    (clickedPoint.Y - Pipes[i].Y) * (clickedPoint.Y - Pipes[i].Y);
-                PointF mapPos1 = WorldPointToMapPoint(link.StartNode.Position, link.StartNode.Elev);
-                PointF currentPoint1 = MapToScreen(mapPos1);
-                PointF mapPos2 = WorldPointToMapPoint(link.EndNode.Position, link.EndNode.Elev);
-                PointF currentPoint2 = MapToScreen(mapPos2);
-                //鏍规嵁currentPoint1鍜宑urrentPoint2锛屽垽鏂璫lickedPoint绂荤嚎娈礳urrentPoint1鍜宑urrentPoint2鐨勮窛绂�
-                float dist = Get_dist(clickedPoint, currentPoint1, currentPoint2, DistLimit);
-
-                //float dist = Get_dist(clickedPoint, currentPoint);
-                if (dist < minDist && dist <= DistLimit)
-                {
-
-
-                    objs.Add(link);
-                }
-            }
-            return objs;
-        }
-
+  
         /// <summary>
         /// 榧犳爣婊氳疆浜嬩欢
         /// </summary>
@@ -1551,7 +1433,7 @@
 
             }
 
-            //else
+
             /*鍒ゆ柇鏄惁瑙︾鍒板璞�*/
             if (_mouseHoverCheckFlag)
             {
@@ -1587,6 +1469,7 @@
             _lastMouseX = e.X;
             _lastMouseY = e.Y;
         }
+
         void CubeViewMouseUp(MouseEventArgs e)
         {
             //BookMark    锛氶紶鏍囨姮璧蜂簨浠�
@@ -1693,20 +1576,12 @@
 
 
         #region 瑙嗚宸ュ叿
-        // 鏄剧ず鐐瑰睘鎬�
-        private void ShowProperties(IBaseViewModel obj)
-        {
-            string str = "point";
-            if (obj is LinkViewModel) str = "pipe";
-            //MessageBox.Show($"{str}锛�({obj.X.ToString("0.000")} 锛寋obj.Y.ToString("0.000")}锛�");
-            //label_choose.Text = $"{str}[{obj.ID}]({obj.X.ToString("0.000")},{obj.Y.ToString("0.000")}锛�";
-            GlobalObject.PropertyForm.SetObj(obj);
-        }
-
+   
         private void label_center_Click(object sender, EventArgs e)
         {
             GlobalObject.PropertyForm.SetObj(MapCenter);
         }
+
         double 淇瑙掑害_bak = 45;
         private void tool瑙嗚_ButtonClick(object sender, EventArgs e)
         {
@@ -1792,13 +1667,14 @@
         }
         private void 璁剧疆闀垮害ToolStripMenuItem_Click(object sender, EventArgs e)
         {
-            double length = 0;
-            DialogResult result;
-            InputBox input = new InputBox("杈撳叆闀垮害");
+             
             if (selectedObjs.Count == 1 && selectedObjs[0] is LinkViewModel l)
             {
-                if (double.TryParse(input.ShowDialog(), out length))
+                var dlg = new InputDlg();
+                dlg.SetBindingData("杈撳叆鍙e緞");
+                dlg.ReloadDataEvent += (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;
@@ -1817,15 +1693,10 @@
 
                     SetMapInvalidate();
 
-                }
 
-            }
+                };
 
-
-
-
-
-            this.SetMapInvalidate();
+            } 
         }
         void MovePointbyLength(NodeViewModel node1, NodeViewModel node2, float Length)
         {
@@ -1850,9 +1721,7 @@
                 node2.X += moveVector.X;
                 node2.Y += moveVector.Y;
                 node2.Elev += moveVector.Z;
-
-                // 杈撳嚭绉诲姩鍚庣殑鐐� B 鍧愭爣
-                //Console.WriteLine("绉诲姩鍚庣偣 B 鐨勫潗鏍囦负 ({0}, {1}, {2})", x2, y2, z2);
+                 
             }
         }
         private void 鍏ㄩ儴鏄剧ずToolStripMenuItem_Click(object sender, EventArgs e)
@@ -1905,6 +1774,7 @@
                 }
             }
         }
+
         private void 鏃х増鎵撳紑ToolStripMenuItem_Click(object sender, EventArgs e)
         {
             // 鍒涘缓鎵撳紑鏂囦欢瀵硅瘽妗�
@@ -1946,13 +1816,8 @@
         {
             if (!_IsEditMode)
             {
-                if (message.show("鎻愰啋", "娴忚妯″紡鏃犳硶淇濆瓨锛屾槸鍚︽仮澶嶄负缂栬緫妯″紡"))
-                {
-                    _IsEditMode = true;
-
-                }
-                else
-                    return;
+                TipFormHelper.ShowWarn("娴忚妯″紡鏃犳硶淇濆瓨锛岃鍒囨崲缂栬緫妯″紡");
+                return;
             }
             else
                 _Network.BuildToInp(_filePath);
@@ -2310,7 +2175,6 @@
 
         #region 鍙抽敭鑿滃崟
 
-
         private void 杞崲ToolStripMenuItem_Click(object sender, EventArgs e)
         {
             var nodes = selectedNodes;
@@ -2417,72 +2281,26 @@
         #region 缂栬緫妯″紡/娴忚妯″紡鍒囨崲宸ュ叿
 
 
-
         private void toolStripComboBox_expandRepeater_ButtonClick(object sender, EventArgs e)
         {
             _IsEditMode = !_IsEditMode;
-            //toolStripComboBox_娴忚妯″紡.Text = isEditMode ? "缂栬緫妯″紡" : "娴忚妯″紡";
-            //LoadData(true);
         }
 
         private void 娴忚妯″紡ToolStripMenuItem_Click(object sender, EventArgs e)
         {
             var obj = sender as ToolStripItem;
             _IsEditMode = obj.Text == "缂栬緫妯″紡";
-            //toolStripComboBox_娴忚妯″紡.Text = isEditMode ? "缂栬緫妯″紡" : "娴忚妯″紡";
-            //LoadData(true);
         }
+
         #endregion
-
-        /// <summary>
-        /// 宸ュ叿鏍忓彲鐢�
-        /// </summary>
-        public void EnableToolBar()
-        {
-            this.toolStrip1.Enabled = true;
-        }
-
-        /// <summary>
-        /// 宸ュ叿鏍忎笉鍙敤
-        /// </summary>
-        public void DisEnableToolBar()
-        {
-            this.toolStrip1.Enabled = false;
-        }
-
-        /// <summary>
-        /// 闅愯棌宸ュ叿鏍�
-        /// </summary>
-        public void HideToolBar()
-        {
-            this.toolStrip1.Visible = false;
-        }
-
-        /// <summary>
-        /// 鏄剧ず宸ュ叿鏍�
-        /// </summary>
-        public void ShowToolBar()
-        {
-            this.toolStrip1.Visible = true;
-        }
-
+        銆�
         #region 鍒嗘瀽宸ュ叿
 
         private void 姘村钩鏃嬭浆ToolStripMenuItem_Click(object sender, EventArgs e)
-        {
-            //if (!selectedObjs[0].isNode())
-            //{
-            //    MessageBox.Show("鍥寸粫绗竴涓妭鐐规棆杞紝閫夋嫨闆嗕腑绗竴涓璞″繀椤绘槸");
-            //}
-
+        { 
             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.Count != 1)
-            //{
-            //    MessageBox.Show("鍥寸粫閫変腑鑺傜偣杩涜骞抽潰鏃嬭浆锛岃鍦ㄥ睘鎬у垪琛ㄤ腑閫変腑涓�涓棆杞腑蹇冨璞�");
-            //    return;
-            //}
+            if (selectobjs.Count <= 0) return; 
             if (!(selectobjs[0] as IBaseViewModel).isNode())
             {
                 MessageBox.Show("鍥寸粫閫変腑鑺傜偣杩涜骞抽潰鏃嬭浆锛岃鍦ㄥ睘鎬у垪琛ㄤ腑閫変腑涓�涓妭鐐圭被瀵硅薄");
@@ -2552,9 +2370,9 @@
             float z = line.Z;
             float[,] rotationMatrix = new float[,]
             {
-        {cos + x * x * (1 - cos), x * y * (1 - cos) - z * sin, x * z * (1 - cos) + y * sin},
-        {y * x * (1 - cos) + z * sin, cos + y * y * (1 - cos), y * z * (1 - cos) - x * sin},
-        {z * x * (1 - cos) - y * sin, z * y * (1 - cos) + x * sin, cos + z * z * (1 - cos)}
+            {cos + x * x * (1 - cos), x * y * (1 - cos) - z * sin, x * z * (1 - cos) + y * sin},
+            {y * x * (1 - cos) + z * sin, cos + y * y * (1 - cos), y * z * (1 - cos) - x * sin},
+            {z * x * (1 - cos) - y * sin, z * y * (1 - cos) + x * sin, cos + z * z * (1 - cos)}
             };
 
             // 瀹氫箟缁撴灉闆嗗悎锛屽苟閬嶅巻杈撳叆鐐归泦鍚堣繘琛屾棆杞鐞�
@@ -2586,15 +2404,8 @@
         {
 
             var objs = GlobalObject.PropertyForm.selectionSet.selectedObjects;
-            var list = objs.FindAll(o => o is NodeViewModel); //GlobalObject.PropertyForm.listBox1.SelectedItems;
+            var list = objs.FindAll(o => o is NodeViewModel);
             if (list.Count <= 0) return;
-            //if (selectobjs.Count != 1)
-            //{
-            //    MessageBox.Show("鍥寸粫閫変腑鑺傜偣杩涜涓夌淮缂╂斁锛岃鍦ㄥ睘鎬у垪琛ㄤ腑閫変腑涓�涓缉鏀句腑蹇冨璞�");
-            //    return;
-            //}
-            //if (!(selectobjs[0] as IBaseViewModel).isNode())
-            //var list = objs.FindAll(o => o.ID == selectobjs[0]);
             if (list.Count >= 1 && !list[0].isNode())
             {
                 MessageBox.Show("鍥寸粫閫変腑鑺傜偣杩涜涓夌淮缂╂斁锛岃鍦ㄥ睘鎬у垪琛ㄤ腑閫変腑涓�涓猍鑺傜偣绫籡缂╂斁涓績瀵硅薄");
@@ -2658,125 +2469,11 @@
         }
 
 
-        private void btn_鍒濆垎閰峗Click(object sender, EventArgs e)
-        {
-            //string result = null;
-            //if ((result=_Template.network.CheckValidate())!=null)
-            //{
-            //    MessageBox.Show(result);
-            //    return;
-            //}
-            List<WaterEquivalentSettings> settings = new List<WaterEquivalentSettings>();
-            settings.Add(new WaterEquivalentSettings()
-            {
-                waterEquivalents = new WaterEquivalentTemplate()
-                {
-                    ID = "1",
-                    Name = "1",
-                    WaterEquivalentCollection = new WaterEquivalentCollection()
-                    {
-                        new WaterEquivalent()
-                        {
-                            ID=1008,
-                            MinRatedFlow=0.48f,
-                            RatedFlow=0.72f,
-                            Count=1,
-                        },
-                        new WaterEquivalent()
-                        {
-                            ID=1009,
-                            MinRatedFlow=0.88f,
-                            RatedFlow=0.96f,
-                            Count=2,
-                        },
-                        new WaterEquivalent()
-                        {
-                            ID=1010,
-                            MinRatedFlow=1.08f,
-                            RatedFlow=1.08f,
-                            Count=3,
-                        }
-                    }
-                },
-                Meters = new List<string>()
-                {
-                    //鎸変互涓嬭寰嬬敓鎴愭暟缁勫埌M10锛�"M1","M2"
-
-                        "M1","M2","M3","M4","M5","M6","M7","M8","M9","M10","M11","M12","M13","M14","M15","M16",
-                    "M17","M18","M19","M20","M21","M22","M23","M24","M25","M26","M27","M28","M29","M30"
-                },
-            });
-
-
-            settings.Add(new WaterEquivalentSettings()
-            {
-                waterEquivalents = new WaterEquivalentTemplate()
-                {
-                    ID = "1",
-                    Name = "1",
-                    WaterEquivalentCollection = new WaterEquivalentCollection()
-                    {
-                        new WaterEquivalent()
-                        {
-                            ID=2008,
-                            MinRatedFlow=0.48f,
-                            RatedFlow=0.48f,
-                            Count=1,
-                        },
-                        new WaterEquivalent()
-                        {
-                            ID=2009,
-                            MinRatedFlow=0.12f,
-                            RatedFlow=0.12f,
-                            Count=5,
-                        },
-                        new WaterEquivalent()
-                        {
-                            ID=2010,
-                            MinRatedFlow=0.16f,
-                            RatedFlow=0.18f,
-                            Count=6,
-                        }
-                    }
-                },
-                Meters = new List<string>()
-                {
-                    //鎸変互涓嬭寰嬬敓鎴愭暟缁勫埌M10锛�"M1","M2"
-
-                       "M31","M32","M33","M34","M35","M36","M37","M38","M39","M40","M41","M42","M43","M44","M45","M46","M47","M48","M49","M50","M51","M52","M53","M54","M55","M56","M57","M58","M59","M60","M61","M62","M63","M64","M65","M66","M67","M68","M69","M70","M71","M72","M73","M74","M75","M76","M77","M78","M79","M80"
-                },
-            });
-            var head = _Network.reservoirs.FirstOrDefault().Head;
-            // _Network.WaterDistribution(_Template.FullPath, GlobalPath.configPath + "config_waterDistri.wdb", settings, 40, head);
-
-        }
-        private void btn_鎷撴墤妫�鏌Click(object sender, EventArgs e)
+        public void btn_鎷撴墤妫�鏌Click(object sender, EventArgs e)
         {
             Dictionary<string, List<string>> result = _Template.network.CheckValidate();
             if (result.Count > 0)
-            {
-                //ListBox listBox2 = new ListBox();
-                //listBox2.Dock = DockStyle.Fill;
-                ////listBox2鐨刬tem涓轰粈涔堟樉绀轰笉鍑烘潵锛�
-
-                //listBox2.SelectedIndexChanged += (s, e) =>
-                //{
-                //    if (listBox2.SelectedIndex >= 0)
-                //    {
-                //        List<IBaseViewModel> Objs = new List<IBaseViewModel>();
-                //        Objs.AddRange(_Nodes.Select(n=>(NodeViewModel)n));
-                //        Objs.AddRange(_Links.Select(l => (LinkViewModel)l));
-                //        var obj = Objs.Find(o => o.ID == listBox2.SelectedItem.ToString());
-                //        if (obj != null)
-                //        {
-                //            obj.Selected = true;
-                //            selectedObjs.Add((NodeViewModel)obj);
-
-                //            SetMapInvalidate();
-                //        }
-
-                //    }
-                //};
+            { 
                 ListBox listBox1 = new ListBox();
                 listBox1.Dock = DockStyle.Fill;
                 listBox1.Width = 200;
@@ -2821,43 +2518,23 @@
                 ResultForm.StartPosition = FormStartPosition.CenterScreen;
                 ResultForm.Controls.Add(listBox1);
                 ResultForm.MinimizeBox = false;
-                ResultForm.MaximizeBox = false;
-                //ResultForm.Controls.Add(listBox2);
-                //listBox2.Invalidate();
+                ResultForm.MaximizeBox = false; 
                 ResultForm.Show();
-
-                //鏂板缓涓�涓獥鍙o紝鏄剧ず妫�鏌ョ粨鏋�
-                //CheckForm checkForm = new CheckForm();
-                //checkForm.Show();
+ 
             }
             else
             {
                 MessageBox.Show("鎷撴墤妫�鏌ラ�氳繃");
             }
-            //if (!string.IsNullOrEmpty(result))
-            //{
-            //    MessageBox.Show(result);
-            //    return;
-            //}
-
-
+            銆�銆�
         }
 
-        public void toolStripButton_璁$畻_Click(object sender, EventArgs e)
-        {
-            //if (_Template == null)
-            //{
-            //    MessageBox.Show("璇峰厛鎵撳紑鏂囦欢");
-            //    return;
-            //}
-            //_Network.Calc(_Template.FullPath, GlobalPath.configPath + "config_calc.wdb");
-        }
+    
 
         public void 鍏抽榾鎼滅储ToolStripMenuItem_Click(object sender, EventArgs e)
         {
-            if (selectedObjs.Count > 0)//&& selectedObjs[0] is Link l
-            {
-
+            if (selectedObjs.Count > 0) 
+            { 
                 var objs = selectedObjs.ToList();
                 var selectsValve = objs.FindAll(o => o is ValveViewModel);
                 selectedObjs.ForEach(o => o.Selected = false);
@@ -2868,6 +2545,7 @@
             }
 
         }
+
         /// <summary>
         /// 鍏抽榾鍒嗘瀽锛堣�冭檻姘存簮鐨勬儏鍐碉級
         /// </summary>
@@ -2948,14 +2626,11 @@
 
             queue.Enqueue(startLink);
             if (visitedNodes == null)
-                visitedNodes = new HashSet<NodeViewModel>();
-            //visitedNodes.Add(startLink.StartNode);
-            //visitedNodes.Add(startLink.EndNode);
+                visitedNodes = new HashSet<NodeViewModel>(); 
 
             while (queue.Count > 0)
             {
-                LinkViewModel currentLink = queue.Dequeue();
-                //Console.WriteLine("Traversing Link: " + currentLink.ID);
+                LinkViewModel currentLink = queue.Dequeue(); 
 
                 foreach (var node in new NodeViewModel[] { currentLink.StartNode, currentLink.EndNode })
                 {
@@ -3068,18 +2743,15 @@
 
                 if (!hasSource.ContainsKey(node))
                 {
-                    //hasSource.Add(node, false);
+               
                     hasSource[node] = FindSouce(node, visitedLinks, visitedLinks2, hasSource);
                 }
 
                 if (hasSource[node] == true) return true;
-
-
+                 
             }
             return false;
-
-
-
+             
         }
         private bool FindSouce(NodeViewModel startNode, HashSet<LinkViewModel> visitedLinks, HashSet<LinkViewModel> visitedLinks2, Dictionary<IBaseViewModel, bool> hasSource = null)
         {
@@ -3094,9 +2766,7 @@
                 else
                     visitedLinks2.Add(link);
                 if (!hasSource.ContainsKey(link))
-                {
-
-                    //hasSource.Add(link,false);
+                {  
                     hasSource[link] = FindSouce(link, visitedLinks, visitedLinks2, hasSource);
                 }
 
@@ -3108,24 +2778,7 @@
 
 
         }
-
-
-
-
-        //private void 鑱旈�氭�oolStripMenuItem_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)
         {
 
@@ -3135,14 +2788,11 @@
 
             queue.Enqueue(startLink);
             if (visitedNodes == null)
-                visitedNodes = new HashSet<NodeViewModel>();
-            //visitedNodes.Add(startLink.StartNode);
-            //visitedNodes.Add(startLink.EndNode);
+                visitedNodes = new HashSet<NodeViewModel>(); 
 
             while (queue.Count > 0)
             {
-                LinkViewModel currentLink = queue.Dequeue();
-                //Console.WriteLine("Traversing Link: " + currentLink.ID);
+                LinkViewModel currentLink = queue.Dequeue(); 
 
                 foreach (var node in new NodeViewModel[] { currentLink.StartNode, currentLink.EndNode })
                 {
@@ -3153,8 +2803,7 @@
                         visitedNodes.Add(node);
                         node.Selected = true;
                         selectedObjs.Add(node);
-
-                        //Console.WriteLine("Visiting Node: " + node.ID);
+                         
                         foreach (var link in node.ViewLinks)
                         {
                             if (!visitedNodes.Contains(link.StartNode) || !visitedNodes.Contains(link.EndNode))
@@ -3471,24 +3120,23 @@
             var result = ofd.ShowDialog();
             if (result == DialogResult.OK)
             {
-                _Template = new Template(new Guid().ToString(), "鏂板缓", "澶嶅埗", TemplateType.鍏朵粬);
+                _Template = new Template(new Guid().ToString(), "鏂板缓", "澶嶅埗", PBS.eModelTemplateType.Custom);
                 string json = File.ReadAllText(ofd.FileName);
                 _Template.network = JsonConvert.DeserializeObject<MapViewNetWork>(json);
                 _Template.network.BuildRelation();
-                TemplateList.AddTemp(_Template);
                 LoadData();
             }
         }
         public void buttonUndo_Click(object sender, EventArgs e)
         {
             SetMapInvalidate();
-            GlobalObject.PropertyForm.propertyGrid.Refresh();
+            GlobalObject.PropertyForm.propertyGridControl1.Refresh();
             MapObjectExtensions.Undo();
         }
         public void buttonRedo_Click(object sender, EventArgs e)
         {
             SetMapInvalidate();
-            GlobalObject.PropertyForm.propertyGrid.Refresh();
+            GlobalObject.PropertyForm.propertyGridControl1.Refresh();
             MapObjectExtensions.Redo();
         }
         public void toolStripButton_save_ButtonClick(object sender, EventArgs e)
@@ -3497,12 +3145,8 @@
 
             if (!_IsEditMode)
             {
-                if (message.show("鎻愰啋", "娴忚妯″紡鏃犳硶淇濆瓨锛屾槸鍚︽仮澶嶄负缂栬緫妯″紡"))
-                {
-                    _IsEditMode = true;
-                }
-                else
-                    return;
+                TipFormHelper.ShowWarn("娴忚妯″紡鏃犳硶淇濆瓨锛岃鍒囨崲缂栬緫妯″紡");
+                return;
             }
             else
             {
@@ -3753,12 +3397,8 @@
 
             if (!_IsEditMode)
             {
-                if (message.show("鎻愰啋", "娴忚妯″紡鏃犳硶淇濆瓨锛屾槸鍚︽仮澶嶄负缂栬緫妯″紡"))
-                {
-                    _IsEditMode = true;
-                }
-                else
-                    return;
+                TipFormHelper.ShowWarn("娴忚妯″紡鏃犳硶淇濆瓨锛岃鍒囨崲缂栬緫妯″紡");
+                return;
             }
             else
             {
@@ -3892,8 +3532,8 @@
             if (openFileDialog.ShowDialog() == DialogResult.OK)
             {
                 var backgroundImagePath = openFileDialog.FileName;
-                Global.ClearFileReadOnly(_Template.BackGroundImg_FullPath);
-                FileCopy.Copy(backgroundImagePath, _Template.BackGroundImg_FullPath, true);
+                HelperC.ClearFileReadOnly(_Template.BackGroundImg_FullPath);
+                HelperC.Copy(backgroundImagePath, _Template.BackGroundImg_FullPath, true);
                 璁剧疆搴曞浘ToolStripMenuItem_Click(1, new EventArgs());
             }
         }
@@ -3940,12 +3580,12 @@
 
         private void label_zoom_Click(object sender, EventArgs e)
         {
-            string inputValue = Prompt.ShowDialog("璇疯緭鍏ユ瘮渚�", "");
-            if (float.TryParse(inputValue, out float result))
-            {
-                zoom = result;
-
-            }
+            TipFormHelper.ShowError("璇疯緭鍏ユ瘮渚�,寰呰ˉ鍏�");
+            //string inputValue = Prompt.ShowDialog("璇疯緭鍏ユ瘮渚�", "");
+            //if (float.TryParse(inputValue, out float result))
+            //{
+            //    zoom = result; 
+            //}
         }
         private void label_file_DoubleClick(object sender, EventArgs e)
         {
@@ -4044,8 +3684,6 @@
             _Template.mapOption._ShowFlowDirection = true;
             this.SetMapInvalidate();
 
-
-
         }
         private void 闅愯棌娴佸悜ToolStripMenuItem_Click(object sender, EventArgs e)
         {
@@ -4114,29 +3752,14 @@
             _Network.MapObjects.ForEach(o => o.Visible = true);
             this.SetMapInvalidate();
         }
-        public void toolStripButton_CalcMiniLoss_Click(object sender, EventArgs e)
-        {
-            //_Network.SetNodeDemand();
-            //_Network.Calc(_Template.FullPath, GlobalPath.configPath + "config_calc.wdb");
-            //_Network.CalcLinkMinorLoss();
-        }
+
         private void toolStripButton_ClearMinor_Click(object sender, EventArgs e)
         {
             _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, _Template);
-            //form_Colour.Show(this);
-        }
-
         private bool __needpaintall = false;
-
 
 
         private void cb_Link_Colour_SelectedIndexChanged(object sender, EventArgs e)
@@ -4174,24 +3797,1416 @@
             _isOrtho = !_isOrtho;
         }
 
-        private void 妤煎眰绠$悊ToolStripMenuItem_Click(object sender, EventArgs e)
-        {
-            //if (_Template.Regions == null)
-            //{
-            //    _Template.Regions = new List<TRegion>();
-            //}
-            //Form_EditFloors form_EditFloors = new Form_EditFloors(_Template.Regions);
-            //form_EditFloors.Show(this);
-        }
-
 
 
 
         #endregion
 
-        private void toolStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
+        #endregion
+
+        #region Model
+        #region  鏍稿績灞炴�� 
+        TContainer TC = new TContainer();
+
+        /// <summary>
+        /// 鍦板浘閫夐」
+        /// </summary>
+        public MapDimensions mapOption
         {
+            get { return TC.mapOption; }
+            set { TC.mapOption = value; }
+        }
+        /// <summary>
+        /// 鍦板浘閫夐」_璧峰鎿嶄綔鏃�
+        /// </summary>
+        private MapDimensions mapOption0 = new MapDimensions();
+        /// <summary>
+        /// 涓存椂绠$綉灞�
+        /// </summary>
+        [Browsable(false)]
+        public Template _newTemplate
+        {
+            get { return TC.newTemplate; }
+            set { TC.newTemplate = value; }
+        }
+
+
+        [Browsable(false)]
+        public Template _Template
+        {
+            get { return TC.template; }
+            set
+            {
+                TC.template = value;
+
+                label_file.Text = TC.template?.filePath;
+            }
+        }
+
+        #endregion
+        #region 浜や簰灞炴��
+        /// <summary>
+        /// 鎮仠瀵硅薄
+        /// </summary>
+        private List<IBaseViewModel> hoveredObjs = new List<IBaseViewModel>();
+        /// <summary>
+        /// 閫変腑瀵硅薄
+        /// </summary>
+        public List<IBaseViewModel> selectedObjs = new List<IBaseViewModel>();
+
+
+        private List<NodeViewModel> selectedNodes => selectedObjs.FindAll(o => o is NodeViewModel).Select(o => (NodeViewModel)o).ToList();
+        private List<LinkViewModel> selectedLinks => selectedObjs.FindAll(o => o is LinkViewModel).Select(o => (LinkViewModel)o).ToList();
+
+        MouseState _mouseState = MouseState.鏃�;
+        private NodeViewModel _OperaNode = null;
+        public PointF mouseXY = new PointF(0, 0);
+
+        PointF DragStartPos;
+        PointF _ClickStartPos;
+        PointF RotaStartPos;
+        PointF BackGroudPicLeftPos;
+        bool _isPanning;
+        /// <summary>
+        /// 鎷栨嫿閫夋嫨
+        /// </summary>
+        bool _isDragging;
+        bool _isRotating;
+        bool _isPainting;
+
+
+        PointF mousePosition;
+        // control+榧犳爣涓棿鎸変笅缂╂斁
+        bool _isInsertingObject = false;
+        bool _isMovingObject = false;
+        bool _isPastingObject = false;
+        Cursor _lastCursor;
+        object _undoOldValue = null;
+        private List<PointF> polygonPoints = new List<PointF>();
+
+        private bool _isDrawingPolygon;
+
+        #endregion
+        #region 鏂板绠$綉锛堣緟鍔╋級
+
+        MapViewNetWork _NewNet
+        {
+            get
+            {
+                if (_newTemplate == null) _newTemplate = new Template();
+                if (_newTemplate.network == null) _newTemplate.network = new MapViewNetWork();
+                return _newTemplate.network;
+            }
+        }
+        #endregion
+        #region 鏄剧ず閫夐」锛堣緟鍔╋級
+
+
+        private string _StartPoint = null;
+        private string _EndPoint = null;
+        //private bool __isEditMode = true;
+        [Browsable(false)]
+        public bool _IsEditMode
+        {
+            get { return this.mapOption?.isEditMode ?? true; }
+            set
+            {
+                toolStripComboBox_娴忚妯″紡.Text = value ? "缂栬緫妯″紡" : "娴忚妯″紡";
+
+                if (this.mapOption != null) this.mapOption.isEditMode = value;
+                杞崲涓篢oolStripMenuItem.Visible = _IsEditMode;
+                toolStripSeparator9.Visible = _IsEditMode;
+                鍒犻櫎ToolStripMenuItem.Visible = _IsEditMode;
+                鍒犻櫎ToolStripMenuItem1.Visible = _IsEditMode;
+
+                澶嶅埗ToolStripMenuItem.Visible = _IsEditMode;
+                澶嶅埗ToolStripMenuItem1.Visible = _IsEditMode;
+                绮樿创ToolStripMenuItem.Visible = _IsEditMode;
+                绮樿创ToolStripMenuItem1.Visible = _IsEditMode;
+                璁剧疆闀垮害ToolStripMenuItem.Visible = _IsEditMode;
+                璁句负鍏抽棴ToolStripMenuItem.Visible = _IsEditMode;
+                璁句负绔嬬鐐筎oolStripMenuItem.Visible = _IsEditMode;
+                瀵归綈ToolStripMenuItem.Visible = _IsEditMode;
+                瀵归綈ToolStripMenuItem1.Visible = _IsEditMode;
+
+                toolStripButton_鏂板缓鑺傜偣.Enabled = _IsEditMode;
+                toolStripButton_鏂板缓绠$嚎.Enabled = _IsEditMode;
+                toolStripButton_鏂板缓绔嬬.Enabled = _IsEditMode;
+                toolStripButton_娣诲姞姘村簱.Enabled = _IsEditMode;
+                toolStripButton_娣诲姞姘存睜.Enabled = _IsEditMode;
+                toolStripButton_娣诲姞姘磋〃.Enabled = _IsEditMode;
+                toolStripButton_娣诲姞闃�闂�.Enabled = _IsEditMode;
+                toolStripButton_閲嶅鍣�.Enabled = _IsEditMode;
+
+
+
+            }
+        }
+
+
+        [Browsable(false)]
+        public float Link_multiply
+        {
+            get
+            {
+                if (_Template == null || _Template.mapOption == null) return 1.0f;
+                return _Template.mapOption.Link_multiply;
+            }
+            set
+            {
+                if (_Template == null || _Template.mapOption == null) return; _Template.mapOption.Link_multiply = value;
+            }
+        }
+        [Browsable(false)]
+        public float junction_multiply
+        {
+            get
+            {
+                if (_Template == null || _Template.mapOption == null) return 1.0f;
+                return _Template.mapOption.junction_multiply;
+            }
+            set
+            {
+                if (_Template == null || _Template.mapOption == null) return; _Template.mapOption.junction_multiply = value;
+            }
+        }
+        [DisplayName("鏄剧ず闃�闂�")]
+
+        public bool _ShowValve
+        {
+            get
+            {
+                if (_Template == null || _Template.mapOption == null) return true;
+                return _Template.mapOption._ShowValve;
+            }
+            set
+            {
+                if (_Template == null || _Template.mapOption == null) return; _Template.mapOption._ShowValve = value;
+            }
+        }
+        [DisplayName("鏄剧ず鑺傜偣")]
+        public bool _ShowJunction
+        {
+            get
+            {
+                if (_Template == null || _Template.mapOption == null) return true;
+                return _Template.mapOption._ShowJunction;
+            }
+            set
+            {
+
+                if (_Template == null || _Template.mapOption == null) return; _Template.mapOption._ShowJunction = value;
+            }
+        }
+        string _filePath
+        {
+            get
+            {
+                if (string.IsNullOrEmpty(_Template?.filePath))
+                    return null;
+                string path = _Template.filePath.TrimStart('\\');
+                return
+                    Path.Combine(Directory.GetCurrentDirectory(), path);
+            }
+            //set 
+            //{
+
+            //    _Template.璺緞 = value; 
+            //} 
+        }
+        private MapViewNetWork _Network
+        {
+            get
+            {
+                return _Template?.network;
+            }
+        }
+        #endregion
+        #region 绠$綉灞炴�э紙杈呭姪锛�
+        [Browsable(false)]
+        public List<NodeCalcModel> _Nodes
+        {
+            get { return _Network?.Nodes ?? new List<NodeCalcModel>(); }
 
         }
+        [Browsable(false)]
+        public List<LinkCalcModel> _Links
+        {
+            get { return _Network?.Links ?? new List<LinkCalcModel>(); }
+
+        }
+
+        #endregion
+        #region 瑙嗚璁剧疆锛堣緟鍔╋級
+
+
+        private const float MinZoom = 0.1f;
+        private const float MaxZoom = 1000.0f;
+
+        [DisplayName("缂╂斁绯绘暟")]
+        public float zoom
+        {
+            get
+            {
+                return mapOption.zoom;
+            }
+            set
+            {
+                label_zoom.Text = $"Zoom锛歿zoom.ToString("0.000")}";
+                mapOption.zoom = value;
+            }
+        }
+        [DisplayName("鏃嬭浆瑙掑害")]
+        public double Rotation
+        {
+            get
+            {
+                return mapOption.rotation;
+            }
+            set
+            {
+                toolStripStatusLabel_rotation.Text = $"Rotation锛�({Rotation.ToString("0")}锛寋RotationF.ToString("0")})";
+                //灏嗘棆杞搴﹁浆鎹负-180~180
+                value = value % 360;
+                if (value > 180)
+                    value -= 360;
+                else if (value < -180)
+                    value += 360;
+                mapOption.rotation = value;
+            }
+        }
+
+        private double Rotation0 = 0;
+        [Browsable(false)]
+        public PointF MapCenter
+        {
+            get
+            {
+                return mapOption.Center;
+            }
+            set
+            {
+                label_center.Text = $"center锛�({MapCenter.X.ToString("0.00")} 锛寋MapCenter.Y.ToString("0.00")}锛�";
+                mapOption.Center = value;
+            }
+        }
+        private PointF MapCenter0;
+        private bool is3Dview = false;
+        double 淇瑙掑害_start = 90;
+
+
+
+        public bool Lock2DView
+        {
+            get
+            {
+                return mapOption.Lock2DView;
+            }
+            set
+            {
+                mapOption.Lock2DView = value;
+            }
+        }
+
+
+        /// <summary>
+        /// 淇绾夸笌搴曢潰鐨勫す瑙掞紝鎶曞奖鐢╯in
+        /// </summary>
+        [DisplayName("淇瑙掑害")]
+        public double RotationF
+        {
+            get
+            {
+                return mapOption.rotationF;
+            }
+            set
+            {
+                mapOption.rotationF = value;
+            }
+        }
+        [Browsable(false)]
+        public double 淇寮у害
+        {
+            get
+            {
+                return RotationF / 180 * Math.PI;
+            }
+        }
+
+        [Browsable(false)]
+        public PointF Zoom
+        {
+            get
+            {
+                return new PointF(zoom, -zoom);
+            }
+        }
+
+
+        private PointF Z(float z)
+        {
+            return new PointF(0, 0);
+        }
+        #endregion
+        #region 棰滆壊鍒嗙骇锛堣緟鍔╋級
+        public Colour NodeColour
+        {
+            set
+            {
+                var type = value.Type;
+                value.isChoosed = true;
+                _Template?.Colours?.RemoveAll(cl => cl.Type == type);
+                _Template.Colours.Add(value);
+                mapOption.ColourNode = type;
+            }
+            private get
+            {
+                return _Template?.Colours?.FirstOrDefault(cl => cl.isChoosed && cl.Type == mapOption.ColourNode);
+            }
+        }
+        public Colour LinkColour
+        {
+            set
+            {
+                var type = value.Type;
+                value.isChoosed = true;
+                _Template?.Colours?.RemoveAll(cl => cl.Type == type);
+                _Template.Colours.Add(value);
+                mapOption.ColourLink = type;
+            }
+            private get
+            {
+                return _Template?.Colours?.FirstOrDefault(cl => cl.isChoosed && cl.Type == mapOption.ColourLink);
+            }
+        }
+
+        //private bool __isOrtho = true;
+
+        #endregion
+        #region 姝d氦妯″紡
+        private bool _isOrtho
+        {
+            get
+            {
+                return mapOption.IsOrtho;
+            }
+            set
+            {
+                mapOption.IsOrtho = value;
+                if (mapOption.IsOrtho)
+                {
+                    label_ZZ.Text = "姝d氦妯″紡:寮�";
+                }
+                else
+                {
+                    label_ZZ.Text = "姝d氦妯″紡:鍏�";
+                }
+            }
+        }
+        #endregion
+
+
+        #endregion
+
+        #region Draw
+
+        #region 浜嬩欢
+        //鎸夊抚鏁板垽鏂槸鍚﹂噸缁橈紝鍑忓皯璁$畻閲忥紙姣忓抚鏈�澶氶噸缁樹竴娆★級
+        bool _timerDraw = false;
+        //鎸夊抚鏁板垽鏂紶鏍囨偓鍋滃璞★紝鍑忓皯璁$畻閲忥紙姣忓抚鏈�澶氬垽鏂竴娆★級
+        bool _mouseHoverCheckFlag = false;
+        #endregion
+
+        void DrawBackGroud(Graphics bufferG, Template template)
+        {
+            if (template == null) return;
+            var _Nodes = template.network.Nodes.ViewNodes;
+            var _Links = template.network.Links.ViewLinks;
+
+            var Cpoints = getCurclePoints(64).ToList();
+
+            var r = 1.73f / zoom;
+            var rt = r;
+
+            r = r * Link_multiply;
+            List<PointF> diametersZoom = new List<PointF>() { new PointF(0, 0.08f), new PointF(150, 0.03f), new PointF(300, 0.001f), new PointF(800, 0.0001f) };
+
+            Pen penN = new Pen(Color.FromArgb(0, 0, 255), 1 * r);
+
+
+            //鑳屾櫙鍥剧粯鍒�
+            if (this.mapOption.isShowPic && template != null && File.Exists(template.BackGroundImg_FullPath))
+            {銆�
+                List<PointF> p = new List<PointF>();
+
+                if (!this.mapOption.isAutoBackgroundImage)
+                {
+                    var Cps = new List<PointF>
+                    {
+                        template.BackGroundPoint1,
+                        new PointF(template.BackGroundPoint2.X,template.BackGroundPoint1.Y),
+                        new PointF(template.BackGroundPoint1.X,template.BackGroundPoint2.Y),
+                        //template.BackGroundPoint2,
+
+
+                    };
+                    Cps.ForEach(cp => p.Add(WorldPointToMapPoint(cp, template.BackGroundElev, template.OffSet)));
+                }
+                else
+                {
+
+
+                    var p1 = new PointF(template.BackGroundImgX, template.BackGroundImgY);
+                    var p2 = new PointF(template.BackGroundImgX + template.BackGroundImgWidth, template.BackGroundImgY + template.BackGroundImgHeight);
+
+                    var f = template.BackGroundImgRotaAngle / 180 * Math.PI;
+                    var djx = Math.Sqrt((Math.Pow(template.BackGroundImgWidth, 2) + Math.Pow(template.BackGroundImgHeight, 2)));
+                    var p3 = new PointF(p1.X + (float)(Math.Cos(f) * template.BackGroundImgWidth), p1.Y + (float)(Math.Sin(f) * template.BackGroundImgWidth));
+                    var p4 = new PointF(p1.X - (float)(Math.Sin(f) * template.BackGroundImgHeight), p1.Y + (float)(Math.Cos(f) * template.BackGroundImgHeight));
+                    p3.Y = p4.Y; 
+                    var Cps = new List<PointF>
+                {
+                    p4,
+                    p3,p1 
+                };
+                    template.BackGroundPoint1 = p4;
+                    template.BackGroundPoint2 = new PointF(p3.X, p1.Y);
+
+
+
+                    Cps.ForEach(cp => p.Add(WorldPointToMapPoint(cp, template.BackGroundElev, template.OffSet)));
+                }
+
+                try
+                {
+                    var img = System.Drawing.Image.FromFile(template.BackGroundImg_FullPath);
+                    if (img != null)
+                    {
+                        bufferG.FillPolygon(penN.Brush, p.ToArray());
+                        bufferG.DrawImage(img, p.ToArray());
+                    }
+                }
+                catch
+                {
+
+                }
+
+            }
+        }
+
+        void Draw(Graphics bufferG, Template template)
+        {
+            if (template == null) return;
+            var _Nodes = template.network.Nodes.ViewNodes;
+            var _Links = template.network.Links.ViewLinks;
+            var _Areas = template.network.Areas;
+            var Cpoints = getCurclePoints(64).ToList();
+
+            var r = 1.73f / zoom;
+            var rt = r;
+
+            float minElve = float.MinValue;
+            float maxElve = float.MaxValue;
+            r = r * Link_multiply;
+            List<PointF> diametersZoom = new List<PointF>() { new PointF(0, 0.08f), new PointF(150, 0.03f), new PointF(300, 0.001f), new PointF(800, 0.0001f) };
+
+            Pen penN = new Pen(Color.FromArgb(0, 0, 255), 1 * r);
+
+            Pen penChoosed = new Pen(Color.Purple, 5 * r);
+            Pen pen_valveChoosed = new Pen(Color.Red, 5 * r);
+
+            Pen penClosed = new Pen(Color.OrangeRed, 2 * r);
+            Pen penHovered = new Pen(Color.DeepSkyBlue, 5 * r);
+
+
+            //缁樺埗闈�
+            using (Pen pen0 = new Pen(Color.FromArgb(0, 0, 255), 2 * r))
+            {
+                foreach (var area in _Areas)
+                {
+
+                    if (!area.Visible) continue;
+                    if (!IsFaceVisibleToCamera(area, GetCameraPosition())) continue;
+                    if (area.Elev < minElve || area.Elev >= maxElve) continue;
+
+                    var p = new List<PointF>();
+                    foreach (var node in area.InnerNodes)
+                    {
+                        p.Add(CubeWorldPointToMapPoint(node, template.OffSet));
+                    }
+                    if (p.Count < 3) continue;
+                    pen0.Color = penClosed.Color = area.color;
+                    Pen pen = pen0;
+                    if (area.Hovered) pen = penHovered;
+                    bufferG.FillPolygon(pen.Brush, p.ToArray());
+                    bufferG.DrawPolygon(pen, p.ToArray());
+                    //鏄剧ずarea鐨勫悕绉�
+                    var c = new PointF(p.Average(p0 => p0.X), p.Average(p0 => p0.Y));
+                    var brush = new SolidBrush(Color.White);
+
+
+                    var gs = bufferG.Save();
+                    // 搴旂敤鐭╅樀鍙樻崲浠ユ姷娑堜箣鍓嶇殑缈昏浆鏁堟灉
+                    bufferG.ScaleTransform(1 / Zoom.X, 1 / Zoom.Y);
+
+                    Font font = new Font(FontFamily.GenericSansSerif, 10 * 10 * zoom);
+
+                    SizeF textSize = bufferG.MeasureString(area.Name, font);
+                    var center = new PointF(c.X * Zoom.X, c.Y * Zoom.Y);
+                    float textLeft = center.X - textSize.Width / 2;
+                    float textTop = center.Y - textSize.Height / 2;
+                    PointF pd = new PointF(textLeft, textTop);
+
+                    bufferG.DrawString(area.Name, font, brush, pd);
+                    // 鎭㈠涔嬪墠淇濆瓨鐨勭粯鍥剧姸鎬�
+                    bufferG.Restore(gs);
+                }
+            }
+
+
+            // 缁樺埗绾� 
+            HashSet<long> dict_flow_direction = new HashSet<long>();
+            using (Pen pen0 = new Pen(Color.FromArgb(0, 0, 255), 2 * r))
+            {
+
+                foreach (var link in _Links)
+                {
+                    if (!link.Visible) continue;
+                    if (link.Elev < minElve || link.Elev >= maxElve) continue;
+                    //if (_isMovingObject && (link.StartNode == _OperaNode || link.EndNode == _OperaNode)) continue;
+                    var p1 = WorldPointToMapPoint(link.StartNode, template.OffSet);
+                    var p2 = WorldPointToMapPoint(link.EndNode, template.OffSet);
+                    if (!isVisible(p1) && !isVisible(p2)) continue;
+                    if (LinkColour != null)
+                    {
+                        pen0.Color = penClosed.Color = GraphHelper.getLinkColor(LinkColour, link);
+                    }
+
+                    Pen pen = pen0;
+#if DEBUG
+#else
+                    if (_Template != null && _Template.mapOption._ShowStatus && link.Status == Hydro.Core.ObjectEnum.StatusType.CLOSED) pen = penClosed;
+#endif
+
+                    if (link.Hovered) pen = penHovered;
+                    float zoomAtMin = 0;
+                    for (int i = 0; i < diametersZoom.Count; i++)
+                    {
+                        PointF point = diametersZoom[i];
+                        if (link.Diameter >= point.X) continue;
+                        zoomAtMin = diametersZoom[i - 1].Y;
+                        break;
+                    }
+                    if (zoomAtMin >= zoom) continue;
+                    if (link is ValveViewModel)
+                    {
+                        if (link.Selected || _ShowValve)
+                        {
+
+                            var c = new PointF((p1.X + p2.X) / 2, (p1.Y + p2.Y) / 2);
+                            bufferG.DrawLines(link.Selected ? penChoosed : pen, new PointF[] { p1, p2 });
+                            var valveShapeHeight = link.Selected ? 10 : 5;
+                            PointF[] points = new PointF[] {
+                                GraphHelper.getRotatePoint(c.X - valveShapeHeight * r, c.Y + valveShapeHeight * r,c,p1,p2),
+                                GraphHelper.getRotatePoint(c.X - valveShapeHeight * r, c.Y - valveShapeHeight * r,c,p1,p2),
+                                GraphHelper.getRotatePoint(c.X + valveShapeHeight * r, c.Y + valveShapeHeight * r,c,p1,p2),
+                                GraphHelper.getRotatePoint(c.X + valveShapeHeight * r, c.Y - valveShapeHeight * r,c,p1,p2),
+                                GraphHelper.getRotatePoint(c.X - valveShapeHeight * r, c.Y + valveShapeHeight * r,c,p1,p2),
+
+                            };
+
+                            bufferG.FillPolygon(link.Selected ? pen_valveChoosed.Brush : pen.Brush, points);
+
+                        }
+
+
+                    }
+                    else if (link is PumpViewModel)
+                    {
+                        if (link.Selected || _ShowValve)
+                        { 
+                            var c = new PointF((p1.X + p2.X) / 2, (p1.Y + p2.Y) / 2);
+                          
+
+                            bufferG.DrawLines(link.Selected ? penChoosed : pen, new PointF[] { p1, p2 });
+                            // 缁樺埗鍦嗗舰閮ㄥ垎锛堟按娉电殑娉典綋锛�
+                            float radius = 5 * r;
+                            float diameter = radius * 2;
+                            #region 鍦嗗舰鎷嗗垎
+                       
+                            List<PointF> p = new List<PointF>();
+                            Cpoints.ForEach(cp => p.Add(GraphHelper.getRotatePoint(c.X + cp.X * radius - radius, c.Y + cp.Y * radius, c, p1, p2)));
+
+                            #endregion
+
+
+
+                            bufferG.FillPolygon(link.Selected ? pen_valveChoosed.Brush : pen.Brush, p.ToArray());
+
+
+                            // 缁樺埗杩炴帴绾�
+
+
+                            var valveShapeHeight = link.Selected ? radius * 2 : radius;
+                            PointF[] points = new PointF[] {
+                                GraphHelper.getRotatePoint(c.X - valveShapeHeight , c.Y + valveShapeHeight ,c,p1,p2),
+                                GraphHelper.getRotatePoint(c.X - valveShapeHeight , c.Y ,c,p1,p2),
+                                GraphHelper.getRotatePoint(c.X + valveShapeHeight , c.Y ,c,p1,p2),
+                                GraphHelper.getRotatePoint(c.X + valveShapeHeight , c.Y + valveShapeHeight ,c,p1,p2),
+                                GraphHelper.getRotatePoint(c.X - valveShapeHeight , c.Y + valveShapeHeight ,c,p1,p2),
+
+                            };
+
+                            bufferG.FillPolygon(link.Selected ? pen_valveChoosed.Brush : pen.Brush, points);
+                        }
+
+
+                    }
+                    else if (link is RepeaterViewModel re)
+                    {
+                        if (re.Status == RepeatStatus.鏀惰捣 || _IsEditMode)
+                        {
+
+                            bufferG.DrawLines(link.Selected ? penChoosed : pen, new PointF[] { p1, p2 });
+
+
+                            var listNode = GraphHelper.Get绛夊垎Nodes(p1, p2, Math.Max(re.RepeatTimes, 1));
+
+                            for (int i = 0; i < listNode.Count; i++)
+                            {
+
+                                var c = listNode[i];
+                                RectangleF[] rects = new RectangleF[] {
+                                    new RectangleF(c.X-10*r,c.Y-8*r,20*r,16*r),
+                                };
+                                bufferG.FillRectangles(new SolidBrush(Color.White), rects);
+
+
+                                // 淇濆瓨褰撳墠缁樺浘鐘舵��
+                                var gs = bufferG.Save();
+                                // 搴旂敤鐭╅樀鍙樻崲浠ユ姷娑堜箣鍓嶇殑缈昏浆鏁堟灉
+                                bufferG.ScaleTransform(1 / Zoom.X, 1 / Zoom.Y);
+                                int index = re.GetIndex(i);
+                                string indexString = index == 0 ? "" : index.ToString();
+                                Font font = new Font(FontFamily.GenericSansSerif, 10);
+                                string text = $"{indexString}{re.NetworkShowName}";
+                                SizeF textSize = bufferG.MeasureString(text, font);
+                                var center = new PointF(c.X * Zoom.X, c.Y * Zoom.Y);
+                                float textLeft = center.X - textSize.Width / 2;
+                                float textTop = center.Y - textSize.Height / 2;
+                                PointF p = new PointF(textLeft, textTop);
+
+                                bufferG.DrawString(text, font, link.Selected ? penChoosed.Brush : pen.Brush, p);
+                                // 鎭㈠涔嬪墠淇濆瓨鐨勭粯鍥剧姸鎬�
+                                bufferG.Restore(gs);
+
+                                if (textSize.Width / Zoom.X > rects[0].Width)
+                                {
+                                    rects[0] = new RectangleF(c.X - textSize.Width / 2 / Zoom.X - 1 * r, c.Y - 8 * r, textSize.Width / Zoom.X + 2 * r, 16 * r);
+                                }
+                                try
+                                {
+                                    bufferG.DrawRectangles(penN, rects);
+
+                                }
+                                catch { }
+
+                            }
+                        }
+
+                    }
+                    else
+                    {
+
+                        if (link.StartNode == null || link.EndNode == null) continue;
+                        try
+                        {
+                            bufferG.DrawLines(link.Selected ? penChoosed : pen, new PointF[] { p1, p2 });
+                        }
+                        catch (Exception ex)
+                        {
+
+                        }
+                        if (_Template.mapOption._ShowFlowDirection)
+                        {
+                            var c = new PointF((p1.X + p2.X) / 2, (p1.Y + p2.Y) / 2);
+                            var ps = MapToScreen(c);
+                            //灏唒s杞崲涓簎long锛岀簿搴︿负20锛屽苟鍔犲叆鍒癲ict_flow_direction涓�
+                            var ps_20 = GraphHelper.GetUlongByPoint(ps, 5);
+                            if (!dict_flow_direction.Contains(ps_20))
+                            {
+                                dict_flow_direction.Add(ps_20);
+                                bufferG.DrawLines(link.Selected ? penChoosed : pen, new PointF[] { p1, p2 });
+                                // 缁樺埗鍦嗗舰閮ㄥ垎锛堟按娉电殑娉典綋锛�
+                                float radius = 5 * r;
+                                float diameter = radius * 2;
+                                #region 鍦嗗舰鎷嗗垎
+                                float activeD = 1;
+                                if (link.EN_FLOW < 0) activeD = -1;
+                                List<PointF> p = new List<PointF>();
+                                Cpoints.ForEach(cp => p.Add(GraphHelper.getRotatePoint(c.X - activeD * cp.X * radius + activeD * radius, c.Y + cp.Y * radius, c, p1, p2)));
+
+                                #endregion
+
+
+                                bufferG.FillPolygon(link.Selected ? pen_valveChoosed.Brush : pen.Brush, p.ToArray());
+
+                                var valveShapeHeight = link.Selected ? radius * 2 : radius;
+                                PointF[] points = new PointF[] {
+                                    GraphHelper.getRotatePoint(c.X -activeD* valveShapeHeight , c.Y + valveShapeHeight ,c,p1,p2),
+                                    GraphHelper.getRotatePoint(c.X  , c.Y ,c,p1,p2),
+                                    GraphHelper.getRotatePoint(c.X - activeD*valveShapeHeight , c.Y - valveShapeHeight,c,p1,p2),
+                                    GraphHelper.getRotatePoint(c.X + activeD*valveShapeHeight , c.Y - valveShapeHeight,c,p1,p2),
+                                    GraphHelper.getRotatePoint(c.X + activeD*valveShapeHeight , c.Y + valveShapeHeight ,c,p1,p2),
+                                    GraphHelper.getRotatePoint(c.X - activeD*valveShapeHeight , c.Y + valveShapeHeight ,c,p1,p2),
+                                };
+
+                                bufferG.FillPolygon(link.Selected ? pen_valveChoosed.Brush : pen.Brush, points);
+                            }
+
+
+
+                        }
+                    }
+
+                }
+            }
+
+
+            r = rt;
+
+
+            HashSet<long> dict_point = new HashSet<long>();
+            //缁樺埗鐐�
+            penChoosed = new Pen(Color.Green, 1f * r);
+            Brush brushChoosed = penChoosed.Brush;
+            SolidBrush whiteBrush = new SolidBrush(Color.White);
+
+            using (Pen pen0 = new Pen(Color.FromArgb(255, 0, 0), 1 * r))
+            {
+
+                foreach (NodeViewModel node in _Nodes)
+                {
+                    if (!node.Visible) continue;
+                    if (node.Elev < minElve || node.Elev >= maxElve) continue;
+                    Pen pen = pen0;
+                    Brush brush = pen.Brush;
+                    float pr = (float)(r * 0.5);
+                    pr = pr * junction_multiply;
+                    PointF p = WorldPointToMapPoint(node, template.OffSet);
+                    if (!isVisible(p)) continue;
+                    var ps_20 = GraphHelper.GetUlongByPoint(p, 0.1f);
+                    if (dict_point.Contains(ps_20))
+                        continue;
+                    dict_point.Add(ps_20);
+                    if (NodeColour != null)
+                    {
+                        pen.Color = penChoosed.Color = GraphHelper.getNodeColor(NodeColour, node);
+                        brush = pen.Brush;
+                        brushChoosed = penChoosed.Brush;
+
+
+                    }
+                    if (node.Hovered)
+                    {
+                        pen = penHovered;
+                        brush = pen.Brush;
+                        pr = pr * 2;
+                    }
+
+                    var rectangle = new RectangleF((float)p.X - 5 * pr, (float)p.Y - 5 * pr, 10 * pr, 10 * pr);
+                    float zoomAtMin = 0;
+                    for (int i = 0; i < diametersZoom.Count; i++)
+                    {
+                        PointF point = diametersZoom[i];
+                        if (node.MaxDiameter >= point.X) continue;
+                        zoomAtMin = diametersZoom[i - 1].Y;
+                        break;
+                    }
+                    if (zoomAtMin >= zoom) continue;
+
+                    if (node == _OperaNode)
+                    {
+                        var whiteRect = new RectangleF(rectangle.X - 4 * pr, rectangle.Y - 4 * pr, rectangle.Width + 8 * pr, rectangle.Height + 8 * pr);
+                        bufferG.FillEllipse(whiteBrush, whiteRect);
+
+                        whiteRect = new RectangleF(rectangle.X + 2 * pr, rectangle.Y + 2 * pr, rectangle.Width - 4 * pr, rectangle.Height - 4 * pr);
+                        bufferG.DrawEllipse(node.Selected ? penChoosed : pen, whiteRect);
+
+
+                        whiteRect = new RectangleF(rectangle.X - 4 * pr, rectangle.Y - 4 * pr, rectangle.Width + 8 * pr, rectangle.Height + 8 * pr);
+                        bufferG.DrawEllipse(node.Selected ? penChoosed : pen, whiteRect);
+
+
+                    }
+                    else if (node.ID == _EndPoint)
+                    {
+
+                        var whiteRect = new RectangleF(rectangle.X - 4 * pr, rectangle.Y - 4 * pr, rectangle.Width + 8 * pr, rectangle.Height + 8 * pr);
+                        bufferG.FillEllipse(whiteBrush, whiteRect);
+
+                        whiteRect = new RectangleF(rectangle.X - 4 * pr, rectangle.Y - 4 * pr, rectangle.Width + 8 * pr, rectangle.Height + 8 * pr);
+                        bufferG.DrawEllipse(node.Selected ? penChoosed : pen, whiteRect);
+
+
+                        var p1 = new PointF(rectangle.X + 2 * pr, rectangle.Y + 2 * pr);
+                        var p2 = new PointF(p1.X + 6 * pr, p1.Y + 6 * pr);
+                        bufferG.DrawLine(node.Selected ? penChoosed : pen, p1, p2);
+                        p1 = new PointF(rectangle.X + 2 * pr, rectangle.Y + 8 * pr);
+                        p2 = new PointF(p1.X + 6 * pr, p1.Y - 6 * pr);
+                        bufferG.DrawLine(node.Selected ? penChoosed : pen, p1, p2);
+                    }
+                    else if (node is TankViewModel)
+                    {
+                        pr *= 2;
+                        rectangle = new RectangleF((float)p.X - 5 * pr, (float)p.Y - 5 * pr, 10 * pr, 10 * pr);
+                        RectangleF r0 = new RectangleF(rectangle.X, rectangle.Y + 5 * pr, 10 * pr, 5 * pr);
+                        RectangleF r1 = new RectangleF(rectangle.X + 2 * pr, rectangle.Y, 6 * pr, 5 * pr);
+                        bufferG.FillRectangle(node.Selected ? brushChoosed : brush, r0);
+                        bufferG.FillRectangle(node.Selected ? brushChoosed : brush, r1);
+
+                    }
+                    else if (node is ReservoirViewModel)
+                    {
+                        pr *= 2;
+                        rectangle = new RectangleF((float)p.X - 5 * pr, (float)p.Y - 5 * pr, 10 * pr, 10 * pr);
+
+                        RectangleF r0 = new RectangleF(rectangle.X, rectangle.Y + 2 * pr, rectangle.Width, 6 * pr);
+                        RectangleF r1 = new RectangleF(rectangle.X, rectangle.Y + 8 * pr, 1 * pr, 2 * pr);
+                        RectangleF r2 = new RectangleF(rectangle.X + 9 * pr, rectangle.Y + 8 * pr, 1 * pr, 2 * pr);
+                        bufferG.FillRectangle(node.Selected ? brushChoosed : brush, r0);
+                        bufferG.FillRectangle(node.Selected ? brushChoosed : brush, r1);
+                        bufferG.FillRectangle(node.Selected ? brushChoosed : brush, r2);
+                    }
+                    else if (node is MeterViewModel)
+                    {
+                        bufferG.FillEllipse(node.Selected ? brushChoosed : brush, rectangle);
+                        var whiteRect = new RectangleF(rectangle.X + 1 * pr, rectangle.Y + 1 * pr, rectangle.Width - 2 * pr, rectangle.Height - 2 * pr);
+                        bufferG.FillEllipse(whiteBrush, whiteRect);
+
+                        var p1 = new PointF(rectangle.X + 5 * pr, rectangle.Y);
+                        var p2 = new PointF(rectangle.X + 5 * pr, rectangle.Y + 10 * pr);
+                        bufferG.DrawLine(node.Selected ? penChoosed : pen, p1, p2);
+                    }
+                    else
+                    {
+                        rectangle = new RectangleF((float)p.X - 3 * pr, (float)p.Y - 3 * pr, 6 * pr, 6 * pr);
+                        if (node.Selected || _ShowJunction)
+                            bufferG.FillEllipse(node.Selected ? brushChoosed : brush, rectangle);
+                    }
+
+                }
+            }
+
+            using (Pen pen = new Pen(Color.FromArgb(255, 0, 0), 1 * r))
+            {
+                Brush brush = pen.Brush;
+                //鑾峰彇_Nodes涓嚜鐢辨按鍘嬫渶灏忕殑鑺傜偣
+                var node = _Nodes.Where(n => n is JunctionViewModel || n is MeterViewModel && n.EN_PRESSURE != float.NaN).OrderBy(n => n.EN_PRESSURE).FirstOrDefault();
+                //鍒ゆ柇node.EN_PRESSURE涓嶆槸float.NaN
+
+                if (node != null && !float.IsNaN(node.EN_PRESSURE))
+                {
+ 
+                    float pr = (float)(r * 0.5);
+                    pr = pr * junction_multiply;
+                    PointF p = WorldPointToMapPoint(node, template.OffSet);
+
+                    var ps_20 = GraphHelper.GetUlongByPoint(p, 0.1f);
+
+                    dict_point.Add(ps_20);
+                    if (NodeColour != null)
+                    {
+                        pen.Color = GraphHelper.getNodeColor(NodeColour, node);
+                        brush = pen.Brush;
+                        brushChoosed = penChoosed.Brush;
+
+
+                    }
+
+
+                    var rectangle = new RectangleF((float)p.X - 5 * pr, (float)p.Y - 5 * pr, 10 * pr, 10 * pr);
+                    float zoomAtMin = 0;
+                    for (int i = 0; i < diametersZoom.Count; i++)
+                    {
+                        PointF point = diametersZoom[i];
+                        if (node.MaxDiameter >= point.X) continue;
+                        zoomAtMin = diametersZoom[i - 1].Y;
+                        break;
+                    }
+
+
+                    var p1 = new PointF((float)p.X - 4 * pr, (float)p.Y - 2 * pr);
+                    var p2 = new PointF((float)p.X + 4 * pr, (float)p.Y - 2 * pr);
+                    var p3 = new PointF((float)p.X, (float)p.Y - 4 * pr);
+                    bufferG.DrawPolygon(node.Selected ? penChoosed : pen, new PointF[] { p1, p2, p3 });
+
+                    var whiteRect = new RectangleF(rectangle.X - 4 * pr, rectangle.Y - 4 * pr, rectangle.Width + 8 * pr, rectangle.Height + 8 * pr);
+                    bufferG.FillEllipse(whiteBrush, whiteRect);
+
+                    whiteRect = new RectangleF(rectangle.X - 4 * pr, rectangle.Y - 4 * pr, rectangle.Width + 8 * pr, rectangle.Height + 8 * pr);
+                    bufferG.DrawEllipse(node.Selected ? penChoosed : pen, whiteRect);
+
+                }
+            }
+        }
+
+        //缁樺埗杈呭姪绾�
+        void DrawH(Graphics bufferG, Template template)
+        {
+            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}";
+                var _lastMousePosition = DragStartPos;
+                // 缁樺埗鐭╁舰
+                var start = new PointF((float)Math.Min(mousePosition.X, _lastMousePosition.X), (float)Math.Min(mousePosition.Y, _lastMousePosition.Y));
+                var size = new SizeF((float)Math.Abs(_lastMousePosition.X - mousePosition.X), (float)Math.Abs(_lastMousePosition.Y - mousePosition.Y));
+                if (size.Width == 0) size.Width = 0.01f;
+                if (size.Height == 0) size.Height = 0.01f;
+                var rectangle0 = new RectangleF(start, size);
+                using (var pen = new Pen(Color.Black, 0.5f * r))
+                {
+                    bufferG.DrawRectangles(pen, new RectangleF[] { rectangle0 });
+                }
+            }
+            if (_isPainting)
+            {
+                if (_mouseState == MouseState.鏂板绔嬬)
+                {
+                    var wPos = GetZZWorldPoint(_select_junction1.Position3D, _MousePosition, new Vector3(0, 0, 1));
+                    using (var pen = new Pen(Color.Black, 1 * r))
+                    {
+                        pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
+                        bufferG.DrawLine(pen, WorldPointToMapPoint(_select_junction1), WorldPointToMapPoint(wPos));
+                    }
+                }
+                else
+                {
+
+                    using (var pen = new Pen(Color.Black, 1 * r))
+                    {
+                        pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
+                        if (mapOption.IsOrtho)
+                        {
+                            var wPos = GetZZWorldPoint(_select_junction1.Position3D, _MousePosition, new Vector3(1, 1, 0)); 
+                            var mapPos = WorldPointToMapPoint(wPos);
+                            if (double.IsNaN(mapPos.X) || double.IsNaN(mapPos.Y))
+                            {
+                                return;
+                            }
+                            bufferG.DrawLine(pen, WorldPointToMapPoint(_select_junction1), mapPos);
+                        }
+                        else
+                        {
+                            bufferG.DrawLine(pen, WorldPointToMapPoint(_select_junction1), _MousePosition);
+                        }
+
+                    }
+                }
+            }
+            if (_isDrawingPolygon && polygonPoints.Count > 0)
+            {
+                List<PointF> pf = polygonPoints.ToList();
+                pf.Add(new PointF(mousePosition.X, mousePosition.Y));
+                using (var pen = new Pen(Color.Black, 1 * r))
+                {
+                    // 缁樺埗澶氳竟褰㈣櫄绾胯竟妗�
+                    pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
+                    bufferG.DrawLines(pen, pf.ToArray());
+                }
+            }
+            if (_isSettingBackGroundPictur)
+            {
+
+                var _lastMousePosition = DragStartPos;
+                // 缁樺埗鐭╁舰
+                var start = new PointF((float)Math.Min(mousePosition.X, _lastMousePosition.X), (float)Math.Min(mousePosition.Y, _lastMousePosition.Y));
+                var size = new SizeF((float)Math.Abs(_lastMousePosition.X - mousePosition.X), (float)Math.Abs(_lastMousePosition.Y - mousePosition.Y));
+                var rectangle0 = new RectangleF(start, size);
+                using (var pen = new Pen(Color.Black, 1 * r))
+                {
+                    bufferG.DrawRectangles(pen, new RectangleF[] { rectangle0 });
+                }
+            }
+
+            if (_isMovingObject)
+            {
+                var newP = _MousePosition;
+                //var p = MapPointToWorldPoint(, _OperaNode.Elev);
+                var oldP3D = (PointF3D)_undoOldValue;
+                var oldP = WorldPointToMapPoint(new PointF(oldP3D.X, oldP3D.Y), oldP3D.Z);
+                List<PointF> pf = new List<PointF> { oldP, newP };
+                using (var pen = new Pen(Color.Black, 1 * r))
+                {
+                    // 缁樺埗澶氳竟褰㈣櫄绾胯竟妗�
+                    pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
+                    bufferG.DrawLines(pen, pf.ToArray());
+                }
+            }
+        }
+
+        #region 鍩虹鍧愭爣杞崲鏂规硶
+        /// <summary>
+        /// 灏嗗睆骞曞潗鏍囪浆鎹负涓栫晫鍧愭爣銆傝緭鍏ュ睆骞曞潗鏍� (x,y)锛岃繑鍥炰笘鐣屽潗鏍� (wx, wy)銆�
+        /// </summary>
+        /// <param name="screenPos"></param>
+        /// <returns></returns>
+        private PointF ScreenToVMap(PointF screenPos, float z = 0)
+        {
+
+            var centerX = this.map.Width / 2;
+            var centerY = this.map.Height / 2;
+            var worldX = (screenPos.X - centerX - Z(z).X) / Zoom.X + MapCenter.X;
+            var worldY = (screenPos.Y - centerY) / Zoom.Y + 0; 
+            return new PointF(worldX, worldY);
+        }
+
+
+        /// <summary>
+        /// 灏嗗睆骞曞潗鏍囪浆鎹负涓栫晫鍧愭爣銆傝緭鍏ュ睆骞曞潗鏍� (x,y)锛岃繑鍥炰笘鐣屽潗鏍� (wx, wy)銆�
+        /// </summary>
+        /// <param name="screenPos"></param>
+        /// <returns></returns>
+        private PointF ScreenToMap(PointF screenPos, float z = 0)
+        {
+
+            var centerX = this.map.Width / 2;
+            var centerY = this.map.Height / 2;
+            var worldX = (screenPos.X - centerX - Z(z).X) / Zoom.X + MapCenter.X;
+            var worldY = (screenPos.Y - centerY - Z(z).Y) / Zoom.Y + MapCenter.Y;
+            //if (is3Dview) worldY = -(screenPos.Y - centerY + 2 * z) / (0.5f* zoom) + center.Y;
+            return new PointF(worldX, worldY);
+        }
+
+        /// <summary>
+        /// 涓栫晫鎶曞奖鍧愭爣杞崲涓哄睆骞曞潗鏍�
+        /// </summary>
+        /// <param name="mapPos"></param>
+        /// <param name="z"></param>
+        /// <returns></returns>
+        private PointF MapToScreen(PointF mapPos, float z = 0)
+        {
+
+            var centerX = this.map.Width / 2;
+            var centerY = this.map.Height / 2;
+            var screenX = (mapPos.X - MapCenter.X) * Zoom.X + centerX + Z(z).X;
+            var screenY = (mapPos.Y - MapCenter.Y) * Zoom.Y + centerY + Z(z).Y;
+            //if (is3Dview) screenY = -(mapPos.Y - center.Y) * (0.5f * zoom) + centerY - 2 * z;
+            return new PointF(screenX, screenY);
+        }
+
+
+        // 鏍规嵁鏃嬭浆瑙掑害璁$畻鏃嬭浆鍚庣殑鍧愭爣
+
+
+        // 鏍规嵁鏃嬭浆瑙掑害璁$畻鏃嬭浆鍚庣殑鍧愭爣
+        private PointF Get骞抽潰鏃嬭浆Point(PointF p, PointF MapC)
+        {
+
+            PointF center = MapC;
+            double radian = Rotation * Math.PI / 180;  // 瑙掑害杞姬搴�
+            float x = (float)(Math.Cos(radian) * (p.X - center.X) - Math.Sin(radian) * (p.Y - center.Y) + center.X);
+            float y = (float)(Math.Sin(radian) * (p.X - center.X) + Math.Cos(radian) * (p.Y - center.Y) + center.Y);
+            return new PointF(x, y);
+        }
+        private PointF Get骞抽潰杩樺師Point(PointF p, PointF MapC)
+        {
+            PointF center = MapC;
+            double radian = -Rotation * Math.PI / 180;  // 瑙掑害杞姬搴�
+            float x = (float)(Math.Cos(radian) * (p.X - center.X) - Math.Sin(radian) * (p.Y - center.Y) + center.X);
+            float y = (float)(Math.Sin(radian) * (p.X - center.X) + Math.Cos(radian) * (p.Y - center.Y) + center.Y);
+            return new PointF(x, y);
+        }
+
+
+
+        private PointF Get淇瑙掓棆杞琍oint(PointF p, float z, PointF MapC)
+        {
+            PointF center = MapC;
+            double radian_fushi = 淇寮у害;
+            float sin = (float)Math.Sin(radian_fushi);
+            float cos = (float)Math.Cos(radian_fushi);
+            float x = (float)p.X;
+            float y = (float)(sin * (p.Y - center.Y) + center.Y) + cos * z;
+            return new PointF(x, y);
+        }
+        private PointF Get淇瑙掕繕鍘烶oint(PointF p, float z, PointF MapC)
+        {
+            PointF center = MapC;
+            double radian_fushi = 淇寮у害;
+            float sin = (float)Math.Sin(radian_fushi);
+            float cos = (float)Math.Cos(radian_fushi);
+            float x = (float)p.X;
+            float y = (p.Y - center.Y - cos * z) / sin + center.Y;
+            return new PointF(x, y);
+        }
+
+
+        private PointF GetRotateVector(PointF p, PointF p0)
+        {
+
+            double radian = Rotation * Math.PI / 180;  // 瑙掑害杞姬搴�
+            float x = (float)(Math.Cos(radian) * (p.X - p0.X) - Math.Sin(radian) * (p.Y - p0.Y));
+            float y = (float)(Math.Sin(radian) * (p.X - p0.X) + Math.Cos(radian) * (p.Y - p0.Y));
+            return new PointF(x, y);
+        }
+        /// <summary>
+        /// 鑾峰彇涓栫晫鎶曞奖鍧愭爣
+        /// </summary>
+        /// <param name="point"></param>
+        /// <param name="z"></param>
+        /// <returns></returns>
+        private PointF WorldPointToMapPoint(PointF point, float z, PointF3D offset = null)
+        {
+            if (offset == null) offset = new PointF3D(0, 0, 0);
+            point = new PointF(point.X + offset.X, point.Y + offset.Y);
+
+            var pointR = Get骞抽潰鏃嬭浆Point(point, MapCenter);
+
+            var pointT = Get淇瑙掓棆杞琍oint(pointR, z + offset.Z, MapCenter);
+              
+            return pointT;
+        }
+        private PointF WorldPointToMapPoint(PointF3D point, PointF3D offset = null)
+        {
+            return WorldPointToMapPoint(new PointF(point.X, point.Y), point.Z, offset);
+
+        }
+        private PointF WorldPointToMapPoint(NodeViewModel junction, PointF3D offset = null)
+        {
+            PointF p;
+            if (junction == null) return new PointF(0, 0);
+            p = WorldPointToMapPoint(junction.Position, junction.Elev, offset);
+            return p;
+        }
+        private PointF CubeWorldPointToMapPoint(NodeViewModel junction, PointF3D offset = null)
+        {
+            PointF p;
+            if (junction == null) return new PointF(0, 0);
+            var point = junction.Position;
+            var z = junction.Elev;
+            if (offset == null) offset = new PointF3D(0, 0, 0);
+            point = new PointF(point.X + offset.X, point.Y + offset.Y);
+            var pointR = Get骞抽潰鏃嬭浆Point(point, new PointF(0, 0));
+            var pointT = Get淇瑙掓棆杞琍oint(pointR, z + offset.Z, new PointF(0, 0)); 
+            return pointT;
+        }
+        
+        /// <summary>
+        /// 鑾峰彇姝d氦鎶曞奖鍧愭爣,杩斿洖鐨勬槸涓栫晫鍧愭爣
+        /// </summary>
+        /// <param name="position3D">涓栫晫鍧愭爣</param>
+        /// <param name="mousePosition">鍦板浘鍧愭爣</param>
+        /// <param name="vector3">鎶曞奖鍚戦噺</param>
+        /// <returns></returns>
+        /// <exception cref="NotImplementedException"></exception>
+        private PointF3D GetZZWorldPoint(PointF3D position3D, PointF mousePosition, Vector3 vector3)
+        {
+            //鍋氫竴鏉¢�氳繃position3D鐨勫钩琛屼簬vector3鐨勭洿绾匡紝
+            if (vector3 == new Vector3(0, 0, 1))
+            {
+                return GetLGWorldPoint(position3D, mousePosition);
+            }
+            else
+            {
+                var p2 = MapPointToWorldPoint(mousePosition, position3D.Z);
+                var vector = new Vector2(p2.X - position3D.X, p2.Y - position3D.Y);
+                //鍒ゆ柇浜岀淮鍚戦噺vector鍦ㄧ鍑犺薄闄愶紝璺濈鍝釜杞存渶杩�
+                var x = vector.X;
+                var y = vector.Y;
+                var x1 = Math.Abs(x);
+                var y1 = Math.Abs(y);
+                if (x1 > y1)
+                {
+                    if (x > 0)
+                    {
+                        //绗竴璞¢檺
+                        return new PointF3D(position3D.X + Math.Abs(x), position3D.Y, position3D.Z);
+                    }
+                    else
+                    {
+                        //绗笁璞¢檺
+                        return new PointF3D(position3D.X - Math.Abs(x), position3D.Y, position3D.Z);
+                    }
+                }
+                else
+                {
+                    if (y > 0)
+                    {
+                        //绗簩璞¢檺
+                        return new PointF3D(position3D.X, position3D.Y + Math.Abs(y), position3D.Z);
+                    }
+                    else
+                    {
+                        //绗洓璞¢檺
+                        return new PointF3D(position3D.X, position3D.Y - Math.Abs(y), position3D.Z);
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// 鑾峰彇姝d氦鎶曞奖鍧愭爣,杩斿洖鐨勬槸涓栫晫鍧愭爣
+        /// </summary>
+        /// <param name="position3D">涓栫晫鍧愭爣</param>
+        /// <param name="mousePosition">鍦板浘鍧愭爣</param>
+        /// <param name="vector3">鎶曞奖鍚戦噺</param>
+        /// <returns></returns>
+        /// <exception cref="NotImplementedException"></exception>
+        private PointF3D GetLGWorldPoint(PointF3D position3D, PointF p2)
+        {
+            double radian_fushi = 淇寮у害;
+            float sin = (float)Math.Sin(radian_fushi);
+            float cos = (float)Math.Cos(radian_fushi);
+            var p1 = WorldPointToMapPoint(position3D);
+            var dy = p2.Y - p1.Y;
+            float dz = dy / cos;
+            return new PointF3D(position3D.X, position3D.Y, position3D.Z + dz);
+
+        }
+         
+        /// <summary>
+        /// 鑾峰彇鍦板浘鎶曞奖鍧愭爣
+        /// </summary>
+        /// <param name="point"></param>
+        /// <param name="z"></param>
+        /// <returns></returns>
+        public PointF MapPointToWorldPoint(PointF point, float z = 0)
+        {
+            var pointT = Get淇瑙掕繕鍘烶oint(point, z, MapCenter);
+            pointT = Get骞抽潰杩樺師Point(pointT, MapCenter);
+            銆�
+            return pointT;
+        }
+   
+
+
+
+        #endregion
+
+        #region 璁$畻涓夌淮鐩告満
+        public PointF3D GetCameraPosition(float distance = 1)
+        {
+            // 灏嗚搴﹁浆鎹负寮у害
+            float rotationRadians = (float)Rotation * (float)Math.PI / 180;
+            float rotationFRadians = (float)RotationF * (float)Math.PI / 180;
+
+            // 璁$畻鐩告満鐨勭悆鍧愭爣绯讳綅缃�
+            float x = distance * (float)Math.Sin(rotationFRadians) * (float)Math.Cos(rotationRadians);
+            float y = distance * (float)Math.Sin(rotationFRadians) * (float)Math.Sin(rotationRadians);
+            float z = distance * (float)Math.Cos(rotationFRadians);
+
+            return new PointF3D(x, y, z);
+        }
+
+        public bool IsFaceVisibleToCamera(AreaViewModel area, PointF3D cameraPosition)
+        {
+
+            //姝i潰鏄�2锛屽彸闈㈡槸1锛屽乏闈㈡槸3锛岃儗闈㈡槸4
+            //Rotation涓�0鏃讹紝鍙樉绀烘闈紝Rotation涓�90鏃讹紝鍙樉绀哄彸闈紝Rotation涓�180鏃讹紝鍙樉绀鸿儗闈紝Rotation涓�270鏃讹紝鍙樉绀哄乏闈�
+            int delta = 5;
+            bool flag = false;
+            switch (area.Name)
+            {
+                case "宸�":
+                    //Rotation涓�0~180鏃舵樉绀�
+                    if (RotationF <= 90 - delta && Rotation >= 0 + delta && Rotation <= 180 - delta)
+                        flag = true;
+                    break;
+                case "鍓�":
+                    //Rotation涓�0~180鏃舵樉绀�
+                    if (RotationF <= 90 - delta && Rotation >= -90 + delta && Rotation <= 90 - delta)
+                        flag = true;
+                    break;
+                case "鍙�":
+                    //Rotation涓�0~180鏃舵樉绀�
+                    if (RotationF <= 90 - delta && Rotation >= -180 + delta && Rotation <= 0 - delta)
+                        flag = true;
+                    break;
+                case "鍚�":
+                    //Rotation涓�0~180鏃舵樉绀�
+                    if (RotationF <= 90 - delta && ((Rotation >= 90 + delta && Rotation <= 180) || (Rotation >= -180 && Rotation <= -90 - delta)))
+                        flag = true;
+                    break;
+                case "涓�":
+                    if (RotationF >= 0 + delta)
+                        flag = true;
+                    break;
+                case "涓�":
+                    if (RotationF <= 0 - delta)
+                        flag = true;
+                    break;
+            }
+            return flag;
+            銆�
+        }
+
+
+        #endregion
+
+        #region 鍒ゆ柇鍙鎬�
+
+        private float Get_dist(PointF A, PointF B)
+        {
+            float dx = A.X - B.X;
+            float dy = A.Y - B.Y;
+            float dist = (float)Math.Sqrt(dx * dx + dy * dy);
+            return dist;
+        }
+
+        //鍒ゆ柇A璺濈绾挎B鍜孋鐨勮窛绂伙紝濡傛灉瓒呭嚭浜嗙嚎娈电殑鑼冨洿锛屽垯杩斿洖鍒版渶杩戠殑绔偣鐨勮窛绂伙紱璺濈绾挎涓績鐐硅秺杩滐紝杩斿洖鐨勮窛绂昏秺澶э紱
+        private float Get_dist(PointF A, PointF B, PointF C, float MaxOff)
+        {
+            //PointF A, PointF B,PointF C锛屾眰鐐笰鍒癇銆丆鏋勬垚绾挎鐨勪腑蹇冪偣鐨勮窛绂�
+
+            float dist_off = GetDistanceFromPointAToMidpointOfLineSegmentBC(A, B, C);
+            //浣跨敤dist_off 璺� 绾挎A銆丅鐨勯暱搴︽瘮杈冿紝濡傛灉澶т簬1/2锛屽垯杩斿洖MaxOff锛屽惁鍒欐寜鐓ф瘮渚嬭繑鍥�
+            float dist_len = Get_dist(B, C);
+            if (dist_len < 5) dist_len = 5;
+            float dist_add = (dist_off / dist_len > 0.5 ? MaxOff : dist_off / dist_len * 2 * MaxOff);
+
+            float dx = C.X - B.X;
+            float dy = C.Y - B.Y;
+            float dist = (float)Math.Sqrt(dx * dx + dy * dy);
+            if (dist == 0) return Get_dist(A, B) + dist_add;
+            float t = ((A.X - B.X) * dx + (A.Y - B.Y) * dy) / (dist * dist);
+            if (t < 0) return Get_dist(A, B) + dist_add;
+            if (t > 1) return Get_dist(A, C) + dist_add;
+            float x = B.X + t * dx;
+            float y = B.Y + t * dy;
+            return Get_dist(A, new PointF(x, y)) + dist_add;
+
+        }
+        private float GetDistanceFromPointAToMidpointOfLineSegmentBC(PointF A, PointF B, PointF C)
+        {
+            // Calculate the midpoint of the line segment BC
+            PointF midpoint = new PointF((B.X + C.X) / 2, (B.Y + C.Y) / 2);
+
+            // Calculate the distance from point A to the midpoint
+            float dx = midpoint.X - A.X;
+            float dy = midpoint.Y - A.Y;
+            float distance = (float)Math.Sqrt(dx * dx + dy * dy);
+
+            return distance;
+        }
+
+        PointF PMin_Show, PMax_Show;
+
+        /// <summary>
+        /// 鍒ゆ柇鏄惁鍦ㄥ睆骞曞潗鏍囧唴
+        /// </summary>
+        /// <param name="screenPos"></param>
+        /// <returns></returns>
+        public bool isVisible(PointF MapPos)
+        {
+            if (MapPos.X < PMin_Show.X || MapPos.X > PMax_Show.X || MapPos.Y < PMin_Show.Y || MapPos.Y > PMax_Show.Y)
+                return false;
+            else
+                return true;
+        }
+銆�
+        #endregion 
+        #endregion
     }
 }
\ No newline at end of file

--
Gitblit v1.9.3