| | |
| | | using Hydro.MapView; |
| | | using DevExpress.XtraPrinting.Native; |
| | | using Hydro.MapView; |
| | | using Hydro.MapView.Base; |
| | | using Hydro.MapView.Common; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Drawing; |
| | |
| | | public delegate void DrawDelegate(Graphics bufferG, Template template); |
| | | |
| | | public delegate void MouseDelegate(MouseEventArgs e); |
| | | |
| | | |
| | | partial class MapViewer |
| | | { |
| | | void Draw(Graphics bufferG, Template template) |
| | | 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; |
| | | var _Nodes = template.network.Nodes.ViewNodes; |
| | | var _Links = template.network.Links.ViewLinks; |
| | | var _Areas = template.network.Areas; |
| | | var Cpoints = getCurclePoints(64).ToList(); |
| | | |
| | | var r = 1.73f / zoom; |
| | |
| | | |
| | | 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)) |
| | | |
| | | |
| | | |
| | | //绘制面 |
| | | using (Pen pen0 = new Pen(Color.FromArgb(0, 0, 255), 2 * r)) |
| | | { |
| | | //var gs = bufferG.Save(); |
| | | // 应用矩阵变换以抵消之前的翻转效果 |
| | | //bufferG.ScaleTransform(1 / Zoom.X, 1 / Zoom.Y); |
| | | |
| | | |
| | | |
| | | // 恢复之前保存的绘图状态 |
| | | |
| | | var Cps = new List<PointF> |
| | | foreach (var area in _Areas) |
| | | { |
| | | template.BackGroundPoint1, |
| | | new PointF(template.BackGroundPoint2.X,template.BackGroundPoint1.Y), |
| | | new PointF(template.BackGroundPoint1.X,template.BackGroundPoint2.Y), |
| | | //template.BackGroundPoint2, |
| | | |
| | | |
| | | }; |
| | | |
| | | if (!area.Visible) continue; |
| | | if (!IsFaceVisibleToCamera(area, GetCameraPosition())) continue; |
| | | if (area.Elev < minElve || area.Elev >= maxElve) continue; |
| | | |
| | | |
| | | 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) |
| | | var p = new List<PointF>(); |
| | | foreach (var node in area.InnerNodes) |
| | | { |
| | | bufferG.FillPolygon(penN.Brush, p.ToArray()); |
| | | bufferG.DrawImage(img, p.ToArray()); |
| | | p.Add(CubeWorldPointToMapPoint(node, template.OffSet)); |
| | | } |
| | | } |
| | | catch |
| | | { |
| | | if (p.Count < 3) continue; |
| | | pen0.Color = penClosed.Color = area.color; |
| | | Pen pen = pen0; |
| | | if (area.Hovered) pen = penHovered; |
| | | bufferG.FillPolygon(pen.Brush, p.ToArray()); |
| | | bufferG.DrawPolygon(pen, p.ToArray()); |
| | | //显示area的名称 |
| | | var c = new PointF(p.Average(p0 => p0.X), p.Average(p0 => p0.Y)); |
| | | var brush=new SolidBrush(Color.White); |
| | | |
| | | |
| | | } |
| | | |
| | | //bufferG.Restore(gs); |
| | | |
| | | var gs = bufferG.Save(); |
| | | // 应用矩阵变换以抵消之前的翻转效果 |
| | | bufferG.ScaleTransform(1 / Zoom.X, 1 / Zoom.Y); |
| | | |
| | | Font font = new Font(FontFamily.GenericSansSerif, 10*10*zoom); |
| | | |
| | | SizeF textSize = bufferG.MeasureString(area.Name, font); |
| | | var center = new PointF(c.X * Zoom.X, c.Y * Zoom.Y); |
| | | float textLeft = center.X - textSize.Width / 2; |
| | | float textTop = center.Y - textSize.Height / 2; |
| | | PointF pd = new PointF(textLeft, textTop); |
| | | |
| | | bufferG.DrawString(area.Name, font, brush, pd); |
| | | // 恢复之前保存的绘图状态 |
| | | bufferG.Restore(gs); |
| | | } |
| | | } |
| | | |
| | | |
| | |
| | | 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)) |
| | |
| | | } |
| | | 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 (mapOption.IsOrtho) |
| | | { |
| | | var wPos = GetZZWorldPoint(_select_junction1.Position3D, _MousePosition, new Vector3(1, 1, 0)); |
| | | //getPointAndHeight(e, _select_junction1, out p, out z); |
| | | 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) |
| | | { |
| | | |
| | |
| | | |
| | | |
| | | // 根据旋转角度计算旋转后的坐标 |
| | | private PointF Get平面旋转Point(PointF p) |
| | | private PointF Get平面旋转Point(PointF p, PointF MapC) |
| | | { |
| | | PointF center = MapCenter; |
| | | |
| | | PointF center = MapC ; |
| | | double radian = Rotation * Math.PI / 180; // 角度转弧度 |
| | | float x = (float)(Math.Cos(radian) * (p.X - center.X) - Math.Sin(radian) * (p.Y - center.Y) + center.X); |
| | | float y = (float)(Math.Sin(radian) * (p.X - center.X) + Math.Cos(radian) * (p.Y - center.Y) + center.Y); |
| | | return new PointF(x, y); |
| | | } |
| | | private PointF Get平面还原Point(PointF p) |
| | | private PointF Get平面还原Point(PointF p, PointF MapC) |
| | | { |
| | | PointF center = MapCenter; |
| | | PointF center = MapC; |
| | | double radian = -Rotation * Math.PI / 180; // 角度转弧度 |
| | | float x = (float)(Math.Cos(radian) * (p.X - center.X) - Math.Sin(radian) * (p.Y - center.Y) + center.X); |
| | | float y = (float)(Math.Sin(radian) * (p.X - center.X) + Math.Cos(radian) * (p.Y - center.Y) + center.Y); |
| | |
| | | |
| | | |
| | | |
| | | private PointF Get俯视角旋转Point(PointF p, float z) |
| | | private PointF Get俯视角旋转Point(PointF p, float z, PointF MapC) |
| | | { |
| | | PointF center = MapCenter; |
| | | PointF center = MapC; |
| | | double radian_fushi = 俯视弧度; |
| | | float sin = (float)Math.Sin(radian_fushi); |
| | | float cos = (float)Math.Cos(radian_fushi); |
| | |
| | | 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) |
| | | private PointF Get俯视角还原Point(PointF p, float z, PointF MapC) |
| | | { |
| | | PointF center = MapCenter; |
| | | PointF center = MapC; |
| | | double radian_fushi = 俯视弧度; |
| | | float sin = (float)Math.Sin(radian_fushi); |
| | | float cos = (float)Math.Cos(radian_fushi); |
| | |
| | | return new PointF(x, y); |
| | | } |
| | | /// <summary> |
| | | /// 获取地图投影坐标 |
| | | /// 获取世界投影坐标 |
| | | /// </summary> |
| | | /// <param name="point"></param> |
| | | /// <param name="z"></param> |
| | |
| | | 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 pointR = Get平面旋转Point(point, MapCenter); |
| | | |
| | | var pointT = Get俯视角旋转Point(pointR, z + offset.Z); |
| | | var pointT = Get俯视角旋转Point(pointR, z + offset.Z, MapCenter); |
| | | |
| | | //var n=new PointF((float)pointR.X - Z(z).X, (float)(pointR.Y - Z(z).Y)); |
| | | return pointT; |
| | |
| | | if (junction == null) return new PointF(0, 0); |
| | | p = WorldPointToMapPoint(junction.Position, junction.Elev, offset); |
| | | return p; |
| | | |
| | | } |
| | | private PointF CubeWorldPointToMapPoint(NodeViewModel junction, PointF3D offset = null) |
| | | { |
| | | PointF p; |
| | | if (junction == null) return new PointF(0, 0); |
| | | var point = junction.Position; |
| | | var z = junction.Elev; |
| | | if (offset == null) offset = new PointF3D(0, 0, 0); |
| | | point = new PointF(point.X + offset.X, point.Y + offset.Y); |
| | | var pointR = Get平面旋转Point(point, new PointF(0, 0)); |
| | | var pointT = Get俯视角旋转Point(pointR, z + offset.Z, new PointF(0, 0)); |
| | | //var n=new PointF((float)pointR.X - Z(z).X, (float)(pointR.Y - Z(z).Y)); |
| | | return pointT; |
| | | } |
| | | private List<PointF> WorldPointToMapPoint(LinkViewModel pipe, PointF3D offset = null) |
| | | { |
| | |
| | | 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 |
| | | { |
| | | return new PointF3D(0, 0, 0); |
| | | var p2 = MapPointToWorldPoint(mousePosition, position3D.Z); |
| | | var vector = new Vector2(p2.X - position3D.X, p2.Y - position3D.Y); |
| | | //判断二维向量vector在第几象限,距离哪个轴最近 |
| | | var x = vector.X; |
| | | var y = vector.Y; |
| | | var x1 = Math.Abs(x); |
| | | var y1 = Math.Abs(y); |
| | | if (x1 > y1) |
| | | { |
| | | if (x > 0) |
| | | { |
| | | //第一象限 |
| | | return new PointF3D(position3D.X + Math.Abs(x), position3D.Y, position3D.Z); |
| | | } |
| | | else |
| | | { |
| | | //第三象限 |
| | | return new PointF3D(position3D.X - Math.Abs(x), position3D.Y, position3D.Z); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | if (y > 0) |
| | | { |
| | | //第二象限 |
| | | return new PointF3D(position3D.X, position3D.Y + Math.Abs(y), position3D.Z); |
| | | } |
| | | else |
| | | { |
| | | //第四象限 |
| | | return new PointF3D(position3D.X, position3D.Y - Math.Abs(y), position3D.Z); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | 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); |
| | | var pointT = Get俯视角还原Point(point, z,MapCenter); |
| | | pointT = Get平面还原Point(pointT, MapCenter); |
| | | |
| | | //var n=new PointF((float)pointR.X - Z(z).X, (float)(pointR.Y - Z(z).Y)); |
| | | return pointT; |
| | |
| | | |
| | | |
| | | #endregion |
| | | #region 计算三维相机 |
| | | public PointF3D GetCameraPosition( float distance=1) |
| | | { |
| | | // 将角度转换为弧度 |
| | | float rotationRadians = (float)Rotation * (float)Math.PI / 180; |
| | | float rotationFRadians = (float)RotationF * (float)Math.PI / 180; |
| | | |
| | | // 计算相机的球坐标系位置 |
| | | float x = distance * (float)Math.Sin(rotationFRadians) * (float)Math.Cos(rotationRadians); |
| | | float y = distance * (float)Math.Sin(rotationFRadians) * (float)Math.Sin(rotationRadians); |
| | | float z = distance * (float)Math.Cos(rotationFRadians); |
| | | |
| | | return new PointF3D(x, y, z); |
| | | } |
| | | public bool IsFaceVisibleToCamera(AreaViewModel area, PointF3D cameraPosition) |
| | | { |
| | | |
| | | //正面是2,右面是1,左面是3,背面是4 |
| | | //Rotation为0时,只显示正面,Rotation为90时,只显示右面,Rotation为180时,只显示背面,Rotation为270时,只显示左面 |
| | | int delta = 5; |
| | | bool flag = false; |
| | | switch (area.Name) |
| | | { |
| | | case "左": |
| | | //Rotation为0~180时显示 |
| | | if (RotationF<=90-delta && Rotation >= 0 + delta && Rotation <= 180 - delta) |
| | | flag = true; |
| | | break; |
| | | case "前": |
| | | //Rotation为0~180时显示 |
| | | if (RotationF <= 90 - delta && Rotation >= -90 + delta && Rotation <= 90 - delta) |
| | | flag = true; |
| | | break; |
| | | case "右": |
| | | //Rotation为0~180时显示 |
| | | if (RotationF <= 90 - delta && Rotation >= -180 + delta && Rotation <= 0 - delta) |
| | | flag = true; |
| | | break; |
| | | case "后": |
| | | //Rotation为0~180时显示 |
| | | if (RotationF <= 90 - delta && ((Rotation >= 90 + delta && Rotation<=180)||( Rotation>=-180 && Rotation <= -90 - delta))) |
| | | flag = true; |
| | | break; |
| | | case "上": |
| | | if (RotationF >= 0 + delta) |
| | | flag = true; |
| | | break; |
| | | case "下": |
| | | if (RotationF <= 0 - delta) |
| | | flag = true; |
| | | break; |
| | | } |
| | | return flag; |
| | | |
| | | var faceVertices = area.InnerNodes; |
| | | if (faceVertices.Count < 3) return false; |
| | | PointF3D faceVertexA = faceVertices[0].Position3D; |
| | | PointF3D faceVertexB = faceVertices[1].Position3D; |
| | | PointF3D faceVertexC = faceVertices[2].Position3D; |
| | | |
| | | // 计算法向量 |
| | | PointF3D AB = faceVertexB - faceVertexA; |
| | | PointF3D AC = faceVertexC - faceVertexA; |
| | | PointF3D normal = AB ^ AC; |
| | | |
| | | // 计算从相机位置到面的向量 |
| | | PointF3D PD = faceVertexA - cameraPosition; |
| | | |
| | | // 计算点积 |
| | | float dotProduct = normal * PD; |
| | | |
| | | // 判断面是否朝向相机 |
| | | bool isFacingCamera = dotProduct > 0; |
| | | return isFacingCamera; |
| | | } |
| | | |
| | | |
| | | #endregion |
| | | |
| | | #region 判断可见性 |
| | | private float Get_dist(PointF A, PointF B) |
| | |
| | | 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) |