duheng
2024-09-25 12a6316ffa897b4ce4205f545b88359195b386d6
Merge branch 'master' of http://47.103.154.90:83/r/HStation/XHS.V1.0
已删除3个文件
已修改25个文件
2394 ■■■■■ 文件已修改
WinFrmUI/HStation.WinFrmUI.Xhs.Core/04-simulation/06-simulation/XhsProjectSimulationCorePage.Designer.cs 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/HStation.WinFrmUI.Xhs.Core/04-simulation/07-l3d/XhsProjectSimulationL3dCtrl.Designer.cs 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/HStation.WinFrmUI.Xhs.Core/04-simulation/07-l3d/XhsProjectSimulationL3dCtrl.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/00-core/BoundingBox3d.cs 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/00-core/CacheHelper.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/00-core/NetworkParas.cs 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/00-core/Point3d.cs 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/01-network/00-core/Network_Method.cs 205 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/01-network/01-parter/Parter.cs 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/01-network/02-node/Junction.cs 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/01-network/02-node/Reservoir.cs 151 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/01-network/02-node/Tank.cs 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/01-network/04-link/Pipe.cs 144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/01-network/04-link/Pump.cs 139 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/01-network/04-link/Valve.cs 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/02-panel/NetworkPanel.Designer.cs 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/02-panel/NetworkPanel.cs 408 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/02-panel/NetworkPanelDebug.Designer.cs 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/02-panel/NetworkPanelDebug.cs 240 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/02-panel/NetworkPanelDebug.resx 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/03-settings/01-paras/00-core/Paras_HydroL3d_Size.cs 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/03-settings/01-paras/02-reservoir/Paras_HydroL3d_Reservoir.cs 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/03-settings/01-paras/03-tank/Paras_HydroL3d_Tank.cs 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/03-settings/01-paras/05-pump/Paras_HydroL3d_Pump.cs 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/03-settings/01-paras/06-valve/Paras_HydroL3d_Valve.cs 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/GlobalUsings.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/Yw.WinFrmUI.Hydro.L3d.Core.csproj.user 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/paras_hydro_l3d_settings.json 109 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WinFrmUI/HStation.WinFrmUI.Xhs.Core/04-simulation/06-simulation/XhsProjectSimulationCorePage.Designer.cs
@@ -56,7 +56,6 @@
            pageQ3d = new DevExpress.XtraBars.Navigation.TabNavigationPage();
            xhsProjectSimulationQ3dCtrl1 = new XhsProjectSimulationQ3dCtrl();
            tabPageL3d = new DevExpress.XtraBars.Navigation.TabNavigationPage();
            xhsProjectSimulationL3dCtrl1 = new XhsProjectSimulationL3dCtrl();
            dockManager1 = new DevExpress.XtraBars.Docking.DockManager(components);
            docPnlProperty = new DevExpress.XtraBars.Docking.DockPanel();
            dockPanel1_Container = new DevExpress.XtraBars.Docking.ControlContainer();
@@ -77,6 +76,7 @@
            controlContainer4 = new DevExpress.XtraBars.Docking.ControlContainer();
            xhsProjectSimulationUnMatchingListCtrl1 = new XhsProjectSimulationUnMatchingListCtrl();
            svgImg32 = new DevExpress.Utils.SvgImageCollection(components);
            xhsProjectSimulationL3dCtrl1 = new XhsProjectSimulationL3dCtrl();
            ((ISupportInitialize)ribbonControl1).BeginInit();
            ((ISupportInitialize)tabPane1).BeginInit();
            tabPane1.SuspendLayout();
@@ -310,15 +310,7 @@
            tabPageL3d.Caption = "L3d";
            tabPageL3d.Controls.Add(xhsProjectSimulationL3dCtrl1);
            tabPageL3d.Name = "tabPageL3d";
            tabPageL3d.Size = new Size(886, 195);
            //
            // xhsProjectSimulationL3dCtrl1
            //
            xhsProjectSimulationL3dCtrl1.Dock = DockStyle.Fill;
            xhsProjectSimulationL3dCtrl1.Location = new Point(0, 0);
            xhsProjectSimulationL3dCtrl1.Name = "xhsProjectSimulationL3dCtrl1";
            xhsProjectSimulationL3dCtrl1.Size = new Size(886, 195);
            xhsProjectSimulationL3dCtrl1.TabIndex = 0;
            tabPageL3d.Size = new Size(886, 185);
            // 
            // dockManager1
            // 
@@ -505,6 +497,14 @@
            svgImg32.ImageSize = new Size(32, 32);
            svgImg32.Add("calculatesheet", "image://svgimages/spreadsheet/calculatesheet.svg");
            // 
            // xhsProjectSimulationL3dCtrl1
            //
            xhsProjectSimulationL3dCtrl1.Dock = DockStyle.Fill;
            xhsProjectSimulationL3dCtrl1.Location = new Point(0, 0);
            xhsProjectSimulationL3dCtrl1.Name = "xhsProjectSimulationL3dCtrl1";
            xhsProjectSimulationL3dCtrl1.Size = new Size(886, 185);
            xhsProjectSimulationL3dCtrl1.TabIndex = 0;
            //
            // XhsProjectSimulationCorePage
            // 
            Appearance.BackColor = SystemColors.Control;
@@ -589,11 +589,11 @@
        private DevExpress.XtraBars.Docking.ControlContainer controlContainer4;
        private DevExpress.XtraBars.BarButtonItem barBtnUnMatchingList;
        private DevExpress.XtraBars.Navigation.TabNavigationPage tabPageL3d;
        private XhsProjectSimulationL3dCtrl xhsProjectSimulationL3dCtrl1;
        private DevExpress.XtraBars.Docking.DockPanel docPnlMatchingList;
        private DevExpress.XtraBars.Docking.ControlContainer controlContainer5;
        private Xhs.AssetsMainChoicePage assetsMainChoicePage1;
        private XhsProjectSimulationUnMatchingListCtrl xhsProjectSimulationUnMatchingListCtrl1;
        private DevExpress.XtraBars.BarButtonItem barBtnOpenView;
        private XhsProjectSimulationL3dCtrl xhsProjectSimulationL3dCtrl1;
    }
}
WinFrmUI/HStation.WinFrmUI.Xhs.Core/04-simulation/07-l3d/XhsProjectSimulationL3dCtrl.Designer.cs
@@ -28,22 +28,22 @@
        /// </summary>
        private void InitializeComponent()
        {
            networkPanelDebug1 = new Yw.WinFrmUI.HydroL3d.NetworkPanelDebug();
            networkPanel1 = new Yw.WinFrmUI.HydroL3d.NetworkPanel();
            SuspendLayout();
            // 
            // networkPanelDebug1
            // networkPanel1
            // 
            networkPanelDebug1.Dock = DockStyle.Fill;
            networkPanelDebug1.Location = new Point(0, 0);
            networkPanelDebug1.Name = "networkPanelDebug1";
            networkPanelDebug1.Size = new Size(889, 597);
            networkPanelDebug1.TabIndex = 0;
            networkPanel1.Dock = DockStyle.Fill;
            networkPanel1.Location = new Point(0, 0);
            networkPanel1.Name = "networkPanel1";
            networkPanel1.Size = new Size(889, 597);
            networkPanel1.TabIndex = 0;
            // 
            // XhsProjectSimulationL3dCtrl
            // 
            AutoScaleDimensions = new SizeF(7F, 14F);
            AutoScaleMode = AutoScaleMode.Font;
            Controls.Add(networkPanelDebug1);
            Controls.Add(networkPanel1);
            Name = "XhsProjectSimulationL3dCtrl";
            Size = new Size(889, 597);
            ResumeLayout(false);
@@ -51,6 +51,6 @@
        #endregion
        private Yw.WinFrmUI.HydroL3d.NetworkPanelDebug networkPanelDebug1;
        private Yw.WinFrmUI.HydroL3d.NetworkPanel networkPanel1;
    }
}
WinFrmUI/HStation.WinFrmUI.Xhs.Core/04-simulation/07-l3d/XhsProjectSimulationL3dCtrl.cs
@@ -20,7 +20,7 @@
                return;
            }
            var netWork = Yw.WinFrmUI.HydroL3dTransferHelper.ToL3dNetworkViewModel(rhs);
            this.networkPanelDebug1.Initial(netWork);
            this.networkPanel1.Initial(netWork);
        }
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/00-core/BoundingBox3d.cs
@@ -1,7 +1,4 @@
using DevExpress.CodeParser;
using DevExpress.Mvvm.POCO;
namespace Yw.WinFrmUI.HydroL3d
namespace Yw.WinFrmUI.HydroL3d
{
    /// <summary>
    /// 
@@ -44,12 +41,32 @@
        {
            return new Point3d()
            {
                X = (this.Min.X + this.Max.X) / 2f,
                Y = (this.Min.Y + this.Max.Y) / 2f,
                Z = (this.Min.Z + this.Max.Z) / 2f
                X = (this.Max.X + this.Min.X) / 2f,
                Y = (this.Max.Y + this.Min.Y) / 2f,
                Z = (this.Max.Z + this.Min.Z) / 2f
            };
        }
        /// <summary>
        /// æ˜¯å¦åŒ…含
        /// </summary>
        public bool Contains(Point3d pt)
        {
            if (pt.X > this.Max.X || pt.X < this.Min.X)
            {
                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;
        }
    }
}
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/00-core/CacheHelper.cs
@@ -24,6 +24,5 @@
    }
}
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/00-core/NetworkParas.cs
@@ -28,6 +28,12 @@
        /// </summary>
        public Point3d Translation { get; set; }
        /// <summary>
        /// ç¼©æ”¾
        /// </summary>
        public Point3d Scale { get; set; }
        /// <summary>
        /// 
        /// </summary>
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/00-core/Point3d.cs
@@ -102,5 +102,64 @@
            return MathF.Sqrt(MathF.Pow(this.X - other.X, 2) + MathF.Pow(this.Y - other.Y, 2) + MathF.Pow(this.Z - other.Z, 2));
        }
        /// <summary>
        ///
        /// </summary>
        public float LengthSquared()
        {
            return X * X + Y * Y + Z * Z;
        }
        /// <summary>
        ///
        /// </summary>
        public float Length()
        {
            return (float)Math.Sqrt(LengthSquared());
        }
        /// <summary>
        ///
        /// </summary>
        public void Normalize()
        {
            float length = Length();
            if (length > 0)
            {
                X /= length;
                Y /= length;
                Z /= length;
            }
        }
        /// <summary>
        /// - è¿ç®—
        /// </summary>
        public static Point3d operator -(Point3d a, Point3d b)
        {
            return new Point3d(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
        }
        /// <summary>
        ///
        /// </summary>
        public static float DotProduct(Point3d a, Point3d b)
        {
            return a.X * b.X + a.Y * b.Y + a.Z * b.Z;
        }
        /// <summary>
        ///
        /// </summary>
        public static Point3d CrossProduct(Point3d a, Point3d b)
        {
            return new Point3d(
                a.Y * b.Z - a.Z * b.Y,
                a.Z * b.X - a.X * b.Z,
                a.X * b.Y - a.Y * b.X);
        }
    }
}
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/01-network/00-core/Network_Method.cs
@@ -1,4 +1,7 @@
namespace Yw.WinFrmUI.HydroL3d
using DevExpress.XtraCharts.Native;
using DevExpress.XtraDiagram.Bars;
namespace Yw.WinFrmUI.HydroL3d
{
    /// <summary>
    /// 
@@ -56,49 +59,23 @@
        }
        /// <summary>
        /// èŽ·å–è§‚å¯Ÿä¿¡æ¯
        /// èŽ·å–è½¬æ¢
        /// </summary>
        public LookAt3d GetLookAt()
        public Point3d GetTranslation(BoundingBox3d boundingBox, Point3d center)
        {
            return new LookAt3d()
            if (boundingBox == null)
            {
                Eye = new Point3d(0, 0, 0),
                Center = new Point3d(0, 0, 0),
                Up = new Point3d(0, 1, 0)
            };
        }
        /// <summary>
        /// èŽ·å–é€è§†ä¿¡æ¯
        /// </summary>
        public Perspective3d GetPerspective(LookAt3d lookAt, SharpGL.OpenGLControl openglControl = null)
        {
            if (lookAt == null)
            {
                lookAt = GetLookAt();
                boundingBox = GetBoundingBox();
            }
            var minDistance = float.MaxValue;
            var maxDistance = float.MinValue;
            foreach (var node in this.Nodes)
            if (center == null)
            {
                var distance = lookAt.Eye.Distance(node.Position);
                minDistance = MathF.Min(minDistance, distance);
                maxDistance = MathF.Max(maxDistance, distance);
                center = GetCenter(boundingBox);
            }
            var bufferFactor = 1.2f;
            var aspect = 1.25f;
            if (openglControl != null)
            return new Point3d()
            {
                aspect = (float)openglControl.Width / (float)openglControl.Height;
            }
            var near = minDistance * bufferFactor;
            var far = maxDistance * bufferFactor;
            return new Perspective3d()
            {
                Fovy = 45f,
                Aspect = aspect,
                Near = near,
                Far = far
                X = -center.X,
                Y = -center.Y,
                Z = -boundingBox.Max.Z * 3f
            };
        }
