已删除4个文件
已重命名10个文件
已修改2个文件
已添加7个文件
ÎļþÃû´Ó Yw.WinFrmUI.Hydro.L3d.Core/03-helper/BoundingBox3.cs ÐÞ¸Ä |
| | |
| | | /// <summary> |
| | | /// |
| | | /// </summary> |
| | | public BoundingBox3() { } |
| | | |
| | | /// <summary> |
| | | /// |
| | | /// </summary> |
| | | public BoundingBox3(Vector3 min, Vector3 max) |
| | | { |
| | | this.Min = min; |
| | |
| | | public Vector3 Max { get; set; } |
| | | |
| | | /// <summary> |
| | | /// è·åä¸å¿ |
| | | /// ä¸å¿ç¹ |
| | | /// </summary> |
| | | public Vector3 GetCenter() |
| | | { |
| | | return new Vector3() |
| | | { |
| | | X = (this.Max.X + this.Min.X) / 2f, |
| | | Y = (this.Max.Y + this.Min.Y) / 2f, |
| | | Z = (this.Max.Z + this.Min.Z) / 2f |
| | | }; |
| | | } |
| | | public Vector3 Center => (Min + Max) / 2f; |
| | | |
| | | /// <summary> |
| | | /// è·åè§ |
| | | /// 尺寸 |
| | | /// </summary> |
| | | public List<Vector3> GetCorners() |
| | | public Vector3 Size => Max - Min; |
| | | |
| | | /// <summary> |
| | | /// æ¯å¦å
å« |
| | | /// </summary> |
| | | public bool Contains(Vector3 pt) |
| | | { |
| | | return new List<Vector3> |
| | | if (pt.X > this.Max.X || pt.X < this.Min.X) |
| | | { |
| | | new Vector3(this.Min.X, this.Min.Y, this.Min.Z), |
| | | new Vector3(this.Max.X, this.Min.Y, this.Min.Z), |
| | | new Vector3(this.Min.X, this.Max.Y, this.Min.Z), |
| | | new Vector3(this.Max.X, this.Max.Y, this.Min.Z), |
| | | new Vector3(this.Min.X, this.Min.Y, this.Max.Z), |
| | | new Vector3(this.Max.X, this.Min.Y, this.Max.Z), |
| | | new Vector3(this.Min.X, this.Max.Y, this.Max.Z), |
| | | new Vector3(this.Max.X, this.Max.Y, this.Max.Z) |
| | | }; |
| | | return false; |
| | | } |
| | | if (pt.Y > this.Max.Y || pt.Y < this.Min.Y) |
| | | { |
| | | return false; |
| | | } |
| | | if (pt.Z > this.Max.Z || pt.Z < this.Min.Z) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// è®¡ç® |
| | | /// </summary> |
| | | public static BoundingBox3 Calculate(List<Vector3> pts) |
| | | { |
| | | if (pts == null || pts.Count < 1) |
| | | { |
| | | return default; |
| | | } |
| | | return new BoundingBox3(pts); |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | ); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è®¡ç® |
| | | /// </summary> |
| | | public static BoundingBox3 Calculate(List<Vector3> pts) |
| | | { |
| | | if (pts == null || pts.Count < 1) |
| | | { |
| | | return default; |
| | | } |
| | | return new BoundingBox3(pts); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | namespace Yw.WinFrmUI.Hydro |
| | | { |
| | | /// <summary> |
| | | /// å
å´çç¼åè¾
å©ç±» |
| | | /// </summary> |
| | | internal class BoundingBox3CacheHelper |
| | | { |
| | | |
| | | /// <summary> |
| | | /// |
| | | /// </summary> |
| | | public BoundingBox3CacheHelper(NetworkL3d nw, Vector3CacheHelper vc) |
| | | { |
| | | _nw = nw; |
| | | _vc = vc; |
| | | Initial(); |
| | | } |
| | | |
| | | private NetworkL3d _nw = null; |
| | | private Vector3CacheHelper _vc = null; |
| | | private Dictionary<string, BoundingBox3> _dict = new(); |
| | | |
| | | /// <summary> |
| | | /// æ¯å¦åå§å |
| | | /// </summary> |
| | | public bool Initialized |
| | | { |
| | | get |
| | | { |
| | | if (_nw == null) |
| | | { |
| | | return false; |
| | | } |
| | | if (_vc == null) |
| | | { |
| | | return false; |
| | | } |
| | | if (_dict.Count < 1) |
| | | { |
| | | return false; |
| | | } |
| | | return true; |
| | | } |
| | | } |
| | | |
| | | //åå§å |
| | | private void Initial() |
| | | { |
| | | if (_nw == null) |
| | | { |
| | | return; |
| | | } |
| | | if (_vc == null) |
| | | { |
| | | return; |
| | | } |
| | | _dict.Clear(); |
| | | _nw.Nodes.ForEach(x => |
| | | { |
| | | var pts = _vc.GetById(x.Id); |
| | | if (pts != null && pts.Count > 0) |
| | | { |
| | | var bx = BoundingBox3Helper.CalcuPointBoundingBox(pts[0], x.Style2d.Normal.Radiu); |
| | | _dict.Add(x.Id, bx); |
| | | } |
| | | }); |
| | | _nw.Links.ForEach((Action<LinkL3d>)(x => |
| | | { |
| | | var pts = _vc.GetById(x.Id); |
| | | if (pts != null && pts.Count > 1) |
| | | { |
| | | var bx = BoundingBox3Helper.CalcuLineBoundingBox(pts[0], pts[1], x.Style2d.Normal.Width); |
| | | _dict.Add(x.Id, bx); |
| | | } |
| | | })); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// éè¿ Id è·å |
| | | /// </summary> |
| | | public BoundingBox3 GetById(string Id) |
| | | { |
| | | if (!Initialized) |
| | | { |
| | | return default; |
| | | } |
| | | if (_dict.ContainsKey(Id)) |
| | | { |
| | | return _dict[Id]; |
| | | } |
| | | return default; |
| | | } |
| | | |
| | | |
| | | } |
| | | } |
ÎļþÃû´Ó Yw.WinFrmUI.Hydro.L3d.Core/03-helper/Draw2dHelper.cs ÐÞ¸Ä |
| | |
| | | /// </summary> |
| | | internal class Draw2dHelper |
| | | { |
| | | /// <summary> |
| | | /// ç»å¶èç¹ |
| | | /// </summary> |
| | | public static void DrawNode(NodeL3d node) |
| | | { |
| | | var size = node.Style2d.Normal.Radiu * 2; |
| | | var color = node.Style2d.Normal.Color; |
| | | if (node.IsSelected) |
| | | { |
| | | size = node.Style2d.Selected.Radiu * 2; |
| | | color = node.Style2d.Selected.Color; |
| | | } |
| | | if (node.IsHovered) |
| | | { |
| | | size = node.Style2d.Hovered.Radiu * 2; |
| | | color = node.Style2d.Hovered.Color; |
| | | } |
| | | DrawPoint(size, color, node.Position); |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// ç»å¶ç¹ |
ÎļþÃû´Ó Yw.WinFrmUI.Hydro.L3d.Core/03-helper/Network2dExtensions.cs ÐÞ¸Ä |
| | |
| | | namespace Yw.WinFrmUI.Hydro |
| | | using OpenTK.Mathematics; |
| | | using System.Windows.Forms; |
| | | |
| | | namespace Yw.WinFrmUI.Hydro |
| | | { |
| | | /// <summary> |
| | | /// |
| | |
| | | /// <summary> |
| | | /// æ¬å2d |
| | | /// </summary> |
| | | public static void Hover2d(this NetworkL3d nw, Ray3 ray, BoundingBox32dCacheHelper bxcache) |
| | | public static void Hover2d(this NetworkL3d nw, Ray3 ray, float zoom, Vector3CacheHelper vecache) |
| | | { |
| | | nw.Visuals.ForEach(x => x.IsHovered = false); |
| | | var visual = ray.CastingClosest2(nw, bxcache); |
| | | var visual = ray.CastingClosest(zoom, nw, vecache); |
| | | if (visual != null) |
| | | { |
| | | visual.IsHovered = true; |
| | |
| | | /// <summary> |
| | | /// 鿩2d |
| | | /// </summary> |
| | | public static void Select2d(this NetworkL3d nw, Ray3 ray, BoundingBox32dCacheHelper bxcache) |
| | | public static void Select2d(this NetworkL3d nw, Ray3 ray, float zoom, Vector3CacheHelper vecache) |
| | | { |
| | | nw.Visuals.ForEach(x => x.IsSelected = false); |
| | | var visual = ray.CastingClosest2(nw, bxcache); |
| | | var visual = ray.CastingClosest(zoom, nw, vecache); |
| | | if (visual != null) |
| | | { |
| | | visual.IsSelected = true; |
ÎļþÃû´Ó Yw.WinFrmUI.Hydro.L3d.Core/03-helper/OrthoCamera2dHelper.cs ÐÞ¸Ä |
| | |
| | | { |
| | | _gl = gl; |
| | | _nw = nw; |
| | | _veccache = new Vector32dCacheHelper(nw); |
| | | var pts = _veccache.GetPositions(); |
| | | _veccache = new Vector3CacheHelper(nw); |
| | | var pts = _veccache.GetAll(); |
| | | _bx = new BoundingBox3(pts); |
| | | _bxcache = new BoundingBox32dCacheHelper(nw, _veccache); |
| | | _mc = (_bx.Max + _bx.Min) * 0.5f; |
| | | _radius = (_bx.Max - _bx.Min).Length / 2f; |
| | | UpdateModelMatrix(); |
| | |
| | | // åºç¡åæ° |
| | | private GLControl _gl = null;//glæ§ä»¶ |
| | | private NetworkL3d _nw = null;//ç®¡ç½æ¨¡å |
| | | private Vector32dCacheHelper _veccache = null;//ä½ç½®è¾
å©ç±» |
| | | private Vector3CacheHelper _veccache = null;//ä½ç½®è¾
å©ç±» |
| | | private BoundingBox3 _bx = null;//å
å´ç |
| | | private BoundingBox32dCacheHelper _bxcache = null;//å
å´çç¼å |
| | | private Vector3 _mc; //模åä¸å¿ |
| | | private float _radius = 100f;//å
å´çåå¾ |
| | | private float _pw = 10f;//æå½±å®½åº¦ |
| | |
| | | return; |
| | | } |
| | | this.Zoom *= e.Delta > 0 ? 0.9f : 1.1f; |
| | | UpdateModelMatrix(); |
| | | UpdateViewMatrix(); |
| | | UpdateProjectionMatrix(); |
| | | _gl.Invalidate(); |
| | |
| | | // æ´æ°åå
æ° |
| | | _rotation = rotationY * rotationX * _rotation; |
| | | _rotation = Quaternion.Normalize(_rotation); |
| | | UpdateModelMatrix(); |
| | | UpdateViewMatrix(); |
| | | UpdateProjectionMatrix(); |
| | | } |
| | | else if (_isDragging) |
| | | { |
| | |
| | | _translation.X += dx * xratio; |
| | | _translation.Y -= dy * yratio; |
| | | UpdateModelMatrix(); |
| | | UpdateViewMatrix(); |
| | | UpdateProjectionMatrix(); |
| | | } |
| | | else |
| | | //var depth = OrthoTransformHelper.GetScreenPointDepth(e.X, e.Y, _gl.Height); |
| | | //var pos = OrthoTransformHelper.ScreenToWorld(e.X, e.Y, depth, _viewMatrix * _modelMatrix, _projMatrix, _gl.Width, _gl.Height); |
| | | //_nw.Hover2d(pos, this.Zoom, _veccache); |
| | | //var ray = OrthoTransformHelper.CreateRay(e.X, e.Y, depth, _forward, _modelMatrix, _viewMatrix, _projMatrix, _gl.Width, _gl.Height); |
| | | var ray = OrthoTransformHelper.CreateRay2(e.X, e.Y, _modelMatrix, _viewMatrix, _projMatrix, _gl.Width, _gl.Height); |
| | | if (ray != null) |
| | | { |
| | | var depth = OrthoTransformHelper.GetScreenPointDepth(e.X, e.Y, _gl.Height); |
| | | var ray = OrthoTransformHelper.CreateRay(e.X, e.Y, depth, _forward, _modelMatrix, _viewMatrix, _projMatrix, _gl.Width, _gl.Height); |
| | | //var ray = OrthoTransformHelper.CreateRay2(e.X, e.Y, _modelMatrix, _viewMatrix, _projMatrix, _gl.Width, _gl.Height); |
| | | if (ray != null) |
| | | { |
| | | _nw.Hover2d(ray, _bxcache); |
| | | } |
| | | _nw.Hover2d(ray, this.Zoom, _veccache); |
| | | //_gl.Invalidate(); |
| | | } |
| | | |
| | | _lastMousePos = e.Location; |
| | | _gl.Invalidate(); |
| | | } |
| | | |
| | | public void HandleMouseHover() |
| | | { |
| | | if (!Initialized) |
| | | { |
| | | return; |
| | | } |
| | | //var depth = OrthoTransformHelper.GetScreenPointDepth(e.X, e.Y, _gl.Height); |
| | | //var pos = OrthoTransformHelper.ScreenToWorld(e.X, e.Y, depth, _viewMatrix * _modelMatrix, _projMatrix, _gl.Width, _gl.Height); |
| | | //_nw.Hover2d(pos, this.Zoom, _veccache); |
| | | //var ray = OrthoTransformHelper.CreateRay(e.X, e.Y, depth, _forward, _modelMatrix, _viewMatrix, _projMatrix, _gl.Width, _gl.Height); |
| | | //var ray = OrthoTransformHelper.CreateRay2(_lastMousePos.X, _lastMousePos.Y, _modelMatrix, _viewMatrix, _projMatrix, _gl.Width, _gl.Height); |
| | | //if (ray != null) |
| | | //{ |
| | | // _nw.Hover2d(ray, this.Zoom, _veccache); |
| | | // _gl.Invalidate(); |
| | | //} |
| | | } |
| | | |
| | | /// <summary> |
| | | /// å¤çé¼ æ ç¹å» |
| | | /// </summary> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | using OpenTK.Mathematics; |
| | | using System.Windows.Forms; |
| | | |
| | | namespace Yw.WinFrmUI.Hydro |
| | | { |
| | | /// <summary> |
| | | /// å°çº¿ |
| | | /// </summary> |
| | | internal class Ray3 |
| | | { |
| | | /// <summary> |
| | | /// |
| | | /// </summary> |
| | | public Ray3() { } |
| | | |
| | | /// <summary> |
| | | /// |
| | | /// </summary> |
| | | public Ray3(Vector3 origin, Vector3 direction) |
| | | { |
| | | Origin = origin; |
| | | Direction = direction.Normalized();//ç¡®ä¿å½ä¸å |
| | | } |
| | | |
| | | /// <summary> |
| | | /// åç¹ |
| | | /// </summary> |
| | | public Vector3 Origin { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æ¹å |
| | | /// </summary> |
| | | public Vector3 Direction { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æ£æµå°çº¿æ¯å¦ä¸ç¹ç¸äº¤ï¼åºäºå®¹å·®ï¼ |
| | | /// </summary> |
| | | /// <param name="point">ç®æ ç¹</param> |
| | | /// <param name="epsilon">容差éå¼ï¼ç¹ä¸å°çº¿çæå¤§å
许è·ç¦» é»è®¤ 0.01fï¼</param> |
| | | /// <param name="maxDistance">æå¤§ææè·ç¦»ï¼å°çº¿æ¹åä¸çèå´ é»è®¤ Float.MaxValueï¼</param> |
| | | /// <param name="distance">è¾åºç¸äº¤è·ç¦»</param> |
| | | /// <returns>æ¯å¦ç¸äº¤</returns> |
| | | public bool IntersectsPoint |
| | | ( |
| | | Vector3 point, |
| | | float epsilon, |
| | | float maxDistance, |
| | | out float distance |
| | | ) |
| | | { |
| | | // 计ç®ä»èµ·ç¹å°ç®æ ç¹çåé |
| | | Vector3 originToPoint = point - Origin; |
| | | |
| | | // 计ç®ç¹å¨å°çº¿æ¹åä¸çæå½±é¿åº¦ï¼åæ°tï¼ |
| | | float t = Vector3.Dot(originToPoint, Direction); |
| | | |
| | | // 妿tä¸ºè´æ°æè¶
è¿æå¤§è·ç¦»ï¼è¯´æç¹å¨å°çº¿åæ¹åæè¶
åºèå´ |
| | | if (t < 0 || t > maxDistance) |
| | | { |
| | | distance = float.NaN; |
| | | return false; |
| | | } |
| | | |
| | | // è®¡ç®æå½±ç¹ä½ç½® |
| | | Vector3 projectedPoint = Origin + Direction * t; |
| | | |
| | | // 计ç®å®é
ç¹ä¸æå½±ç¹çè·ç¦»ï¼æçè·ç¦»ï¼ |
| | | float pointDistance = Vector3.Distance(point, projectedPoint); |
| | | |
| | | // 夿æ¯å¦å¨å®¹å·®èå´å
|
| | | if (pointDistance <= epsilon) |
| | | { |
| | | distance = t; // è¿åå°çº¿èµ·ç¹å°æå½±ç¹çè·ç¦»ï¼è¥Directionæ¯åä½åéï¼tå³å®é
è·ç¦»ï¼ |
| | | return true; |
| | | } |
| | | |
| | | distance = float.NaN; |
| | | return false; |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// æ£æµå°çº¿æ¯å¦ä¸çº¿æ®µç¸äº¤ |
| | | /// </summary> |
| | | /// <param name="start">线段å¼å§ç¹</param> |
| | | /// <param name="end">çº¿æ®µç»æç¹</param> |
| | | /// <param name="epsilon">误差ï¼å
å«çº¿æ®µçåå¾ï¼</param> |
| | | /// <param name="maxDistance">å°çº¿æ¹åçæå¤§ææè·ç¦»</param> |
| | | /// <param name="distance">è¾åºå°çº¿èµ·ç¹å°äº¤ç¹çè·ç¦»</param> |
| | | /// <returns>æ¯å¦ç¸äº¤</returns> |
| | | public bool IntersectsLine |
| | | ( |
| | | Vector3 segStart, |
| | | Vector3 segEnd, |
| | | float epsilon, |
| | | float maxDistance, |
| | | out float distance |
| | | ) |
| | | { |
| | | distance = float.MaxValue; |
| | | Vector3 ab = segEnd - segStart; |
| | | Vector3 ao = Origin - segStart; |
| | | Vector3 n = Vector3.Cross(ab, Direction); |
| | | float denom = n.Length * n.Length; |
| | | |
| | | if (Math.Abs(denom) < 1e-8) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | Vector3 q = Vector3.Cross(ao, Direction); |
| | | float s = Vector3.Dot(q, n) / denom; |
| | | |
| | | if (s < 0 || s > 1) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | Vector3 closestPointOnSegment = segStart + Vector3.Multiply(ab, s); |
| | | Vector3 v = closestPointOnSegment - Origin; |
| | | float t = Vector3.Dot(v, Direction); |
| | | |
| | | if (t < 0) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | Vector3 intersectionPoint = Origin + Vector3.Multiply(Direction, t); |
| | | double distanceToSegment = (intersectionPoint - closestPointOnSegment).Length; |
| | | |
| | | if (distanceToSegment > epsilon) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | distance = t; |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | namespace Yw.WinFrmUI.Hydro |
| | | { |
| | | /// <summary> |
| | | /// å°çº¿ç¢°æ |
| | | /// </summary> |
| | | internal static class Ray32dCaster |
| | | { |
| | | |
| | | /// <summary> |
| | | /// æå° |
| | | /// </summary> |
| | | /// <param name="ray">å°çº¿</param> |
| | | /// <param name="zoom">缩æ¾</param> |
| | | /// <param name="visuals">å¯è§æä»¶å表</param> |
| | | /// <param name="vecache">ç¹ç¼å</param> |
| | | public static List<VisualL3d> Casting(this Ray3 ray, float zoom, List<VisualL3d> visuals, Vector3CacheHelper vecache) |
| | | { |
| | | if (ray == null) |
| | | { |
| | | return default; |
| | | } |
| | | if (visuals == null || visuals.Count < 1) |
| | | { |
| | | return default; |
| | | } |
| | | if (vecache == null) |
| | | { |
| | | return default; |
| | | } |
| | | var list = new List<VisualL3d>(); |
| | | foreach (var visual in visuals) |
| | | { |
| | | if (visual is NodeL3d node) |
| | | { |
| | | var vec = vecache.GetById(node.Id); |
| | | var epsilon = node.Style2d.Normal.Radiu * zoom; |
| | | if (ray.IntersectsPoint(vec[0], epsilon, float.MaxValue, out _)) |
| | | { |
| | | list.Add(visual); |
| | | } |
| | | } |
| | | else if (visual is LinkL3d link) |
| | | { |
| | | var vec = vecache.GetById(link.Id); |
| | | var epsilon = link.Style2d.Normal.Width / 2f * zoom; |
| | | if (ray.IntersectsLine(vec[0], vec[1], epsilon, float.MaxValue, out _)) |
| | | { |
| | | list.Add(visual); |
| | | } |
| | | } |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æå°æè¿èç¹ |
| | | /// </summary> |
| | | /// <param name="ray">å°çº¿</param> |
| | | /// <param name="zoom">缩æ¾</param> |
| | | /// <param name="nodes">èç¹</param> |
| | | /// <param name="vecache">ç¹ç¼å</param> |
| | | /// <returns></returns> |
| | | public static NodeL3d CastingClosest(this Ray3 ray, float zoom, List<NodeL3d> nodes, Vector3CacheHelper vecache) |
| | | { |
| | | if (ray == null) |
| | | { |
| | | return default; |
| | | } |
| | | if (nodes == null || nodes.Count < 1) |
| | | { |
| | | return default; |
| | | } |
| | | if (vecache == null) |
| | | { |
| | | return default; |
| | | } |
| | | NodeL3d closest = null; |
| | | float minDistance = float.MaxValue; |
| | | foreach (var node in nodes) |
| | | { |
| | | var vec = vecache.GetById(node.Id); |
| | | var epsilon = node.Style2d.Normal.Radiu * zoom; |
| | | if (ray.IntersectsPoint(vec[0], epsilon, float.MaxValue, out float distance)) |
| | | { |
| | | if (distance <= minDistance) |
| | | { |
| | | minDistance = distance; |
| | | closest = node; |
| | | } |
| | | } |
| | | } |
| | | return closest; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æå°æè¿ç®¡æ®µ |
| | | /// </summary> |
| | | /// <param name="ray">å°çº¿</param> |
| | | /// <param name="links">管段</param> |
| | | /// <param name="vecache">ç¹ç¼å</param> |
| | | /// <returns></returns> |
| | | public static LinkL3d CastingClosest(this Ray3 ray, float zoom, List<LinkL3d> links, Vector3CacheHelper vecache) |
| | | { |
| | | if (ray == null) |
| | | { |
| | | return default; |
| | | } |
| | | if (links == null || links.Count < 1) |
| | | { |
| | | return default; |
| | | } |
| | | if (vecache == null) |
| | | { |
| | | return default; |
| | | } |
| | | LinkL3d closest = null; |
| | | float minDistance = float.MaxValue; |
| | | foreach (var link in links) |
| | | { |
| | | var vec = vecache.GetById(link.Id); |
| | | var epsilon = link.Style2d.Normal.Width * zoom; |
| | | if (ray.IntersectsLine(vec[0], vec[1], epsilon, float.MaxValue, out float distance)) |
| | | { |
| | | if (distance <= minDistance) |
| | | { |
| | | minDistance = distance; |
| | | closest = link; |
| | | } |
| | | } |
| | | } |
| | | return closest; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æå°æè¿æä»¶ |
| | | /// </summary> |
| | | /// <param name="ray">å°çº¿</param> |
| | | /// <param name="nw">管ç½</param> |
| | | /// <param name="vecache">ç¹ç¼å</param> |
| | | /// <returns></returns> |
| | | public static VisualL3d CastingClosest(this Ray3 ray, float zoom, NetworkL3d nw, Vector3CacheHelper vecache) |
| | | { |
| | | VisualL3d visual = CastingClosest(ray, zoom, nw?.Nodes, vecache); |
| | | if (visual == null) |
| | | { |
| | | visual = CastingClosest(ray, zoom, nw?.Links, vecache); |
| | | } |
| | | return visual; |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | using OpenTK.Mathematics; |
| | | |
| | | namespace Yw.WinFrmUI.Hydro |
| | | { |
| | | /// <summary> |
| | | /// ä¸ç»´ç¹ç¼åè¾
å©ç±» |
| | | /// </summary> |
| | | internal class Vector3CacheHelper |
| | | { |
| | | /// <summary> |
| | | /// |
| | | /// </summary> |
| | | public Vector3CacheHelper(NetworkL3d nw) |
| | | { |
| | | _nw = nw; |
| | | Initial(); |
| | | } |
| | | |
| | | private NetworkL3d _nw = null; |
| | | private Dictionary<string, List<Vector3>> _dict = new(); |
| | | |
| | | /// <summary> |
| | | /// æ¯å¦åå§å |
| | | /// </summary> |
| | | public bool Initialized |
| | | { |
| | | get |
| | | { |
| | | if (_nw == null) |
| | | { |
| | | return false; |
| | | } |
| | | if (_dict.Count < 1) |
| | | { |
| | | return false; |
| | | } |
| | | return true; |
| | | } |
| | | } |
| | | |
| | | //åå§å |
| | | private void Initial() |
| | | { |
| | | if (_nw == null) |
| | | { |
| | | return; |
| | | } |
| | | foreach (var visual in _nw.Visuals) |
| | | { |
| | | var pts = visual.GetPositions(); |
| | | var vpts = pts.Select(x => new Vector3(x.X, x.Y, x.Z)).ToList(); |
| | | _dict.Add(visual.Id, vpts); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åææ |
| | | /// </summary> |
| | | /// <returns></returns> |
| | | public List<Vector3> GetAll() |
| | | { |
| | | if (!Initialized) |
| | | { |
| | | return default; |
| | | } |
| | | return _dict.SelectMany(x => x.Value).Distinct().ToList(); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// éè¿ Id è·å |
| | | /// </summary> |
| | | public List<Vector3> GetById(string Id) |
| | | { |
| | | if (string.IsNullOrEmpty(Id)) |
| | | { |
| | | return default; |
| | | } |
| | | if (_dict.ContainsKey(Id)) |
| | | { |
| | | return _dict[Id]; |
| | | } |
| | | return default; |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | } |
| | | } |
ÎļþÃû´Ó Yw.WinFrmUI.Hydro.L3d.Core/03-helper/ViewPort3.cs ÐÞ¸Ä |
| | |
| | | /// <summary> |
| | | /// x |
| | | /// </summary> |
| | | public float X { get; set; } |
| | | public int X { get; set; } |
| | | |
| | | /// <summary> |
| | | /// y |
| | | /// </summary> |
| | | public float Y { get; set; } |
| | | public int Y { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 宽度 |
| | | /// </summary> |
| | | public float Width { get; set; } |
| | | public int Width { get; set; } |
| | | |
| | | /// <summary> |
| | | /// é«åº¦ |
| | | /// </summary> |
| | | public float Height { get; set; } |
| | | public int Height { get; set; } |
| | | |
| | | |
| | | } |
ÎļþÃû´Ó Yw.WinFrmUI.Hydro.L3d.Core/04-control/OrthoDrawer2d.cs ÐÞ¸Ä |
| | |
| | | this.glControl1.MouseUp += OnMouseUp; |
| | | this.glControl1.MouseMove += OnMouseMove; |
| | | this.glControl1.MouseClick += OnMouseClick; |
| | | this.glControl1.MouseDoubleClick += GlControl1_MouseDoubleClick; |
| | | this.glControl1.MouseDoubleClick += OnMouseDoubleClick; |
| | | this.glControl1.MouseHover += GlControl1_MouseHover; |
| | | } |
| | | |
| | | |
| | | |
| | | private NetworkL3d _nw = null; |
| | | private OrthoCamera2dHelper _orthoHelper = null; |
| | |
| | | GL.ShadeModel(ShadingModel.Smooth); |
| | | GL.Enable(EnableCap.DepthTest);//深度æµè¯ |
| | | GL.DepthMask(true); // å
许åå
¥æ·±åº¦ç¼å²åº |
| | | GL.DepthMask(true); |
| | | GL.Enable(EnableCap.PointSmooth);//å¯ç¨ç¹å¹³æ» |
| | | GL.Enable(EnableCap.LineSmooth);//å¯ç¨çº¿å¹³æ» |
| | | |
| | | GL.DepthFunc(DepthFunction.Lequal); // é»è®¤å¼ï¼å¯å°è¯æ¹ä¸º LessEqual |
| | | _orthoHelper.HandleResize(); |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | //é¼ æ åå» |
| | | private void GlControl1_MouseDoubleClick(object sender, MouseEventArgs e) |
| | | private void OnMouseDoubleClick(object sender, MouseEventArgs e) |
| | | { |
| | | _orthoHelper.HandleMouseDoubleClick(e); |
| | | } |
| | | |
| | | //é¼ æ hover |
| | | private void GlControl1_MouseHover(object sender, EventArgs e) |
| | | { |
| | | _orthoHelper?.HandleMouseHover(); |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | <Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
| | | <PropertyGroup /> |
| | | <ItemGroup> |
| | | <Compile Update="04-control\OrthoDrawer2d.cs"> |
| | | <Compile Update="03-control\OrthoDrawer2d.cs"> |
| | | <SubType>UserControl</SubType> |
| | | </Compile> |
| | | </ItemGroup> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | namespace Yw.WinFrmUI |
| | | { |
| | | partial class TestForm |
| | | { |
| | | /// <summary> |
| | | /// Required designer variable. |
| | | /// </summary> |
| | | private System.ComponentModel.IContainer components = null; |
| | | |
| | | /// <summary> |
| | | /// Clean up any resources being used. |
| | | /// </summary> |
| | | /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> |
| | | protected override void Dispose(bool disposing) |
| | | { |
| | | if (disposing && (components != null)) |
| | | { |
| | | components.Dispose(); |
| | | } |
| | | base.Dispose(disposing); |
| | | } |
| | | |
| | | #region Windows Form Designer generated code |
| | | |
| | | /// <summary> |
| | | /// Required method for Designer support - do not modify |
| | | /// the contents of this method with the code editor. |
| | | /// </summary> |
| | | private void InitializeComponent() |
| | | { |
| | | toolStrip1 = new ToolStrip(); |
| | | glControl1 = new OpenTK.GLControl.GLControl(); |
| | | SuspendLayout(); |
| | | // |
| | | // toolStrip1 |
| | | // |
| | | toolStrip1.Location = new Point(0, 0); |
| | | toolStrip1.Name = "toolStrip1"; |
| | | toolStrip1.Size = new Size(800, 25); |
| | | toolStrip1.TabIndex = 0; |
| | | toolStrip1.Text = "toolStrip1"; |
| | | // |
| | | // glControl1 |
| | | // |
| | | glControl1.API = OpenTK.Windowing.Common.ContextAPI.OpenGL; |
| | | glControl1.APIVersion = new Version(3, 3, 0, 0); |
| | | glControl1.Dock = DockStyle.Fill; |
| | | glControl1.Flags = OpenTK.Windowing.Common.ContextFlags.Default; |
| | | glControl1.IsEventDriven = true; |
| | | glControl1.Location = new Point(0, 25); |
| | | glControl1.Name = "glControl1"; |
| | | glControl1.Profile = OpenTK.Windowing.Common.ContextProfile.Core; |
| | | glControl1.SharedContext = null; |
| | | glControl1.Size = new Size(800, 425); |
| | | glControl1.TabIndex = 1; |
| | | glControl1.Load += glControl1_Load; |
| | | glControl1.MouseClick += glControl1_MouseClick; |
| | | glControl1.MouseDoubleClick += glControl1_MouseDoubleClick; |
| | | glControl1.MouseDown += glControl1_MouseDown; |
| | | glControl1.MouseEnter += glControl1_MouseEnter; |
| | | glControl1.MouseLeave += glControl1_MouseLeave; |
| | | glControl1.MouseHover += glControl1_MouseHover; |
| | | glControl1.MouseMove += glControl1_MouseMove; |
| | | glControl1.MouseUp += glControl1_MouseUp; |
| | | glControl1.Resize += glControl1_Resize; |
| | | // |
| | | // TestForm |
| | | // |
| | | AutoScaleDimensions = new SizeF(7F, 17F); |
| | | AutoScaleMode = AutoScaleMode.Font; |
| | | ClientSize = new Size(800, 450); |
| | | Controls.Add(glControl1); |
| | | Controls.Add(toolStrip1); |
| | | Name = "TestForm"; |
| | | Text = "TestForm"; |
| | | ResumeLayout(false); |
| | | PerformLayout(); |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | private ToolStrip toolStrip1; |
| | | private OpenTK.GLControl.GLControl glControl1; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | using OpenTK.Mathematics; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.ComponentModel; |
| | | using System.Data; |
| | | using System.Drawing; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using System.Windows.Forms; |
| | | |
| | | |
| | | |
| | | namespace Yw.WinFrmUI |
| | | { |
| | | public partial class TestForm : Form |
| | | { |
| | | public TestForm() |
| | | { |
| | | InitializeComponent(); |
| | | this.Load += TestForm_Load; |
| | | } |
| | | |
| | | private void TestForm_Load(object sender, EventArgs e) |
| | | { |
| | | |
| | | } |
| | | |
| | | private void glControl1_MouseClick(object sender, MouseEventArgs e) |
| | | { |
| | | |
| | | } |
| | | |
| | | private void glControl1_MouseDoubleClick(object sender, MouseEventArgs e) |
| | | { |
| | | |
| | | } |
| | | |
| | | private void glControl1_MouseDown(object sender, MouseEventArgs e) |
| | | { |
| | | |
| | | } |
| | | |
| | | private void glControl1_MouseHover(object sender, EventArgs e) |
| | | { |
| | | |
| | | } |
| | | |
| | | private void glControl1_MouseEnter(object sender, EventArgs e) |
| | | { |
| | | |
| | | } |
| | | |
| | | private void glControl1_MouseLeave(object sender, EventArgs e) |
| | | { |
| | | |
| | | } |
| | | |
| | | private void glControl1_MouseMove(object sender, MouseEventArgs e) |
| | | { |
| | | |
| | | } |
| | | |
| | | private void glControl1_MouseUp(object sender, MouseEventArgs e) |
| | | { |
| | | |
| | | } |
| | | |
| | | private void glControl1_Load(object sender, EventArgs e) |
| | | { |
| | | |
| | | } |
| | | |
| | | private void glControl1_Resize(object sender, EventArgs e) |
| | | { |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <root> |
| | | <!-- |
| | | Microsoft ResX Schema |
| | | |
| | | Version 2.0 |
| | | |
| | | The primary goals of this format is to allow a simple XML format |
| | | that is mostly human readable. The generation and parsing of the |
| | | various data types are done through the TypeConverter classes |
| | | associated with the data types. |
| | | |
| | | Example: |
| | | |
| | | ... ado.net/XML headers & schema ... |
| | | <resheader name="resmimetype">text/microsoft-resx</resheader> |
| | | <resheader name="version">2.0</resheader> |
| | | <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> |
| | | <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> |
| | | <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> |
| | | <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> |
| | | <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> |
| | | <value>[base64 mime encoded serialized .NET Framework object]</value> |
| | | </data> |
| | | <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> |
| | | <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> |
| | | <comment>This is a comment</comment> |
| | | </data> |
| | | |
| | | There are any number of "resheader" rows that contain simple |
| | | name/value pairs. |
| | | |
| | | Each data row contains a name, and value. The row also contains a |
| | | type or mimetype. Type corresponds to a .NET class that support |
| | | text/value conversion through the TypeConverter architecture. |
| | | Classes that don't support this are serialized and stored with the |
| | | mimetype set. |
| | | |
| | | The mimetype is used for serialized objects, and tells the |
| | | ResXResourceReader how to depersist the object. This is currently not |
| | | extensible. For a given mimetype the value must be set accordingly: |
| | | |
| | | Note - application/x-microsoft.net.object.binary.base64 is the format |
| | | that the ResXResourceWriter will generate, however the reader can |
| | | read any of the formats listed below. |
| | | |
| | | mimetype: application/x-microsoft.net.object.binary.base64 |
| | | value : The object must be serialized with |
| | | : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter |
| | | : and then encoded with base64 encoding. |
| | | |
| | | mimetype: application/x-microsoft.net.object.soap.base64 |
| | | value : The object must be serialized with |
| | | : System.Runtime.Serialization.Formatters.Soap.SoapFormatter |
| | | : and then encoded with base64 encoding. |
| | | |
| | | mimetype: application/x-microsoft.net.object.bytearray.base64 |
| | | value : The object must be serialized into a byte array |
| | | : using a System.ComponentModel.TypeConverter |
| | | : and then encoded with base64 encoding. |
| | | --> |
| | | <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> |
| | | <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> |
| | | <xsd:element name="root" msdata:IsDataSet="true"> |
| | | <xsd:complexType> |
| | | <xsd:choice maxOccurs="unbounded"> |
| | | <xsd:element name="metadata"> |
| | | <xsd:complexType> |
| | | <xsd:sequence> |
| | | <xsd:element name="value" type="xsd:string" minOccurs="0" /> |
| | | </xsd:sequence> |
| | | <xsd:attribute name="name" use="required" type="xsd:string" /> |
| | | <xsd:attribute name="type" type="xsd:string" /> |
| | | <xsd:attribute name="mimetype" type="xsd:string" /> |
| | | <xsd:attribute ref="xml:space" /> |
| | | </xsd:complexType> |
| | | </xsd:element> |
| | | <xsd:element name="assembly"> |
| | | <xsd:complexType> |
| | | <xsd:attribute name="alias" type="xsd:string" /> |
| | | <xsd:attribute name="name" type="xsd:string" /> |
| | | </xsd:complexType> |
| | | </xsd:element> |
| | | <xsd:element name="data"> |
| | | <xsd:complexType> |
| | | <xsd:sequence> |
| | | <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> |
| | | <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> |
| | | </xsd:sequence> |
| | | <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> |
| | | <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> |
| | | <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> |
| | | <xsd:attribute ref="xml:space" /> |
| | | </xsd:complexType> |
| | | </xsd:element> |
| | | <xsd:element name="resheader"> |
| | | <xsd:complexType> |
| | | <xsd:sequence> |
| | | <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> |
| | | </xsd:sequence> |
| | | <xsd:attribute name="name" type="xsd:string" use="required" /> |
| | | </xsd:complexType> |
| | | </xsd:element> |
| | | </xsd:choice> |
| | | </xsd:complexType> |
| | | </xsd:element> |
| | | </xsd:schema> |
| | | <resheader name="resmimetype"> |
| | | <value>text/microsoft-resx</value> |
| | | </resheader> |
| | | <resheader name="version"> |
| | | <value>2.0</value> |
| | | </resheader> |
| | | <resheader name="reader"> |
| | | <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> |
| | | </resheader> |
| | | <resheader name="writer"> |
| | | <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> |
| | | </resheader> |
| | | <metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> |
| | | <value>17, 17</value> |
| | | </metadata> |
| | | </root> |
| | |
| | | <Compile Update="MainForm.cs"> |
| | | <SubType>Form</SubType> |
| | | </Compile> |
| | | <Compile Update="TestForm.cs"> |
| | | <SubType>Form</SubType> |
| | | </Compile> |
| | | </ItemGroup> |
| | | </Project> |