Yw.WinFrmUI.Hydro.L3d2.Core/LogicalViewerL3d2.Designer.cs
ÎļþÃû´Ó Yw.WinFrmUI.Hydro.L3d2.Core/ViewerL3d2.Designer.cs ÐÞ¸Ä @@ -1,6 +1,6 @@ namespace Yw.WinFrmUI.Hydro { partial class ViewerL3d2 partial class LogicalViewerL3d2 { /// <summary> /// Required designer variable. Yw.WinFrmUI.Hydro.L3d2.Core/LogicalViewerL3d2.cs
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,242 @@ using System.Windows.Forms.Integration; namespace Yw.WinFrmUI.Hydro { public partial class LogicalViewerL3d2 : UserControl { public LogicalViewerL3d2() { InitializeComponent(); } #region äºä»¶éå /// <summary> /// éæ©æ¹åäºä»¶ /// </summary> public event Action<List<Yw.WpfUI.Hydro.VisualL3d>> SelectionChangedEvent; #endregion #region ç§æåæ®µ private Yw.WpfUI.Hydro.LogicalViewerL3d _wpfViewer = null;//wpfæ§ä»¶ #endregion #region åå§å /// <summary> /// åå§å /// </summary> public void Initial(Yw.WpfUI.Hydro.NetworkL3d nw) { InitialWpfControl(); _wpfViewer.Initial(nw); } //åå§åwpfæ§ä»¶ private void InitialWpfControl() { _wpfViewer = new WpfUI.Hydro.LogicalViewerL3d(); _wpfViewer.SelectionChangedEvent += (visuals) => this.SelectionChangedEvent?.Invoke(visuals); var elementHost = new ElementHost(); elementHost.Dock = DockStyle.Fill; elementHost.Child = _wpfViewer; this.Controls.Clear(); this.Controls.Add(elementHost); } #endregion #region ç¸æºè§è§ /// <summary> /// 设置ä¸è§å¾ /// </summary> public void SetTopView() { _wpfViewer?.SetTopView(); } /// <summary> /// 设置ä¸è§å¾ /// </summary> public void SetBottomView() { _wpfViewer?.SetBottomView(); } /// <summary> /// 设置左è§å¾ /// </summary> public void SetLeftView() { _wpfViewer?.SetLeftView(); } /// <summary> /// 设置å³è§å¾ /// </summary> public void SetRightView() { _wpfViewer?.SetRightView(); } /// <summary> /// 设置åè§å¾ /// </summary> public void SetFrontView() { _wpfViewer?.SetFrontView(); } /// <summary> /// 设置åè§å¾ /// </summary> public void SetBackView() { _wpfViewer?.SetBackView(); } /// <summary> /// 西åè§è§ /// ä»ç©ä½çå·¦å䏿¹è§å¯ /// </summary> public void SetSouthWestView() { _wpfViewer?.SetSouthWestView(); } /// <summary> /// ä¸åè§è§ /// ä»ç©ä½çå³å䏿¹è§å¯ /// </summary> public void SetSouthEastView() { _wpfViewer?.SetSouthEastView(); } /// <summary> /// ä¸åè§è§ /// ä»ç©ä½çå³å䏿¹è§å¯ /// </summary> public void SetNorthEastView() { _wpfViewer?.SetNorthEastView(); } /// <summary> /// 西åè§è§ /// ä»ç©ä½çå·¦å䏿¹è§å¯ /// </summary> public void SetNorthWestView() { _wpfViewer?.SetNorthWestView(); } #endregion #region ç½æ ¼çº¿ /// <summary> /// æ¾ç¤ºç½æ ¼çº¿ /// </summary> public void ShowGridLines() { _wpfViewer?.ShowGridLines(); } /// <summary> /// éèç½æ ¼çº¿ /// </summary> public void HideGridLines() { _wpfViewer?.HideGridLines(); } /// <summary> /// ç½æ ¼çº¿å¯è§æ§ /// </summary> public bool GridLinesVisible { get { return _wpfViewer == null ? false : _wpfViewer.GridLinesVisible; } set { if (_wpfViewer != null) { _wpfViewer.GridLinesVisible = value; } } } #endregion #region 缩æ¾è³æä»¶ /// <summary> /// 缩æ¾è³å¯è§æä»¶ /// </summary> public void ZoomToVisual(string Id) { _wpfViewer?.ZoomToVisual(Id); } /// <summary> /// 缩æ¾è³å¯è§æä»¶ /// </summary> public void ZoomToVisual(List<string> Ids) { _wpfViewer?.ZoomToVisual(Ids); } #endregion #region éæ©æä»¶ /// <summary> /// éæ©æä»¶ /// </summary> public void SelectVisual(string Id) { _wpfViewer?.SelectVisual(Id); } /// <summary> /// éæ©æä»¶ /// </summary> public void SelectVisual(List<string> Ids) { _wpfViewer?.SelectVisual(Ids); } #endregion #region 缩æ¾å¹¶éæ©æä»¶ /// <summary> /// 缩æ¾å¹¶éæ©æä»¶ /// </summary> public void ZoomAndSelectVisual(string Id) { _wpfViewer?.ZoomAndSelectVisual(Id); } /// <summary> /// 缩æ¾å¹¶éæ©æä»¶ /// </summary> public void ZoomAndSelectVisual(List<string> Ids) { _wpfViewer?.ZoomAndSelectVisual(Ids); } #endregion } } Yw.WinFrmUI.Hydro.L3d2.Core/LogicalViewerL3d2.resx
Yw.WinFrmUI.Hydro.L3d2.Core/Properties/PublishProfiles/FolderProfile.pubxml.user
@@ -2,7 +2,7 @@ <!-- https://go.microsoft.com/fwlink/?LinkID=208121. --> <Project> <PropertyGroup> <History>True|2025-04-03T07:07:50.7868897Z||;True|2025-04-03T14:53:27.6125391+08:00||;True|2025-04-03T14:09:06.0738035+08:00||;</History> <History>True|2025-04-22T07:50:06.4794535Z||;True|2025-04-03T15:07:50.7868897+08:00||;True|2025-04-03T14:53:27.6125391+08:00||;True|2025-04-03T14:09:06.0738035+08:00||;</History> <LastFailureDetails /> </PropertyGroup> </Project> Yw.WinFrmUI.Hydro.L3d2.Core/ViewerL3d2.cs
ÎļþÒÑɾ³ý Yw.WinFrmUI.Hydro.L3d2.Core/Yw.WinFrmUI.Hydro.L3d2.Core.csproj
@@ -8,11 +8,11 @@ <OutputType>Library</OutputType> <UseWPF>True</UseWPF> <GeneratePackageOnBuild>True</GeneratePackageOnBuild> <Version>1.0.2</Version> <Version>1.0.3</Version> </PropertyGroup> <ItemGroup> <PackageReference Include="Yw.WpfUI.Hydro.L3d.Core" Version="1.0.1" /> <PackageReference Include="Yw.WpfUI.Hydro.L3d.Core" Version="1.0.2" /> </ItemGroup> </Project> Yw.WinFrmUI.Hydro.L3d2.Core/Yw.WinFrmUI.Hydro.L3d2.Core.csproj.user
@@ -4,7 +4,7 @@ <_LastSelectedProfileId>D:\WorkData\Module\Epanet\Yw.WinFrmUI.Hydro.L3d2.Core\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId> </PropertyGroup> <ItemGroup> <Compile Update="ViewerL3d2.cs"> <Compile Update="LogicalViewerL3d2.cs"> <SubType>UserControl</SubType> </Compile> </ItemGroup> Yw.WinFrmUI.Test.Core/Form3.Designer.cs
@@ -28,7 +28,7 @@ /// </summary> private void InitializeComponent() { viewerL3d21 = new Yw.WinFrmUI.Hydro.ViewerL3d2(); viewerL3d21 = new Yw.WinFrmUI.Hydro.LogicalViewerL3d2(); SuspendLayout(); // // viewerL3d21 @@ -52,6 +52,6 @@ #endregion private Hydro.ViewerL3d2 viewerL3d21; private Hydro.LogicalViewerL3d2 viewerL3d21; } } Yw.WpfUI.Hydro.L3d.Core/00-core/Point3DExtensions.cs
@@ -12,5 +12,7 @@ { return new PointL3d(pt.X, pt.Y, pt.Z); } } } Yw.WpfUI.Hydro.L3d.Core/01-network/99-model/02-text/TextL3d.cs
ÎļþÃû´Ó Yw.WpfUI.Hydro.L3d.Core/03-logical/03-text/LogicalTextL3d.cs ÐÞ¸Ä @@ -1,9 +1,9 @@ namespace Yw.WpfUI.Hydro { /// <summary> /// æ½è±¡ææ¬ /// ææ¬ /// </summary> public class LogicalTextL3d public class TextL3d { /// <summary> /// æä»¶id Yw.WpfUI.Hydro.L3d.Core/01-network/99-model/03-flow/FlowDirectionL3d.cs
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,21 @@ namespace Yw.WpfUI.Hydro { /// <summary> /// æ°´æµæ¹å /// </summary> public class FlowDirectionL3d { /// <summary> /// æä»¶id /// </summary> public string Id { get; set; } /// <summary> /// æ£å /// </summary> public bool Positive { get; set; } } } Yw.WpfUI.Hydro.L3d.Core/03-logical/00-core/LogicalSelectionHelper.cs
@@ -130,7 +130,7 @@ /// <summary> /// 鿩Visuals /// </summary> public void SelectVisuals(List<LogicalVisual3D> visuals) public void SelectVisual(List<LogicalVisual3D> visuals) { ClearSelection(); if (visuals == null || visuals.Count < 1) Yw.WpfUI.Hydro.L3d.Core/03-logical/00-core/LogicalZoomHelper.cs
@@ -13,7 +13,7 @@ _viewport = viewport; } private readonly HelixViewport3D _viewport;//ä¸ç»´ç»ä»¶ private readonly HelixViewport3D _viewport;// ä¸ç»´ç»ä»¶ private readonly double _animationDuration = 0.5; // å¨ç»æç»æ¶é´(ç§) private readonly double _zoomFactor = 1.2; // 缩æ¾å å(å¨è¾¹çæ¡å¤çäºç©ºé´) @@ -52,33 +52,34 @@ /// <summary> /// 缩æ¾è³Visual /// </summary> public void ZoomToVisual(Visual3D visual) public void ZoomToVisual(LogicalVisual3D visual3d) { if (visual == null) if (visual3d == null) { return; } // è·å模åçè¾¹çæ¡ var bounds = Visual3DHelper.FindBounds(visual, Transform3D.Identity); var bounds = Visual3DHelper.FindBounds(visual3d, Transform3D.Identity); ZoomToBounds(bounds); } /// <summary> /// 缩æ¾è³Visuals /// 缩æ¾è³Visual /// </summary> public void ZoomToVisuals(List<Visual3D> visuals) public void ZoomToVisual(List<LogicalVisual3D> visual3ds) { if (visuals == null || visuals.Count < 1) if (visual3ds == null || visual3ds.Count < 1) { return; } // è®¡ç®æææ¨¡åçèåè¾¹çæ¡ var bounds = Rect3D.Empty; foreach (var visual in visuals) foreach (var visual in visual3ds) { bounds.Union(Visual3DHelper.FindBounds(visual, Transform3D.Identity)); } ZoomToBounds(bounds); } Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/00-core/LogicalVisual3D.cs
@@ -38,6 +38,15 @@ protected readonly LogicalOverrideOpacityHelper _overrideOpacityHelper = null;//è¦çéæåº¦è¾ å©ç±» protected readonly LogicalOverrideVisibleHelper _overrideVisibleHelper = null;//è¦çå¯è§æ§è¾ å©ç±» #region äºä»¶éå /// <summary> /// ç¶ææ¹åäºä»¶ /// </summary> public event Action VisualChangedEvent; #endregion /// <summary> /// Vmo /// </summary> @@ -59,6 +68,7 @@ this.UpdateMaterial(); this.UpdateTransform(); this.UpdateVisibility(); this.VisualChangedEvent?.Invoke(); } /// <summary> Yw.WpfUI.Hydro.L3d.Core/03-logical/03-text/LogicalBillboardTextHelper.cs
ÎļþÃû´Ó Yw.WpfUI.Hydro.L3d.Core/03-logical/03-text/LogicalBillboardLeadLabelHelper.cs ÐÞ¸Ä @@ -1,14 +1,14 @@ namespace Yw.WpfUI.Hydro { /// <summary> /// æ½è±¡å¼çº¿æ ç¾è¾ å©ç±» /// æ½è±¡å ¬åææ¬è¾ å©ç±» /// </summary> internal class LogicalBillboardLeadLabelHelper internal class LogicalBillboardTextHelper { /// <summary> /// /// </summary> public LogicalBillboardLeadLabelHelper(HelixViewport3D viewport) public LogicalBillboardTextHelper(HelixViewport3D viewport) { _viewport = viewport; } @@ -23,7 +23,7 @@ /// <summary> /// 设置 /// </summary> public void Set(List<LogicalTextL3d> items) public void Set(List<TextL3d> items) { Clear(); items?.ForEach(x => AddTextVisual3D(x)); @@ -47,7 +47,7 @@ /// <summary> /// æ´æ° /// </summary> public void Update(LogicalTextL3d item) public void Update(TextL3d item) { if (item == null) { @@ -70,14 +70,14 @@ /// <summary> /// æ´æ° /// </summary> public void Update(List<LogicalTextL3d> items) public void Update(List<TextL3d> items) { items?.ForEach(x => Update(x)); } //æ·»å å ¬åçææ¬ private void AddTextVisual3D(LogicalTextL3d item) private void AddTextVisual3D(TextL3d item) { if (!_cache.ContainsKey(item.Id)) { @@ -91,7 +91,7 @@ } //åå»ºå ¬åçææ¬ private BillboardTextVisual3D CreateTextVisual3D(LogicalTextL3d item) private BillboardTextVisual3D CreateTextVisual3D(TextL3d item) { if (item == null) { Yw.WpfUI.Hydro.L3d.Core/03-logical/03-text/LogicalLeadLabelVisual3D.cs
ÎļþÃû´Ó Yw.WpfUI.Hydro.L3d.Core/03-logical/03-text/LogicalBillboardLeadLabelVisual3D.cs ÐÞ¸Ä @@ -3,7 +3,7 @@ /// <summary> /// æ½è±¡å¼çº¿æ ç¾ /// </summary> public class LogicalBillboardLeadLabelVisual3D : ModelVisual3D public class LogicalLeadLabelVisual3D : ModelVisual3D { } Yw.WpfUI.Hydro.L3d.Core/03-logical/06-flow/01-effect/LogicalFlowEffect3D.cs
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,216 @@ using System.Diagnostics; using System.Windows.Threading; namespace Yw.WpfUI.Hydro { internal class LogicalFlowEffect3D : ModelVisual3D { public LogicalFlowEffect3D(LogicalLink3D link, LogicalMaterialHelper materialHelper) { _link = link; _materialHelper = materialHelper; this.Content = new Model3DGroup(); InitializeParticles(); _animationTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(16) }; } private readonly LogicalMaterialHelper _materialHelper = null; private const int _max_particles = 500;//æå¤§ç²åæ° private readonly LogicalLink3D _link;//管段 private readonly Random _random = new();//éæº private readonly List<LogicalParticle3D> _particles = new(_max_particles);//ç²å private readonly DispatcherTimer _animationTimer;//å¨ç»å®æ¶å¨ private readonly Stopwatch _stopWatch = new();//ç§è¡¨ /// <summary> /// æµé /// </summary> public double FlowRate { get; set; } = 1.0; /// <summary> /// æ¹æµ /// </summary> public double Turbulence { get; set; } = 0.3; /// <summary> /// æ¯å¦è¿è¡ /// </summary> public bool IsRunning { get; private set; } #region åºç¡æ¹æ³ //è®¡ç®æä¼ç²åæ°é private int CalculateOptimalParticleCount() { var diameter = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Normal.Diameter; var length = (_link.EndPosition - _link.StartPosition).Length; double volume = Math.PI * Math.Pow(diameter / 2, 2) * length; int count = (int)(volume * 0.3); return Math.Clamp(count, 20, _max_particles); } //计ç®ç²å尺寸 private double CalculateParticleSize() { var diameter = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Normal.Diameter; var length = (_link.EndPosition - _link.StartPosition).Length; return diameter * (_random.NextDouble() * 0.3 + 0.2); } //åºç¨æ¹æµ private Point3D ApplyTurbulence(Point3D position, Vector3D velocity) { double diameter = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Normal.Diameter; var normal1 = Vector3D.CrossProduct(velocity, new Vector3D(0, 0, 1)); var normal2 = Vector3D.CrossProduct(velocity, normal1); double turbulence = Turbulence * diameter; //position += normal1 * (_random.NextDouble() - 0.5) * turbulence; //position += normal2 * (_random.NextDouble() - 0.5) * turbulence; return position; } //è·å沿ç管段çç¹ private Point3D GetPointAlongLink(double t) { return new Point3D( _link.EndPosition.X + t * (_link.EndPosition.X - _link.StartPosition.X), _link.StartPosition.Y + t * (_link.EndPosition.Y - _link.StartPosition.Y), _link.StartPosition.Z + t * (_link.EndPosition.Z - _link.StartPosition.Z)); } //è·ååºç¡é度 private Vector3D GetBaseVelocity() { var direction = _link.EndPosition - _link.StartPosition; direction.Normalize(); return direction; } //æ¯å¦ç®¡æ®µå¤é¨ private bool IsOutsideLink(Point3D point) { var linkVec = _link.EndPosition - _link.StartPosition; var pointVec = point - _link.StartPosition; double dot = Vector3D.DotProduct(linkVec, pointVec); if (dot < 0 || dot > linkVec.LengthSquared) { return true; } double diameter = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Normal.Diameter; double distance = (pointVec - linkVec * (dot / linkVec.LengthSquared)).Length; return distance > diameter * 0.6; } //éç½®ç²å private void ResetParticle(LogicalParticle3D particle) { double t = _random.NextDouble(); particle.Position = GetPointAlongLink(t); particle.Velocity = GetBaseVelocity() * (_random.NextDouble() * 0.4 + 0.8); particle.Age = 0; var position = particle.Position; particle.Position = ApplyTurbulence(position, particle.Velocity); particle.Update(); } #endregion //åå§åç²å private void InitializeParticles() { var modelGroup = (Model3DGroup)this.Content; modelGroup.Children.Clear(); int particleCount = CalculateOptimalParticleCount(); for (int i = 0; i < particleCount; i++) { var particle = new LogicalParticle3D(_materialHelper); particle.Position = _link.StartPosition; particle.Size = CalculateParticleSize(); particle.Color = Colors.Green; particle.Lifetime = _random.NextDouble() * 10 + 5; particle.Age = _random.NextDouble() * 10; ResetParticle(particle); _particles.Add(particle); modelGroup.Children.Add(particle.Content); } } /// <summary> /// å¼å§å¨ç» /// </summary> public void Play() { if (IsRunning) { return; } _animationTimer.Tick += OnAnimationFrame; _animationTimer.Start(); _stopWatch.Start(); this.IsRunning = true; } /// <summary> /// 忢å¨ç» /// </summary> public void Stop() { if (!IsRunning) { return; } _animationTimer.Tick -= OnAnimationFrame; _animationTimer.Stop(); _stopWatch.Stop(); this.IsRunning = false; } private void OnAnimationFrame(object sender, EventArgs e) { double deltaTime = _stopWatch.Elapsed.TotalSeconds; _stopWatch.Restart(); double speedFactor = this.FlowRate * deltaTime * 2; foreach (var particle in _particles) { particle.Age += deltaTime; if (particle.Age > particle.Lifetime) { ResetParticle(particle); continue; } particle.Position += particle.Velocity * speedFactor; if (IsOutsideLink(particle.Position)) { ResetParticle(particle); continue; } if (_random.NextDouble() < 0.1) { particle.Position = ApplyTurbulence(particle.Position, particle.Velocity); } particle.Update(); } } } } Yw.WpfUI.Hydro.L3d.Core/03-logical/06-flow/01-effect/LogicalFlowEffectHelper.cs
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,78 @@ namespace Yw.WpfUI.Hydro { /// <summary> /// æ½è±¡æ°´æµå¨ç»è¾ å©ç±» /// </summary> internal class LogicalFlowEffectHelper { /// <summary> /// /// </summary> public LogicalFlowEffectHelper(HelixViewport3D viewport, LogicalMaterialHelper materialHelper) { _viewport = viewport; _materialHelper = materialHelper; } private readonly HelixViewport3D _viewport;//ä¸ç»´ç»ä»¶ private readonly LogicalMaterialHelper _materialHelper;//æè´¨è¾ å©ç±» private readonly Dictionary<LogicalLink3D, LogicalFlowEffect3D> _cache = new();//ç¼å public void Load() { } public void Unload() { } public void Update() { } public void Clear() { } /// <summary> /// 设置æµé /// </summary> public void SetFlowRate(LogicalLink3D link, double flowRate) { if (link.Vmo.Id == "918437") { if (_cache.TryGetValue(link, out var flowEffect)) { flowEffect.FlowRate = Math.Clamp(flowRate, 0, 2); flowEffect.Turbulence = 0.2 + flowRate * 0.15; } else { flowEffect = new LogicalFlowEffect3D(link, _materialHelper); flowEffect.FlowRate = Math.Clamp(flowRate, 0, 2); flowEffect.Turbulence = 0.2 + flowRate * 0.15; _viewport.Children.Add(flowEffect); flowEffect.Play(); } } } public void StartAllAnimations() { foreach (var system in _cache.Values) { system.Play(); } } } } Yw.WpfUI.Hydro.L3d.Core/03-logical/06-flow/01-effect/LogicalParticle3D.cs
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,122 @@ namespace Yw.WpfUI.Hydro { /// <summary> /// æ½è±¡3Dç²å /// </summary> internal class LogicalParticle3D { /// <summary> /// /// </summary> public LogicalParticle3D(LogicalMaterialHelper materialHelper) { _materialHelper = materialHelper; } private readonly LogicalMaterialHelper _materialHelper = null; /// <summary> /// ä½ç½® /// </summary> public Point3D Position { get; set; } /// <summary> /// æµé /// </summary> public Vector3D Velocity { get; set; } /// <summary> /// é¢è² /// </summary> public Color Color { get; set; } /// <summary> /// 尺寸 /// </summary> public double Size { get; set; } /// <summary> /// å¹´é¾ /// </summary> public double Age { get; set; } /// <summary> /// çå½å¨æ /// </summary> public double Lifetime { get; set; } /// <summary> /// å 容 /// </summary> public GeometryModel3D Content { get { if (_content == null) { _content = new GeometryModel3D() { Material = GetMaterial(this.Color), Geometry = CreateGeometry(this.Size), Transform = CreateTransform() }; } return _content; } } private GeometryModel3D _content; //è·åæè´¨ private Material GetMaterial(Color color) { return _materialHelper.GetMaterial(color); } //è·åæè´¨ private Material GetMaterial(Color color, double opacity) { return _materialHelper.GetMaterial(color, opacity); } //å建å ä½å¾å½¢ private MeshGeometry3D CreateGeometry(double radius) { var builder = new MeshBuilder(); builder.AddSphere(new Point3D(0, 0, 0), radius, 12, 12); return builder.ToMesh(); } //åå»ºè½¬æ¢ private TranslateTransform3D CreateTransform() { return new TranslateTransform3D() { OffsetX = this.Position.X, OffsetY = this.Position.Y, OffsetZ = this.Position.Z }; } /// <summary> /// æ´æ° /// </summary> public void Update() { var content = this.Content; double lifeRatio = this.Age / this.Lifetime; if (lifeRatio > 0.8) { var opacity = 1.0 - (lifeRatio - 0.8) * 5; content.Material = GetMaterial(this.Color, opacity); } content.Geometry = CreateGeometry(this.Size); var transform = content.Transform as TranslateTransform3D; transform.OffsetX = this.Position.X; transform.OffsetY = this.Position.Y; transform.OffsetZ = this.Position.Z; } } } Yw.WpfUI.Hydro.L3d.Core/03-logical/06-flow/02-direction/LogicalFlowDirection3D.cs
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,101 @@ namespace Yw.WpfUI.Hydro { /// <summary> /// æ½è±¡3Dæ°´æµæ¹å /// </summary> internal class LogicalFlowDirection3D : MeshGeometryVisual3D, IDisposable { /// <summary> /// /// </summary> public LogicalFlowDirection3D ( LogicalLink3D link, LogicalMaterialHelper materialHelper, bool positive = true ) { _link = link; _link.VisualChangedEvent += OnVisualChanged; _materialHelper = materialHelper; _positive = positive; UpdateVisual(); } private readonly LogicalLink3D _link;//管段 private readonly LogicalMaterialHelper _materialHelper;//æè´¨è¾ å©ç±» /// <summary> /// æ£å /// </summary> public bool Positive { get { return _positive; } set { _positive = value; } } private bool _positive = true; /// <summary> /// æ´æ°æè´¨ /// </summary> public void UpdateMaterial() { this.Material = _materialHelper.GetMaterial(Colors.Green); } /// <summary> /// æ´æ°å ä½å¾å½¢ /// </summary> public void UpdateGeometry() { var diameter = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Normal.Diameter; var center = _link.StartPosition + (_link.EndPosition - _link.StartPosition) / 2d; var start = _link.StartPosition + (center - _link.StartPosition) / 2d; var end = center + (_link.EndPosition - center) / 2d; var builder = new MeshBuilder(); if (this.Positive) { builder.AddArrow(start, end, diameter); } else { builder.AddArrow(end, start, diameter); } var geometry = builder.ToMesh(); this.MeshGeometry = geometry; } /// <summary> /// æ´æ°å¯è§æ§ /// </summary> public void UpdateVisibility() { this.Visible = _link.Visible; } /// <summary> /// æ´æ°å¯è§å ç´ /// </summary> public void UpdateVisual() { this.UpdateMaterial(); this.UpdateGeometry(); this.UpdateVisibility(); } //å¤çå¯è§äºä»¶ private void OnVisualChanged() { this.UpdateVisual(); } /// <summary> /// éæ¾ /// </summary> public void Dispose() { _link.VisualChangedEvent -= OnVisualChanged; } } } Yw.WpfUI.Hydro.L3d.Core/03-logical/06-flow/02-direction/LogicalFlowDirection3DGroup.cs
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,9 @@ namespace Yw.WpfUI.Hydro { /// <summary> /// æ½è±¡3Dæ°´æµæ¹åç» /// </summary> internal class LogicalFlowDirection3DGroup : ModelVisual3D { } } Yw.WpfUI.Hydro.L3d.Core/03-logical/06-flow/02-direction/LogicalFlowDirectionHelper.cs
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,93 @@ namespace Yw.WpfUI.Hydro { /// <summary> /// æ½è±¡ /// </summary> internal class LogicalFlowDirectionHelper { /// <summary> /// /// </summary> public LogicalFlowDirectionHelper ( HelixViewport3D viewport, LogicalMaterialHelper materialHelper ) { _viewport = viewport; _materialHelper = materialHelper; } private readonly HelixViewport3D _viewport;//ä¸ç»´ç»ä»¶ private readonly LogicalMaterialHelper _materialHelper;//æè´¨è¾ å©ç±» private readonly LogicalFlowDirection3DGroup _group = new();//æ¹åç» private readonly Dictionary<LogicalLink3D, LogicalFlowDirection3D> _cache = new();//ç¼å /// <summary> /// 设置 /// </summary> public void Set(List<LogicalLink3D> allLinkList) { Clear(); if (allLinkList == null || allLinkList.Count < 1) { return; } foreach (var link in allLinkList) { var direction = new LogicalFlowDirection3D(link, _materialHelper); _cache.Add(link, direction); _group.Children.Add(direction); } Append(); } /// <summary> /// 设置 /// </summary> public void Set(Dictionary<LogicalLink3D, bool> dict) { Clear(); if (dict == null || dict.Count < 1) { return; } foreach (var item in dict) { var direction = new LogicalFlowDirection3D(item.Key, _materialHelper, item.Value); _cache.Add(item.Key, direction); _group.Children.Add(direction); } Append(); } /// <summary> /// æ¸ é¤ /// </summary> public void Clear() { if (_cache.Count > 0) { foreach (var item in _cache) { item.Value.Dispose(); } _cache.Clear(); } _group.Children.Clear(); } //éå private void Append() { var group = _viewport.Children.OfType<LogicalFlowDirection3DGroup>().FirstOrDefault(); if (group == null) { _viewport.Children.Add(_group); } } } } Yw.WpfUI.Hydro.L3d.Core/03-logical/08-manager/LogicalEditManager.cs
@@ -820,5 +820,6 @@ #endregion } } Yw.WpfUI.Hydro.L3d.Core/03-logical/08-manager/LogicalManager.cs
@@ -1,6 +1,4 @@ using System.Windows.Controls; namespace Yw.WpfUI.Hydro namespace Yw.WpfUI.Hydro { /// <summary> /// æ½è±¡ç®¡çå¨ @@ -20,8 +18,9 @@ _highlightHelper = new LogicalHighlightHelper(_viewport); _selectionHelper = new LogicalSelectionHelper(_viewport); _zoomHelper = new LogicalZoomHelper(_viewport); _billboardTextHelper = new LogicalBillboardLeadLabelHelper(_viewport); _billboardTextHelper = new LogicalBillboardTextHelper(_viewport); _cameraHelper = new LogicalCameraHelper(_viewport); _flowDirectionHelper = new LogicalFlowDirectionHelper(_viewport, _materialHelper); } #region äºä»¶éå @@ -46,8 +45,9 @@ protected readonly LogicalHighlightHelper _highlightHelper = null;//é«äº®è¾ å©ç±» protected readonly LogicalSelectionHelper _selectionHelper = null;//éæ©è¾ å©ç±» protected readonly LogicalZoomHelper _zoomHelper = null;//缩æ¾è¾ å©ç±» protected readonly LogicalBillboardLeadLabelHelper _billboardTextHelper = null;//å ¬åçæåè¾ å©ç±» protected readonly LogicalBillboardTextHelper _billboardTextHelper = null;//å ¬åçæåè¾ å©ç±» protected readonly LogicalCameraHelper _cameraHelper = null;//ç¸æºè¾ å©ç±» protected readonly LogicalFlowDirectionHelper _flowDirectionHelper = null;//æ°´æµæ¹åè¾ å©ç±» #endregion @@ -436,6 +436,45 @@ #endregion #region å¿«æ·æ¹æ³ //è·åVisual3D protected virtual LogicalVisual3D GetVisual3D(string Id) { if (!Initialized) { return default; } var id = Id?.Trim(); if (string.IsNullOrEmpty(id)) { return default; } if (_allVisualL3dDict.ContainsKey(id)) { var visual = _allVisualL3dDict[Id]; if (_allVisualLogicalDict.ContainsKey(visual)) { var visual3d = _allVisualLogicalDict[visual]; return visual3d; } } return default; } //è·åVisual3D protected virtual List<LogicalVisual3D> GetVisual3D(List<string> Ids) { if (!Initialized) { return default; } var list = Ids?.Select(x => GetVisual3D(x)).Where(x => x != null).ToList(); return list; } #endregion #region è§è§ /// <summary> @@ -710,12 +749,110 @@ #endregion #region ç¼©æ¾ /// <summary> /// 缩æ¾è³å¯è§æä»¶ /// </summary> public virtual void ZoomToVisual(string Id) { if (!Initialized) { return; } var visual3d = GetVisual3D(Id); if (visual3d != null) { _zoomHelper.ZoomToVisual(visual3d); } } /// <summary> /// 缩æ¾è³å¯è§æä»¶ /// </summary> public virtual void ZoomToVisual(List<string> Ids) { if (!Initialized) { return; } var visual3ds = GetVisual3D(Ids); if (visual3ds != null && visual3ds.Count > 0) { _zoomHelper.ZoomToVisual(visual3ds); } } #endregion #region éæ© /// <summary> /// éæ©å¯è§æä»¶ /// </summary> public virtual void SelectVisual(string Id) { if (!Initialized) { return; } var visual3d = GetVisual3D(Id); _selectionHelper.SelectVisual(visual3d); } /// <summary> /// éæ©å¯è§æä»¶ /// </summary> public virtual void SelectVisual(List<string> Ids) { if (!Initialized) { return; } var visual3ds = GetVisual3D(Ids); _selectionHelper.SelectVisual(visual3ds); } #endregion #region 缩æ¾å¹¶éæ© /// <summary> /// 缩æ¾å¹¶éæ©å¯è§æä»¶ /// </summary> public virtual void ZoomAndSelectVisual(string Id) { if (!Initialized) { return; } var visual3d = GetVisual3D(Id); _zoomHelper.ZoomToVisual(visual3d); _selectionHelper.SelectVisual(visual3d); } /// <summary> /// 缩æ¾å¹¶éæ©å¯è§æä»¶ /// </summary> public virtual void ZoomAndSelectVisual(List<string> Ids) { if (!Initialized) { return; } var visual3ds = GetVisual3D(Ids); _zoomHelper.ZoomToVisual(visual3ds); _selectionHelper.SelectVisual(visual3ds); } #endregion #region å ¬åæ¿ææ¬ /// <summary> /// è®¾ç½®å ¬åæ¿ææ¬ /// </summary> public virtual void SetBillboardText(List<LogicalTextL3d> items) public virtual void SetBillboardText(List<TextL3d> items) { if (!Initialized) { @@ -727,7 +864,7 @@ /// <summary> /// æ´æ°å ¬åæ¿ææ¬ /// </summary> public virtual void UpdateBillboardText(LogicalTextL3d item) public virtual void UpdateBillboardText(TextL3d item) { if (!Initialized) { @@ -739,7 +876,7 @@ /// <summary> /// æ´æ°å ¬åæ¿ææ¬ /// </summary> public virtual void UpdateBillboardText(List<LogicalTextL3d> items) public virtual void UpdateBillboardText(List<TextL3d> items) { if (!Initialized) { @@ -791,7 +928,50 @@ #endregion #region æ°´æµæ¹å /// <summary> /// æ¾ç¤ºæ°´æµæ¹å /// </summary> public void ShowFlowDirection() { var allLinkList = _allVisualLogicalDict.Values.Where(x => x is LogicalLink3D).Select(x => x as LogicalLink3D).ToList(); _flowDirectionHelper.Set(allLinkList); } /// <summary> /// è®¾ç½®æ°´æµæ¹å /// </summary> public void SetFlowDirection(List<FlowDirectionL3d> list) { var dict = new Dictionary<LogicalLink3D, bool>(); list?.ForEach(x => { if (_allVisualL3dDict.ContainsKey(x.Id)) { var visual = _allVisualL3dDict[x.Id]; if (_allVisualLogicalDict.ContainsKey(visual)) { var visual3d = _allVisualLogicalDict[visual]; if (visual3d is LogicalLink3D link3d) { dict.Add(link3d, x.Positive); } } } }); _flowDirectionHelper.Set(dict); } /// <summary> /// æ¸ é¤æ°´æµæ¹å /// </summary> public void ClearFlowDirection() { _flowDirectionHelper.Clear(); } #endregion } Yw.WpfUI.Hydro.L3d.Core/03-logical/09-control/LogicalEditerL3d.xaml.cs
@@ -148,7 +148,7 @@ #region å ¬åæ¿ææ¬ public void SetBillboardText(List<LogicalTextL3d> items) public void SetBillboardText(List<TextL3d> items) { _manager.SetBillboardText(items); } @@ -248,5 +248,11 @@ } #endregion public void ShowFlowDirection() { _manager.ShowFlowDirection(); } } } Yw.WpfUI.Hydro.L3d.Core/03-logical/09-control/LogicalViewerL3d.xaml
@@ -14,7 +14,7 @@ x:Name="viewport" ShowCoordinateSystem="True" ZoomExtentsWhenLoaded="True"> <hx:DefaultLights /> <hx:SunLight /> </hx:HelixViewport3D> </Grid> </UserControl> Yw.WpfUI.Hydro.L3d.Core/03-logical/09-control/LogicalViewerL3d.xaml.cs
@@ -40,6 +40,8 @@ #endregion #region åå§å /// <summary> /// åå§å /// </summary> @@ -50,5 +52,196 @@ _manager.SelectionChangedEvent += (List<VisualL3d> visuals) => this.SelectionChangedEvent?.Invoke(visuals); } #endregion #region ç¸æºè§è§ /// <summary> /// 设置ä¸è§å¾ /// </summary> public void SetTopView() { _manager?.SetTopView(); } /// <summary> /// 设置ä¸è§å¾ /// </summary> public void SetBottomView() { _manager?.SetBottomView(); } /// <summary> /// 设置左è§å¾ /// </summary> public void SetLeftView() { _manager?.SetLeftView(); } /// <summary> /// 设置å³è§å¾ /// </summary> public void SetRightView() { _manager?.SetRightView(); } /// <summary> /// 设置åè§å¾ /// </summary> public void SetFrontView() { _manager?.SetFrontView(); } /// <summary> /// 设置åè§å¾ /// </summary> public void SetBackView() { _manager?.SetBackView(); } /// <summary> /// 西åè§è§ /// ä»ç©ä½çå·¦å䏿¹è§å¯ /// </summary> public void SetSouthWestView() { _manager?.SetSouthWestView(); } /// <summary> /// ä¸åè§è§ /// ä»ç©ä½çå³å䏿¹è§å¯ /// </summary> public void SetSouthEastView() { _manager?.SetSouthEastView(); } /// <summary> /// ä¸åè§è§ /// ä»ç©ä½çå³å䏿¹è§å¯ /// </summary> public void SetNorthEastView() { _manager?.SetNorthEastView(); } /// <summary> /// 西åè§è§ /// ä»ç©ä½çå·¦å䏿¹è§å¯ /// </summary> public void SetNorthWestView() { _manager?.SetNorthWestView(); } #endregion #region ç½æ ¼çº¿ /// <summary> /// æ¾ç¤ºç½æ ¼çº¿ /// </summary> public void ShowGridLines() { _manager?.ShowGridLines(); } /// <summary> /// éèç½æ ¼çº¿ /// </summary> public void HideGridLines() { _manager?.HideGridLines(); } /// <summary> /// ç½æ ¼çº¿å¯è§æ§ /// </summary> public bool GridLinesVisible { get { return _manager == null ? false : _manager.GridLinesVisible; } set { if (_manager != null) { _manager.GridLinesVisible = value; } } } #endregion #region 缩æ¾è³æä»¶ /// <summary> /// 缩æ¾è³å¯è§æä»¶ /// </summary> public void ZoomToVisual(string Id) { _manager?.ZoomToVisual(Id); } /// <summary> /// 缩æ¾è³å¯è§æä»¶ /// </summary> public void ZoomToVisual(List<string> Ids) { _manager?.ZoomToVisual(Ids); } #endregion #region éæ©æä»¶ /// <summary> /// éæ©æä»¶ /// </summary> public void SelectVisual(string Id) { _manager?.SelectVisual(Id); } /// <summary> /// éæ©æä»¶ /// </summary> public void SelectVisual(List<string> Ids) { _manager?.SelectVisual(Ids); } #endregion #region 缩æ¾å¹¶éæ©æä»¶ /// <summary> /// 缩æ¾å¹¶éæ©æä»¶ /// </summary> public void ZoomAndSelectVisual(string Id) { _manager?.ZoomAndSelectVisual(Id); } /// <summary> /// 缩æ¾å¹¶éæ©æä»¶ /// </summary> public void ZoomAndSelectVisual(List<string> Ids) { _manager?.ZoomAndSelectVisual(Ids); } #endregion } } Yw.WpfUI.Hydro.L3d.Core/Properties/PublishProfiles/FolderProfile.pubxml.user
@@ -2,7 +2,7 @@ <!-- https://go.microsoft.com/fwlink/?LinkID=208121. --> <Project> <PropertyGroup> <History>True|2025-04-03T06:51:22.5389895Z||;True|2025-04-03T13:39:16.2049845+08:00||;</History> <History>True|2025-04-22T07:43:19.8599243Z||;True|2025-04-03T14:51:22.5389895+08:00||;True|2025-04-03T13:39:16.2049845+08:00||;</History> <LastFailureDetails /> </PropertyGroup> </Project> Yw.WpfUI.Hydro.L3d.Core/Yw.WpfUI.Hydro.L3d.Core.csproj
@@ -7,7 +7,7 @@ <UseWPF>true</UseWPF> <ImplicitUsings>enable</ImplicitUsings> <GeneratePackageOnBuild>True</GeneratePackageOnBuild> <Version>1.0.1</Version> <Version>1.0.2</Version> </PropertyGroup> <ItemGroup> @@ -21,7 +21,7 @@ </ItemGroup> <ItemGroup> <PackageReference Include="HelixToolkit.Core.Wpf" Version="2.26.0" /> <PackageReference Include="HelixToolkit.Core.Wpf" Version="2.27.0" /> <PackageReference Include="Yw.Newtonsoft.Core" Version="3.0.0" /> <PackageReference Include="Yw.Untity.Core" Version="3.0.6" /> </ItemGroup> Yw.WpfUI.Test.Core/MainWindow.xaml
@@ -130,6 +130,7 @@ Checked="ckBackgroud_Checked" Content="èæ¯" Unchecked="ckBackgroud_Unchecked" /> <Button Click="FlowEffect_Click" Content="æ°´æµå¨ç»" /> </ToolBar> <local:LogicalEditerL3d Name="editer" Grid.Row="1" /> </Grid> Yw.WpfUI.Test.Core/MainWindow.xaml.cs
@@ -170,7 +170,7 @@ private void BillboardText_Click(object sender, RoutedEventArgs e) { var list = _nw.Visuals.Select(x => new LogicalTextL3d() var list = _nw.Visuals.Select(x => new TextL3d() { Id = x.Id, Text = x.Id @@ -238,6 +238,11 @@ { this.editer.EndEdit(); } private void FlowEffect_Click(object sender, RoutedEventArgs e) { this.editer.ShowFlowDirection(); } }