@@ -112,26 +89,77 @@
        }
        /// <summary>
        /// èŽ·å–è½¬æ¢
        /// ç¼©æ”¾
        /// </summary>
        public Point3d GetTranslation(BoundingBox3d boudingBox, Point3d center)
        public Point3d GetScale()
        {
            if (boudingBox == null)
            return new Point3d() { X = 1f, Y = 1f, Z = 1f };
        }
        /// <summary>
        /// èŽ·å–è§‚å¯Ÿä¿¡æ¯
        /// </summary>
        public LookAt3d GetLookAt(BoundingBox3d boundingBox, Point3d center)
        {
            if (boundingBox == null)
            {
                boudingBox = GetBoundingBox();
                boundingBox = GetBoundingBox();
            }
            if (center == null)
            {
                center = GetCenter(boudingBox);
                center = boundingBox.GetCenter();
            }
            var zBufferFactor = 3f;
            return new Point3d()
            return new LookAt3d()
            {
                X = -center.X,
                Y = -center.Y,
                Z = -boudingBox.Max.Z * zBufferFactor
                Eye = new Point3d(center.X, center.Y, center.Z),
                Center = new Point3d(center.X, center.Y, center.Z),
                Up = new Point3d(0, 1, 0)
            };
        }
        /// <summary>
        /// èŽ·å–é€è§†ä¿¡æ¯
        /// </summary>
        public Perspective3d GetPerspective(BoundingBox3d boundingBox, Point3d center, LookAt3d lookAt, SharpGL.OpenGLControl openglControl = null)
        {
            if (boundingBox == null)
            {
                boundingBox = GetBoundingBox();
            }
            if (center == null)
            {
                center = boundingBox.GetCenter();
            }
            if (lookAt == null)
            {
                lookAt = GetLookAt(boundingBox, center);
            }
            var minDistance = float.MaxValue;
            var maxDistance = float.MinValue;
            foreach (var node in this.Nodes)
            {
                var distance = lookAt.Eye.Distance(node.Position);
                minDistance = MathF.Min(minDistance, distance);
                maxDistance = MathF.Max(maxDistance, distance);
            }
            var fovy = 45f;
            var aspect = 1.25f;
            if (openglControl != null)
            {
                aspect = (float)openglControl.Width / (float)openglControl.Height;
            }
            var bufferFactor = 1.2f;
            var near = minDistance / 100f;
            var far = maxDistance * 5f * bufferFactor;
            return new Perspective3d()
            {
                Fovy = fovy,
                Aspect = aspect,
                Near = near,
                Far = far
            };
        }
        /// <summary>
        /// èŽ·å–å‚æ•°
