using Hydro.MapView; using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; using System.Numerics; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Hydro.WinfrmUI { //定义一个委托,用来存储void Draw(Graphics bufferG, Template template) public delegate void DrawDelegate(Graphics bufferG, Template template); public delegate void MouseDelegate(MouseEventArgs e); partial class ViewBrowser { void Draw(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; float minElve = float.MinValue; float maxElve = float.MaxValue; //if (this.mapOption!=null && this.mapOption.ShowFloor!=int.MinValue ) //{ // var fl = template.Floors.Find(f => f.FloorIndex == this.mapOption.ShowFloor); // var fl_1 = template.Floors.Find(f => f.FloorIndex == this.mapOption.ShowFloor+1); // if (fl!=null) // { // minElve = fl.Elev; // maxElve = fl_1!=null ? fl_1.Elev : float.MaxValue; // } //} r = r * Link_multiply; List diametersZoom = new List() { 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); //背景图绘制 if (this.mapOption.isShowPic && template != null && File.Exists(template.BackGroundImg_FullPath)) { //var gs = bufferG.Save(); // 应用矩阵变换以抵消之前的翻转效果 //bufferG.ScaleTransform(1 / Zoom.X, 1 / Zoom.Y); // 恢复之前保存的绘图状态 var Cps = new List { template.BackGroundPoint1, new PointF(template.BackGroundPoint2.X,template.BackGroundPoint1.Y), new PointF(template.BackGroundPoint1.X,template.BackGroundPoint2.Y), //template.BackGroundPoint2, }; List p = new List(); Cps.ForEach(cp => p.Add(WorldPointToMapPoint(cp, template.BackGroundElev, template.OffSet))); //bufferG.DrawImage(System.Drawing.Image.FromFile(@"C:\Users\cloud\Pictures\GenshinImpactCloudGame\QQ截图20230919105637.png"), p[0]); 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 { } //bufferG.Restore(gs); } // 绘制线 HashSet dict_flow_direction = new HashSet(); 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.DrawLine(link.Selected ? pen_valveChoosed : pen, p1, p2); bufferG.DrawLines(link.Selected ? penChoosed : pen, new PointF[] { p1, p2 }); // 绘制圆形部分(水泵的泵体) float radius = 5 * r; float diameter = radius * 2; #region 圆形拆分 //var p = new PointF[] //{ // GraphHelper.getRotatePoint(c.X - radius - radius, c.Y - radius, c, p1, p2), // GraphHelper.getRotatePoint(c.X + radius - radius, c.Y - radius, c, p1, p2), // GraphHelper.getRotatePoint(c.X + radius - radius, c.Y + radius, c, p1, p2), // GraphHelper.getRotatePoint(c.X - radius - radius, c.Y + radius, c, p1, p2), // GraphHelper.getRotatePoint(c.X - radius - radius, c.Y - radius, c, p1, p2), //}; List p = new List(); Cpoints.ForEach(cp => p.Add(GraphHelper.getRotatePoint(c.X + cp.X * radius - radius, c.Y + cp.Y * radius, c, p1, p2))); #endregion //RectangleF circleRect = new RectangleF(p[0].X, p[0].Y,p[1].X-p[0].X>0? diameter:-diameter,p[1].Y-p[0].Y>0? diameter:-diameter); //bufferG.FillEllipse(link.Selected ? pen_valveChoosed.Brush : pen.Brush, circleRect); bufferG.FillPolygon(link.Selected ? pen_valveChoosed.Brush : pen.Brush, p.ToArray()); //// 绘制矩形部分(水泵的出口) //float rectangleWidth = 6*r; //float rectangleHeight = 2*r; //PointF rectTopLeft = new PointF(c.X - rectangleWidth / 2, c.Y + radius); //SizeF rectSize = new SizeF(rectangleWidth, rectangleHeight); //RectangleF rectangleRect = new RectangleF(rectTopLeft, rectSize); //bufferG.DrawRectangles(link.Selected ? pen_valveChoosed : pen,new RectangleF[] { rectangleRect }); // 绘制连接线 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 == RepeaterViewModel.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++) { //foreach (var c in listNode) //{ 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); //bufferG.FillRectangles(link.Selected ? penChoosed.Brush : pen.Brush, new RectangleF[] //{ // new RectangleF(c.X-5*r,c.Y-5*r,3*r,3*r), // new RectangleF(c.X-5*r,c.Y+2*r,3*r,3*r), // new RectangleF(c.X+2*r,c.Y+2*r,3*r,3*r), // new RectangleF(c.X+2*r,c.Y-5*r,3*r,3*r), //}); // 保存当前绘图状态 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 { } } //var c = new PointF((p1.X + p2.X) / 2, (p1.Y + p2.Y) / 2); } //else //{ // DrawRepeater(bufferG,re); //} } else { if (link.StartNode == null || link.EndNode == null) continue; bufferG.DrawLines(link.Selected ? penChoosed : pen, new PointF[] { p1, p2 }); 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 p = new List(); 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 dict_point = new HashSet(); //绘制点 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); //var x = junction.Position.X * zoom + PanningOffset.X - radius / 2.0f; //var y = junction.Position.Y * zoom + PanningOffset.Y - radius / 2.0f; 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.ID == _StartPoint) //{ // 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 == _OperaNode) { //bufferG.DrawEllipse(junction.Choosed ? penChoosed : pen, rectangle); 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); //bufferG.DrawEllipse(junction.Choosed ? penChoosed : pen, rectangle); } 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); //whiteRect = new RectangleF(rectangle.X + 2 * pr, rectangle.Y + 2 * pr, rectangle.Width - 4 * pr, rectangle.Height - 4 * pr); //bufferG.DrawEllipse(junction.Choosed ? 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); //bufferG.FillEllipse(junction.Choosed ? 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); //whiteRect = new RectangleF(rectangle.X - 2 * pr, rectangle.Y - 2 * pr, rectangle.Width + 4 * pr, rectangle.Height + 4 * pr); //bufferG.DrawEllipse(junction.Choosed ? penChoosed : pen, whiteRect); } 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.DrawEllipse(junction.Choosed ? penChoosed : pen, rectangle); 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)) { //if (node.Elev < minElve || node.Elev >= maxElve) continue; 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); //var x = junction.Position.X * zoom + PanningOffset.X - radius / 2.0f; //var y = junction.Position.Y * zoom + PanningOffset.Y - radius / 2.0f; 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 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); 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 ==MapViewEnum.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; bufferG.DrawLine(pen, WorldPointToMapPoint(_select_junction1), _MousePosition); } } } if (_isDrawingPolygon && polygonPoints.Count > 0) { List 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 pf = new List { oldP, newP }; using (var pen = new Pen(Color.Black, 1 * r)) { // 绘制多边形虚线边框 pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash; bufferG.DrawLines(pen, pf.ToArray()); } } } #region 基础坐标转换方法 /// /// 将屏幕坐标转换为世界坐标。输入屏幕坐标 (x,y),返回世界坐标 (wx, wy)。 /// /// /// 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; //if (is3Dview) worldY = -(screenPos.Y - centerY + 2 * z) / (0.5f* zoom) + center.Y; return new PointF(worldX, worldY); } /// /// 将屏幕坐标转换为世界坐标。输入屏幕坐标 (x,y),返回世界坐标 (wx, wy)。 /// /// /// 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); } 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 center = MapCenter; 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 center = MapCenter; 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 center = MapCenter; 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 center = MapCenter; 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); } /// /// 获取地图投影坐标 /// /// /// /// 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); var pointT = Get俯视角旋转Point(pointR, z + offset.Z); //var n=new PointF((float)pointR.X - Z(z).X, (float)(pointR.Y - Z(z).Y)); 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 List WorldPointToMapPoint(LinkViewModel pipe, PointF3D offset = null) { List list = new List(); PointF p; p = WorldPointToMapPoint(pipe.StartNode, offset); list.Add(p); p = WorldPointToMapPoint(pipe.EndNode, offset); list.Add(p); return list; } /// /// 获取正交投影坐标,返回的是世界坐标 /// /// 世界坐标 /// 地图坐标 /// 投影向量 /// /// private PointF3D GetZZWorldPoint(PointF3D position3D, PointF mousePosition, Vector3 vector3) { //做一条通过position3D的平行于vector3的直线, if (vector3==new Vector3(0,0,1)) { return GetLGWorldPoint(position3D, mousePosition); } else { return new PointF3D(0, 0, 0); } } /// /// 获取正交投影坐标,返回的是世界坐标 /// /// 世界坐标 /// 地图坐标 /// 投影向量 /// /// 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); } private PointF MapPointToWorldPoint(PointF3D point) { return MapPointToWorldPoint(new PointF(point.X, point.Y), point.Z); } /// /// 获取地图投影坐标 /// /// /// /// private PointF MapPointToWorldPoint(PointF point, float z = 0) { var pointT = Get俯视角还原Point(point, z); pointT = Get平面还原Point(pointT); //var n=new PointF((float)pointR.X - Z(z).X, (float)(pointR.Y - Z(z).Y)); return pointT; } private PointF GetMapPoint_还原(NodeViewModel junction) { PointF p; p = MapPointToWorldPoint(junction.Position, junction.Elev); return p; } #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; /// /// 判断是否在屏幕坐标内 /// /// /// 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; } /// /// 判断是否在屏幕坐标内 /// /// /// public bool isVisible(List list_MapPos) { bool visible = false; foreach (var MapPos in list_MapPos) { if (MapPos.X < PMin_Show.X || MapPos.X > PMax_Show.X || MapPos.Y < PMin_Show.Y || MapPos.Y > PMax_Show.Y) { } else { visible = true; return true; } } return visible; } #endregion } }