| | |
| | | |
| | | using Newtonsoft.Json; |
| | | using System.ComponentModel; |
| | | using 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 |
| | | { |
| | |
| | | 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() |
| | | { |
| | | |
| | |
| | | BackColor = Color.Transparent; |
| | | |
| | | } |
| | | public void SetEditMode(bool isEditMode) |
| | | { |
| | | _IsEditMode = isEditMode; |
| | | } |
| | | |
| | | private void MapViewer_Load(object sender, EventArgs e) |
| | | { |
| | | GlobalObject.PropertyForm = this.propertyForm; |
| | |
| | | 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) |
| | |
| | | { |
| | | GlobalObject.PropertyForm.SetEnabled(_IsEditMode); |
| | | GlobalObject.PropertyForm.SetNet(_Template.network); |
| | | //_Template.network.MapObjects.AddUndoRedoSupport(GlobalObject.PropertyForm.propertyGrid); |
| | | } |
| | | |
| | | |
| | |
| | | } |
| | | |
| | | |
| | | Dictionary<TemplateType, bool> _ViewModel = null; |
| | | Dictionary<PBS.eModelTemplateType, bool> _ViewModel = null; |
| | | public void Clear() |
| | | { |
| | | _Template = null; |
| | |
| | | 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; |
| | |
| | | this._ViewModel = viewMode; |
| | | |
| | | |
| | | //if ( _Template?.Floors!=null) |
| | | //{ |
| | | |
| | | // _Template.Floors.ForEach(f=> |
| | | // { |
| | | // var btn = new ToolStripButton(" "+f.Name+" "); |
| | | // btn.Click += (s, e) => |
| | | // { |
| | | // this.mapOption.ShowFloor = f.FloorIndex; |
| | | // if (f.MapView != null ) |
| | | // { |
| | | // this.mapOption= f.MapView.Copy(); |
| | | // } |
| | | // this.SetInvalidated(); |
| | | // }; |
| | | // ToolStripMenuItem_Floor.DropDownItems.Add(btn); |
| | | |
| | | // }); |
| | | //} |
| | | |
| | | //_Template.network = null; |
| | | if (!LoadData()) return; |
| | | //LoadData(); |
| | | // temp.network.LoadRepeaters(); |
| | | |
| | | // map.SetStartEndPoint(temp.Node1, temp.Node2); |
| | | |
| | | if (!reLoad) |
| | | { |
| | | if (_Template.view == null) |
| | | InitCenter(); |
| | | else |
| | | { |
| | | //MapCenter = _Template.view.Center; |
| | | //zoom = _Template.view.zoom; |
| | | //Rotation = _Template.view.rotation; |
| | | //RotationF = _Template.view.rotationF; |
| | | this.mapOption = _Template.view.Copy(); |
| | | SetMapInvalidate(); |
| | | } |
| | |
| | | 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() |
| | |
| | | _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) |
| | |
| | | |
| | | protected override void OnResize(EventArgs e) |
| | | { |
| | | base.OnResize(e); |
| | | |
| | | base.OnResize(e); |
| | | // 当控件尺寸改变时,触发重绘 |
| | | this.SetMapInvalidate(); |
| | | |
| | | this.SetMapInvalidate(); |
| | | } |
| | | |
| | | #endregion |
| | |
| | | _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; |
| | | } |
| | |
| | | { |
| | | 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); |
| | | } |
| | | } |
| | |
| | | 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); |
| | | } |
| | | } |
| | |
| | | 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; |
| | | } |
| | |
| | | |
| | | 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 |
| | |
| | | _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; |
| | | |
| | | } |
| | | |
| | | |
| | |
| | | var list = _Network.Add(net); |
| | | |
| | | var j = _Network.AddPipe(minNode, _OperaNode); |
| | | //j.Length = 0.0001f; |
| | | list.Add(j); |
| | | _OperaNode = null; |
| | | _NewNet.Clear(); |
| | |
| | | selectedObjs.AddRange(list); |
| | | |
| | | MapObjectExtensions.AddCommand(_Network, "Add", null, list); |
| | | |
| | | |
| | | |
| | | _isInsertingObject = false; |
| | |
| | | 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; |
| | |
| | | //需要把鼠标位置转换为立管的位置,获取鼠标位置的高程 |
| | | |
| | | 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); |
| | |
| | | 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); |
| | |
| | | _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; |
| | | |
| | |
| | | |
| | | } |
| | | else |
| | | { |
| | | //GlobalObject.LockSelect |
| | | { |
| | | |
| | | selectedObjs.ForEach(o => o.Selected = false); |
| | | selectedObjs.Clear(); |
| | |
| | | { |
| | | 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和currentPoint2,判断clickedPoint离线段currentPoint1和currentPoint2的距离 |
| | | float dist = Get_dist(clickedPoint, currentPoint1, currentPoint2, DistLimit); |
| | | |
| | | //float dist = Get_dist(clickedPoint, currentPoint); |
| | | if (dist < minDist && dist <= DistLimit) |
| | | { |
| | | minDist = dist; |
| | |
| | | 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和currentPoint2,判断clickedPoint离线段currentPoint1和currentPoint2的距离 |
| | | 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> |
| | |
| | | |
| | | } |
| | | |
| | | //else |
| | | |
| | | /*判断是否触碰到对象*/ |
| | | if (_mouseHoverCheckFlag) |
| | | { |
| | |
| | | _lastMouseX = e.X; |
| | | _lastMouseY = e.Y; |
| | | } |
| | | |
| | | void CubeViewMouseUp(MouseEventArgs e) |
| | | { |
| | | //BookMark :鼠标抬起事件 |
| | |
| | | |
| | | |
| | | #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) |
| | | { |
| | |
| | | } |
| | | 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("输入口径"); |
| | | 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; |
| | |
| | | |
| | | SetMapInvalidate(); |
| | | |
| | | } |
| | | |
| | | } |
| | | }; |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | this.SetMapInvalidate(); |
| | | } |
| | | } |
| | | void MovePointbyLength(NodeViewModel node1, NodeViewModel node2, float Length) |
| | | { |
| | |
| | | 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) |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void 旧版打开ToolStripMenuItem_Click(object sender, EventArgs e) |
| | | { |
| | | // 创建打开文件对话框 |
| | |
| | | { |
| | | if (!_IsEditMode) |
| | | { |
| | | if (message.show("提醒", "浏览模式无法保存,是否恢复为编辑模式")) |
| | | { |
| | | _IsEditMode = true; |
| | | |
| | | } |
| | | else |
| | | return; |
| | | TipFormHelper.ShowWarn("浏览模式无法保存,请切换编辑模式"); |
| | | return; |
| | | } |
| | | else |
| | | _Network.BuildToInp(_filePath); |
| | |
| | | |
| | | #region 右键菜单 |
| | | |
| | | |
| | | private void 转换ToolStripMenuItem_Click(object sender, EventArgs e) |
| | | { |
| | | var nodes = selectedNodes; |
| | |
| | | #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("围绕选中节点进行平面旋转,请在属性列表中选中一个节点类对象"); |
| | |
| | | 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)} |
| | | }; |
| | | |
| | | // 定义结果集合,并遍历输入点集合进行旋转处理 |
| | |
| | | { |
| | | |
| | | 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("围绕选中节点进行三维缩放,请在属性列表中选中一个[节点类]缩放中心对象"); |
| | |
| | | } |
| | | |
| | | |
| | | 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的item为什么显示不出来? |
| | | |
| | | //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; |
| | |
| | | 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(); |
| | | |
| | | //新建一个窗口,显示检查结果 |
| | | //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); |
| | |
| | | } |
| | | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 关阀分析(考虑水源的情况) |
| | | /// </summary> |
| | |
| | | |
| | | 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 }) |
| | | { |
| | |
| | | |
| | | 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) |
| | | { |
| | |
| | | else |
| | | visitedLinks2.Add(link); |
| | | if (!hasSource.ContainsKey(link)) |
| | | { |
| | | |
| | | //hasSource.Add(link,false); |
| | | { |
| | | hasSource[link] = FindSouce(link, visitedLinks, visitedLinks2, hasSource); |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | //private void 联通性ToolStripMenuItem_Click(object sender, EventArgs e) |
| | | //{ |
| | | // if (selectedObjs.Count > 0)//&& selectedObjs[0] is Link l |
| | | // { |
| | | |
| | | // var objs = selectedObjs.FindAll(o => o is LinkViewModel).Select(o => o as LinkViewModel).ToList(); |
| | | // var visitedNodes = new HashSet<NodeViewModel>(); |
| | | // objs.ForEach(o => TraversePipeNetworkALL(o, visitedNodes)); |
| | | |
| | | |
| | | // this.SetInvalidated(); |
| | | |
| | | // } |
| | | //} |
| | | |
| | | private void TraversePipeNetworkALL(LinkViewModel startLink, HashSet<NodeViewModel> visitedNodes = null, int direction = 0) |
| | | { |
| | | |
| | |
| | | |
| | | 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 }) |
| | | { |
| | |
| | | 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)) |
| | |
| | | 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) |
| | |
| | | |
| | | if (!_IsEditMode) |
| | | { |
| | | if (message.show("提醒", "浏览模式无法保存,是否恢复为编辑模式")) |
| | | { |
| | | _IsEditMode = true; |
| | | } |
| | | else |
| | | return; |
| | | TipFormHelper.ShowWarn("浏览模式无法保存,请切换编辑模式"); |
| | | return; |
| | | } |
| | | else |
| | | { |
| | |
| | | |
| | | if (!_IsEditMode) |
| | | { |
| | | if (message.show("提醒", "浏览模式无法保存,是否恢复为编辑模式")) |
| | | { |
| | | _IsEditMode = true; |
| | | } |
| | | else |
| | | return; |
| | | TipFormHelper.ShowWarn("浏览模式无法保存,请切换编辑模式"); |
| | | return; |
| | | } |
| | | else |
| | | { |
| | |
| | | |
| | | // 计算点投影到直线上的坐标 |
| | | |
| | | List<PointF3D> projectedPoints = new List<PointF3D>(); |
| | | List<PointF3D> modelTemplateedPoints = new List<PointF3D>(); |
| | | |
| | | foreach (PointF3D point in points) |
| | | { |
| | | double projectedY = slope * point.X + interceptY; |
| | | double projectedZ = slope * point.X + interceptZ; |
| | | double modelTemplateedY = slope * point.X + interceptY; |
| | | double modelTemplateedZ = slope * point.X + interceptZ; |
| | | |
| | | projectedPoints.Add(new PointF3D(point.X, (float)projectedY, (float)projectedZ)); |
| | | modelTemplateedPoints.Add(new PointF3D(point.X, (float)modelTemplateedY, (float)modelTemplateedZ)); |
| | | } |
| | | |
| | | return projectedPoints; |
| | | return modelTemplateedPoints; |
| | | } |
| | | |
| | | public void 添加底图ToolStripMenuItem_Click(object sender, EventArgs e) |
| | |
| | | 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()); |
| | | } |
| | | } |
| | |
| | | |
| | | 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) |
| | | { |
| | |
| | | _Template.mapOption._ShowFlowDirection = true; |
| | | this.SetMapInvalidate(); |
| | | |
| | | |
| | | |
| | | } |
| | | private void 隐藏流向ToolStripMenuItem_Click(object sender, EventArgs e) |
| | | { |
| | |
| | | _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) |
| | |
| | | _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; |
| | | 转换为ToolStripMenuItem.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; |
| | | 设为立管点ToolStripMenuItem.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> |
| | | /// 俯视线与底面的夹角,投影用sin |
| | | /// </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 正交模式 |
| | | private bool _isOrtho |
| | | { |
| | | get |
| | | { |
| | | return mapOption.IsOrtho; |
| | | } |
| | | set |
| | | { |
| | | mapOption.IsOrtho = value; |
| | | if (mapOption.IsOrtho) |
| | | { |
| | | label_ZZ.Text = "正交模式:开"; |
| | | } |
| | | else |
| | | { |
| | | label_ZZ.Text = "正交模式:关"; |
| | | } |
| | | } |
| | | } |
| | | #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); |
| | | //将ps转换为ulong,精度为20,并加入到dict_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俯视角旋转Point(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俯视角还原Point(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俯视角旋转Point(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俯视角旋转Point(pointR, z + offset.Z, new PointF(0, 0)); |
| | | return pointT; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 获取正交投影坐标,返回的是世界坐标 |
| | | /// </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> |
| | | /// 获取正交投影坐标,返回的是世界坐标 |
| | | /// </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俯视角还原Point(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) |
| | | { |
| | | |
| | | //正面是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和C的距离,如果超出了线段的范围,则返回到最近的端点的距离;距离线段中心点越远,返回的距离越大; |
| | | private float Get_dist(PointF A, PointF B, PointF C, float MaxOff) |
| | | { |
| | | //PointF A, PointF B,PointF C,求点A到B、C构成线段的中心点的距离 |
| | | |
| | | float dist_off = GetDistanceFromPointAToMidpointOfLineSegmentBC(A, B, C); |
| | | //使用dist_off 跟 线段A、B的长度比较,如果大于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 |
| | | } |
| | | } |