using Yw.WinFrmUI.Q3D;
|
|
using Newtonsoft.Json;
|
using System;
|
using System.Collections;
|
using System.Collections.Generic;
|
using System.ComponentModel;
|
using System.Data;
|
using System.Data.Common;
|
using System.Drawing;
|
using System.IO;
|
using System.Linq;
|
using System.Numerics;
|
using System.Reflection;
|
using System.Runtime.CompilerServices;
|
using System.Security.Cryptography;
|
using System.Text;
|
using System.Threading;
|
using System.Threading.Tasks;
|
using System.Windows.Forms;
|
using static Yw.WinFrmUI.Q3D.MapViewEnum;
|
using static System.Net.Mime.MediaTypeNames;
|
using static System.Windows.Forms.AxHost;
|
using static System.Windows.Forms.LinkLabel;
|
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Button;
|
using static System.Windows.Forms.VisualStyles.VisualStyleElement.TrackBar;
|
using Cursor = System.Windows.Forms.Cursor;
|
using Yw.WinFrmUI.Q3D;
|
using Yw.WinFrmUI.Q3D;
|
|
namespace Yw.WinFrmUI.Q3D
|
{
|
public partial class Map : UserControl
|
{
|
|
#region 一、全局
|
|
|
#region 初始化
|
|
|
|
|
public Map()
|
{
|
|
|
InitializeComponent();
|
this.DoubleBuffered = true;
|
MapCenter = PointF.Empty;
|
zoom = 1.0f;
|
|
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
|
BackColor = Color.Transparent;
|
|
}
|
public void SetEditMode(bool isEditMode)
|
{
|
IsEditMode = isEditMode;
|
}
|
private void MapViewer_Load(object sender, EventArgs e)
|
{
|
//GlobalObject.PropertyForm = this.propertyForm;
|
|
int i = 0;
|
//遍历ColourType
|
|
|
|
|
|
|
this.TC = TC;
|
this.DrawNet = Draw;
|
this.DrawNetNew = Draw;
|
this.DrawBackGroundPic = DrawBackGroud;
|
this.DrawAuxiliary = DrawH;
|
this.onMouseDown = mapMouseDown;
|
this.onMouseMove = mapMouseMove;
|
this.onMouseUp = mapMouseUp;
|
this.onMouseWheel = mapMouseWheel;
|
this.Inited = true;
|
this.Status = DrawingStatus.Ready;
|
|
|
//TContainer TCCube = new TContainer();
|
//TCCube.settings = new Settings();
|
//TCCube.settings.network = new MapViewNetWork();
|
//TCCube.settings.network.Areas = new List<AreaViewModel>();
|
//Cube cb = new Cube();
|
//foreach (var item in cb.FacesVertices)
|
//{
|
// AreaViewModel area = new AreaViewModel();
|
// area.ID = item.Key.ToString();
|
// area.InnerNodes = new List<NodeViewModel>();
|
// //area.Name= item.Key.ToString();
|
|
// //6个面设置不一样的颜色
|
// switch (item.Key)
|
// {
|
// case 1:
|
// area.color = Color.Red;
|
// area.Name = "右";
|
// break;
|
// case 2:
|
// area.color = Color.SkyBlue;
|
// area.Name = "左";
|
// break;
|
// case 3:
|
// area.color = Color.Green;
|
// area.Name = "后";
|
// break;
|
// case 4:
|
// area.color = Color.DarkBlue;
|
// area.Name = "前";
|
// break;
|
// case 5:
|
// area.color = Color.Purple;
|
// area.Name = "上";
|
// break;
|
// case 6:
|
// area.color = Color.Orange;
|
// area.Name = "下";
|
// break;
|
// default:
|
// area.color = Color.White;
|
// break;
|
// }
|
|
// foreach (var p in item.Value)
|
// {
|
// NodeViewModel node = new NodeViewModel();
|
// node.X = p.X;
|
// node.Y = p.Y;
|
// node.Z = p.Z;
|
// area.InnerNodes.Add(node);
|
// }
|
// TCCube.settings.network.Areas.Add(area);
|
//}
|
|
}
|
|
#endregion
|
|
|
#region 对外开放,全局控制方法
|
|
private bool LoadData(bool isDelCache = false)
|
{
|
|
if (_Template == null) return false;
|
if (isDelCache || _network == null)
|
{
|
_network = new MapViewNetWork();
|
}
|
|
SuspendLayout();
|
|
|
|
|
SetStartEndPoint(_Template.Node1, _Template.Node2);
|
|
ResumeLayout(false);
|
return true;
|
}
|
|
|
Dictionary<TemplateType, bool> _ViewModel = null;
|
public void Clear()
|
{
|
_Template = null;
|
MapCenter = PointF.Empty;
|
zoom = 1.0f;
|
Rotation = 0;
|
RotationF = 90;
|
SetMapInvalidate();
|
}
|
|
|
|
public void SetData(MapViewNetWork netWork, Settings template = null)
|
{
|
|
bool reLoad = _network == netWork;
|
this._Template = template;
|
this._network = netWork;
|
|
if (_Template == null) _Template = new Settings();
|
|
if (!LoadData()) return;
|
|
|
if (!reLoad)
|
{
|
if (_Template.view == null)
|
InitCenter();
|
else
|
{
|
|
this.mapOption = _Template.view.Copy();
|
SetMapInvalidate();
|
}
|
}
|
|
|
//将$"{MapCenter.X.ToString("0.00")},{MapCenter.Y.ToString("0.00")}"通过CenterChanged传出
|
CenterChanged?.Invoke(this, $"{MapCenter.X.ToString("0.00")},{MapCenter.Y.ToString("0.00")}");
|
//将zoom.ToString("0.000")通过ZoomChanged传出
|
ZoomChanged?.Invoke(this, zoom.ToString("0.000"));
|
//将Rotation.ToString("0")通过RotationChanged传出
|
RotationChanged?.Invoke(this, Rotation.ToString("0"));
|
//将RotationF.ToString("0")通过RotationFChanged传出
|
RotationFChanged?.Invoke(this, RotationF.ToString("0"));
|
|
|
}
|
|
private void InitCenter()
|
{
|
//MapCenter
|
var p = PointF.Empty;
|
float x0 = 99999999999f, y0 = 99999999999f, x1 = -99999999999f, y1 = -99999999999f;
|
|
foreach (NodeViewModel junction in _Nodes)
|
{
|
p.X += (float)junction.X;
|
p.Y += (float)junction.Y;
|
if (x0 > junction.X) x0 = junction.X;
|
if (y0 > junction.Y) y0 = junction.Y;
|
if (x1 < junction.X) x1 = junction.X;
|
if (y1 < junction.Y) y1 = junction.Y;
|
}
|
|
float x_span = x1 - x0, y_span = y1 - y0;
|
|
zoom = Math.Min(this.Width / x_span, this.Height / y_span);
|
zoom = Math.Max(zoom, MinZoom);
|
zoom = Math.Min(zoom, MaxZoom);
|
|
Rotation = 0;
|
RotationF = 90;
|
|
|
if (_Nodes.Count > 0)
|
{
|
p.X /= _Nodes.Count;
|
p.Y /= _Nodes.Count;
|
}
|
MapCenter = p;
|
}
|
|
public void SetMapInvalidate()
|
{
|
|
_needPaintAll = true;
|
PMin_Show = ScreenToMap(new PointF(0, this.Height));
|
PMax_Show = ScreenToMap(new PointF(this.Width, 0));
|
_timerDraw = true;
|
|
|
}
|
|
public void SetStartEndPoint(String node1, string node2)
|
{
|
_StartPoint = node1;
|
_EndPoint = node2;
|
SetMapInvalidate();
|
}
|
public void Set3DView(bool is3Dview, double 俯视角度)
|
|
{
|
this.RotationF = 俯视角度;
|
this.is3Dview = is3Dview;
|
SetMapInvalidate();
|
}
|
|
|
|
public void SetRotation(double d)
|
{
|
this.Rotation = d;
|
SetMapInvalidate();
|
}
|
|
#endregion
|
|
|
|
|
#region 重绘函数
|
|
bool _needPaintAll
|
{
|
get
|
{
|
return __needpaintall;
|
}
|
set
|
{
|
__needpaintall = value;
|
}
|
}
|
|
|
PointF[] getCurclePoints(int num)
|
{
|
PointF[] points = new PointF[num + 1];
|
float angle = 0;
|
for (int i = 0; i < points.Length; i++)
|
{
|
float x = (float)Math.Cos(angle);
|
float y = (float)Math.Sin(angle);
|
points[i] = new PointF(x, y);
|
angle += 2 * (float)Math.PI / num;
|
}
|
points[num] = points[0];
|
return points;
|
}
|
|
|
|
|
|
|
private void timer_draw_Tick(object sender, EventArgs e)
|
{
|
_mouseHoverCheckFlag = true;
|
if (_timerDraw && this.Status == DrawingStatus.Ready)
|
{
|
this.Invalidate();
|
_timerDraw = false;
|
}
|
|
}
|
|
protected override void OnResize(EventArgs e)
|
{
|
base.OnResize(e);
|
|
// 当控件尺寸改变时,触发重绘
|
this.SetMapInvalidate();
|
|
}
|
|
#endregion
|
|
|
#region 鼠标事件
|
|
void mapMouseDown(MouseEventArgs e)
|
{
|
base.OnMouseDown(e);
|
|
_ClickStartPos = new PointF(e.X, e.Y);
|
DragStartPos = ScreenToMap(new PointF(e.X, e.Y));
|
mousePosition = _MousePosition = ScreenToMap(new PointF(e.X, e.Y));
|
|
if (e.Button == MouseButtons.Middle || e.Button == MouseButtons.XButton2)
|
{
|
|
if (ModifierKeys == Keys.Control || ModifierKeys == Keys.Shift)//按下框选放大
|
{
|
DragStartPos = ScreenToMap(new PointF(e.X, e.Y));
|
_isDragging = true;
|
}
|
|
else
|
{
|
|
_lastCursor = this.Cursor;
|
this.Cursor = Cursors.SizeAll;
|
MapCenter0 = MapCenter;
|
mapOption0 = mapOption.Copy();
|
_isPanning = true;
|
}
|
}
|
else if (e.Button == MouseButtons.Left && _mouseState == MouseState.无)
|
{
|
|
|
if (ModifierKeys == Keys.Shift)
|
{
|
var point = ScreenToMap(new PointF(e.X, e.Y));
|
if (!_isDrawingPolygon)
|
{
|
// 开始绘制多边形
|
polygonPoints.Clear();
|
|
_isDrawingPolygon = true;
|
}
|
|
polygonPoints.Add(point);
|
mousePosition = _MousePosition = ScreenToMap(new PointF(e.X, e.Y));
|
SetMapInvalidate();
|
return;
|
}
|
if (_isDrawingPolygon)
|
{
|
return;
|
}
|
|
|
if (!_isMovingObject)//拖拽选择
|
{
|
DragStartPos = ScreenToMap(new PointF(e.X, e.Y));
|
_isDragging = true;
|
}
|
|
}
|
|
else if (e.Button == MouseButtons.Left && _mouseState == MouseState.设置底图范围)
|
{
|
_mouseState = MouseState.无;
|
DragStartPos = ScreenToMap(new PointF(e.X, e.Y));
|
BackGroudPicLeftPos = MapPointToWorldPoint(ScreenToMap(new PointF(e.X, e.Y)), _Template.BackGroundElev);
|
_isSettingBackGroundPictur = true;
|
}
|
else if (e.Button == MouseButtons.Right)
|
{
|
RotaStartPos = new PointF(e.X, e.Y);
|
Rotation0 = Rotation;
|
俯视角度_start = RotationF;
|
_lastCursor = this.Cursor;
|
|
Cursor = Cursors.Hand;
|
mapOption0 = mapOption.Copy();
|
_isRotating = true;
|
}
|
|
}
|
private bool IsPointInPolygon(PointF point, List<PointF> polygon)
|
{
|
int count = polygon.Count;
|
bool inside = false;
|
|
PointF p1, p2;
|
for (int i = 0, j = count - 1; i < count; j = i++)
|
{
|
p1 = polygon[i];
|
p2 = polygon[j];
|
|
if (((p1.Y > point.Y) != (p2.Y > point.Y)) &&
|
(point.X < (p2.X - p1.X) * (point.Y - p1.Y) / (p2.Y - p1.Y) + p1.X))
|
{
|
inside = !inside;
|
}
|
}
|
|
return inside;
|
}
|
|
bool controlDown = false;
|
PointF _MousePosition = new PointF(0, 0);
|
void mapMouseMove(MouseEventArgs e)
|
{
|
//base.OnMouseMove(e);
|
bool needInvalidate = false;
|
_MousePosition = ScreenToMap(new PointF(e.X, e.Y));
|
if (_isMovingObject)
|
{
|
var p = MapPointToWorldPoint(_MousePosition, _OperaNode.Z);
|
var oldP = (PointF3D)_undoOldValue;
|
if (!float.IsInfinity(p.X) && !float.IsInfinity(p.Y)) _newTemplate.OffSet = new PointF3D(p.X - oldP.X, p.Y - oldP.Y, 0); //_OperaNode.Position = p;
|
|
//GlobalObject.PropertyForm.propertyGrid.Refresh();
|
|
needInvalidate = true;
|
}
|
|
|
else if (_isPainting)
|
{
|
needInvalidate = true;
|
|
|
}
|
else if (_isPanning)
|
{
|
var vector = GetRotateVector(new PointF(e.X, e.Y), new PointF(_lastMouseX, _lastMouseY));
|
MapCenter = new PointF(MapCenter.X - vector.X / Zoom.X, MapCenter.Y - vector.Y / Zoom.Y);
|
|
|
//将$"{MapCenter.X.ToString("0.00")},{MapCenter.Y.ToString("0.00")}"通过CenterChanged传出
|
CenterChanged?.Invoke(this, $"{MapCenter.X.ToString("0.00")},{MapCenter.Y.ToString("0.00")}");
|
needInvalidate = true;
|
|
}
|
else if (_isDragging || _isDrawingPolygon || _isSettingBackGroundPictur)
|
{
|
mousePosition = _MousePosition;
|
// 绘制选择框
|
// Rectangle selectionRect = new Rectangle(
|
// Math.Min((int)DragStartPos.X, (int)MP.X),
|
// Math.Min((int)DragStartPos.Y, (int)MP.Y),
|
// Math.Abs((int)DragStartPos.X - (int)MP.X),
|
// Math.Abs((int)DragStartPos.Y - (int)MP.Y));
|
//DrawSelectionRect(selectionRect);
|
needInvalidate = true;
|
|
}
|
else if (_isRotating)
|
{
|
mousePosition = _MousePosition;
|
bool is下半屏幕 = RotaStartPos.Y >= this.Height / 2;
|
if (ModifierKeys != Keys.Alt) Rotation = Rotation0 + ((float)e.X - (float)RotaStartPos.X) * 180 * 2.5 / (float)this.Width * (is下半屏幕 ? 1 : 1);
|
if (ModifierKeys != Keys.Shift) RotationF = 俯视角度_start + ((float)e.Y - (float)RotaStartPos.Y) * 180 * 2.5 / (float)this.Height;
|
if (RotationF > 90) RotationF = 90;
|
if (RotationF < 0) RotationF = 0;
|
needInvalidate = true;
|
|
}
|
else
|
|
if (_isInsertingObject)
|
{
|
var p = MapPointToWorldPoint(_MousePosition, _OperaNode.Z);
|
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;
|
|
SelectedObjectsChanged?.Invoke(this, null);
|
needInvalidate = 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)
|
{
|
//needInvalidate = false;
|
}
|
else
|
{
|
needInvalidate = true;
|
hoveredObjs.ForEach(o => o.Hovered = false);
|
hoveredObjs.Clear();
|
if (obj != null)
|
{
|
obj.Hovered = true;
|
hoveredObjs.Add(obj);
|
}
|
|
|
}
|
|
|
}
|
|
|
|
if (needInvalidate) this.SetMapInvalidate();
|
//将$"{e.X.ToString("0")},{e.Y.ToString("0")}"通过MousePositionChanged传出
|
MousePositionChanged?.Invoke(this, $"{_MousePosition.X.ToString("0.00")},{_MousePosition.Y.ToString("0.00")}");
|
|
_lastMouseX = e.X;
|
_lastMouseY = e.Y;
|
}
|
|
bool RectangContain(RectangleF r, PointF p)
|
{
|
var x = p.X; var y = p.Y;
|
|
|
if (r.X <= x && x < r.X + r.Width && r.Y <= y)
|
{
|
return y < r.Y + r.Height;
|
}
|
|
return false;
|
}
|
|
/// <summary>
|
/// 用于绘制管线
|
/// </summary>
|
NodeViewModel _select_junction1 = null;
|
NodeViewModel _select_junction2 = null;
|
DateTime _lastMouseUp = DateTime.Now;
|
int doubleClick_Delay = 500;//毫秒
|
bool recordView = false;
|
|
|
void mapMouseUp(MouseEventArgs e)
|
{
|
//BookMark :鼠标抬起事件
|
base.OnMouseUp(e);
|
bool isMouseMoved = Get_dist(_ClickStartPos, new PointF(e.X, e.Y)) > 10;
|
bool isdoubleClick = (DateTime.Now - _lastMouseUp).TotalMilliseconds <= doubleClick_Delay;
|
_lastMouseUp = DateTime.Now;
|
if /*框选放大*/(ModifierKeys == Keys.Control && (e.Button == MouseButtons.Middle || e.Button == MouseButtons.XButton2))
|
{
|
_isDragging = false;
|
|
this.Cursor = _lastCursor;
|
|
mapOption0 = mapOption;
|
var _lastMousePosition = DragStartPos;
|
|
List<IBaseViewModel> objs = new List<IBaseViewModel>();
|
// 绘制矩形
|
var start = new Point((int)Math.Min(mousePosition.X, _lastMousePosition.X), (int)Math.Min(mousePosition.Y, _lastMousePosition.Y));
|
var size = new Size((int)Math.Abs(_lastMousePosition.X - mousePosition.X), (int)Math.Abs(_lastMousePosition.Y - mousePosition.Y));
|
var rectangle0 = new Rectangle(start, size);
|
|
var new_center = MapPointToWorldPoint(new PointF(start.X + size.Width / 2, start.Y + size.Height / 2));
|
|
this.MapCenter = new_center;
|
this.zoom = Math.Max(1.0f * this.Width / size.Width, 1.0f * this.Height / size.Height);
|
|
if (recordView) MapObjectExtensions.AddCommand(mapOption, "Map", mapOption0, mapOption);
|
|
CenterChanged?.Invoke(this, $"{MapCenter.X.ToString("0.00")},{MapCenter.Y.ToString("0.00")}");
|
//将zoom.ToString("0.000")通过ZoomChanged传出
|
ZoomChanged?.Invoke(this, zoom.ToString("0.000"));
|
SetMapInvalidate();
|
return;
|
}
|
if /*平移视角*/(ModifierKeys == Keys.None && (e.Button == MouseButtons.Middle || e.Button == MouseButtons.XButton2))
|
{
|
if (recordView) MapObjectExtensions.AddCommand(mapOption, "Map", mapOption0, mapOption);
|
//将$"{MapCenter.X.ToString("0.00")},{MapCenter.Y.ToString("0.00")}"通过CenterChanged传出
|
CenterChanged?.Invoke(this, $"{MapCenter.X.ToString("0.00")},{MapCenter.Y.ToString("0.00")}");
|
this.Cursor = _lastCursor;
|
_isPanning = false;
|
return;
|
}
|
if /*设置背景*/(e.Button == MouseButtons.Left && _isSettingBackGroundPictur)
|
{
|
_Template.BackGroundPoint1 = BackGroudPicLeftPos;
|
_Template.BackGroundPoint2 = MapPointToWorldPoint(mousePosition, _Template.BackGroundElev);
|
|
_isSettingBackGroundPictur = false;
|
mapOption.isShowPic = true;
|
this.Cursor = _lastCursor;
|
SetMapInvalidate();
|
return;
|
}
|
|
if /*多边形选择*/(_isDrawingPolygon && e.Button == MouseButtons.Left && ModifierKeys == Keys.None)
|
{
|
_isDrawingPolygon = false;
|
if (polygonPoints.Count >= 3)
|
{
|
_Nodes.ForEach(n0 =>
|
{
|
var n = (NodeViewModel)n0;
|
if (IsPointInPolygon(WorldPointToMapPoint(n), polygonPoints))
|
{
|
selectedObjs.Add(n);
|
n.Selected = true;
|
}
|
});
|
_Links.ForEach(n0 =>
|
{
|
var n = (LinkViewModel)n0;
|
if (IsPointInPolygon(WorldPointToMapPoint(n.Position, n.Z), polygonPoints))
|
{
|
selectedObjs.Add(n);
|
n.Selected = true;
|
}
|
});
|
//将选中的对象通过SelectedObjectsChanged传出
|
SelectedObjectsChanged?.Invoke(this, selectedObjs);
|
|
}
|
SetMapInvalidate();
|
// 结束绘制多边形
|
return;
|
}
|
|
if /*取消移动对象*/(_isMovingObject && !isMouseMoved && e.Button == MouseButtons.Left)
|
{
|
_isMovingObject = 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);
|
_OperaNode = null;
|
_NewNet.Clear();
|
return;
|
}
|
|
|
if /*叠加框选*/(isMouseMoved && _mouseState == MouseState.无 && e.Button == MouseButtons.Left && ModifierKeys == Keys.Control)
|
{
|
|
_isDragging = false;
|
Cursor = Cursors.Default;
|
|
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);
|
for (int i = 0; i < _Nodes.Count; i++)
|
{
|
|
var node = _Nodes[i] as NodeViewModel;
|
if (!node.Visible) continue;
|
PointF p = WorldPointToMapPoint(node);
|
|
if (RectangContain(rectangle0, p))
|
{
|
if (selectedObjs.Contains(node))
|
{
|
node.Selected = false;
|
selectedObjs.Remove(node);
|
}
|
else
|
{
|
node.Selected = true;
|
selectedObjs.Add(node);
|
}
|
|
}
|
}
|
|
for (int i = 0; i < _Links.Count; i++)
|
{
|
var link = _Links[i] as LinkViewModel;
|
if (!link.Visible) continue;
|
PointF p = WorldPointToMapPoint(link.Position, link.Z);
|
if (RectangContain(rectangle0, p))
|
{
|
if (selectedObjs.Contains(link))
|
{
|
link.Selected = false;
|
selectedObjs.Remove(link);
|
}
|
else
|
{
|
link.Selected = true;
|
selectedObjs.Add(link);
|
}
|
}
|
}
|
|
SelectedObjectsChanged?.Invoke(this, selectedObjs);
|
SetMapInvalidate();
|
mousePosition = new PointF(0, 0);
|
return;
|
}
|
if /*框选*/(isMouseMoved && _mouseState == MouseState.无 && e.Button == MouseButtons.Left && ModifierKeys == Keys.None)
|
{
|
_isDragging = false;
|
Cursor = Cursors.Default;
|
|
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);
|
selectedObjs.ForEach(obj => obj.Selected = false);
|
selectedObjs.Clear();
|
for (int i = 0; i < _Nodes.Count; i++)
|
{
|
var node = _Nodes[i] as NodeViewModel;
|
if (!node.Visible) continue;
|
PointF p = WorldPointToMapPoint(node);
|
|
if (RectangContain(rectangle0, p))
|
{
|
node.Selected = true;
|
selectedObjs.Add(node);
|
}
|
}
|
|
for (int i = 0; i < _Links.Count; i++)
|
{
|
var link = _Links[i] as LinkViewModel;
|
|
if (!link.Visible) continue;
|
PointF p = WorldPointToMapPoint(link.Position, link.Z);
|
if (RectangContain(rectangle0, p))
|
{
|
link.Selected = true;
|
selectedObjs.Add(link);
|
}
|
}
|
|
//将selectedObjs通过SelectedObjectsChanged传出
|
SelectedObjectsChanged?.Invoke(this, selectedObjs);
|
SetMapInvalidate();
|
mousePosition = new PointF(0, 0);
|
return;
|
}
|
|
if /*点选*/(!isMouseMoved && _mouseState == MouseState.无 && e.Button == MouseButtons.Left && ModifierKeys == Keys.None)
|
{
|
_isDragging = false;
|
|
// 遍历所有点,找出最近的点
|
PointF clickedPoint = new PointF(e.X, e.Y); //ScreenToMap(new PointF(e.X, e.Y));
|
var obj = GetObj_by_ScreenPoint(clickedPoint);
|
bool isJunction = obj is NodeViewModel;
|
|
if (obj != null)
|
{
|
selectedObjs.ForEach(o => o.Selected = false);
|
selectedObjs.Clear();
|
obj.Selected = true;
|
selectedObjs.Add(obj);
|
|
SelectedObjectsChanged?.Invoke(this, selectedObjs);
|
_OperaNode = null;
|
|
|
SetMapInvalidate();
|
mousePosition = new PointF(0, 0);
|
|
|
}
|
else
|
{
|
//GlobalObject.LockSelect
|
|
selectedObjs.ForEach(o => o.Selected = false);
|
selectedObjs.Clear();
|
SelectedObjectsChanged?.Invoke(this, selectedObjs);
|
|
_OperaNode = null;
|
|
SetMapInvalidate();
|
}
|
return;
|
|
|
}
|
|
if (/*叠加点选*/!isMouseMoved && _mouseState == MouseState.无 && e.Button == MouseButtons.Left && ModifierKeys == Keys.Control)
|
{
|
_isDragging = false;
|
|
// 遍历所有点,找出最近的点
|
PointF clickedPoint = new PointF(e.X, e.Y); //ScreenToMap(new PointF(e.X, e.Y));
|
var obj = GetObj_by_ScreenPoint(clickedPoint);
|
bool isJunction = obj is NodeViewModel;
|
if (obj != null)
|
{
|
if (selectedObjs.Contains(obj))
|
{
|
obj.Selected = false;
|
selectedObjs.Remove(obj);
|
SelectedObjectsChanged?.Invoke(this, selectedObjs);
|
|
SetMapInvalidate();
|
mousePosition = new PointF(0, 0);
|
}
|
else
|
{
|
obj.Selected = true;
|
selectedObjs.Add(obj);
|
SelectedObjectsChanged?.Invoke(this, selectedObjs);
|
SetMapInvalidate();
|
mousePosition = new PointF(0, 0);
|
}
|
}
|
return;
|
}
|
|
if (/*旋转*/e.Button == MouseButtons.Right && _isRotating)
|
{
|
_isRotating = false;
|
this.Cursor = _lastCursor;
|
if (recordView) MapObjectExtensions.AddCommand(mapOption, "Map", mapOption0, mapOption);
|
mousePosition = new PointF(0, 0);
|
|
//将Rotation.ToString("0")通过RotationChanged传出
|
RotationChanged?.Invoke(this, Rotation.ToString("0"));
|
//将RotationF.ToString("0")通过RotationFChanged传出
|
RotationFChanged?.Invoke(this, RotationF.ToString("0"));
|
}
|
}
|
private void getPointAndHeight(MouseEventArgs e, out PointF p, out float z)
|
{
|
z = 0;
|
if (RotationF != 0)
|
{
|
p = MapPointToWorldPoint(ScreenToMap(new PointF(e.X, e.Y), z));
|
|
}
|
else
|
{
|
var m = ScreenToVMap(new PointF(e.X, e.Y));
|
z = m.Y;
|
p = new PointF(m.X, 0);
|
}
|
}
|
private void getPointAndHeight(MouseEventArgs e, NodeViewModel j, out PointF p, out float z)
|
{
|
z = j.Z;
|
if (RotationF != 0)
|
{
|
p = MapPointToWorldPoint(ScreenToMap(new PointF(e.X, e.Y), j.Z), j.Z);
|
|
}
|
else
|
{
|
var m = ScreenToVMap(new PointF(e.X, e.Y));
|
z = m.Y;
|
p = new PointF(j.X, j.Y);
|
}
|
}
|
IBaseViewModel GetObj_by_ScreenPoint(PointF clickedPoint, float DistLimit = 15f)
|
{
|
float minDist = float.MaxValue;
|
|
int minIndex = -1;
|
bool isJunction = true;
|
IBaseViewModel obj = null;
|
|
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 < minDist && dist <= DistLimit)
|
{
|
minDist = dist;
|
minIndex = i;
|
obj = 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.Z);
|
PointF currentPoint1 = MapToScreen(mapPos1);
|
PointF mapPos2 = WorldPointToMapPoint(link.EndNode.Position, link.EndNode.Z);
|
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;
|
minIndex = i;
|
isJunction = false;
|
obj = link;
|
}
|
}
|
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.Z);
|
PointF currentPoint1 = MapToScreen(mapPos1);
|
PointF mapPos2 = WorldPointToMapPoint(link.EndNode.Position, link.EndNode.Z);
|
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>
|
/// <param name="e"></param>
|
void mapMouseWheel(MouseEventArgs e)
|
{
|
base.OnMouseWheel(e);
|
mapOption0 = mapOption.Copy();
|
float oldZoom = zoom;
|
zoom *= (float)Math.Pow(2, e.Delta / 120.0 / 10.0);
|
zoom = Math.Max(MinZoom, Math.Min(MaxZoom, zoom));
|
|
if (recordView) MapObjectExtensions.AddCommand(mapOption, "Map", mapOption0, mapOption);
|
SetMapInvalidate();
|
}
|
|
private int _lastMouseX;
|
private int _lastMouseY;
|
#endregion
|
|
|
#region CubeView鼠标事件
|
void CubeViewMouseDown(MouseEventArgs e)
|
{
|
base.OnMouseDown(e);
|
|
_ClickStartPos = new PointF(e.X, e.Y);
|
DragStartPos = ScreenToMap(new PointF(e.X, e.Y));
|
mousePosition = _MousePosition = ScreenToMap(new PointF(e.X, e.Y));
|
if (e.Button == MouseButtons.Left && _isInsertingObject)
|
{
|
|
}
|
else if (e.Button == MouseButtons.Left && _mouseState == MouseState.无)
|
{
|
|
}
|
|
else if (e.Button == MouseButtons.Left && _mouseState == MouseState.设置底图范围)
|
{
|
|
}
|
else if (e.Button == MouseButtons.Right)
|
{
|
RotaStartPos = new PointF(e.X, e.Y);
|
Rotation0 = Rotation;
|
俯视角度_start = RotationF;
|
_lastCursor = this.Cursor;
|
|
Cursor = Cursors.Hand;
|
mapOption0 = mapOption.Copy();
|
_isRotating = true;
|
}
|
|
}
|
void CubeViewMouseMove(MouseEventArgs e)
|
{
|
//base.OnMouseMove(e);
|
bool needInvalidate = false;
|
_MousePosition = ScreenToMap(new PointF(e.X, e.Y));
|
|
|
if (_isRotating)
|
{
|
mousePosition = _MousePosition;
|
bool is下半屏幕 = RotaStartPos.Y >= this.Height / 2;
|
if (ModifierKeys != Keys.Alt) Rotation = Rotation0 + ((float)e.X - (float)RotaStartPos.X) * 180 * 2.5 / (float)this.Width * (is下半屏幕 ? 1 : 1);
|
if (ModifierKeys != Keys.Shift) RotationF = 俯视角度_start + ((float)e.Y - (float)RotaStartPos.Y) * 180 * 2.5 / (float)this.Height;
|
if (RotationF > 90) RotationF = 90;
|
if (RotationF < 0) RotationF = 0;
|
needInvalidate = 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)
|
{
|
//needInvalidate = false;
|
}
|
else
|
{
|
needInvalidate = true;
|
hoveredObjs.ForEach(o => o.Hovered = false);
|
hoveredObjs.Clear();
|
if (obj != null)
|
{
|
obj.Hovered = true;
|
hoveredObjs.Add(obj);
|
}
|
|
|
}
|
|
|
}
|
|
|
|
if (needInvalidate) this.SetMapInvalidate();
|
MousePositionChanged?.Invoke(this, $"{_MousePosition.X.ToString("0.00")},{_MousePosition.Y.ToString("0.00")}");
|
_lastMouseX = e.X;
|
_lastMouseY = e.Y;
|
}
|
void CubeViewMouseUp(MouseEventArgs e)
|
{
|
//BookMark :鼠标抬起事件
|
base.OnMouseUp(e);
|
bool isMouseMoved = Get_dist(_ClickStartPos, new PointF(e.X, e.Y)) > 10;
|
bool isdoubleClick = (DateTime.Now - _lastMouseUp).TotalMilliseconds <= doubleClick_Delay;
|
_lastMouseUp = DateTime.Now;
|
|
if /*点选*/(!isMouseMoved && _mouseState == MouseState.无 && e.Button == MouseButtons.Left && ModifierKeys == Keys.None)
|
{
|
_isDragging = false;
|
|
// 遍历所有点,找出最近的点
|
PointF clickedPoint = new PointF(e.X, e.Y); //ScreenToMap(new PointF(e.X, e.Y));
|
var obj = GetObj_by_ScreenPoint(clickedPoint);
|
bool isJunction = obj is NodeViewModel;
|
|
if (obj != null)
|
{
|
selectedObjs.ForEach(o => o.Selected = false);
|
selectedObjs.Clear();
|
obj.Selected = true;
|
selectedObjs.Add(obj);
|
SelectedObjectsChanged?.Invoke(this, selectedObjs);
|
_OperaNode = null;
|
|
|
SetMapInvalidate();
|
mousePosition = new PointF(0, 0);
|
|
|
}
|
else
|
{
|
//GlobalObject.LockSelect
|
|
selectedObjs.ForEach(o => o.Selected = false);
|
selectedObjs.Clear();
|
SelectedObjectsChanged?.Invoke(this, selectedObjs);
|
|
_OperaNode = null;
|
|
SetMapInvalidate();
|
}
|
return;
|
|
|
}
|
|
if (/*叠加点选*/!isMouseMoved && _mouseState == MouseState.无 && e.Button == MouseButtons.Left && ModifierKeys == Keys.Control)
|
{
|
_isDragging = false;
|
|
// 遍历所有点,找出最近的点
|
PointF clickedPoint = new PointF(e.X, e.Y); //ScreenToMap(new PointF(e.X, e.Y));
|
var obj = GetObj_by_ScreenPoint(clickedPoint);
|
bool isJunction = obj is NodeViewModel;
|
if (obj != null)
|
{
|
if (selectedObjs.Contains(obj))
|
{
|
obj.Selected = false;
|
selectedObjs.Remove(obj);
|
SelectedObjectsChanged?.Invoke(this, selectedObjs);
|
|
SetMapInvalidate();
|
mousePosition = new PointF(0, 0);
|
}
|
else
|
{
|
obj.Selected = true;
|
selectedObjs.Add(obj);
|
SelectedObjectsChanged?.Invoke(this, selectedObjs);
|
SetMapInvalidate();
|
mousePosition = new PointF(0, 0);
|
}
|
}
|
return;
|
}
|
|
if (e.Button == MouseButtons.Right)
|
{
|
if (_isRotating)
|
{
|
_isRotating = false;
|
this.Cursor = _lastCursor;
|
|
|
if (recordView) MapObjectExtensions.AddCommand(mapOption, "Map", mapOption0, mapOption);
|
mousePosition = new PointF(0, 0);
|
}
|
}
|
}
|
#endregion
|
|
|
#endregion 一、全局
|
|
#region 二、工具栏
|
|
|
#region 视角工具
|
// 显示点属性
|
|
double 俯视角度_bak = 45;
|
private void tool视角_ButtonClick(object sender, EventArgs e)
|
{
|
mapOption0 = mapOption.Copy();
|
if (RotationF == 90)
|
{
|
RotationF = 俯视角度_bak;
|
}
|
else
|
{
|
俯视角度_bak = RotationF;
|
RotationF = 90;
|
|
}
|
if (recordView) MapObjectExtensions.AddCommand(mapOption, "Map", mapOption0, mapOption);
|
SetMapInvalidate();
|
}
|
|
private void tool设置俯视角度_Click(object sender, EventArgs e)
|
{
|
mapOption0 = mapOption.Copy();
|
double jiaodu = 45;
|
var tool = sender as ToolStripItem;
|
jiaodu = Convert.ToDouble(tool.Text);
|
RotationF = jiaodu;
|
if (recordView) MapObjectExtensions.AddCommand(mapOption, "Map", mapOption0, mapOption);
|
SetMapInvalidate();
|
|
}
|
|
public void 重置视角ToolStripMenuItem_Click(object sender, EventArgs e)
|
{
|
mapOption0 = mapOption.Copy();
|
|
RotationF = 90;
|
Rotation = 0;
|
InitCenter();
|
if (recordView) MapObjectExtensions.AddCommand(mapOption, "Map", mapOption0, mapOption);
|
SetMapInvalidate();
|
}
|
private void 正视图ToolStripMenuItem_Click(object sender, EventArgs e)
|
{
|
mapOption0 = mapOption.Copy();
|
RotationF = 0;
|
if (recordView) MapObjectExtensions.AddCommand(mapOption, "Map", mapOption0, mapOption);
|
|
SetMapInvalidate();
|
}
|
private void 俯视图ToolStripMenuItem_Click(object sender, EventArgs e)
|
{
|
mapOption0 = mapOption.Copy();
|
RotationF = 90;
|
MapObjectExtensions.AddCommand(mapOption, "Map", mapOption0, mapOption);
|
|
SetMapInvalidate();
|
}
|
private void 默认视角ToolStripMenuItem_Click(object sender, EventArgs e)
|
{
|
|
|
mapOption0 = mapOption.Copy();
|
|
InitCenter();
|
RotationF = 45;
|
Rotation = -45;
|
MapObjectExtensions.AddCommand(mapOption, "Map", mapOption0, mapOption);
|
|
SetMapInvalidate();
|
}
|
private void 设为隐藏ToolStripMenuItem_Click(object sender, EventArgs e)
|
{
|
selectedObjs.ForEach(v =>
|
{
|
if (v.Visible)
|
{
|
MapObjectExtensions.AddCommand(v, "Visible", v.Visible, false);
|
v.Visible = false;
|
}
|
|
});
|
|
this.SetMapInvalidate();
|
}
|
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 count1 = _Links.FindAll(ll => ll.Node1 == l.StartNode.ID || ll.Node2 == l.StartNode.ID).Count;
|
var count2 = _Links.FindAll(ll => ll.Node1 == l.EndNode.ID || ll.Node2 == l.EndNode.ID).Count;
|
if (count1 > 1 && count2 <= 1)
|
{
|
MovePointbyLength(l.StartNode, l.EndNode, (float)length);
|
}
|
else if (count2 > 1 && count1 <= 1)
|
{
|
MovePointbyLength(l.EndNode, l.StartNode, (float)length);
|
}
|
else
|
{
|
MovePointbyLength(l.StartNode, l.EndNode, (float)length);
|
}
|
|
SetMapInvalidate();
|
|
}
|
|
}
|
|
|
|
|
|
this.SetMapInvalidate();
|
}
|
void MovePointbyLength(NodeViewModel node1, NodeViewModel node2, float Length)
|
{
|
|
float distance = Vector3.Distance(new Vector3(node1.X, node1.Y, node1.Z), new Vector3(node2.X, node2.Y, node2.Z));
|
|
if (distance > 0)
|
{ // 如果 A 和 B 不是同一个点
|
// 计算要移动多少距离
|
float moveDistance = Length - distance;
|
|
// 计算向量 AB(从 A 指向 B)
|
Vector3 AB = new Vector3(node2.X - node1.X, node2.Y - node1.Y, node2.Z - node1.Z);
|
|
// 计算 AB 的单位向量
|
Vector3 unitAB = Vector3.Normalize(AB);
|
|
// 计算需要移动的距离的向量(与 AB 方向相同)
|
Vector3 moveVector = unitAB * moveDistance;
|
|
// 更新点 B 的坐标
|
node2.X += moveVector.X;
|
node2.Y += moveVector.Y;
|
node2.Z += moveVector.Z;
|
|
// 输出移动后的点 B 坐标
|
//Console.WriteLine("移动后点 B 的坐标为 ({0}, {1}, {2})", x2, y2, z2);
|
}
|
}
|
private void 全部显示ToolStripMenuItem_Click(object sender, EventArgs e)
|
{
|
_Nodes.Select(n => (NodeViewModel)n).ToList().ForEach(v =>
|
{
|
if (!v.Visible)
|
{
|
MapObjectExtensions.AddCommand(v, "Visible", v.Visible, true);
|
v.Visible = true;
|
}
|
});
|
_Links.Select(n => (LinkViewModel)n).ToList().ForEach(v0 =>
|
{
|
var v = (LinkViewModel)v0;
|
if (!v.Visible)
|
{
|
MapObjectExtensions.AddCommand(v, "Visible", v.Visible, true);
|
v.Visible = true;
|
}
|
});
|
this.SetMapInvalidate();
|
}
|
#endregion
|
|
|
|
#region 绘图工具
|
|
|
|
public void toolStripButton_新建节点_Click(object sender, EventArgs e)
|
{
|
_mouseState = MouseState.新增节点;
|
Cursor = Cursors.Cross;
|
}
|
|
public void toolStripButton_普通_Click(object sender, EventArgs e)
|
{
|
_mouseState = MouseState.无;
|
Cursor = Cursors.Default;
|
if (_isPainting)
|
{
|
_select_junction1 = null;
|
_isPainting = false;
|
SetMapInvalidate();
|
}
|
else if (_isDragging)
|
{
|
_isDragging = false;
|
SetMapInvalidate();
|
}
|
else if (_isPanning)
|
{
|
_isPanning = false;
|
SetMapInvalidate();
|
}
|
else if (_isRotating)
|
{
|
Rotation = Rotation0;
|
_isRotating = false;
|
SetMapInvalidate();
|
}
|
else if (_isMovingObject)
|
{
|
_NewNet.Clear();
|
_isMovingObject = false;
|
SetMapInvalidate();
|
}
|
else if (_mouseState != MouseState.无)
|
{
|
_mouseState = MouseState.无;
|
Cursor = Cursors.Default;
|
}
|
else if (_isInsertingObject)
|
{
|
_NewNet.Clear();
|
_isInsertingObject = false;
|
_OperaNode = null;
|
SetMapInvalidate();
|
}
|
else
|
{
|
_Nodes.ForEach(o => ((NodeViewModel)o).Selected = false);
|
_Links.ForEach(o => ((LinkViewModel)o).Selected = false);
|
selectedObjs.Clear();
|
SetMapInvalidate();
|
|
|
}
|
}
|
|
public void toolStripButton_新建管线_Click(object sender, EventArgs e)
|
{
|
_mouseState = MouseState.新增管线;
|
Cursor = Cursors.Cross;
|
}
|
public void toolStripButton_新建立管_Click(object sender, EventArgs e)
|
{
|
_mouseState = MouseState.新增立管;
|
Cursor = Cursors.Cross;
|
}
|
|
|
private List<IBaseViewModel> AddLink(PointF e, bool isdoubleClick, PointF p, float z)
|
{
|
List<IBaseViewModel> l = new List<IBaseViewModel>();
|
var node = GetObj_by_ScreenPoint(e);
|
if (node != null || isdoubleClick)
|
{
|
if (node != null && node is NodeViewModel j)
|
{
|
_select_junction2 = j;
|
}
|
else if (isdoubleClick)
|
{
|
_select_junction2 = Network.AddJunction(p, z);
|
l.Add(_select_junction2);
|
}
|
|
if (_mouseState == MouseState.新增管线 || _mouseState == MouseState.新增立管)
|
l.Add(Network.AddPipe(_select_junction1, _select_junction2));
|
else if (_mouseState == MouseState.新建阀门)
|
l.Add(Network.AddValve(_select_junction1, _select_junction2));
|
else if (_mouseState == MouseState.新建水泵)
|
l.Add(Network.AddPump(_select_junction1, _select_junction2));
|
|
_select_junction1 = null;
|
_select_junction2 = null;
|
_isPainting = false;
|
|
|
}
|
return l;
|
}
|
|
private void Set_junction1(MouseEventArgs e)
|
{
|
var node = GetObj_by_ScreenPoint(new PointF(e.X, e.Y));
|
|
if (node != null && node is NodeViewModel j)
|
{
|
_select_junction1 = j;
|
_isPainting = true;
|
}
|
}
|
|
public void toolStripButton_添加水表_Click(object sender, EventArgs e)
|
{
|
_mouseState = MouseState.新建水表;
|
Cursor = Cursors.Cross;
|
}
|
|
public void toolStripButton_添加阀门_Click(object sender, EventArgs e)
|
{
|
_mouseState = MouseState.新建阀门;
|
Cursor = Cursors.Cross;
|
}
|
public void toolStripButton_添加水泵_Click(object sender, EventArgs e)
|
{
|
_mouseState = MouseState.新建水泵;
|
Cursor = Cursors.Cross;
|
}
|
public void toolStripButton_添加水库_Click(object sender, EventArgs e)
|
{
|
_mouseState = MouseState.新建水库;
|
Cursor = Cursors.Cross;
|
}
|
|
public void toolStripButton_添加水池_Click(object sender, EventArgs e)
|
{
|
_mouseState = MouseState.新建水池;
|
Cursor = Cursors.Cross;
|
}
|
public void toolStripButton_重复器_Click(object sender, EventArgs e)
|
{
|
_mouseState = MouseState.新建重复器;
|
Cursor = Cursors.Cross;
|
}
|
|
bool Buzylock = false;
|
public void MapViewer_KeyDown(object sender, KeyEventArgs e)
|
{
|
|
if (e.KeyCode == Keys.Escape)
|
{
|
Cursor = _lastCursor;
|
if (_isPainting)
|
{
|
_select_junction1 = null;
|
_isPainting = false;
|
SetMapInvalidate();
|
}
|
else if (_isDragging)
|
{
|
_isDragging = false;
|
SetMapInvalidate();
|
}
|
else if (_isPanning)
|
{
|
_isPanning = false;
|
SetMapInvalidate();
|
}
|
else if (_isRotating)
|
{
|
Rotation = Rotation0;
|
_isRotating = false;
|
SetMapInvalidate();
|
}
|
else if (_isMovingObject)
|
{
|
_NewNet.Clear();
|
_isMovingObject = false;
|
SetMapInvalidate();
|
}
|
else if (_mouseState != MouseState.无)
|
{
|
_mouseState = MouseState.无;
|
Cursor = Cursors.Default;
|
}
|
else if (_isInsertingObject)
|
{
|
_NewNet.Clear();
|
_isInsertingObject = false;
|
_OperaNode = null;
|
SetMapInvalidate();
|
}
|
else
|
{
|
_Nodes.ForEach(o => ((NodeViewModel)o).Selected = false);
|
_Links.ForEach(o => ((LinkViewModel)o).Selected = false);
|
selectedObjs.Clear();
|
SetMapInvalidate();
|
|
|
}
|
|
|
}
|
if (IsEditMode && e.KeyCode == Keys.Delete)
|
{
|
DeleteChoosedObj();
|
}
|
if (e.KeyCode == Keys.A && e.Modifiers == Keys.Control)
|
{
|
selectedObjs.Clear();
|
_Nodes.ForEach(o => { ((NodeViewModel)o).Selected = true; selectedObjs.Add((NodeViewModel)o); });
|
_Links.ForEach(o => { ((LinkViewModel)o).Selected = true; selectedObjs.Add((LinkViewModel)o); });
|
SetMapInvalidate();
|
}
|
|
|
}
|
|
|
|
private void MapViewer_KeyPress(object sender, KeyPressEventArgs e)
|
{
|
if (IsEditMode && ctrlPressed && e.KeyChar == 'Z' - 64)
|
{
|
// 执行相应的操作
|
buttonUndo_Click(sender, e);
|
ctrlPressed = false;
|
|
// 防止默认操作
|
e.Handled = true;
|
}
|
if (IsEditMode && ctrlPressed && e.KeyChar == 'Y' - 64)
|
{
|
// 执行相应的操作
|
buttonRedo_Click(sender, e);
|
ctrlPressed = false;
|
|
// 防止默认操作
|
e.Handled = true;
|
}
|
if (ctrlPressed && e.KeyChar == 'R' - 64)
|
{
|
// 执行相应的操作
|
tool视角_ButtonClick(sender, e);
|
ctrlPressed = false;
|
|
// 防止默认操作
|
e.Handled = true;
|
}
|
}
|
private void MapViewer_PreKeyPress(object sender, PreviewKeyDownEventArgs e)
|
{
|
if (IsEditMode && e.Control && e.KeyCode == Keys.Z)
|
{
|
ctrlPressed = true;
|
// 防止默认操作
|
e.IsInputKey = true;
|
|
}
|
if (IsEditMode && e.Control && e.KeyCode == Keys.Y)
|
{
|
ctrlPressed = true;
|
// 防止默认操作
|
e.IsInputKey = true;
|
|
}
|
if (e.Control && e.KeyCode == Keys.R)
|
{
|
ctrlPressed = true;
|
// 防止默认操作
|
e.IsInputKey = true;
|
|
}
|
}
|
public void setCenter(IBaseViewModel obj)
|
{
|
PointF position;
|
if (obj is LinkViewModel link)
|
position = link.Position;
|
else
|
position = obj.Position;
|
PointF currentPos = MapToScreen(WorldPointToMapPoint(position, obj.Z));
|
PointF centerScreen = new PointF(this.Width / 2, this.Height / 2);
|
var vector = GetRotateVector(centerScreen, currentPos);
|
MapCenter = new PointF(
|
MapCenter.X - vector.X / Zoom.X,
|
MapCenter.Y - vector.Y / Zoom.Y);
|
}
|
|
bool ctrlPressed = false;
|
#endregion
|
|
|
#region 右键菜单
|
|
|
private void 转换ToolStripMenuItem_Click(object sender, EventArgs e)
|
{
|
var nodes = selectedNodes;
|
foreach (var obj in nodes)
|
{
|
if (obj == null) return;
|
var toolItem = sender as ToolStripItem;
|
NodeViewModel junc = null;
|
int i = 0;
|
string ID;
|
switch (toolItem.Text)
|
{
|
case "水表":
|
junc = Network.AddMeter(obj.Position);
|
i = 0;
|
ID = $"{Default.GetPreString(junc)}{i}";
|
while (_Nodes.Find(p0 => p0.ID == ID) != null)
|
{
|
i++;
|
ID = $"{Default.GetPreString(junc)}{i}";
|
}
|
junc.ID = ID;
|
break;
|
case "基本节点":
|
|
junc = Network.AddJunction(obj.Position, obj.Z);
|
i = 0;
|
ID = $"{Default.GetPreString(junc)}{i}";
|
while (_Nodes.Find(p0 => p0.ID == ID) != null)
|
{
|
i++;
|
ID = $"{Default.GetPreString(junc)}{i}";
|
}
|
junc.ID = ID;
|
break;
|
case "水库":
|
junc = Network.AddReservoir(obj.Position);
|
i = 0;
|
ID = $"{Default.GetPreString(junc)}{i}";
|
while (_Nodes.Find(p0 => p0.ID == ID) != null)
|
{
|
i++;
|
ID = $"{Default.GetPreString(junc)}{i}";
|
}
|
junc.ID = ID;
|
break;
|
case "水池":
|
junc = Network.AddTank(obj.Position);
|
i = 0;
|
ID = $"{Default.GetPreString(junc)}{i}";
|
while (_Nodes.Find(p0 => p0.ID == ID) != null)
|
{
|
i++;
|
ID = $"{Default.GetPreString(junc)}{i}";
|
}
|
junc.ID = ID;
|
break;
|
}
|
//junc.ID = obj.ID;
|
|
junc.Level = obj.Level;
|
junc.Z = obj.Z;
|
junc.Demand = obj.Demand;
|
|
|
junc.Selected = true;
|
foreach (var p in _Links)
|
{
|
if (p.StartNode == obj)
|
{
|
p.StartNode = junc;
|
|
}
|
else if (p.EndNode == obj)
|
{
|
p.EndNode = junc;
|
}
|
}
|
selectedObjs.Add(junc);
|
selectedObjs.Remove(obj);
|
//MapObjectExtensions.AddCommand(obj, "Add", null, new List<MapObject>() { n });
|
_Nodes.Remove(obj);
|
}
|
|
|
SetMapInvalidate();
|
}
|
|
public void 删除ToolStripMenuItem_Click(object sender, EventArgs e)
|
{
|
DeleteChoosedObj();
|
}
|
|
private void DeleteChoosedObj()
|
{
|
var list = Network.Remove(selectedObjs);
|
MapObjectExtensions.AddCommand(Network, "Remove", null, list);
|
selectedObjs.Clear();
|
SetMapInvalidate();
|
}
|
#endregion
|
|
|
#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
|
|
|
|
|
#region 分析工具
|
|
|
public List<PointF> GetRotatedPoints(List<PointF> points, PointF origin, float angle)
|
{
|
// 将角度转换为弧度
|
float radians = angle * (float)Math.PI / 180.0f;
|
|
// 计算正余弦值
|
float cos = (float)Math.Cos(radians);
|
float sin = (float)Math.Sin(radians);
|
|
// 定义结果集合,并遍历输入点集合进行旋转处理
|
List<PointF> result = new List<PointF>(points.Count);
|
foreach (PointF point in points)
|
{
|
// 将点相对于旋转中心点平移,使其成为以原点为中心的坐标系
|
float translatedX = point.X - origin.X;
|
float translatedY = point.Y - origin.Y;
|
|
// 应用旋转变换
|
float rotatedX = translatedX * cos - translatedY * sin;
|
float rotatedY = translatedX * sin + translatedY * cos;
|
|
// 将点相对于原坐标系平移回去
|
float finalX = rotatedX + origin.X;
|
float finalY = rotatedY + origin.Y;
|
|
// 添加到结果集合中
|
result.Add(new PointF(finalX, finalY));
|
}
|
|
return result;
|
}
|
|
|
public List<PointF3D> GetRotatedPoints(List<PointF3D> points, Vector3 line, float angle)
|
{
|
// 将角度转换为弧度
|
float radians = (float)(angle * Math.PI / 180.0f);
|
|
// 根据旋转直线的方向矢量和旋转角度计算旋转矩阵
|
float cos = (float)Math.Cos(radians);
|
float sin = (float)Math.Sin(radians);
|
float x = line.X;
|
float y = line.Y;
|
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)}
|
};
|
|
// 定义结果集合,并遍历输入点集合进行旋转处理
|
List<PointF3D> result = new List<PointF3D>(points.Count);
|
foreach (PointF3D point in points)
|
{
|
// 将点按照旋转中心线平移,使其成为以原点为中心的坐标系
|
Vector3 translatedPoint = new Vector3(point.X - line.X, point.Y - line.Y, point.Z - line.Z);
|
|
// 应用旋转变换
|
Vector3 rotatedPointVector = new Vector3(
|
translatedPoint.X * rotationMatrix[0, 0] + translatedPoint.Y * rotationMatrix[0, 1] + translatedPoint.Z * rotationMatrix[0, 2],
|
translatedPoint.X * rotationMatrix[1, 0] + translatedPoint.Y * rotationMatrix[1, 1] + translatedPoint.Z * rotationMatrix[1, 2],
|
translatedPoint.X * rotationMatrix[2, 0] + translatedPoint.Y * rotationMatrix[2, 1] + translatedPoint.Z * rotationMatrix[2, 2]);
|
|
// 将点相对于原坐标系平移回去
|
float finalX = rotatedPointVector.X + line.X;
|
float finalY = rotatedPointVector.Y + line.Y;
|
float finalZ = rotatedPointVector.Z + line.Z;
|
|
// 将旋转后的点添加到结果集合中
|
result.Add(new PointF3D(finalX, finalY, finalZ));
|
}
|
|
return result;
|
}
|
|
public static List<PointF3D> ScalePoints(List<PointF3D> points, PointF3D centerPoint, float scale)
|
{
|
//定义结果集合,并遍历输入点集合进行缩放处理
|
List<PointF3D> result = new List<PointF3D>(points.Count);
|
foreach (PointF3D point in points)
|
{
|
//将点相对于缩放中心点平移,使其成为以原点为中心的坐标系
|
Vector3 translatedPoint = new Vector3(point.X - centerPoint.X, point.Y - centerPoint.Y, point.Z - centerPoint.Z);
|
|
//应用缩放变换
|
Vector3 scaledPointVector = new Vector3(
|
translatedPoint.X * scale + centerPoint.X,
|
translatedPoint.Y * scale + centerPoint.Y,
|
translatedPoint.Z * scale + centerPoint.Z);
|
|
//将缩放后的点添加到结果集合中
|
result.Add(new PointF3D(scaledPointVector.X, scaledPointVector.Y, scaledPointVector.Z));
|
}
|
|
return result;
|
}
|
|
|
|
private void btn_拓扑检查_Click(object sender, EventArgs e)
|
{
|
Dictionary<string, List<string>> result = _network.CheckValidate();
|
if (result.Count > 0)
|
{
|
|
ListBox listBox1 = new ListBox();
|
listBox1.Dock = DockStyle.Fill;
|
listBox1.Width = 200;
|
listBox1.Height = 400;
|
listBox1.Items.AddRange(result.Keys.ToArray());
|
listBox1.SelectedIndexChanged += (s, e) =>
|
{
|
//listBox2.Items.Clear();
|
if (listBox1.SelectedIndex >= 0)
|
{
|
var arr = result[listBox1.SelectedItem.ToString()].ToHashSet();
|
|
List<IBaseViewModel> Objs = new List<IBaseViewModel>();
|
Objs.AddRange(_Nodes.Select(n => (NodeViewModel)n));
|
Objs.AddRange(_Links.Select(l => (LinkViewModel)l));
|
var nodes = _Nodes.FindAll(o => arr.Contains(o.ID));
|
var links = _Links.FindAll(o => arr.Contains(o.ID));
|
//listBox2.Items.AddRange(result[listBox1.SelectedItem.ToString()].ToArray());
|
selectedObjs.ForEach(obj => obj.Selected = false);
|
selectedObjs.Clear();
|
nodes.ForEach(obj =>
|
{
|
obj.Selected = true;
|
selectedObjs.Add((NodeViewModel)obj);
|
});
|
links.ForEach(obj =>
|
{
|
obj.Selected = true;
|
selectedObjs.Add((LinkViewModel)obj);
|
});
|
|
SelectedObjectsChanged?.Invoke(this, selectedObjs);
|
SetMapInvalidate();
|
}
|
};
|
|
|
Form ResultForm = new Form();
|
ResultForm.Text = "拓扑检查结果";
|
ResultForm.Width = 300;
|
ResultForm.Height = 400;
|
ResultForm.StartPosition = FormStartPosition.CenterScreen;
|
ResultForm.Controls.Add(listBox1);
|
ResultForm.MinimizeBox = false;
|
ResultForm.MaximizeBox = false;
|
|
ResultForm.Show();
|
|
}
|
else
|
{
|
MessageBox.Show("拓扑检查通过");
|
}
|
|
|
|
}
|
|
|
List<LinkViewModel> LinksToFindSource = null;
|
Dictionary<LinkViewModel, List<IBaseViewModel>> Sets = null;
|
Dictionary<LinkViewModel, bool> Sets_hasSource = null;
|
private void TraversePipeNetwork(List<IBaseViewModel> startObjs, HashSet<NodeViewModel> visitedNodes = null, bool consider = true)
|
{
|
|
LinksToFindSource = new List<LinkViewModel>();
|
|
if (visitedNodes == null)
|
visitedNodes = new HashSet<NodeViewModel>();
|
|
startObjs.ForEach(o =>
|
{
|
if (o is LinkViewModel l)
|
{
|
TraversePipeNetwork(l, visitedNodes);
|
}
|
else if (o is NodeViewModel n)
|
{
|
n.Links.Select(oo => oo as LinkViewModel).ToList().ForEach(link => TraversePipeNetwork(link, visitedNodes));
|
|
}
|
});
|
if (!consider) return;
|
Sets = new Dictionary<LinkViewModel, List<IBaseViewModel>>();
|
Sets_hasSource = new Dictionary<LinkViewModel, bool>();
|
LinksToFindSource.ForEach(l =>
|
{
|
TraversePipeNetwork_Set(l, visitedNodes);
|
});
|
|
foreach (var kp in Sets)
|
{
|
if (!Sets_hasSource[kp.Key])
|
{
|
kp.Value.ForEach(o =>
|
{
|
if (!(o is ValveViewModel))
|
{
|
o.Selected = true;
|
selectedObjs.Add(o);
|
}
|
|
});
|
}
|
}
|
SelectedObjectsChanged?.Invoke(this, selectedObjs);
|
|
|
}
|
private void TraversePipeNetwork(LinkViewModel startLink, HashSet<NodeViewModel> visitedNodes = null)
|
{
|
|
Queue<LinkViewModel> queue = new Queue<LinkViewModel>();
|
|
|
|
queue.Enqueue(startLink);
|
if (visitedNodes == null)
|
visitedNodes = new HashSet<NodeViewModel>();
|
//visitedNodes.Add(startLink.StartNode);
|
//visitedNodes.Add(startLink.EndNode);
|
|
while (queue.Count > 0)
|
{
|
LinkViewModel currentLink = queue.Dequeue();
|
//Console.WriteLine("Traversing Link: " + currentLink.ID);
|
|
foreach (var node in new NodeViewModel[] { currentLink.StartNode, currentLink.EndNode })
|
{
|
if (!visitedNodes.Contains(node) && node != null)
|
{
|
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))
|
{
|
link.Selected = true;
|
selectedObjs.Add(link);
|
|
|
if (!(link is ValveViewModel))
|
{
|
queue.Enqueue(link);
|
|
}
|
else
|
{
|
LinksToFindSource.Add(link);
|
}
|
|
|
}
|
}
|
}
|
}
|
|
}
|
|
}
|
private void TraversePipeNetwork_Set(LinkViewModel startLink, HashSet<NodeViewModel> visitedNodes = null)
|
{
|
|
Queue<LinkViewModel> queue = new Queue<LinkViewModel>();
|
|
|
|
|
queue.Enqueue(startLink);
|
if (visitedNodes == null)
|
visitedNodes = new HashSet<NodeViewModel>();
|
|
Sets.Add(startLink, new List<IBaseViewModel>());
|
Sets_hasSource.Add(startLink, false);
|
while (queue.Count > 0)
|
{
|
LinkViewModel currentLink = queue.Dequeue();
|
//Console.WriteLine("Traversing Link: " + currentLink.ID);
|
|
foreach (var node in new NodeViewModel[] { currentLink.StartNode, currentLink.EndNode })
|
{
|
if (node == null) continue;
|
if (!visitedNodes.Contains(node))
|
{
|
Sets[startLink].Add(node);
|
visitedNodes.Add(node);
|
if (node is TankViewModel || node is ReservoirViewModel)
|
{
|
Sets_hasSource[startLink] = true;
|
}
|
|
//Console.WriteLine("Visiting Node: " + node.ID);
|
foreach (var link in node.ViewLinks)
|
{
|
if (!visitedNodes.Contains(link.StartNode) || !visitedNodes.Contains(link.EndNode))
|
{
|
Sets[startLink].Add(link);
|
queue.Enqueue(link);
|
}
|
}
|
}
|
else
|
{
|
foreach (var kp in Sets)
|
{
|
if (kp.Key != startLink && kp.Value.Contains(node))
|
{
|
kp.Value.AddRange(Sets[startLink]);
|
Sets_hasSource[kp.Key] = Sets_hasSource[startLink] || Sets_hasSource[kp.Key];
|
Sets.Remove(startLink);
|
Sets_hasSource.Remove(startLink);
|
startLink = kp.Key;
|
break;
|
}
|
}
|
}
|
}
|
|
}
|
|
|
|
}
|
private bool FindSouce(LinkViewModel startLink, HashSet<LinkViewModel> visitedLinks, HashSet<LinkViewModel> visitedLinks2, Dictionary<IBaseViewModel, bool> hasSource = null)
|
{
|
|
|
foreach (var node in new NodeViewModel[] { startLink.StartNode, startLink.EndNode })
|
{
|
|
if (!hasSource.ContainsKey(node))
|
{
|
//hasSource.Add(node, false);
|
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)
|
{
|
|
foreach (var link in startNode.ViewLinks)
|
{
|
if (hasSource.ContainsKey(link) && hasSource[link] == true) return true;
|
if (visitedLinks.Contains(link) && startNode == link.StartNode) continue;
|
if (visitedLinks2.Contains(link) && startNode == link.EndNode) continue;
|
if (startNode == link.StartNode)
|
visitedLinks.Add(link);
|
else
|
visitedLinks2.Add(link);
|
if (!hasSource.ContainsKey(link))
|
{
|
|
//hasSource.Add(link,false);
|
hasSource[link] = FindSouce(link, visitedLinks, visitedLinks2, hasSource);
|
}
|
|
if (hasSource[link] == true) return true;
|
|
|
}
|
return false;
|
|
|
}
|
|
private void TraversePipeNetworkALL(LinkViewModel startLink, HashSet<NodeViewModel> visitedNodes = null, int direction = 0)
|
{
|
|
Queue<LinkViewModel> queue = new Queue<LinkViewModel>();
|
|
|
|
queue.Enqueue(startLink);
|
if (visitedNodes == null)
|
visitedNodes = new HashSet<NodeViewModel>();
|
//visitedNodes.Add(startLink.StartNode);
|
//visitedNodes.Add(startLink.EndNode);
|
|
while (queue.Count > 0)
|
{
|
LinkViewModel currentLink = queue.Dequeue();
|
//Console.WriteLine("Traversing Link: " + currentLink.ID);
|
|
foreach (var node in new NodeViewModel[] { currentLink.StartNode, currentLink.EndNode })
|
{
|
if (direction == 1 && currentLink.EN_FLOW >= 0 && node == currentLink.StartNode) continue;
|
if (direction == -1 && currentLink.EN_FLOW <= 0 && node == currentLink.EndNode) continue;
|
if (node != null && !visitedNodes.Contains(node))
|
{
|
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))
|
{
|
link.Selected = true;
|
selectedObjs.Add(link);
|
queue.Enqueue(link);
|
|
|
|
|
}
|
}
|
}
|
}
|
|
}
|
|
|
|
}
|
#endregion
|
|
|
#region 显示选项
|
|
private void 显示节点ToolStripMenuItem_Click(object sender, EventArgs e)
|
{
|
IsShowJunction = true;
|
SetMapInvalidate();
|
}
|
|
private void 隐藏节点ToolStripMenuItem_Click(object sender, EventArgs e)
|
{
|
IsShowJunction = false;
|
SetMapInvalidate();
|
}
|
|
private void 大ToolStripMenuItem_Click(object sender, EventArgs e)
|
{
|
var item = sender as ToolStripItem;
|
if (item.Text == "大")
|
{
|
Junction_multiply = 1f;
|
}
|
else if (item.Text == "中")
|
{
|
Junction_multiply = 0.6667f;
|
}
|
else
|
{
|
Junction_multiply = 0.4f;
|
}
|
SetMapInvalidate();
|
}
|
|
private void 显示阀门ToolStripMenuItem_Click(object sender, EventArgs e)
|
{
|
IsShowValve = true;
|
SetMapInvalidate();
|
|
}
|
|
private void 隐藏阀门ToolStripMenuItem_Click(object sender, EventArgs e)
|
{
|
IsShowValve = false;
|
SetMapInvalidate();
|
|
|
}
|
|
private void 大ToolStripMenuItem1_Click(object sender, EventArgs e)
|
{
|
var item = sender as ToolStripItem;
|
if (item.Text == "大")
|
{
|
Link_multiply = 1f;
|
}
|
else if (item.Text == "中")
|
{
|
Link_multiply = 0.6667f;
|
}
|
else
|
{
|
Link_multiply = 0.4f;
|
}
|
SetMapInvalidate();
|
}
|
|
|
#endregion
|
|
|
#endregion 二、工具栏
|
|
#region 方法
|
private void 标高推测ToolStripMenuItem_Click(object sender, EventArgs e)
|
{
|
int num = UpdateNodesEle();
|
if (num > 0)
|
{
|
MessageBox.Show($"更新成功,更新节点数量:{num}个");
|
}
|
else
|
{
|
MessageBox.Show($"没有需要更新的节点");
|
|
}
|
}
|
public int UpdateNodesEle()
|
{
|
int num = 0;
|
foreach (NodeViewModel node in _Nodes)
|
{
|
if (node.Z == 0 && node is JunctionViewModel)
|
{
|
HashSet<NodeViewModel> nodeSet = new HashSet<NodeViewModel>();
|
nodeSet.Add(node);
|
List<NodeViewModel> nonZeroNeighbors = new List<NodeViewModel>();
|
FindNonZeroNeighbors(node, nonZeroNeighbors, nodeSet);
|
if (nonZeroNeighbors.Count != 0)
|
{
|
float sum = 0;
|
float weightSum = 0;
|
|
foreach (NodeViewModel neighbor in nonZeroNeighbors)
|
{
|
float dist = Get_dist(node.Position, neighbor.Position);
|
if (dist == 0)
|
{
|
dist = 0.0000000001f;
|
}
|
float weight = 1 / dist;// CalculateWeight(node, neighbor);
|
sum += neighbor.Z * weight;
|
weightSum += weight;
|
}
|
|
float average = sum / weightSum;
|
node.Z = average;
|
num++;
|
}
|
}
|
}
|
return num;
|
}
|
|
private void FindNonZeroNeighbors(NodeViewModel node, List<NodeViewModel> result, HashSet<NodeViewModel> origin)
|
{
|
foreach (LinkViewModel link in node.ViewLinks)
|
{
|
NodeViewModel neighbor = null;
|
if (link.StartNode == node)
|
{
|
neighbor = link.EndNode;
|
|
}
|
else
|
{
|
neighbor = link.StartNode;
|
}
|
|
if (neighbor.Z != 0)
|
{
|
result.Add(neighbor);
|
}
|
else if (!origin.Contains(neighbor))
|
{
|
origin.Add(neighbor);
|
FindNonZeroNeighbors(neighbor, result, origin);
|
}
|
}
|
}
|
private void 标高导出ToolStripMenuItem_Click(object sender, EventArgs e)
|
{
|
DataTable dt = new DataTable();
|
dt.Columns.Add("ID");
|
dt.Columns.Add("Elev", typeof(float));
|
foreach (NodeViewModel node in _Nodes)
|
{
|
if (node is JunctionViewModel junction)
|
{
|
var dr = dt.NewRow();
|
dr.ItemArray = new object[] { junction.ID, junction.Z };
|
dt.Rows.Add(dr);
|
}
|
}
|
dtToSql(dt);
|
|
}
|
void dtToCsv(DataTable dt)
|
{
|
// 创建 SaveFileDialog 对象
|
SaveFileDialog saveFileDialog = new SaveFileDialog();
|
saveFileDialog.Filter = "CSV Files (*.csv)|*.csv";
|
saveFileDialog.FileName = "output.csv";
|
|
// 如果用户选择了保存位置和文件名,则执行保存操作
|
if (saveFileDialog.ShowDialog() == DialogResult.OK)
|
{
|
// 获取用户选择的保存路径和文件名
|
string filePath = saveFileDialog.FileName;
|
|
// 假设 dt 是包含数据的 DataTable 对象
|
|
// 构建 CSV 字符串
|
StringBuilder csvContent = new StringBuilder();
|
|
// 写入表头
|
foreach (DataColumn column in dt.Columns)
|
{
|
csvContent.Append(column.ColumnName);
|
csvContent.Append(",");
|
}
|
csvContent.AppendLine();
|
|
// 写入数据行
|
foreach (DataRow row in dt.Rows)
|
{
|
for (int i = 0; i < dt.Columns.Count; i++)
|
{
|
csvContent.Append(row[i]);
|
csvContent.Append(",");
|
}
|
csvContent.AppendLine();
|
}
|
|
// 将 CSV 内容写入文件
|
File.WriteAllText(filePath, csvContent.ToString());
|
|
// 显示保存成功消息框
|
MessageBox.Show("文件保存成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
}
|
}
|
void dtToSql(DataTable dt)
|
{
|
// 创建 SaveFileDialog 对象
|
SaveFileDialog saveFileDialog = new SaveFileDialog();
|
saveFileDialog.Filter = "Txt Files (*.txt)|*.txt";
|
|
|
// 如果用户选择了保存位置和文件名,则执行保存操作
|
if (saveFileDialog.ShowDialog() == DialogResult.OK)
|
{
|
// 获取用户选择的保存路径和文件名
|
string filePath = saveFileDialog.FileName;
|
|
// 假设 dt 是包含数据的 DataTable 对象
|
string tableString = @"
|
IF OBJECT_ID('Elev', 'U') IS NOT NULL
|
BEGIN
|
-- 清空表
|
TRUNCATE TABLE Elev;
|
END
|
ELSE
|
BEGIN
|
-- 创建表
|
CREATE TABLE Elev (
|
ID NVARCHAR(50),
|
Elev REAL
|
);
|
END
|
|
|
";
|
// 构建 CSV 字符串
|
StringBuilder csvContent = new StringBuilder();
|
|
csvContent.AppendLine(tableString);
|
|
|
|
//// 写入表头
|
//foreach (DataColumn column in dt.Columns)
|
//{
|
|
// csvContent.Append(column.ColumnName);
|
// csvContent.Append(",");
|
//}
|
//csvContent.AppendLine();
|
|
int i = 0;
|
int j = 0;
|
while (i < dt.Rows.Count)
|
{
|
|
if (j == 0) csvContent.AppendLine("INSERT INTO Elev (ID, Elev) VALUES");
|
// 写入数据行
|
|
DataRow row = dt.Rows[i];
|
csvContent.Append($"('{row[0]}',{row[1]})");
|
csvContent.Append(i == dt.Rows.Count - 1 || j == 999 ? ";" : ",");
|
csvContent.AppendLine();
|
i++;
|
j++;
|
if (j == 1000) j = 0;
|
|
|
|
}
|
|
|
// 将 CSV 内容写入文件
|
File.WriteAllText(filePath, csvContent.ToString());
|
|
// 显示保存成功消息框
|
MessageBox.Show("文件保存成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
}
|
}
|
|
private void 导入jsonToolStripMenuItem_Click(object sender, EventArgs e)
|
{
|
var ofd = new OpenFileDialog();
|
ofd.Filter = "json文件|*.json";
|
var result = ofd.ShowDialog();
|
if (result == DialogResult.OK)
|
{
|
_Template = new Settings(new Guid().ToString(), "新建", "复制", TemplateType.其他);
|
string json = File.ReadAllText(ofd.FileName);
|
_network = JsonConvert.DeserializeObject<MapViewNetWork>(json);
|
_network.BuildRelation();
|
TemplateList.AddTemp(_Template);
|
LoadData();
|
}
|
}
|
public void buttonUndo_Click(object sender, EventArgs e)
|
{
|
SetMapInvalidate();
|
|
SelectedObjectsChanged?.Invoke(this, null);
|
MapObjectExtensions.Undo();
|
}
|
public void buttonRedo_Click(object sender, EventArgs e)
|
{
|
SetMapInvalidate();
|
SelectedObjectsChanged?.Invoke(this, null);
|
MapObjectExtensions.Redo();
|
}
|
|
|
private void 连通性检查ToolStripMenuItem1_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();
|
if (objs.Count == 0) selectedObjs.FindAll(o => o is NodeViewModel).Select(o => o as NodeViewModel).ToList().ForEach(o => objs.AddRange(o.Links.Select(l => l as LinkViewModel).ToList()));
|
//objs去掉重复的元素
|
objs = objs.Distinct().ToList();
|
var visitedNodes = new HashSet<NodeViewModel>();
|
objs.ForEach(o => TraversePipeNetworkALL(o, visitedNodes));
|
|
|
this.SetMapInvalidate();
|
|
}
|
}
|
private void 下游连通性ToolStripMenuItem_Click(object sender, EventArgs e)
|
{
|
if (selectedObjs.Count > 0)//&& selectedObjs[0] is Link l
|
{
|
|
var objs = selectedObjs.FindAll(o => o is LinkViewModel).Select(o => o as LinkViewModel).ToList();
|
if (objs.Count == 0) selectedObjs.FindAll(o => o is NodeViewModel).Select(o => o as NodeViewModel).ToList().ForEach(o =>
|
{
|
objs.AddRange(o.Links.Select(oo => oo as LinkViewModel).ToList().FindAll(oo => oo.StartNode == o ? oo.EN_FLOW > 0 : oo.EN_FLOW < 0));
|
});
|
//objs去掉重复的元素
|
objs = objs.Distinct().ToList();
|
var visitedNodes = new HashSet<NodeViewModel>();
|
objs.ForEach(o => TraversePipeNetworkALL(o, visitedNodes, 1));
|
this.SetMapInvalidate();
|
|
}
|
}
|
|
List<PointF3D> ProjectPointsToLine(List<PointF3D> points)
|
{
|
// 使用最小二乘法构造直线,并将点投影到直线上
|
|
// 计算均值
|
double sumX = 0;
|
double sumY = 0;
|
double sumZ = 0;
|
|
foreach (PointF3D point in points)
|
{
|
sumX += point.X;
|
sumY += point.Y;
|
sumZ += point.Z;
|
}
|
|
double meanX = sumX / points.Count;
|
double meanY = sumY / points.Count;
|
double meanZ = sumZ / points.Count;
|
|
// 计算最小二乘法拟合直线的参数
|
|
double sumXY = 0;
|
double sumX2 = 0;
|
|
foreach (PointF3D point in points)
|
{
|
double devX = point.X - meanX;
|
double devY = point.Y - meanY;
|
double devZ = point.Z - meanZ;
|
|
sumXY += devX * devY;
|
sumX2 += devX * devX;
|
}
|
|
double slope = sumXY / sumX2;
|
double interceptY = meanY - slope * meanX;
|
double interceptZ = meanZ - slope * meanX;
|
|
// 计算点投影到直线上的坐标
|
|
List<PointF3D> projectedPoints = new List<PointF3D>();
|
|
foreach (PointF3D point in points)
|
{
|
double projectedY = slope * point.X + interceptY;
|
double projectedZ = slope * point.X + interceptZ;
|
|
projectedPoints.Add(new PointF3D(point.X, (float)projectedY, (float)projectedZ));
|
}
|
|
return projectedPoints;
|
}
|
|
bool _isSettingBackGroundPictur = false;
|
|
|
private bool __needpaintall = false;
|
|
|
|
|
|
|
|
|
#endregion
|
}
|
}
|