@@ -141,23 +169,94 @@
        {
            var boundingBox = GetBoundingBox();
            var center = boundingBox.GetCenter();
            var lookAt = GetLookAt();
            var perspective = GetPerspective(lookAt, openglControl);
            var rotation = GetRotation();
            var translation = GetTranslation(boundingBox, center);
            var scale = GetScale();
            var rotation = GetRotation();
            var lookAt = GetLookAt(boundingBox, center);
            var perspective = GetPerspective(boundingBox, center, lookAt, openglControl);
            return new NetworkParas()
            {
                BoundingBox = boundingBox,
                Ceneter = center,
                Perspective = perspective,
                LookAt = lookAt,
                Translation = translation,
                Rotation = rotation,
                Translation = translation
                Scale = scale,
                LookAt = lookAt,
                Perspective = perspective,
            };
        }
        /// <summary>
        /// ç»˜åˆ¶
        /// </summary>
        public void Draw(SharpGL.OpenGL gl)
        {
            foreach (var link in this.Links)
            {
                link.Draw(gl);
            }
            foreach (var node in this.Nodes)
            {
                node.Draw(gl);
            }
        }
        /// <summary>
        /// é€‰æ‹©
        /// </summary>
        public List<Parter> Select(Point3d pt)
        {
            int i = 0;
            foreach (var node in this.Nodes)
            {
                node.Selected = node.Contains(pt);
                if (node.Selected)
                {
                    i++;
                }
            }
            if (i > 0)
            {
                this.Links.ForEach(x => x.Selected = false);
                return this.Nodes.Where(x => x.Selected).Select(x => x as Parter).ToList();
            }
            foreach (var link in this.Links)
            {
                link.Selected = link.Contains(pt);
            }
            return this.Links.Where(x => x.Selected).Select(x => x as Parter).ToList();
        }
        /// <summary>
        /// æ‚¬åœ
        /// </summary>
        public List<Parter> Hover(Point3d pt)
        {
            int i = 0;
            foreach (var node in this.Nodes)
            {
                node.Hovered = node.Contains(pt);
                if (node.Hovered)
                {
                    i++;
                }
            }
            if (i > 0)
            {
                this.Links.ForEach(x => x.Hovered = false);
                return this.Nodes.Where(x => x.Hovered).Select(x => x as Parter).ToList();
            }
            foreach (var link in this.Links)
            {
                link.Hovered = link.Contains(pt);
            }
            return this.Links.Where(x => x.Hovered).Select(x => x as Parter).ToList();
        }
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/01-network/01-parter/Parter.cs
@@ -48,6 +48,16 @@
        /// </summary>
        public bool Hovered { get; set; }
        /// <summary>
        /// ç»˜åˆ¶
        /// </summary>
        public abstract void Draw(SharpGL.OpenGL gl);
        /// <summary>
        /// åŒ…含
        /// </summary>
        public abstract bool Contains(Point3d pt);
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/01-network/02-node/Junction.cs
@@ -5,6 +5,10 @@
    /// </summary>
    public class Junction : Node
    {
        /// <summary>
        /// é•¿åº¦
        /// </summary>
        public float? Length { get; set; }
        /// <summary>
        /// å®½åº¦
@@ -22,6 +26,11 @@
        public Color? FillColor { get; set; }
        /// <summary>
        /// æ‚¬åœé•¿åº¦
        /// </summary>
        public float? HoveredLength { get; set; }
        /// <summary>
        /// æ‚¬åœå®½åº¦
        /// </summary>
        public float? HoveredWidth { get; set; }
@@ -37,6 +46,11 @@
        public Color? HoveredFillColor { get; set; }
        /// <summary>
        /// é€‰æ‹©é•¿åº¦
        /// </summary>
        public float? SelectedLength { get; set; }
        /// <summary>
        /// é€‰æ‹©å®½åº¦
        /// </summary>
        public float? SelectedWidth { get; set; }
@@ -51,6 +65,127 @@
        /// </summary>
        public Color? SelectedFillColor { get; set; }
        //包围盒
        private BoundingBox3d _boundingBox = null;
        //获取包围盒
        private BoundingBox3d GetBoundingBox()
        {
            var length = this.Length.HasValue ? this.Length.Value : CacheHelper.HydroL3d.Junction.Size.Length;
            var width = this.Width.HasValue ? this.Width.Value : CacheHelper.HydroL3d.Junction.Size.Width;
            var height = this.Height.HasValue ? this.Height.Value : CacheHelper.HydroL3d.Junction.Size.Height;
            return new BoundingBox3d()
            {
                Min = new Point3d()
                {
                    X = this.Position.X - length / 2f,
                    Y = this.Position.Y - width / 2f,
                    Z = this.Position.Z - height / 2f
                },
                Max = new Point3d()
                {
                    X = this.Position.X + length / 2f,
                    Y = this.Position.Y + width / 2f,
                    Z = this.Position.Z + height / 2f
                }
            };
        }
        /// <summary>
        /// ç»˜åˆ¶
        /// </summary>
        public override void Draw(SharpGL.OpenGL gl)
        {
            _boundingBox = GetBoundingBox();
            if (this.Hovered)
            {
                var length = this.HoveredLength.HasValue ? this.HoveredLength.Value : CacheHelper.HydroL3d.Junction.HoveredSize.Length;
                var width = this.HoveredWidth.HasValue ? this.HoveredWidth.Value : CacheHelper.HydroL3d.Junction.HoveredSize.Width;
                var height = this.HoveredHeight.HasValue ? this.HoveredHeight.Value : CacheHelper.HydroL3d.Junction.HoveredSize.Height;
                var fillColor = this.HoveredFillColor.HasValue ? this.HoveredFillColor.Value : ColorTranslator.FromHtml(CacheHelper.HydroL3d.Junction.HoveredFill.Color);
                DrawJunction(gl, length / 2f, width / 2f, height / 2f, fillColor);
            }
            else if (this.Selected)
            {
                var length = this.SelectedLength.HasValue ? this.SelectedLength.Value : CacheHelper.HydroL3d.Junction.SelectedSize.Length;
                var width = this.SelectedWidth.HasValue ? this.SelectedWidth.Value : CacheHelper.HydroL3d.Junction.SelectedSize.Width;
                var height = this.SelectedHeight.HasValue ? this.SelectedHeight.Value : CacheHelper.HydroL3d.Junction.SelectedSize.Height;
                var fillColor = this.SelectedFillColor.HasValue ? this.SelectedFillColor.Value : ColorTranslator.FromHtml(CacheHelper.HydroL3d.Junction.SelectedFill.Color);
                DrawJunction(gl, length / 2f, width / 2f, height / 2f, fillColor);
            }
            else
            {
                var length = this.Length.HasValue ? this.Length.Value : CacheHelper.HydroL3d.Junction.Size.Length;
                var width = this.Width.HasValue ? this.Width.Value : CacheHelper.HydroL3d.Junction.Size.Width;
                var height = this.Height.HasValue ? this.Height.Value : CacheHelper.HydroL3d.Junction.Size.Height;
                var fillColor = this.FillColor.HasValue ? this.FillColor.Value : ColorTranslator.FromHtml(CacheHelper.HydroL3d.Junction.Fill.Color);
                DrawJunction(gl, length / 2f, width / 2f, height / 2f, fillColor);
            }
        }
        //绘制节点
        private void DrawJunction(OpenGL gl, float halfLength, float halfWidth, float halfHeight, Color fillColor)
        {
            const int stacks = 32;
            const int slices = 32;
            // è®¾ç½®æ¤­çƒä½“的中心点坐标
            float x0 = this.Position.X;
            float y0 = this.Position.Y;
            float z0 = this.Position.Z;
            // è®¾ç½®æ¤­çƒä½“的半轴长
            float a = halfLength;
            float b = halfWidth;
            float c = halfHeight;
            gl.Color(fillColor.R / 255f, fillColor.G / 255f, fillColor.B / 255f);
            for (int i = 0; i < stacks; i++)
            {
                float lat0 = ((float)i / (float)stacks - 0.5f) * (float)MathF.PI;
                float z0_ = (float)MathF.Sin(lat0);
                float zr0 = (float)MathF.Cos(lat0);
                float lat1 = ((float)(i + 1) / (float)stacks - 0.5f) * (float)MathF.PI;
                float z1_ = (float)MathF.Sin(lat1);
                float zr1 = (float)MathF.Cos(lat1);
                gl.Begin(SharpGL.OpenGL.GL_TRIANGLE_STRIP);
                for (int j = 0; j <= slices; j++)
                {
                    float lng = ((float)j / (float)slices) * 2.0f * (float)MathF.PI;
                    // æ ¹æ®æ¤­çƒä½“方程计算顶点坐标并加上中心点坐标
                    float x = a * (float)MathF.Cos(lng) * zr0 + x0;
                    float y = b * (float)MathF.Sin(lng) * zr0 + y0;
                    float z = c * z0_ + z0;
                    gl.Color(1.0f, 0.0f, 0.0f);
                    gl.Vertex(x, y, z);
                    x = a * (float)MathF.Cos(lng) * zr1 + x0;
                    y = b * (float)MathF.Sin(lng) * zr1 + y0;
                    z = c * z1_ + z0;
                    gl.Color(1.0f, 0.0f, 0.0f);
                    gl.Vertex(x, y, z);
                }
                gl.End();
            }
        }
        /// <summary>
        /// åŒ…含
        /// </summary>
        public override bool Contains(Point3d pt)
        {
            if (_boundingBox == null)
            {
                return false;
            }
            return _boundingBox.Contains(pt);
        }
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/01-network/02-node/Reservoir.cs
@@ -7,6 +7,11 @@
    {
        /// <summary>
        /// é•¿åº¦
        /// </summary>
        public float? Length { get; set; }
        /// <summary>
        /// å®½åº¦
        /// </summary>
        public float? Width { get; set; }
@@ -15,6 +20,16 @@
        /// é«˜åº¦
        /// </summary>
        public float? Height { get; set; }
        /// <summary>
        /// å¡«å……颜色
        /// </summary>
        public Color? FillColor { get; set; }
        /// <summary>
        /// æ‚¬åœé•¿åº¦
        /// </summary>
        public float? HoveredLength { get; set; }
        /// <summary>
        /// æ‚¬åœå®½åº¦
@@ -27,6 +42,16 @@
        public float? HoveredHeight { get; set; }
        /// <summary>
        /// æ‚¬åœå¡«å……颜色
        /// </summary>
        public Color? HoveredFillColor { get; set; }
        /// <summary>
        /// é€‰æ‹©é•¿åº¦
        /// </summary>
        public float? SelectedLength { get; set; }
        /// <summary>
        /// é€‰æ‹©å®½åº¦
        /// </summary>
        public float? SelectedWidth { get; set; }
@@ -36,6 +61,132 @@
        /// </summary>
        public float? SelectedHeight { get; set; }
        /// <summary>
        /// é€‰æ‹©å¡«å……颜色
        /// </summary>
        public Color? SelectedFillColor { get; set; }
        //包围盒
        private BoundingBox3d _boundingBox = null;
        //获取包围盒
        private BoundingBox3d GetBoundingBox()
        {
            var length = this.Length.HasValue ? this.Length.Value : CacheHelper.HydroL3d.Reservoir.Size.Length;
            var width = this.Width.HasValue ? this.Width.Value : CacheHelper.HydroL3d.Reservoir.Size.Width;
            var height = this.Height.HasValue ? this.Height.Value : CacheHelper.HydroL3d.Reservoir.Size.Height;
            return new BoundingBox3d()
            {
                Min = new Point3d()
                {
                    X = this.Position.X - length / 2f,
                    Y = this.Position.Y - width / 2f,
                    Z = this.Position.Z - height / 2f
                },
                Max = new Point3d()
                {
                    X = this.Position.X + length / 2f,
                    Y = this.Position.Y + width / 2f,
                    Z = this.Position.Z + height / 2f
                }
            };
        }
        /// <summary>
        /// ç»˜åˆ¶
        /// </summary>
        public override void Draw(SharpGL.OpenGL gl)
        {
            _boundingBox = GetBoundingBox();
            if (this.Hovered)
            {
                var length = this.HoveredLength.HasValue ? this.HoveredLength.Value : CacheHelper.HydroL3d.Reservoir.HoveredSize.Length;
                var width = this.HoveredWidth.HasValue ? this.HoveredWidth.Value : CacheHelper.HydroL3d.Reservoir.HoveredSize.Width;
                var height = this.HoveredHeight.HasValue ? this.HoveredHeight.Value : CacheHelper.HydroL3d.Reservoir.HoveredSize.Height;
                var fillColor = this.HoveredFillColor.HasValue ? this.HoveredFillColor.Value : ColorTranslator.FromHtml(CacheHelper.HydroL3d.Reservoir.HoveredFill.Color);
                DrawEllipsoid(gl, length / 2f, width / 2f, height / 2f, fillColor);
            }
            else if (this.Selected)
            {
                var length = this.SelectedLength.HasValue ? this.SelectedLength.Value : CacheHelper.HydroL3d.Reservoir.SelectedSize.Length;
                var width = this.SelectedWidth.HasValue ? this.SelectedWidth.Value : CacheHelper.HydroL3d.Reservoir.SelectedSize.Width;
                var height = this.SelectedHeight.HasValue ? this.SelectedHeight.Value : CacheHelper.HydroL3d.Reservoir.SelectedSize.Height;
                var fillColor = this.SelectedFillColor.HasValue ? this.SelectedFillColor.Value : ColorTranslator.FromHtml(CacheHelper.HydroL3d.Reservoir.SelectedFill.Color);
                DrawEllipsoid(gl, length / 2f, width / 2f, height / 2f, fillColor);
            }
            else
            {
                var length = this.Length.HasValue ? this.Length.Value : CacheHelper.HydroL3d.Reservoir.Size.Length;
                var width = this.Width.HasValue ? this.Width.Value : CacheHelper.HydroL3d.Reservoir.Size.Width;
                var height = this.Height.HasValue ? this.Height.Value : CacheHelper.HydroL3d.Reservoir.Size.Height;
                var fillColor = this.FillColor.HasValue ? this.FillColor.Value : ColorTranslator.FromHtml(CacheHelper.HydroL3d.Reservoir.Fill.Color);
                DrawEllipsoid(gl, length / 2f, width / 2f, height / 2f, fillColor);
            }
        }
        //绘制椭球体
        private void DrawEllipsoid(OpenGL gl, float halfLength, float halfWidth, float halfHeight, Color fillColor)
        {
            const int stacks = 32;
            const int slices = 32;
            // è®¾ç½®æ¤­çƒä½“的中心点坐标
            float x0 = this.Position.X;
            float y0 = this.Position.Y;
            float z0 = this.Position.Z;
            // è®¾ç½®æ¤­çƒä½“的半轴长
            float a = halfLength;
            float b = halfWidth;
            float c = halfHeight;
            gl.Color(fillColor.R, fillColor.G, fillColor.B);
            for (int i = 0; i < stacks; i++)
            {
                float lat0 = ((float)i / (float)stacks - 0.5f) * (float)MathF.PI;
                float z0_ = (float)MathF.Sin(lat0);
                float zr0 = (float)MathF.Cos(lat0);
                float lat1 = ((float)(i + 1) / (float)stacks - 0.5f) * (float)MathF.PI;
                float z1_ = (float)MathF.Sin(lat1);
                float zr1 = (float)MathF.Cos(lat1);
                gl.Begin(SharpGL.OpenGL.GL_TRIANGLE_STRIP);
                for (int j = 0; j <= slices; j++)
                {
                    float lng = ((float)j / (float)slices) * 2.0f * (float)MathF.PI;
                    // æ ¹æ®æ¤­çƒä½“方程计算顶点坐标并加上中心点坐标
                    float x = a * (float)MathF.Cos(lng) * zr0 + x0;
                    float y = b * (float)MathF.Sin(lng) * zr0 + y0;
                    float z = c * z0_ + z0;
                    gl.Color(1.0f, 0.0f, 0.0f);
                    gl.Vertex(x, y, z);
                    x = a * (float)MathF.Cos(lng) * zr1 + x0;
                    y = b * (float)MathF.Sin(lng) * zr1 + y0;
                    z = c * z1_ + z0;
                    gl.Color(1.0f, 0.0f, 0.0f);
                    gl.Vertex(x, y, z);
                }
                gl.End();
            }
        }
        /// <summary>
        /// åŒ…含
        /// </summary>
        public override bool Contains(Point3d pt)
        {
            if (_boundingBox == null)
            {
                return false;
            }
            return _boundingBox.Contains(pt);
        }
    }
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/01-network/02-node/Tank.cs
@@ -5,7 +5,10 @@
    /// </summary>
    public class Tank : Source
    {
        /// <summary>
        /// é•¿åº¦
        /// </summary>
        public float? Length { get; set; }
        /// <summary>
        /// å®½åº¦
@@ -18,6 +21,16 @@
        public float? Height { get; set; }
        /// <summary>
        /// å¡«å……颜色
        /// </summary>
        public Color? FillColor { get; set; }
        /// <summary>
        /// æ‚¬åœé•¿åº¦
        /// </summary>
        public float? HoveredLength { get; set; }
        /// <summary>
        /// æ‚¬åœå®½åº¦
        /// </summary>
        public float? HoveredWidth { get; set; }
@@ -28,6 +41,16 @@
        public float? HoveredHeight { get; set; }
        /// <summary>
        /// æ‚¬åœå¡«å……颜色
        /// </summary>
        public Color? HoveredFillColor { get; set; }
        /// <summary>
        /// é€‰æ‹©é•¿åº¦
        /// </summary>
        public float? SelectedLength { get; set; }
        /// <summary>
        /// é€‰æ‹©å®½åº¦
        /// </summary>
        public float? SelectedWidth { get; set; }
@@ -37,6 +60,133 @@
        /// </summary>
        public float? SelectedHeight { get; set; }
        /// <summary>
        /// é€‰æ‹©å¡«å……颜色
        /// </summary>
        public Color? SelectedFillColor { get; set; }
        //包围盒
        private BoundingBox3d _boundingBox = null;
        //获取包围盒
        private BoundingBox3d GetBoundingBox()
        {
            var length = this.Length.HasValue ? this.Length.Value : CacheHelper.HydroL3d.Tank.Size.Length;
            var width = this.Width.HasValue ? this.Width.Value : CacheHelper.HydroL3d.Tank.Size.Width;
            var height = this.Height.HasValue ? this.Height.Value : CacheHelper.HydroL3d.Tank.Size.Height;
            return new BoundingBox3d()
            {
                Min = new Point3d()
                {
                    X = this.Position.X - length / 2f,
                    Y = this.Position.Y - width / 2f,
                    Z = this.Position.Z - height / 2f
                },
                Max = new Point3d()
                {
                    X = this.Position.X + length / 2f,
                    Y = this.Position.Y + width / 2f,
                    Z = this.Position.Z + height / 2f
                }
            };
        }
        /// <summary>
        /// ç»˜åˆ¶
        /// </summary>
        public override void Draw(SharpGL.OpenGL gl)
        {
            _boundingBox = GetBoundingBox();
            if (this.Hovered)
            {
                var length = this.HoveredLength.HasValue ? this.HoveredLength.Value : CacheHelper.HydroL3d.Tank.HoveredSize.Length;
                var width = this.HoveredWidth.HasValue ? this.HoveredWidth.Value : CacheHelper.HydroL3d.Tank.HoveredSize.Width;
                var height = this.HoveredHeight.HasValue ? this.HoveredHeight.Value : CacheHelper.HydroL3d.Tank.HoveredSize.Height;
                var fillColor = this.HoveredFillColor.HasValue ? this.HoveredFillColor.Value : ColorTranslator.FromHtml(CacheHelper.HydroL3d.Tank.HoveredFill.Color);
                DrawEllipsoid(gl, length / 2f, width / 2f, height / 2f, fillColor);
            }
            else if (this.Selected)
            {
                var length = this.SelectedLength.HasValue ? this.SelectedLength.Value : CacheHelper.HydroL3d.Tank.SelectedSize.Length;
                var width = this.SelectedWidth.HasValue ? this.SelectedWidth.Value : CacheHelper.HydroL3d.Tank.SelectedSize.Width;
                var height = this.SelectedHeight.HasValue ? this.SelectedHeight.Value : CacheHelper.HydroL3d.Tank.SelectedSize.Height;
                var fillColor = this.SelectedFillColor.HasValue ? this.SelectedFillColor.Value : ColorTranslator.FromHtml(CacheHelper.HydroL3d.Tank.SelectedFill.Color);
                DrawEllipsoid(gl, length / 2f, width / 2f, height / 2f, fillColor);
            }
            else
            {
                var length = this.Length.HasValue ? this.Length.Value : CacheHelper.HydroL3d.Tank.Size.Length;
                var width = this.Width.HasValue ? this.Width.Value : CacheHelper.HydroL3d.Tank.Size.Width;
                var height = this.Height.HasValue ? this.Height.Value : CacheHelper.HydroL3d.Tank.Size.Height;
                var fillColor = this.FillColor.HasValue ? this.FillColor.Value : ColorTranslator.FromHtml(CacheHelper.HydroL3d.Tank.Fill.Color);
                DrawEllipsoid(gl, length / 2f, width / 2f, height / 2f, fillColor);
            }
        }
        //绘制椭球体
        private void DrawEllipsoid(OpenGL gl, float halfLength, float halfWidth, float halfHeight, Color fillColor)
        {
            const int stacks = 32;
            const int slices = 32;
            // è®¾ç½®æ¤­çƒä½“的中心点坐标
            float x0 = this.Position.X;
            float y0 = this.Position.Y;
            float z0 = this.Position.Z;
            // è®¾ç½®æ¤­çƒä½“的半轴长
            float a = halfLength;
            float b = halfWidth;
            float c = halfHeight;
            gl.Color(fillColor.R, fillColor.G, fillColor.B);
            for (int i = 0; i < stacks; i++)
            {
                float lat0 = ((float)i / (float)stacks - 0.5f) * (float)MathF.PI;
                float z0_ = (float)MathF.Sin(lat0);
                float zr0 = (float)MathF.Cos(lat0);
                float lat1 = ((float)(i + 1) / (float)stacks - 0.5f) * (float)MathF.PI;
                float z1_ = (float)MathF.Sin(lat1);
                float zr1 = (float)MathF.Cos(lat1);
                gl.Begin(SharpGL.OpenGL.GL_TRIANGLE_STRIP);
                for (int j = 0; j <= slices; j++)
                {
                    float lng = ((float)j / (float)slices) * 2.0f * (float)MathF.PI;
                    // æ ¹æ®æ¤­çƒä½“方程计算顶点坐标并加上中心点坐标
                    float x = a * (float)MathF.Cos(lng) * zr0 + x0;
                    float y = b * (float)MathF.Sin(lng) * zr0 + y0;
                    float z = c * z0_ + z0;
                    gl.Color(1.0f, 0.0f, 0.0f);
                    gl.Vertex(x, y, z);
                    x = a * (float)MathF.Cos(lng) * zr1 + x0;
                    y = b * (float)MathF.Sin(lng) * zr1 + y0;
                    z = c * z1_ + z0;
                    gl.Color(1.0f, 0.0f, 0.0f);
                    gl.Vertex(x, y, z);
                }
                gl.End();
            }
        }
        /// <summary>
        /// åŒ…含
        /// </summary>
        public override bool Contains(Point3d pt)
        {
            if (_boundingBox == null)
            {
                return false;
            }
            return _boundingBox.Contains(pt);
        }
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/01-network/04-link/Pipe.cs
@@ -1,4 +1,7 @@
namespace Yw.WinFrmUI.HydroL3d
using DevExpress.CodeParser;
using DevExpress.Diagram.Core.Shapes;
namespace Yw.WinFrmUI.HydroL3d
{
    /// <summary>
    /// ç®¡é“
@@ -6,14 +9,14 @@
    public class Pipe : Link
    {
        /// <summary>
        /// çº¿è‰²
        /// </summary>
        public Color? LineColor { get; set; }
        /// <summary>
        /// çº¿å®½
        /// </summary>
        public float? LineWidth { get; set; }
        /// <summary>
        /// çº¿è‰²
        /// </summary>
        public Color? LineColor { get; set; }
        /// <summary>
        /// æ‚¬åœçº¿è‰²
@@ -36,7 +39,136 @@
        public float? SelectedLineWidth { get; set; }
        //包围盒
        private BoundingBox3d _boundingBox = null;
        //获取包围盒
        private BoundingBox3d GetBoundingBox()
        {
            var lineWidth = this.LineWidth.HasValue ? this.LineWidth.Value : CacheHelper.HydroL3d.Pipe.Line.Width;
            return new BoundingBox3d()
            {
                Min = new Point3d()
                {
                    X = Math.Min(this.StartPosition.X, this.EndPosition.X) - lineWidth / 2f,
                    Y = Math.Min(this.StartPosition.Y, this.EndPosition.Y) - lineWidth / 2f,
                    Z = Math.Min(this.StartPosition.Z, this.EndPosition.Z) - lineWidth / 2f
                },
                Max = new Point3d()
                {
                    X = Math.Max(this.StartPosition.X, this.EndPosition.X) + lineWidth / 2f,
                    Y = Math.Max(this.StartPosition.Y, this.EndPosition.Y) + lineWidth / 2f,
                    Z = Math.Max(this.StartPosition.Z, this.EndPosition.Z) + lineWidth / 2f
                }
            };
        }
        /// <summary>
        /// ç»˜åˆ¶
        /// </summary>
        public override void Draw(SharpGL.OpenGL gl)
        {
            _boundingBox = GetBoundingBox();
            if (this.Hovered)
            {
                var lineWidth = this.HoveredLineWidth.HasValue ? this.HoveredLineWidth.Value : CacheHelper.HydroL3d.Pipe.HoveredLine.Width;
                var lineColor = this.HoveredLineColor.HasValue ? this.HoveredLineColor.Value : ColorTranslator.FromHtml(CacheHelper.HydroL3d.Pipe.HoveredLine.Color);
                DrawPipe(gl, lineWidth / 2f, lineColor);
            }
            else if (this.Selected)
            {
                var lineWidth = this.SelectedLineWidth.HasValue ? this.SelectedLineWidth.Value : CacheHelper.HydroL3d.Pipe.SelectedLine.Width;
                var lineColor = this.SelectedLineColor.HasValue ? this.SelectedLineColor.Value : ColorTranslator.FromHtml(CacheHelper.HydroL3d.Pipe.SelectedLine.Color);
                DrawPipe(gl, lineWidth / 2f, lineColor);
            }
            else
            {
                var lineWidth = this.LineWidth.HasValue ? this.LineWidth.Value : CacheHelper.HydroL3d.Pipe.Line.Width;
                var lineColor = this.LineColor.HasValue ? this.LineColor.Value : ColorTranslator.FromHtml(CacheHelper.HydroL3d.Pipe.Line.Color);
                DrawPipe(gl, lineWidth / 2f, lineColor);
            }
        }
        //绘制管道
        private void DrawPipe(SharpGL.OpenGL gl, float radius, Color fillColor)
        {
            gl.Color(fillColor.R / 255.0f, fillColor.G / 255.0f, fillColor.B / 255.0f);
            int slices = 32;  // ç®¡é“圆周的分段数,可根据需要修改
            Point3d direction = new Point3d(this.EndPosition - this.StartPosition);
            float length = direction.Length();
            direction.Normalize();
            // è®¡ç®—旋转轴
            Point3d axis = Point3d.CrossProduct(new Point3d(0, 0, 1), direction);
            if (axis.LengthSquared() < 0.0001f)
            {
                axis = new Point3d(1, 0, 0);
            }
            axis.Normalize();
            float angle = (float)Math.Acos(Point3d.DotProduct(new Point3d(0, 0, 1), direction));
            gl.PushMatrix();
            // å¹³ç§»åˆ°èµ·ç‚¹
            gl.Translate(this.StartPosition.X, this.StartPosition.Y, this.StartPosition.Z);
            // ç»•轴旋转
            gl.Rotate(angle * 180.0f / (float)Math.PI, axis.X, axis.Y, axis.Z);
            // ç»˜åˆ¶ç®¡é“侧面
            gl.Begin(OpenGL.GL_QUAD_STRIP);
            for (int i = 0; i <= slices; i++)
            {
                float theta = (float)i / slices * 2.0f * (float)Math.PI;
                float x = radius * (float)Math.Cos(theta);
                float y = radius * (float)Math.Sin(theta);
                gl.Vertex(x, y, 0.0f);
                gl.Vertex(x, y, length);
            }
            gl.End();
            // ç»˜åˆ¶ç®¡é“两端的圆面
            gl.Begin(OpenGL.GL_POLYGON);
            for (int i = 0; i <= slices; i++)
            {
                float theta = (float)i / slices * 2.0f * (float)Math.PI;
                float x = radius * (float)Math.Cos(theta);
                float y = radius * (float)Math.Sin(theta);
                gl.Vertex(x, y, 0.0f);
            }
            gl.End();
            gl.Begin(OpenGL.GL_POLYGON);
            for (int i = 0; i <= slices; i++)
            {
                float theta = (float)i / slices * 2.0f * (float)Math.PI;
                float x = radius * (float)Math.Cos(theta);
                float y = radius * (float)Math.Sin(theta);
                gl.Vertex(x, y, length);
            }
            gl.End();
            gl.PopMatrix();
        }
        /// <summary>
        /// åŒ…含
        /// </summary>
        public override bool Contains(Point3d pt)
        {
            if (_boundingBox == null)
            {
                return false;
            }
            return _boundingBox.Contains(pt);
        }
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/01-network/04-link/Pump.cs
@@ -6,14 +6,14 @@
    public class Pump : Link
    {
        /// <summary>
        /// çº¿è‰²
        /// </summary>
        public Color? LineColor { get; set; }
        /// <summary>
        /// çº¿å®½
        /// </summary>
        public float? LineWidth { get; set; }
        /// <summary>
        /// çº¿è‰²
        /// </summary>
        public Color? LineColor { get; set; }
        /// <summary>
        /// æ‚¬åœçº¿è‰²
@@ -67,6 +67,135 @@
        //包围盒
        private BoundingBox3d _boundingBox = null;
        //获取包围盒
        private BoundingBox3d GetBoundingBox()
        {
            var lineWidth = this.LineWidth.HasValue ? this.LineWidth.Value : CacheHelper.HydroL3d.Pipe.Line.Width;
            return new BoundingBox3d()
            {
                Min = new Point3d()
                {
                    X = Math.Min(this.StartPosition.X, this.EndPosition.X) - lineWidth / 2f,
                    Y = Math.Min(this.StartPosition.Y, this.EndPosition.Y) - lineWidth / 2f,
                    Z = Math.Min(this.StartPosition.Z, this.EndPosition.Z) - lineWidth / 2f
                },
                Max = new Point3d()
                {
                    X = Math.Max(this.StartPosition.X, this.EndPosition.X) + lineWidth / 2f,
                    Y = Math.Max(this.StartPosition.Y, this.EndPosition.Y) + lineWidth / 2f,
                    Z = Math.Max(this.StartPosition.Z, this.EndPosition.Z) + lineWidth / 2f
                }
            };
        }
        /// <summary>
        /// ç»˜åˆ¶
        /// </summary>
        public override void Draw(SharpGL.OpenGL gl)
        {
            _boundingBox = GetBoundingBox();
            if (this.Hovered)
            {
                var lineWidth = this.HoveredLineWidth.HasValue ? this.HoveredLineWidth.Value : CacheHelper.HydroL3d.Pipe.HoveredLine.Width;
                var lineColor = this.HoveredLineColor.HasValue ? this.HoveredLineColor.Value : ColorTranslator.FromHtml(CacheHelper.HydroL3d.Pipe.HoveredLine.Color);
                DrawPipe(gl, lineWidth / 2f, lineColor);
            }
            else if (this.Selected)
            {
                var lineWidth = this.SelectedLineWidth.HasValue ? this.SelectedLineWidth.Value : CacheHelper.HydroL3d.Pipe.SelectedLine.Width;
                var lineColor = this.SelectedLineColor.HasValue ? this.SelectedLineColor.Value : ColorTranslator.FromHtml(CacheHelper.HydroL3d.Pipe.SelectedLine.Color);
                DrawPipe(gl, lineWidth / 2f, lineColor);
            }
            else
            {
                var lineWidth = this.LineWidth.HasValue ? this.LineWidth.Value : CacheHelper.HydroL3d.Pipe.Line.Width;
                var lineColor = this.LineColor.HasValue ? this.LineColor.Value : ColorTranslator.FromHtml(CacheHelper.HydroL3d.Pipe.Line.Color);
                DrawPipe(gl, lineWidth / 2f, lineColor);
            }
        }
        //绘制管道
        private void DrawPipe(SharpGL.OpenGL gl, float radius, Color fillColor)
        {
            gl.Color(fillColor.R / 255.0f, fillColor.G / 255.0f, fillColor.B / 255.0f);
            int slices = 32;  // ç®¡é“圆周的分段数,可根据需要修改
            Point3d direction = new Point3d(this.EndPosition - this.StartPosition);
            float length = direction.Length();
            direction.Normalize();
            // è®¡ç®—旋转轴
            Point3d axis = Point3d.CrossProduct(new Point3d(0, 0, 1), direction);
            if (axis.LengthSquared() < 0.0001f)
            {
                axis = new Point3d(1, 0, 0);
            }
            axis.Normalize();
            float angle = (float)Math.Acos(Point3d.DotProduct(new Point3d(0, 0, 1), direction));
            gl.PushMatrix();
            // å¹³ç§»åˆ°èµ·ç‚¹
            gl.Translate(this.StartPosition.X, this.StartPosition.Y, this.StartPosition.Z);
            // ç»•轴旋转
            gl.Rotate(angle * 180.0f / (float)Math.PI, axis.X, axis.Y, axis.Z);
            // ç»˜åˆ¶ç®¡é“侧面
            gl.Begin(OpenGL.GL_QUAD_STRIP);
            for (int i = 0; i <= slices; i++)
            {
                float theta = (float)i / slices * 2.0f * (float)Math.PI;
                float x = radius * (float)Math.Cos(theta);
                float y = radius * (float)Math.Sin(theta);
                gl.Vertex(x, y, 0.0f);
                gl.Vertex(x, y, length);
            }
            gl.End();
            // ç»˜åˆ¶ç®¡é“两端的圆面
            gl.Begin(OpenGL.GL_POLYGON);
            for (int i = 0; i <= slices; i++)
            {
                float theta = (float)i / slices * 2.0f * (float)Math.PI;
                float x = radius * (float)Math.Cos(theta);
                float y = radius * (float)Math.Sin(theta);
                gl.Vertex(x, y, 0.0f);
            }
            gl.End();
            gl.Begin(OpenGL.GL_POLYGON);
            for (int i = 0; i <= slices; i++)
            {
                float theta = (float)i / slices * 2.0f * (float)Math.PI;
                float x = radius * (float)Math.Cos(theta);
                float y = radius * (float)Math.Sin(theta);
                gl.Vertex(x, y, length);
            }
            gl.End();
            gl.PopMatrix();
        }
        /// <summary>
        /// åŒ…含
        /// </summary>
        public override bool Contains(Point3d pt)
        {
            if (_boundingBox == null)
            {
                return false;
            }
            return _boundingBox.Contains(pt);
        }
    }
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/01-network/04-link/Valve.cs
@@ -66,5 +66,134 @@
        public float? SelectedHeight { get; set; }
        //包围盒
        private BoundingBox3d _boundingBox = null;
        //获取包围盒
        private BoundingBox3d GetBoundingBox()
        {
            var lineWidth = this.LineWidth.HasValue ? this.LineWidth.Value : CacheHelper.HydroL3d.Pipe.Line.Width;
            return new BoundingBox3d()
            {
                Min = new Point3d()
                {
                    X = Math.Min(this.StartPosition.X, this.EndPosition.X) - lineWidth / 2f,
                    Y = Math.Min(this.StartPosition.Y, this.EndPosition.Y) - lineWidth / 2f,
                    Z = Math.Min(this.StartPosition.Z, this.EndPosition.Z) - lineWidth / 2f
                },
                Max = new Point3d()
                {
                    X = Math.Max(this.StartPosition.X, this.EndPosition.X) + lineWidth / 2f,
                    Y = Math.Max(this.StartPosition.Y, this.EndPosition.Y) + lineWidth / 2f,
                    Z = Math.Max(this.StartPosition.Z, this.EndPosition.Z) + lineWidth / 2f
                }
            };
        }
        /// <summary>
        /// ç»˜åˆ¶
        /// </summary>
        public override void Draw(SharpGL.OpenGL gl)
        {
            _boundingBox = GetBoundingBox();
            if (this.Hovered)
            {
                var lineWidth = this.HoveredLineWidth.HasValue ? this.HoveredLineWidth.Value : CacheHelper.HydroL3d.Pipe.HoveredLine.Width;
                var lineColor = this.HoveredLineColor.HasValue ? this.HoveredLineColor.Value : ColorTranslator.FromHtml(CacheHelper.HydroL3d.Pipe.HoveredLine.Color);
                DrawPipe(gl, lineWidth / 2f, lineColor);
            }
            else if (this.Selected)
            {
                var lineWidth = this.SelectedLineWidth.HasValue ? this.SelectedLineWidth.Value : CacheHelper.HydroL3d.Pipe.SelectedLine.Width;
                var lineColor = this.SelectedLineColor.HasValue ? this.SelectedLineColor.Value : ColorTranslator.FromHtml(CacheHelper.HydroL3d.Pipe.SelectedLine.Color);
                DrawPipe(gl, lineWidth / 2f, lineColor);
            }
            else
            {
                var lineWidth = this.LineWidth.HasValue ? this.LineWidth.Value : CacheHelper.HydroL3d.Pipe.Line.Width;
                var lineColor = this.LineColor.HasValue ? this.LineColor.Value : ColorTranslator.FromHtml(CacheHelper.HydroL3d.Pipe.Line.Color);
                DrawPipe(gl, lineWidth / 2f, lineColor);
            }
        }
        //绘制管道
        private void DrawPipe(SharpGL.OpenGL gl, float radius, Color fillColor)
        {
            gl.Color(fillColor.R / 255.0f, fillColor.G / 255.0f, fillColor.B / 255.0f);
            int slices = 32;  // ç®¡é“圆周的分段数,可根据需要修改
            Point3d direction = new Point3d(this.EndPosition - this.StartPosition);
            float length = direction.Length();
            direction.Normalize();
            // è®¡ç®—旋转轴
            Point3d axis = Point3d.CrossProduct(new Point3d(0, 0, 1), direction);
            if (axis.LengthSquared() < 0.0001f)
            {
                axis = new Point3d(1, 0, 0);
            }
            axis.Normalize();
            float angle = (float)Math.Acos(Point3d.DotProduct(new Point3d(0, 0, 1), direction));
            gl.PushMatrix();
            // å¹³ç§»åˆ°èµ·ç‚¹
            gl.Translate(this.StartPosition.X, this.StartPosition.Y, this.StartPosition.Z);
            // ç»•轴旋转
            gl.Rotate(angle * 180.0f / (float)Math.PI, axis.X, axis.Y, axis.Z);
            // ç»˜åˆ¶ç®¡é“侧面
            gl.Begin(OpenGL.GL_QUAD_STRIP);
            for (int i = 0; i <= slices; i++)
            {
                float theta = (float)i / slices * 2.0f * (float)Math.PI;
                float x = radius * (float)Math.Cos(theta);
                float y = radius * (float)Math.Sin(theta);
                gl.Vertex(x, y, 0.0f);
                gl.Vertex(x, y, length);
            }
            gl.End();
            // ç»˜åˆ¶ç®¡é“两端的圆面
            gl.Begin(OpenGL.GL_POLYGON);
            for (int i = 0; i <= slices; i++)
            {
                float theta = (float)i / slices * 2.0f * (float)Math.PI;
                float x = radius * (float)Math.Cos(theta);
                float y = radius * (float)Math.Sin(theta);
                gl.Vertex(x, y, 0.0f);
            }
            gl.End();
            gl.Begin(OpenGL.GL_POLYGON);
            for (int i = 0; i <= slices; i++)
            {
                float theta = (float)i / slices * 2.0f * (float)Math.PI;
                float x = radius * (float)Math.Cos(theta);
                float y = radius * (float)Math.Sin(theta);
                gl.Vertex(x, y, length);
            }
            gl.End();
            gl.PopMatrix();
        }
        /// <summary>
        /// åŒ…含
        /// </summary>
        public override bool Contains(Point3d pt)
        {
            if (_boundingBox == null)
            {
                return false;
            }
            return _boundingBox.Contains(pt);
        }
    }
}
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/02-panel/NetworkPanel.Designer.cs
@@ -28,8 +28,18 @@
        /// </summary>
        private void InitializeComponent()
        {
            openGLControl1 = new SharpGL.OpenGLControl();
            openGLControl1 = new SceneControl();
            splitContainerControl1 = new DevExpress.XtraEditors.SplitContainerControl();
            propertyGridControl1 = new DevExpress.XtraVerticalGrid.PropertyGridControl();
            labelControl1 = new DevExpress.XtraEditors.LabelControl();
            ((ISupportInitialize)openGLControl1).BeginInit();
            ((ISupportInitialize)splitContainerControl1).BeginInit();
            ((ISupportInitialize)splitContainerControl1.Panel1).BeginInit();
            splitContainerControl1.Panel1.SuspendLayout();
            ((ISupportInitialize)splitContainerControl1.Panel2).BeginInit();
            splitContainerControl1.Panel2.SuspendLayout();
            splitContainerControl1.SuspendLayout();
            ((ISupportInitialize)propertyGridControl1).BeginInit();
            SuspendLayout();
            // 
            // openGLControl1
@@ -41,27 +51,83 @@
            openGLControl1.Margin = new Padding(4, 3, 4, 3);
            openGLControl1.Name = "openGLControl1";
            openGLControl1.OpenGLVersion = SharpGL.Version.OpenGLVersion.OpenGL2_1;
            openGLControl1.RenderContextType = SharpGL.RenderContextType.DIBSection;
            openGLControl1.RenderTrigger = SharpGL.RenderTrigger.TimerBased;
            openGLControl1.Size = new Size(455, 321);
            openGLControl1.RenderContextType = RenderContextType.DIBSection;
            openGLControl1.RenderTrigger = RenderTrigger.TimerBased;
            openGLControl1.Size = new Size(702, 619);
            openGLControl1.TabIndex = 0;
            openGLControl1.OpenGLInitialized += openGLControl1_OpenGLInitialized;
            openGLControl1.OpenGLDraw += openGLControl1_OpenGLDraw;
            openGLControl1.Resize += openGLControl1_Resize;
            openGLControl1.Resized += openGLControl1_Resized;
            openGLControl1.MouseClick += openGLControl1_MouseClick;
            openGLControl1.MouseDoubleClick += openGLControl1_MouseDoubleClick;
            openGLControl1.MouseDown += openGLControl1_MouseDown;
            openGLControl1.MouseHover += openGLControl1_MouseHover;
            openGLControl1.MouseMove += openGLControl1_MouseMove;
            openGLControl1.MouseUp += openGLControl1_MouseUp;
            //
            // splitContainerControl1
            //
            splitContainerControl1.Dock = DockStyle.Fill;
            splitContainerControl1.FixedPanel = DevExpress.XtraEditors.SplitFixedPanel.Panel2;
            splitContainerControl1.Location = new Point(0, 0);
            splitContainerControl1.Name = "splitContainerControl1";
            //
            // splitContainerControl1.Panel1
            //
            splitContainerControl1.Panel1.Controls.Add(labelControl1);
            splitContainerControl1.Panel1.Controls.Add(openGLControl1);
            splitContainerControl1.Panel1.Text = "Panel1";
            //
            // splitContainerControl1.Panel2
            //
            splitContainerControl1.Panel2.Controls.Add(propertyGridControl1);
            splitContainerControl1.Panel2.Text = "Panel2";
            splitContainerControl1.Size = new Size(1031, 619);
            splitContainerControl1.SplitterPosition = 319;
            splitContainerControl1.TabIndex = 1;
            //
            // propertyGridControl1
            //
            propertyGridControl1.Dock = DockStyle.Fill;
            propertyGridControl1.Location = new Point(0, 0);
            propertyGridControl1.Name = "propertyGridControl1";
            propertyGridControl1.OptionsView.AllowReadOnlyRowAppearance = DevExpress.Utils.DefaultBoolean.True;
            propertyGridControl1.Size = new Size(319, 619);
            propertyGridControl1.TabIndex = 0;
            //
            // labelControl1
            //
            labelControl1.AutoSizeMode = DevExpress.XtraEditors.LabelAutoSizeMode.None;
            labelControl1.Dock = DockStyle.Bottom;
            labelControl1.Location = new Point(0, 605);
            labelControl1.Name = "labelControl1";
            labelControl1.Size = new Size(702, 14);
            labelControl1.TabIndex = 1;
            labelControl1.Text = "labelControl1";
            // 
            // NetworkPanel
            // 
            AutoScaleDimensions = new SizeF(7F, 14F);
            AutoScaleMode = AutoScaleMode.Font;
            Controls.Add(openGLControl1);
            Controls.Add(splitContainerControl1);
            Name = "NetworkPanel";
            Size = new Size(455, 321);
            Size = new Size(1031, 619);
            ((ISupportInitialize)openGLControl1).EndInit();
            ((ISupportInitialize)splitContainerControl1.Panel1).EndInit();
            splitContainerControl1.Panel1.ResumeLayout(false);
            ((ISupportInitialize)splitContainerControl1.Panel2).EndInit();
            splitContainerControl1.Panel2.ResumeLayout(false);
            ((ISupportInitialize)splitContainerControl1).EndInit();
            splitContainerControl1.ResumeLayout(false);
            ((ISupportInitialize)propertyGridControl1).EndInit();
            ResumeLayout(false);
        }
        #endregion
        private SharpGL.OpenGLControl openGLControl1;
        private SharpGL.SceneControl openGLControl1;
        private DevExpress.XtraEditors.SplitContainerControl splitContainerControl1;
        private DevExpress.XtraVerticalGrid.PropertyGridControl propertyGridControl1;
        private DevExpress.XtraEditors.LabelControl labelControl1;
    }
}
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/02-panel/NetworkPanel.cs
@@ -1,16 +1,6 @@
using DevExpress.XtraBars.Docking.Paint;
using DevExpress.XtraEditors;
using SharpGL;
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;
using System.Windows.Media;
using DevExpress.CodeParser;
using DevExpress.XtraCharts.Native;
using Yw.Untity;
namespace Yw.WinFrmUI.HydroL3d
{
@@ -19,11 +9,19 @@
        public NetworkPanel()
        {
            InitializeComponent();
            this.openGLControl1.MouseWheel += openGLControl1_MouseWheel;
            this.propertyGridControl1.CellValueChanged += PropertyGridControl1_CellValueChanged;
        }
        protected Network _network = null;//管网
        protected BoundingBox3d _bounndingBox = null;//包围盒
        protected Point3d _center = null;//中心
        private Network _network = null;//管网
        private NetworkParas _paras = null;//参数
        private float _zoom = 1f;//缩放
        private float _rotationX = 0.0f;//x旋转角度
        private float _rotationY = 0.0f;//y旋转角度
        private float _viewPortX = 0f;//
        private float _viewPortY = 0f;//
        /// <summary>
        /// æ˜¯å¦åˆå§‹åŒ–
@@ -37,108 +35,50 @@
        public virtual void Initial(Network network)
        {
            _network = network;
            _bounndingBox = _network.GetBoundingBox();
            _center = _bounndingBox.GetCenter();
            _paras = _network.GetParas();
            InitialParas();
            this.propertyGridControl1.SelectedObject = _paras;
        }
        private void openGLControl1_OpenGLDraw(object sender, RenderEventArgs args)
        //初始化参数
        private void InitialParas()
        {
            if (_network == null)
            {
                return;
            }
            SharpGL.OpenGL gl = this.openGLControl1.OpenGL;
            //清除深度缓存
            gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
            //重置当前指定的矩阵为单位矩阵,将当前的用户坐标系的原点移到了屏幕中心
            gl.LoadIdentity();
            gl.Translate(-_center.X, -_center.Y, -_bounndingBox.Max.Z);
            foreach (var pipe in _network.Pipes)
            {
                var startPosition = pipe.StartPosition;
                var endPosition = pipe.EndPosition;
                gl.Begin(OpenGL.GL_LINES);
                gl.Color(1.0f, 1.0f, 1.0f);
                gl.Vertex(startPosition.X, startPosition.Y, startPosition.Z);//左顶点
                gl.Vertex(endPosition.X, endPosition.Y, endPosition.Z);//右顶点
                gl.End();
            }
            //坐标轴变换位置到(0.0f, 0.0f, -5.0f),这样我们的坐标轴就相当于往屏幕内走5个单位
            //gl.Translate(0.0f, 0.0f, -5.0f);
            //rotation_X += 1f;
            //gl.Rotate(rotation_X, 1.0f, 0.0f, 0.0f);//rotationX:角度
            //rotation_Y += 1f;
            //gl.Rotate(rotation_Y, 0.0f, 1.0f, 0.0f);//rotationY:角度
            //rotation_Z += 1f;
            //gl.Rotate(rotation_Z, 0.0f, 0.0f, 1.0f);//rotationZ:角度
            //#region ç‚¹åˆ°çº¿
            //gl.Begin(OpenGL.GL_LINES);
            //gl.Color(1.0f, 1.0f, 1.0f);
            //gl.Vertex(-2.0f, 0.0f, 0.0f);//左顶点
            //gl.Vertex(2.0f, 2.0f, 0.0f);//右顶点
            //gl.End();
            //#endregion
            //#region çº¿æˆé¢(三角形)
            //gl.Begin(OpenGL.GL_TRIANGLES);//第一个面
            //gl.Color(1.0f, 0.0f, 0.0f);
            //gl.Vertex(0.0f, 1f, 0.0f);//顶点
            //gl.Color(0.0f, 1.0f, 0.0f);
            //gl.Vertex(-1.0f, -1.0f, 0.0f);//左顶点
            //gl.Color(0.0f, 0.0f, 1.0f);
            //gl.Vertex(1.0f, -1.0f, 0.0f);//右顶点
            //gl.End();
            //#endregion
            //#region é¢ç»„合成体
            //gl.Begin(OpenGL.GL_TRIANGLES);//第二个面
            //gl.Color(1.0f, 1.0f, 1.0f);
            //gl.Vertex(0.0f, 0.0f, -2.0f);//第四个点
            //gl.Color(0.0f, 1.0f, 0.0f);
            //gl.Vertex(-1.0f, -1.0f, 0.0f);//左顶点
            //gl.Color(0.0f, 0.0f, 1.0f);
            //gl.Vertex(1.0f, -1.0f, 0.0f);//右顶点
            //gl.End();
            //gl.Begin(OpenGL.GL_TRIANGLES);//第三个面
            //gl.Color(1.0f, 1.0f, 1.0f);
            //gl.Vertex(0.0f, 0.0f, -2.0f);//第四个点
            //gl.Color(0.0f, 1.0f, 0.0f);
            //gl.Vertex(-1.0f, -1.0f, 0.0f);//左顶点
            //gl.Color(1.0f, 0.0f, 0.0f);
            //gl.Vertex(0.0f, 1f, 0.0f);//顶点
            //gl.End();
            //gl.Begin(OpenGL.GL_TRIANGLES);//第四个面
            //gl.Color(1.0f, 1.0f, 1.0f);
            //gl.Vertex(0.0f, 0.0f, -2.0f);//第四个点
            //gl.Color(0.0f, 0.0f, 1.0f);
            //gl.Vertex(1.0f, -1.0f, 0.0f);//右顶点
            //gl.Color(1.0f, 0.0f, 0.0f);
            //gl.Vertex(0.0f, 1f, 0.0f);//顶点
            //gl.End();
            //#endregion
            gl.Flush();   //强制刷新
            _zoom = _paras.Scale.X;
            _rotationX = _paras.Rotation.X;
            _rotationY = _paras.Rotation.Y;
            _viewPortX = 0f;
            _viewPortY = 0f;
        }
        private void PropertyGridControl1_CellValueChanged(object sender, DevExpress.XtraVerticalGrid.Events.CellValueChangedEventArgs e)
        {
            InitialParas();
            this.openGLControl1.Refresh();
        }
        //OpenGL åˆå§‹åŒ–
        private void openGLControl1_OpenGLInitialized(object sender, EventArgs e)
        {
            OpenGL gl = openGLControl1.OpenGL;
            gl.ClearColor(0, 0, 0, 0);
            gl.ClearColor(214 / 255f, 224 / 255f, 235 / 255f, 0);
        }
        private void openGLControl1_Resize(object sender, EventArgs e)
        //OpenGL ç»˜åˆ¶
        private void openGLControl1_OpenGLDraw(object sender, RenderEventArgs args)
        {
            if (_network == null)
            if (!Initialized)
            {
                return;
            }
            OpenGL gl = openGLControl1.OpenGL;
            //启用深度测试
            gl.Enable(OpenGL.GL_DEPTH_TEST);
            //清除深度缓存
            gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
            // è®¾ç½®è§†å£
            gl.Viewport((int)_viewPortX, (int)_viewPortY, this.openGLControl1.Width, this.openGLControl1.Height);
            // è®¾ç½®å½“前矩阵模式,对投影矩阵应用随后的矩阵操作
            gl.MatrixMode(OpenGL.GL_PROJECTION);
@@ -147,16 +87,266 @@
            gl.LoadIdentity();
            // åˆ›å»ºé€è§†æŠ•影变换
            //gl.Perspective(30.0f, (double)Width / (double)Height, 5, 100);
            gl.Perspective(150, (double)Width / (double)Height, 5, _bounndingBox.Max.Z);
            // è§†ç‚¹å˜æ¢
            //gl.LookAt(0, 5, 0, 0, 0, 0, 0, 1, 0);
            gl.LookAt(_center.X, _center.Y, 0, _center.X, _center.Y, _center.Z, 0, 1, 0);
            gl.Perspective(_paras.Perspective.Fovy, _paras.Perspective.Aspect, _paras.Perspective.Near, _paras.Perspective.Far);
            // è®¾ç½®å½“前矩阵为模型视图矩阵
            gl.MatrixMode(OpenGL.GL_MODELVIEW);
            //重置当前指定的矩阵为单位矩阵,将当前的用户坐标系的原点移到了屏幕中心
            gl.LoadIdentity();
            //平移
            gl.Translate(_paras.Translation.X, _paras.Translation.Y, _paras.Translation.Z);
            //将z轴向上
            //gl.Rotate(90f, 1f, 0f, 0f);
            //旋转
            gl.Rotate(_rotationX, 1, 0, 0);
            gl.Rotate(_rotationY, 0, 1, 0);
            //缩放
            gl.Scale(_zoom, _zoom, _zoom);
            _network.Draw(gl);
            gl.LookAt(_paras.LookAt.Eye.X, _paras.LookAt.Eye.Y, _paras.LookAt.Eye.Z,
                _paras.LookAt.Center.X, _paras.LookAt.Center.Y, _paras.LookAt.Center.Z,
                _paras.LookAt.Up.X, _paras.LookAt.Up.Y, _paras.LookAt.Up.Z);
            gl.Flush();   //强制刷新
        }
        //Resize
        private void openGLControl1_Resized(object sender, EventArgs e)
        {
            if (!Initialized)
            {
                return;
            }
            _paras.Perspective.Aspect = (float)this.openGLControl1.Width / (float)this.openGLControl1.Height;
            _viewPortX = 0f;
            _viewPortY = 0f;
        }
        #region é¼ æ ‡å·¦é”®æŒ‰ä¸‹æ—‹è½¬
        /// <summary>
        /// å½“鼠标左键按下时允许旋转
        /// </summary>
        [Browsable(true)]
        [Description("当鼠标左键按下时允许旋转")]
        [DefaultValue(true)]
        public bool AllowRotateWhenMouseLeftDown
        {
            get => _allowRotateWhenMouseLeftDown;
            set => _allowRotateWhenMouseLeftDown = value;
        }
        private bool _allowRotateWhenMouseLeftDown = true;
        protected bool _hasMouseLeftDown = false;//鼠标左键是否按下
        protected Point _mouseLeftDownRotatePoint;//鼠标左键按下旋转点
        /// <summary>
        /// åˆ¤æ–­é¼ æ ‡å·¦é”®æ˜¯å¦æŒ‰ä¸‹
        /// </summary>
        protected virtual bool HasMouseLeftDown(MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                _hasMouseLeftDown = true;
                _mouseLeftDownRotatePoint = e.Location;
                return true;
            }
            return false;
        }
        /// <summary>
        /// é¼ æ ‡å·¦é”®æŒ‰ä¸‹æ—‹è½¬
        /// </summary>
        protected virtual bool MouseLeftDownRotate(MouseEventArgs e)
        {
            if (_hasMouseLeftDown)
            {
                if (this.AllowRotateWhenMouseLeftDown)
                {
                    if (this.Initialized)
                    {
                        int deltaX = e.X - _mouseLeftDownRotatePoint.X;
                        int deltaY = e.Y - _mouseLeftDownRotatePoint.Y;
                        _rotationX += deltaY * 0.05f;
                        _rotationY += deltaX * 0.05f;
                        _mouseLeftDownRotatePoint = e.Location;
                        return true;
                    }
                }
            }
            return false;
        }
        /// <summary>
        /// åˆ¤æ–­é¼ æ ‡å·¦é”®æ˜¯å¦å¼¹èµ·
        /// </summary>
        protected virtual bool HasMouseLeftUp(MouseEventArgs e)
        {
            if (_hasMouseLeftDown)
            {
                _hasMouseLeftDown = false;
                return true;
            }
            return false;
        }
        #endregion
        #region é¼ æ ‡å³é”®æŒ‰ä¸‹æ‹–动
        /// <summary>
        /// å½“鼠标右键按下时允许拖动
        /// </summary>
        [Browsable(true)]
        [Description("当鼠标右键按下时允许拖动")]
        [DefaultValue(true)]
        public bool AllowMoveWhenMouseRightDown
        {
            get => _allowMoveWhenMouseRightDown;
            set => _allowMoveWhenMouseRightDown = value;
        }
        private bool _allowMoveWhenMouseRightDown = true;
        protected bool _hasMouseRightDown = false;//鼠标右键是否按下
        protected Point _mouseRightDownMovePoint;//鼠标右键按下移动点
        /// <summary>
        /// åˆ¤æ–­é¼ æ ‡å³é”®æ˜¯å¦æŒ‰ä¸‹
        /// </summary>
        protected virtual bool HasMouseRightDown(MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                _hasMouseRightDown = true;
                _mouseRightDownMovePoint = e.Location;
                return true;
            }
            return false;
        }
        /// <summary>
        /// é¼ æ ‡å³é”®æŒ‰ä¸‹ç§»åЍ
        /// </summary>
        protected virtual bool MouseRightDownMove(MouseEventArgs e)
        {
            if (_hasMouseRightDown)
            {
                if (this.AllowMoveWhenMouseRightDown)
                {
                    if (this.Initialized)
                    {
                        int deltaX = e.X - _mouseRightDownMovePoint.X;
                        int deltaY = e.Y - _mouseRightDownMovePoint.Y;
                        _viewPortX += deltaX;
                        _viewPortY -= deltaY;
                        _mouseRightDownMovePoint = e.Location;
                        return true;
                    }
                }
            }
            return false;
        }
        /// <summary>
        /// åˆ¤æ–­é¼ æ ‡å·¦é”®æ˜¯å¦å¼¹èµ·
        /// </summary>
        protected virtual bool HasMouseRightUp(MouseEventArgs e)
        {
            if (_hasMouseRightDown)
            {
                _hasMouseRightDown = false;
                return true;
            }
            return false;
        }
        #endregion
        #region é¼ æ ‡äº‹ä»¶
        private void openGLControl1_MouseDown(object sender, MouseEventArgs e)
        {
            HasMouseLeftDown(e);
            HasMouseRightDown(e);
        }
        private void openGLControl1_MouseMove(object sender, MouseEventArgs e)
        {
            var list = this.openGLControl1.OpenGL.UnProject(e.X, e.Y, 0);
            this.labelControl1.Text = DoubleListHelper.ToString(list);
            var hasMouseLeftDownRotate = MouseLeftDownRotate(e);
            var hasMouseRightDownMove = MouseRightDownMove(e);
            if (hasMouseLeftDownRotate || hasMouseRightDownMove)
            {
                this.openGLControl1.Invalidate();
            }
        }
        private void openGLControl1_MouseUp(object sender, MouseEventArgs e)
        {
            var hasMouseLeftUp = HasMouseLeftUp(e);
            var hasMouseRightUp = HasMouseRightUp(e);
            if (hasMouseLeftUp || hasMouseRightUp)
            {
                this.openGLControl1.Invalidate();
            }
        }
        private void openGLControl1_MouseHover(object sender, EventArgs e)
        {
            if (!Initialized)
            {
                return;
            }
            var pt = this.openGLControl1.PointToClient(MousePosition);
            var list = this.openGLControl1.OpenGL.UnProject(pt.X, pt.Y, 0);
            var wpt = new Point3d(list[0], list[1], list[2]);
            _network.Hover(wpt);
        }
        private void openGLControl1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (!Initialized)
            {
                return;
            }
            if (e.Button == MouseButtons.Left)
            {
                InitialParas();
                this.openGLControl1.Invalidate();
            }
        }
        private void openGLControl1_MouseClick(object sender, MouseEventArgs e)
        {
        }
        private void openGLControl1_MouseWheel(object sender, MouseEventArgs e)
        {
            if (e.Delta > 0)
            {
                _zoom *= 1.1f;
            }
            else
            {
                _zoom /= 1.1f;
            }
            this.openGLControl1.Refresh();
        }
        #endregion
    }
}
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/02-panel/NetworkPanelDebug.Designer.cs
ÎļþÒÑɾ³ý
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/02-panel/NetworkPanelDebug.cs
ÎļþÒÑɾ³ý
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/02-panel/NetworkPanelDebug.resx
ÎļþÒÑɾ³ý
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/03-settings/01-paras/00-core/Paras_HydroL3d_Size.cs
@@ -6,6 +6,11 @@
    public class Paras_HydroL3d_Size
    {
        /// <summary>
        /// é•¿åº¦
        /// </summary>
        public float Length { get; set; }
        /// <summary>
        /// å®½åº¦
        /// </summary>
        public float Width { get; set; }
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/03-settings/01-paras/02-reservoir/Paras_HydroL3d_Reservoir.cs
@@ -6,19 +6,14 @@
    public class Paras_HydroL3d_Reservoir
    {
        /// <summary>
        /// å›¾ç‰‡
        /// </summary>
        public string Image { get; set; }
        /// <summary>
        /// å°ºå¯¸
        /// </summary>
        public Paras_HydroL3d_Size Size { get; set; }
        /// <summary>
        /// é€‰æ‹©å›¾ç‰‡
        /// å¡«å……
        /// </summary>
        public string SelectedImage { get; set; }
        public Paras_HydroL3d_Fill Fill { get; set; }
        /// <summary>
        /// é€‰æ‹©å°ºå¯¸
@@ -26,15 +21,20 @@
        public Paras_HydroL3d_Size SelectedSize { get; set; }
        /// <summary>
        /// æ‚¬åœå›¾ç‰‡
        /// é€‰æ‹©å¡«å……
        /// </summary>
        public string HoveredImage { get; set; }
        public Paras_HydroL3d_Fill SelectedFill { get; set; }
        /// <summary>
        /// æ‚¬åœå°ºå¯¸
        /// </summary>
        public Paras_HydroL3d_Size HoveredSize { get; set; }
        /// <summary>
        /// æ‚¬åœå¡«å……
        /// </summary>
        public Paras_HydroL3d_Fill HoveredFill { get; set; }
    }
}
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/03-settings/01-paras/03-tank/Paras_HydroL3d_Tank.cs
@@ -5,10 +5,6 @@
    /// </summary>
    public class Paras_HydroL3d_Tank
    {
        /// <summary>
        /// å›¾ç‰‡
        /// </summary>
        public string Image { get; set; }
        /// <summary>
        /// å°ºå¯¸
@@ -16,9 +12,9 @@
        public Paras_HydroL3d_Size Size { get; set; }
        /// <summary>
        /// é€‰æ‹©å›¾ç‰‡
        /// å¡«å……
        /// </summary>
        public string SelectedImage { get; set; }
        public Paras_HydroL3d_Fill Fill { get; set; }
        /// <summary>
        /// é€‰æ‹©å°ºå¯¸
@@ -26,15 +22,20 @@
        public Paras_HydroL3d_Size SelectedSize { get; set; }
        /// <summary>
        /// æ‚¬åœå›¾ç‰‡
        /// é€‰æ‹©å¡«å……
        /// </summary>
        public string HoveredImage { get; set; }
        public Paras_HydroL3d_Fill SelectedFill { get; set; }
        /// <summary>
        /// æ‚¬åœå°ºå¯¸
        /// </summary>
        public Paras_HydroL3d_Size HoveredSize { get; set; }
        /// <summary>
        /// æ‚¬åœå¡«å……
        /// </summary>
        public Paras_HydroL3d_Fill HoveredFill { get; set; }
    }
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/03-settings/01-paras/05-pump/Paras_HydroL3d_Pump.cs
@@ -6,34 +6,9 @@
    public class Paras_HydroL3d_Pump
    {
        /// <summary>
        /// å›¾ç‰‡
        /// </summary>
        public string Image { get; set; }
        /// <summary>
        /// çº¿
        /// </summary>
        public Paras_HydroL3d_Line Line { get; set; }
        /// <summary>
        /// å°ºå¯¸
        /// </summary>
        public Paras_HydroL3d_Size Size { get; set; }
        /// <summary>
        /// é€‰æ‹©çº¿
        /// </summary>
        public Paras_HydroL3d_Line SelectedLine { get; set; }
        /// <summary>
        /// é€‰æ‹©å›¾ç‰‡
        /// </summary>
        public string SelectedImage { get; set; }
        /// <summary>
        /// é€‰æ‹©å°ºå¯¸
        /// </summary>
        public Paras_HydroL3d_Size SelectedSize { get; set; }
        /// <summary>
        /// æ‚¬åœçº¿
@@ -41,14 +16,9 @@
        public Paras_HydroL3d_Line HoveredLine { get; set; }
        /// <summary>
        /// æ‚¬åœå›¾ç‰‡
        /// é€‰æ‹©çº¿
        /// </summary>
        public string HoveredImage { get; set; }
        /// <summary>
        /// æ‚¬åœå°ºå¯¸
        /// </summary>
        public Paras_HydroL3d_Size HoveredSize { get; set; }
        public Paras_HydroL3d_Line SelectedLine { get; set; }
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/03-settings/01-paras/06-valve/Paras_HydroL3d_Valve.cs
@@ -6,34 +6,9 @@
    public class Paras_HydroL3d_Valve
    {
        /// <summary>
        /// å›¾ç‰‡
        /// </summary>
        public string Image { get; set; }
        /// <summary>
        /// çº¿
        /// </summary>
        public Paras_HydroL3d_Line Line { get; set; }
        /// <summary>
        /// å°ºå¯¸
        /// </summary>
        public Paras_HydroL3d_Size Size { get; set; }
        /// <summary>
        /// é€‰æ‹©çº¿
        /// </summary>
        public Paras_HydroL3d_Line SelectedLine { get; set; }
        /// <summary>
        /// é€‰æ‹©å›¾ç‰‡
        /// </summary>
        public string SelectedImage { get; set; }
        /// <summary>
        /// é€‰æ‹©å°ºå¯¸
        /// </summary>
        public Paras_HydroL3d_Size SelectedSize { get; set; }
        /// <summary>
        /// æ‚¬åœçº¿
@@ -41,14 +16,9 @@
        public Paras_HydroL3d_Line HoveredLine { get; set; }
        /// <summary>
        /// æ‚¬åœå›¾ç‰‡
        /// é€‰æ‹©çº¿
        /// </summary>
        public string HoveredImage { get; set; }
        /// <summary>
        /// æ‚¬åœå°ºå¯¸
        /// </summary>
        public Paras_HydroL3d_Size HoveredSize { get; set; }
        public Paras_HydroL3d_Line SelectedLine { get; set; }
    }
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/GlobalUsings.cs
@@ -4,3 +4,4 @@
global using System.Text;
global using Yw.Settings;
global using System.IO;
global using SharpGL;
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/Yw.WinFrmUI.Hydro.L3d.Core.csproj.user
@@ -4,8 +4,5 @@
    <Compile Update="02-panel\NetworkPanel.cs">
      <SubType>UserControl</SubType>
    </Compile>
    <Compile Update="02-panel\NetworkPanelDebug.cs">
      <SubType>UserControl</SubType>
    </Compile>
  </ItemGroup>
</Project>
WinFrmUI/Yw.WinFrmUI.Hydro.L3d.Core/paras_hydro_l3d_settings.json
@@ -5,13 +5,15 @@
  "HydroL3d": {
    "Junction": {
      "Size": {
        "Width": 10,
        "Height": 10
        "Length": 100,
        "Width": 100,
        "Height": 100
      },
      "Fill": {
        "Color": "Black"
      },
      "HoveredSize": {
        "Length": 12,
        "Width": 12,
        "Height": 12
      },
@@ -19,6 +21,7 @@
        "Color": "#ffbf00"
      },
      "SelectedSize": {
        "Length": 12,
        "Width": 12,
        "Height": 12
      },
@@ -27,109 +30,97 @@
      }
    },
    "Reservoir": {
      "Image": "reservoir",
      "Size": {
        "Width": 30,
        "Height": 30
        "Length": 10,
        "Width": 10,
        "Height": 10
      },
      "HoveredImage": "reservoir_hovered",
      "Fill": {
        "Color": "Black"
      },
      "HoveredSize": {
        "Width": 32,
        "Height": 32
        "Length": 12,
        "Width": 12,
        "Height": 12
      },
      "SelectedImage": "reservoir_selected",
      "HoveredFill": {
        "Color": "#ffbf00"
      },
      "SelectedSize": {
        "Width": 32,
        "Height": 32
        "Length": 12,
        "Width": 12,
        "Height": 12
      },
      "SelectedFill": {
        "Color": "Red"
      }
    },
    "Tank": {
      "Image": "tank",
      "Size": {
        "Width": 30,
        "Height": 30
        "Length": 10,
        "Width": 10,
        "Height": 10
      },
      "HoveredImage": "tank_hovered",
      "Fill": {
        "Color": "Black"
      },
      "HoveredSize": {
        "Width": 32,
        "Height": 32
        "Length": 12,
        "Width": 12,
        "Height": 12
      },
      "SelectedImage": "tank_selected",
      "HoveredFill": {
        "Color": "#ffbf00"
      },
      "SelectedSize": {
        "Width": 32,
        "Height": 32
        "Length": 12,
        "Width": 12,
        "Height": 12
      },
      "SelectedFill": {
        "Color": "Red"
      }
    },
    "Pipe": {
      "Line": {
        "Color": "Blue",
        "Width": 3
        "Width": 60
      },
      "HoveredLine": {
        "Color": "#ffbf00",
        "Width": 4
        "Width": 8
      },
      "SelectedLine": {
        "Color": "Red",
        "Width": 4
        "Width": 8
      }
    },
    "Pump": {
      "Line": {
        "Color": "Blue",
        "Width": 3
      },
      "Image": "pump",
      "Size": {
        "Width": 30,
        "Height": 30
        "Width": 6
      },
      "HoveredLine": {
        "Color": "#ffbf00",
        "Width": 4
      },
      "HoveredImage": "pump_hovered",
      "HoveredSize": {
        "Width": 32,
        "Height": 32
        "Width": 8
      },
      "SelectedLine": {
        "Color": "Red",
        "Width": 4
      },
      "SelectedImage": "pump_selected",
      "SelectedSize": {
        "Width": 32,
        "Height": 32
        "Width": 8
      }
    },
    "Valve": {
      "Line": {
        "Color": "Blue",
        "Width": 3
      },
      "Image": "valve",
      "Size": {
        "Width": 30,
        "Height": 30
        "Width": 6
      },
      "HoveredLine": {
        "Color": "#ffbf00",
        "Width": 4
      },
      "HoveredImage": "valve_hovered",
      "HoveredSize": {
        "Width": 32,
        "Height": 32
        "Width": 8
      },
      "SelectedLine": {
        "Color": "Red",
        "Width": 4
      },
      "SelectedImage": "valve_selected",
      "SelectedSize": {
        "Width": 32,
        "Height": 32
        "Width": 8
      }
    }
  }