| | |
| | | public delegate void DrawDelegate(Graphics bufferG, Template template); |
| | | |
| | | public delegate void MouseDelegate(MouseEventArgs e); |
| | | |
| | | |
| | | partial class MapViewer |
| | | { |
| | | 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; |
| | | |
| | | 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); |
| | | |
| | | |
| | | //背景图绘制 |
| | | if (this.mapOption.isShowPic && template != null && File.Exists(template.BackGroundImg_FullPath)) |
| | | |
| | | |
| | | { |
| | | //var gs = bufferG.Save(); |
| | | // 应用矩阵变换以抵消之前的翻转效果 |
| | | //bufferG.ScaleTransform(1 / Zoom.X, 1 / Zoom.Y); |
| | | 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 Cps = new List<PointF> |
| | | //{ |
| | | // template.BackGroundPoint1, |
| | | // new PointF(template.BackGroundPoint2.X,template.BackGroundPoint1.Y), |
| | | // new PointF(template.BackGroundPoint1.X,template.BackGroundPoint2.Y), |
| | | // //template.BackGroundPoint2, |
| | | |
| | | |
| | | //}; |
| | | 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; |
| | | //p4.Y = -p4.Y; |
| | | var Cps = new List<PointF> |
| | | { |
| | | //template.BackGroundPoint1, |
| | | //new PointF(template.BackGroundImgX,template.BackGroundImgY), |
| | | p4, |
| | | p3,p1 |
| | | //template.BackGroundPoint2, |
| | | |
| | | |
| | | }; |
| | | template.BackGroundPoint1 = p4; |
| | | template.BackGroundPoint2 = new PointF(p3.X, p1.Y); |
| | | |
| | | |
| | | |
| | | //List<PointF> p = new List<PointF>(); |
| | | 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); |
| | | } |
| | | } |
| | | |
| | | void Draw(Graphics bufferG, Template template) |
| | | { |
| | | if (template == null) return; |
| | |
| | | |
| | | 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<PointF> |
| | | { |
| | | template.BackGroundPoint1, |
| | | new PointF(template.BackGroundPoint2.X,template.BackGroundPoint1.Y), |
| | | new PointF(template.BackGroundPoint1.X,template.BackGroundPoint2.Y), |
| | | //template.BackGroundPoint2, |
| | | |
| | | |
| | | }; |
| | | |
| | | |
| | | |
| | | List<PointF> p = new List<PointF>(); |
| | | 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); |
| | | } |
| | | |
| | | |
| | | |
| | | // 绘制线 |
| | |
| | | var p1 = WorldPointToMapPoint(link.StartNode, template.OffSet); |
| | | var p2 = WorldPointToMapPoint(link.EndNode, template.OffSet); |
| | | if (!isVisible(p1) && !isVisible(p2)) continue; |
| | | if (_LinkColour != null) |
| | | if (LinkColour != null) |
| | | { |
| | | pen0.Color = penClosed.Color = GraphHelper.getLinkColor(_LinkColour, link); |
| | | pen0.Color = penClosed.Color = GraphHelper.getLinkColor(LinkColour, link); |
| | | } |
| | | |
| | | Pen pen = pen0; |
| | |
| | | { |
| | | |
| | | if (link.StartNode == null || link.EndNode == null) continue; |
| | | try |
| | | { |
| | | bufferG.DrawLines(link.Selected ? penChoosed : pen, new PointF[] { p1, p2 }); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | |
| | | 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); |
| | |
| | | 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) |
| | | if (NodeColour != null) |
| | | { |
| | | pen.Color = penChoosed.Color = GraphHelper.getNodeColor(_NodeColour, node); |
| | | pen.Color = penChoosed.Color = GraphHelper.getNodeColor(NodeColour, node); |
| | | brush = pen.Brush; |
| | | brushChoosed = penChoosed.Brush; |
| | | |
| | |
| | | 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) |
| | | if (NodeColour != null) |
| | | { |
| | | pen.Color = GraphHelper.getNodeColor(_NodeColour, node); |
| | | pen.Color = GraphHelper.getNodeColor(NodeColour, node); |
| | | brush = pen.Brush; |
| | | brushChoosed = penChoosed.Brush; |
| | | |
| | |
| | | } |
| | | if (_isPainting) |
| | | { |
| | | if (_mouseState ==MapViewEnum.MouseState.新增立管) |
| | | 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)) |
| | |
| | | { |
| | | var wPos = GetZZWorldPoint(_select_junction1.Position3D, _MousePosition, new Vector3(1, 1, 0)); |
| | | //getPointAndHeight(e, _select_junction1, out p, out z); |
| | | var mapPos= WorldPointToMapPoint(wPos); |
| | | var mapPos = WorldPointToMapPoint(wPos); |
| | | bufferG.DrawLine(pen, WorldPointToMapPoint(_select_junction1), mapPos); |
| | | } |
| | | else |
| | | { |
| | | bufferG.DrawLine(pen, WorldPointToMapPoint(_select_junction1), _MousePosition); |
| | | } |
| | | |
| | | |
| | | } |
| | | } |
| | | } |
| | |
| | | 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) |
| | | { |
| | | |
| | |
| | | return new PointF(x, y); |
| | | } |
| | | /// <summary> |
| | | /// 获取地图投影坐标 |
| | | /// 获取世界投影坐标 |
| | | /// </summary> |
| | | /// <param name="point"></param> |
| | | /// <param name="z"></param> |
| | |
| | | private PointF3D GetZZWorldPoint(PointF3D position3D, PointF mousePosition, Vector3 vector3) |
| | | { |
| | | //做一条通过position3D的平行于vector3的直线, |
| | | if (vector3==new Vector3(0,0,1)) |
| | | if (vector3 == new Vector3(0, 0, 1)) |
| | | { |
| | | return GetLGWorldPoint(position3D, mousePosition); |
| | | } |
| | | else |
| | | { |
| | | var p2=MapPointToWorldPoint(mousePosition, position3D.Z); |
| | | var p2 = MapPointToWorldPoint(mousePosition, position3D.Z); |
| | | var vector = new Vector2(p2.X - position3D.X, p2.Y - position3D.Y); |
| | | //判断二维向量vector在第几象限,距离哪个轴最近 |
| | | var x = vector.X; |
| | |
| | | return new PointF3D(position3D.X - Math.Abs(x), position3D.Y, position3D.Z); |
| | | } |
| | | } |
| | | else |
| | | else |
| | | { |
| | | if (y > 0) |
| | | { |
| | |
| | | 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); |
| | | 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); |
| | | } |
| | | /// <summary> |
| | |
| | | /// <param name="point"></param> |
| | | /// <param name="z"></param> |
| | | /// <returns></returns> |
| | | private PointF MapPointToWorldPoint(PointF point, float z = 0) |
| | | public PointF MapPointToWorldPoint(PointF point, float z = 0) |
| | | { |
| | | var pointT = Get俯视角还原Point(point, z); |
| | | pointT = Get平面还原Point(pointT); |
| | |
| | | return dist; |
| | | } |
| | | //判断A距离线段B和C的距离,如果超出了线段的范围,则返回到最近的端点的距离;距离线段中心点越远,返回的距离越大; |
| | | private float Get_dist(PointF A, PointF B,PointF C,float MaxOff) |
| | | 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); |
| | | 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 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; |
| | | 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; |
| | | 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; |
| | | return Get_dist(A, new PointF(x, y)) + dist_add; |
| | | |
| | | } |
| | | private float GetDistanceFromPointAToMidpointOfLineSegmentBC(PointF A, PointF B, PointF C) |