From 19e6eb0b172154f9b44323a4174ff9b61628439d Mon Sep 17 00:00:00 2001
From: lixiaojun <1287241240@qq.com>
Date: 星期六, 12 四月 2025 20:44:00 +0800
Subject: [PATCH] WpfUI 绘制重构

---
 Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/00-core/HydroL3dParas.cs                         |   13 
 Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/00-core/Paras_HydroL3d_Logical.cs                |   19 
 Yw.WpfUI.Test.Core/MainWindow.xaml                                                            |   74 +
 Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/02-link/02-pump/LogicalPump3D.cs                 |  138 ++
 Yw.WpfUI.Hydro.L3d.Core/03-logical/06-selection/LogicalSelectionHelper.cs                     |   53 
 Yw.WpfUI.Hydro.L3d.Core/03-logical/03-state/LogicalStateHelper.cs                             |   61 +
 Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/01-node/00-core/Paras_HydroL3d_Logical_Node.cs   |   34 
 Yw.WpfUI.Hydro.L3d.Core/03-logical/04-override/LogicalOverrideColorHelper.cs                  |   16 
 Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/02-link/00-core/LogicalLink3D.cs                 |   60 +
 Yw.WpfUI.Hydro.L3d.Core/03-logical/05-highlight/eLogicalHighlight.cs                          |    6 
 Yw.WpfUI.Hydro.L3d.Core/03-logical/06-selection/eLogicalSelection.cs                          |    5 
 Yw.WpfUI.Hydro.L3d.Core/03-logical/05-highlight/LogicalHighlightHelper.cs                     |   60 +
 Yw.WpfUI.Hydro.L3d.Core/paras_hydrol3d_settings.json                                          |   40 
 Yw.WpfUI.Hydro.L3d.Core/03-logical/04-override/LogicalOverrideVisibleHelper.cs                |   66 +
 Yw.WpfUI.Hydro.L3d.Core/Yw.WpfUI.Hydro.L3d.Core.csproj.user                                   |   16 
 Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/02-link/03-valve/LogicalValve3D.cs               |  126 ++
 Yw.WpfUI.Hydro.L3d.Core/00-core/PointL3dExtensions.cs                                         |    0 
 Yw.WpfUI.Hydro.L3d.Core/02-settings/00-core/HydroL3dParasHelper.cs                            |   27 
 Yw.WpfUI.Test.Core/MainWindow.xaml.cs                                                         |   39 
 Yw.WpfUI.Hydro.L3d.Core/03-logical/00-core/LogicalCreateHelper.cs                             |   56 +
 Yw.WpfUI.Hydro.L3d.Core/03-logical/09-control/LogicalViewerL3d.xaml                           |    6 
 Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/00-core/Paras_HydroL3d_Line.cs                   |   21 
 Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/01-node/00-core/LogicalNode3D.cs                 |   54 +
 Yw.WpfUI.Hydro.L3d.Core/02-settings/00-core/HydroL3dFileHelper.cs                             |   65 +
 Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/01-node/02-source/00-core/LogicalSource3D.cs     |  102 ++
 Yw.WpfUI.Hydro.L3d.Core/Yw.WpfUI.Hydro.L3d.Core.csproj                                        |   25 
 Yw.WpfUI.Hydro.L3d.Core/00-core/ColorExtensions.cs                                            |    2 
 Yw.WpfUI.Hydro.L3d.Core/GlobalUsings.cs                                                       |    5 
 Yw.WpfUI.Hydro.L3d.Core/03-logical/07-zoom/LogicalZoomHelper.cs                               |   19 
 Yw.WpfUI.Hydro.L3d.Core/03-logical/08-manager/LogicalEditManager.cs                           |  443 ++++++++
 Yw.WpfUI.Hydro.L3d.Core/03-logical/04-override/LogicalOverrideOpacityHelper.cs                |   65 +
 Yw.WpfUI.Hydro.L3d.Core/03-logical/09-control/LogicalEditerL3d.xaml.cs                        |   85 +
 Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/00-core/LogicalVisual3D.cs                       |   73 +
 Yw.WpfUI.Hydro.L3d.Core/03-logical/03-state/LogicalStateExtensions.cs                         |   20 
 Yw.WpfUI.Hydro.L3d.Core/03-logical/09-control/LogicalEditerL3d.xaml                           |    6 
 Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/02-link/00-core/Paras_HydroL3d_Logical_Link.cs   |   32 
 Yw.WinFrmUI.Hydro.Q3d.Core/Yw.WinFrmUI.Hydro.Q3d.Core.csproj.user                             |   24 
 Yw.WpfUI.Hydro.L3d.Core/00-core/Point3DExtensions.cs                                          |   16 
 Yw.WpfUI.Hydro.L3d.Core/03-logical/02-material/LogicalMaterialHelper.cs                       |   55 +
 Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/00-core/Paras_HydroL3d_Point.cs                  |   20 
 Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/01-node/01-junction/00-core/LogicalJunction3D.cs |   99 +
 Yw.WpfUI.Hydro.L3d.Core/03-logical/08-manager/LogicalViewManager.cs                           |   30 
 Yw.WpfUI.Hydro.L3d.Core/03-logical/08-manager/LogicalManager.cs                               |  439 ++++++++
 Yw.WpfUI.Hydro.L3d.Core/03-logical/03-state/eLogicalState.cs                                  |   46 
 Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/02-link/01-pipe/LogicalPipe3D.cs                 |  107 ++
 /dev/null                                                                                     |  125 --
 Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/00-core/Paras_HydroL3d.cs                        |   15 
 Yw.WpfUI.Hydro.L3d.Core/03-logical/09-control/LogicalViewerL3d.xaml.cs                        |   54 +
 Yw.WpfUI.Hydro.L3d.Core/03-logical/08-manager/eLogicalEditMode.cs                             |   20 
 49 files changed, 2,791 insertions(+), 191 deletions(-)

diff --git a/Yw.WinFrmUI.Hydro.Q3d.Core/Yw.WinFrmUI.Hydro.Q3d.Core.csproj.user b/Yw.WinFrmUI.Hydro.Q3d.Core/Yw.WinFrmUI.Hydro.Q3d.Core.csproj.user
new file mode 100644
index 0000000..0fcdcb0
--- /dev/null
+++ b/Yw.WinFrmUI.Hydro.Q3d.Core/Yw.WinFrmUI.Hydro.Q3d.Core.csproj.user
@@ -0,0 +1,24 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup />
+  <ItemGroup>
+    <Compile Update="MapView\Base\TagEditorForm.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Update="WindowsForm\CalcParamForm.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Update="WindowsForm\FormFilter.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Update="WindowsForm\Form_importObjs.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Update="WindowsForm\InputBox.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Update="WindowsForm\ResultForm.cs">
+      <SubType>Form</SubType>
+    </Compile>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/Yw.WpfUI.Hydro.L3d.Core/02-helper/00-core/ColorExtensions.cs b/Yw.WpfUI.Hydro.L3d.Core/00-core/ColorExtensions.cs
similarity index 99%
rename from Yw.WpfUI.Hydro.L3d.Core/02-helper/00-core/ColorExtensions.cs
rename to Yw.WpfUI.Hydro.L3d.Core/00-core/ColorExtensions.cs
index 9fbac3e..bac96ae 100644
--- a/Yw.WpfUI.Hydro.L3d.Core/02-helper/00-core/ColorExtensions.cs
+++ b/Yw.WpfUI.Hydro.L3d.Core/00-core/ColorExtensions.cs
@@ -46,5 +46,7 @@
 
             return Color.FromArgb(a, r, g, b);
         }
+
+
     }
 }
diff --git a/Yw.WpfUI.Hydro.L3d.Core/00-core/Point3DExtensions.cs b/Yw.WpfUI.Hydro.L3d.Core/00-core/Point3DExtensions.cs
new file mode 100644
index 0000000..957f788
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/00-core/Point3DExtensions.cs
@@ -0,0 +1,16 @@
+锘縩amespace Yw.WpfUI.Hydro
+{
+    /// <summary>
+    /// 
+    /// </summary>
+    internal static class Point3DExtensions
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public static PointL3d ToPointL3d(this Point3D pt)
+        {
+            return new PointL3d(pt.X, pt.Y, pt.Z);
+        }
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/02-helper/00-core/PointL3dExtensions.cs b/Yw.WpfUI.Hydro.L3d.Core/00-core/PointL3dExtensions.cs
similarity index 100%
rename from Yw.WpfUI.Hydro.L3d.Core/02-helper/00-core/PointL3dExtensions.cs
rename to Yw.WpfUI.Hydro.L3d.Core/00-core/PointL3dExtensions.cs
diff --git a/Yw.WpfUI.Hydro.L3d.Core/02-helper/01-material/MaterialHelper.cs b/Yw.WpfUI.Hydro.L3d.Core/02-helper/01-material/MaterialHelper.cs
deleted file mode 100644
index 3ea2cae..0000000
--- a/Yw.WpfUI.Hydro.L3d.Core/02-helper/01-material/MaterialHelper.cs
+++ /dev/null
@@ -1,98 +0,0 @@
-锘縩amespace Yw.WpfUI.Hydro
-{
-    /// <summary>
-    /// 鏉愯川杈呭姪绫�
-    /// </summary>
-    internal static class MaterialHelper
-    {
-        /// <summary>
-        /// 鍒涘缓鏍囧噯鏉愯川锛堟极鍙嶅皠+楂樺厜锛�
-        /// </summary>
-        public static Material CreateMaterial
-            (
-                Color color,
-                double ambient = 0.1,
-                double specular = 0.5,
-                double specularPower = 100
-            )
-        {
-            var group = new MaterialGroup();
-
-            // 鐜鍏�
-            if (ambient > 0)
-            {
-                group.Children.Add(new EmissiveMaterial(
-                    new SolidColorBrush(ScaleColor(color, ambient))));
-            }
-
-            // 婕弽灏�
-            group.Children.Add(new DiffuseMaterial(
-                new SolidColorBrush(color)));
-
-            // 楂樺厜
-            if (specular > 0)
-            {
-                group.Children.Add(new SpecularMaterial(
-                    new SolidColorBrush(Colors.White),
-                    specularPower * specular));
-            }
-
-            return group;
-        }
-
-        /// <summary>
-        /// 鍒涘缓绾圭悊鏉愯川
-        /// </summary>
-        public static Material CreateMaterial
-            (
-                Brush brush,
-                double specularPower = 100,
-                double specularStrength = 0.2
-            )
-        {
-            var group = new MaterialGroup();
-
-            // 婕弽灏�
-            group.Children.Add(new DiffuseMaterial(brush));
-
-            // 楂樺厜
-            if (specularStrength > 0)
-            {
-                group.Children.Add(new SpecularMaterial(
-                    new SolidColorBrush(Colors.White),
-                    specularPower * specularStrength));
-            }
-
-            return group;
-        }
-
-        /// <summary>
-        /// 鍒涘缓绾壊鏉愯川锛堟�ц兘鏈�浼橈級
-        /// </summary>
-        public static Material CreateSimpleMaterial(Color color)
-        {
-            return new DiffuseMaterial(new SolidColorBrush(color));
-        }
-
-        /// <summary>
-        /// 鍒涘缓鍙戝厜鏉愯川
-        /// </summary>
-        public static Material CreateEmissiveMaterial(Color color, double strength = 1.0)
-        {
-            return new EmissiveMaterial(new SolidColorBrush(
-                ScaleColor(color, strength)));
-        }
-
-        //缂╂斁棰滆壊
-        private static Color ScaleColor(Color color, double factor)
-        {
-            return Color.FromArgb(
-                color.A,
-                (byte)(color.R * factor),
-                (byte)(color.G * factor),
-                (byte)(color.B * factor));
-        }
-
-
-    }
-}
\ No newline at end of file
diff --git a/Yw.WpfUI.Hydro.L3d.Core/02-helper/01-material/SimpleMaterialManager.cs b/Yw.WpfUI.Hydro.L3d.Core/02-helper/01-material/SimpleMaterialManager.cs
deleted file mode 100644
index 4417d33..0000000
--- a/Yw.WpfUI.Hydro.L3d.Core/02-helper/01-material/SimpleMaterialManager.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-锘縩amespace Yw.WpfUI.Hydro
-{
-    /// <summary>
-    /// 绠�鍗曟潗璐ㄧ鐞嗗櫒
-    /// </summary>
-    internal class SimpleMaterialManager
-    {
-        //缂撳瓨
-        private readonly ConcurrentDictionary<Color, Material> _cache = new();
-
-        /// <summary>
-        /// 鑾峰彇鏉愯川
-        /// </summary>
-        public Material GetMaterial(string htmlColor)
-        {
-            var color = htmlColor.ToMediaColor();
-            return GetMaterial(color);
-        }
-
-        /// <summary>
-        /// 鑾峰彇鏉愯川
-        /// </summary>
-        public Material GetMaterial(Color color)
-        {
-            var material = _cache.GetOrAdd(color, CreateMaterial(color));
-            return material;
-        }
-
-        //鍒涘缓鏉愯川
-        private static Material CreateMaterial(Color color)
-        {
-            return MaterialHelper.CreateSimpleMaterial(color);
-        }
-
-    }
-}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/02-helper/02-property/Visual3DProperties.cs b/Yw.WpfUI.Hydro.L3d.Core/02-helper/02-property/Visual3DProperties.cs
deleted file mode 100644
index 3eb1118..0000000
--- a/Yw.WpfUI.Hydro.L3d.Core/02-helper/02-property/Visual3DProperties.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-锘縩amespace Yw.WpfUI.Hydro
-{
-    /// <summary>
-    ///  涓� Visual3D 娣诲姞灞炴��
-    /// </summary>
-    public static class Visual3DProperties
-    {
-        //Tag灞炴��
-        public static readonly DependencyProperty TagProperty =
-            DependencyProperty.RegisterAttached(
-                "Tag",
-                typeof(VisualL3d),
-                typeof(Visual3DProperties),
-                new PropertyMetadata(null));
-
-        /// <summary>
-        /// 鑾峰彇Tag
-        /// </summary>
-        public static VisualL3d GetTag(Visual3D visual)
-        {
-            return (VisualL3d)visual.GetValue(TagProperty);
-        }
-
-        /// <summary>
-        /// 璁剧疆Tag
-        /// </summary>
-        public static void SetTag(Visual3D visual, VisualL3d value)
-        {
-            visual.SetValue(TagProperty, value);
-        }
-
-
-    }
-}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/02-helper/03-geometry/SimpleGeometryExtensions.cs b/Yw.WpfUI.Hydro.L3d.Core/02-helper/03-geometry/SimpleGeometryExtensions.cs
deleted file mode 100644
index c954873..0000000
--- a/Yw.WpfUI.Hydro.L3d.Core/02-helper/03-geometry/SimpleGeometryExtensions.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-锘縩amespace Yw.WpfUI.Hydro
-{
-    /// <summary>
-    /// 绠�鍗曞嚑浣曟墿灞�
-    /// </summary>
-    internal static class SimpleGeometryExtensions
-    {
-        /// <summary>
-        /// 鑾峰彇绠�鍗曞嚑浣曠被鍨�
-        /// </summary>
-        public static eSimpleGeometry GetSimpleGeometryType(this VisualL3d visual)
-        {
-            var geometryType = eSimpleGeometry.Junction;
-            if (visual == null)
-            {
-                return geometryType;
-            }
-            if (visual is JunctionL3d junction)
-            {
-                geometryType = eSimpleGeometry.Junction;
-            }
-            else if (visual is SourceL3d souce)
-            {
-                geometryType = eSimpleGeometry.Source;
-            }
-            else if (visual is PipeL3d pipe)
-            {
-                geometryType = eSimpleGeometry.Pipe;
-            }
-            else if (visual is PumpL3d pump)
-            {
-                geometryType = eSimpleGeometry.Pump;
-            }
-            else if (visual is ValveL3d valve)
-            {
-                geometryType = eSimpleGeometry.Valve;
-            }
-            return geometryType;
-        }
-
-
-    }
-}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/02-helper/03-geometry/SimpleGeometryManager.cs b/Yw.WpfUI.Hydro.L3d.Core/02-helper/03-geometry/SimpleGeometryManager.cs
deleted file mode 100644
index 6728cbd..0000000
--- a/Yw.WpfUI.Hydro.L3d.Core/02-helper/03-geometry/SimpleGeometryManager.cs
+++ /dev/null
@@ -1,183 +0,0 @@
-锘縩amespace Yw.WpfUI.Hydro
-{
-    /// <summary>
-    /// 绠�鍗曞嚑浣曠鐞嗗櫒
-    /// </summary>
-    internal class SimpleGeometryManager
-    {
-        //缂撳瓨
-        private readonly ConcurrentDictionary<string, Geometry3D> _cache = new();
-
-        /// <summary>
-        /// 鑾峰彇鍑犱綍
-        /// </summary>
-        /// <param name="visual">鏋勪欢</param>
-        /// <param name="size">灏哄</param>
-        /// <param name="factor">鍥犲瓙</param>
-        /// <returns></returns>
-        public Geometry3D GetGeometry(VisualL3d visual, double size, double factor)
-        {
-            var geometryType = visual.GetSimpleGeometryType();
-            var pts = visual.GetPositions();
-            var cacheKey = CreateCacheKey(geometryType, pts, size, factor);
-            var geometry = _cache.GetOrAdd(cacheKey, CreateGeometry(geometryType, pts, size, factor));
-            return geometry;
-        }
-
-        //鍒涘缓鍑犱綍
-        private static Geometry3D CreateGeometry(eSimpleGeometry geometryType, List<PointL3d> pts, double size, double factor)
-        {
-            Geometry3D geometry = null;
-            switch (geometryType)
-            {
-                case eSimpleGeometry.Junction:
-                    geometry = CreateJunctionGeometry(pts[0], size, factor);
-                    break;
-                case eSimpleGeometry.Source:
-                    geometry = CreateSourceGeometry(pts[0], size, factor);
-                    break;
-                case eSimpleGeometry.Pipe:
-                    geometry = CreatePipeGeometry(pts[0], pts[1], size, factor);
-                    break;
-                case eSimpleGeometry.Pump:
-                    geometry = CreatePumpGeometry(pts[0], pts[1], size, factor);
-                    break;
-                case eSimpleGeometry.Valve:
-                    geometry = CreateValveGeometry(pts[0], pts[1], size, factor);
-                    break;
-                default: break;
-            }
-            return geometry;
-        }
-
-        //鍒涘缓杩炴帴鑺傜偣鍑犱綍
-        private static Geometry3D CreateJunctionGeometry(PointL3d pt, double radiu, double factor)
-        {
-            var builder = new MeshBuilder();
-            builder.AddSphere(pt.ToPoint3D(), radiu * factor);
-            return builder.ToMesh();
-        }
-
-        //鍒涘缓姘存簮鍑犱綍
-        private static Geometry3D CreateSourceGeometry(PointL3d pt, double radiu, double factor)
-        {
-            var x = radiu * 4d * factor;
-            var y = radiu * 4d * factor;
-            var z = radiu * 2d * factor;
-            var builder = new MeshBuilder();
-            builder.AddBox(pt.ToPoint3D(), x, y, z);
-            return builder.ToMesh();
-        }
-
-        //鍒涘缓绠¢亾鍑犱綍
-        private static Geometry3D CreatePipeGeometry(PointL3d start, PointL3d end, double diameter, double factor)
-        {
-            var builder = new MeshBuilder();
-            builder.AddTube(
-                path: new[] { start.ToPoint3D(), end.ToPoint3D() },
-                diameter: diameter * factor,  // 绾跨洿寰�(3D绌洪棿鍗曚綅)
-                thetaDiv: 8,    // 妯埅闈㈢粏鍒嗗害
-                false
-            );
-            return builder.ToMesh();
-        }
-
-        //鍒涘缓姘存车鍑犱綍
-        private static Geometry3D CreatePumpGeometry(PointL3d start, PointL3d end, double diameter, double factor)
-        {
-            var sv = start.ToVector3D();
-            var ev = end.ToVector3D();
-            var center = (sv + ev) * 0.5d;
-            var direction = (ev - sv);
-            var length = direction.Length;
-            direction.Normalize();
-
-            //姘存车绠¢亾
-            var builder = new MeshBuilder();
-            builder.AddTube(
-                path: new[] { start.ToPoint3D(), end.ToPoint3D() },
-                diameter: diameter * factor,  // 绾跨洿寰�(3D绌洪棿鍗曚綅)
-                thetaDiv: 8,    // 妯埅闈㈢粏鍒嗗害
-                false
-            );
-
-            // 姘存车涓讳綋锛堝渾鏌卞舰锛�
-            var pumpCenter = sv + direction * (length * 0.5d);
-            builder.AddCylinder(
-                p1: (pumpCenter - direction * (length * 0.3d)).ToPoint3D(),
-                p2: (pumpCenter + direction * (length * 0.3d)).ToPoint3D(),
-                diameter: diameter * factor * 1.5d,
-                thetaDiv: 16);
-
-            double bladeWidth = diameter * factor * 2d;
-            double bladeLength = length * 0.6d;
-
-            // 鍒涘缓涓や釜浜ゅ弶鐨勫彾鐗�
-            for (int i = 0; i < 2; i++)
-            {
-                var rotation = new RotateTransform3D(
-                    new AxisAngleRotation3D(direction, i * 90));
-
-                // 鍙剁墖1
-                var p1 = center + rotation.Transform(new Vector3D(-bladeLength / 2, -bladeWidth / 2, 0));
-                var p2 = center + rotation.Transform(new Vector3D(bladeLength / 2, -bladeWidth / 2, 0));
-                var p3 = center + rotation.Transform(new Vector3D(bladeLength / 2, bladeWidth / 2, 0));
-                var p4 = center + rotation.Transform(new Vector3D(-bladeLength / 2, bladeWidth / 2, 0));
-
-                builder.AddQuad(p1.ToPoint3D(), p2.ToPoint3D(), p3.ToPoint3D(), p4.ToPoint3D());
-            }
-
-            return builder.ToMesh();
-        }
-
-        //鍒涘缓闃�闂ㄥ嚑浣�
-        private static Geometry3D CreateValveGeometry(PointL3d start, PointL3d end, double diameter, double factor)
-        {
-            var sv = start.ToVector3D();
-            var ev = end.ToVector3D();
-            var center = (sv + ev) * 0.5d;
-            var direction = (ev - sv);
-            var length = direction.Length;
-            direction.Normalize();
-            var size = diameter * factor * 2d;
-            if (size > length)
-            {
-                size = length;
-            }
-
-            //闃�闂ㄧ閬�
-            var builder = new MeshBuilder();
-            builder.AddTube(
-                path: new[] { start.ToPoint3D(), end.ToPoint3D() },
-                diameter: diameter * factor,  // 绾跨洿寰�(3D绌洪棿鍗曚綅)
-                thetaDiv: 8,    // 妯埅闈㈢粏鍒嗗害
-                false
-            );
-
-            builder.AddBox(center.ToPoint3D(), size, size, size);
-
-            return builder.ToMesh();
-        }
-
-        //鍒涘缓缂撳瓨閿�
-        private static string CreateCacheKey(eSimpleGeometry geometryType, List<PointL3d> pts, double size, double factor)
-        {
-            var sb = new StringBuilder();
-            sb.Append(geometryType);
-            sb.Append('-');
-            foreach (var pt in pts)
-            {
-                sb.Append(pt.ToString());
-                sb.Append('-');
-            }
-            sb.Append(size);
-            sb.Append('-');
-            sb.Append(factor);
-            return sb.ToString();
-        }
-
-
-
-
-    }
-}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/02-helper/03-geometry/eSimpleGeometry.cs b/Yw.WpfUI.Hydro.L3d.Core/02-helper/03-geometry/eSimpleGeometry.cs
deleted file mode 100644
index 79f4ce0..0000000
--- a/Yw.WpfUI.Hydro.L3d.Core/02-helper/03-geometry/eSimpleGeometry.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-锘縩amespace Yw.WpfUI.Hydro
-{
-    /// <summary>
-    /// 绠�鍗曞嚑浣�
-    /// </summary>
-    internal enum eSimpleGeometry
-    {
-        Junction,
-        Source,
-        Pipe,
-        Pump,
-        Valve,
-    }
-}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/02-helper/04-highlight/SimpleHighlightManager.cs b/Yw.WpfUI.Hydro.L3d.Core/02-helper/04-highlight/SimpleHighlightManager.cs
deleted file mode 100644
index b835c38..0000000
--- a/Yw.WpfUI.Hydro.L3d.Core/02-helper/04-highlight/SimpleHighlightManager.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-锘縩amespace Yw.WpfUI.Hydro
-{
-    /// <summary>
-    /// 绠�鍗曢珮浜鐞嗗櫒
-    /// </summary>
-    internal class SimpleHighlightManager
-    {
-        /// <summary>
-        /// 
-        /// </summary>
-        public SimpleHighlightManager(HelixViewport3D viewport)
-        {
-            _viewport = viewport;
-        }
-
-        /// <summary>
-        /// 鐘舵�佹敼鍙樹簨浠�
-        /// </summary>
-        public event Action<Visual3D, eHighlightType> StateChangedEvent;
-
-
-        private readonly HelixViewport3D _viewport;
-        private Visual3D _visual;
-
-
-        /// <summary>
-        /// 楂樹寒
-        /// </summary>
-        public void Highlight(Point pt)
-        {
-            var visual = _viewport.FindNearestVisual(pt);
-            if (visual == null)
-            {
-                Reset();
-                return;
-            }
-            if (_visual == visual)
-            {
-                return;
-            }
-            Reset();
-            _visual = visual;
-            this.StateChangedEvent?.Invoke(_visual, eHighlightType.Load);
-        }
-
-        //閲嶇疆
-        private void Reset()
-        {
-            if (_visual != null)
-            {
-                this.StateChangedEvent?.Invoke(_visual, eHighlightType.Unload);
-                _visual = null;
-            }
-        }
-
-
-
-
-
-    }
-}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/02-helper/05-selection/eSelectionType.cs b/Yw.WpfUI.Hydro.L3d.Core/02-helper/05-selection/eSelectionType.cs
deleted file mode 100644
index f58be9a..0000000
--- a/Yw.WpfUI.Hydro.L3d.Core/02-helper/05-selection/eSelectionType.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-锘縩amespace Yw.WpfUI.Hydro
-{
-    /// <summary>
-    /// 閫夋嫨绫诲瀷
-    /// </summary>
-    internal enum eSelectionType
-    {
-        /// <summary>
-        /// 鍔犺浇
-        /// </summary>
-        Load,
-
-        /// <summary>
-        /// 鍗歌浇
-        /// </summary>
-        Unload
-    }
-
-}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/02-helper/08-state/VisualStateManager.cs b/Yw.WpfUI.Hydro.L3d.Core/02-helper/08-state/VisualStateManager.cs
deleted file mode 100644
index 64b8791..0000000
--- a/Yw.WpfUI.Hydro.L3d.Core/02-helper/08-state/VisualStateManager.cs
+++ /dev/null
@@ -1,93 +0,0 @@
-锘縩amespace Yw.WpfUI.Hydro
-{
-    /// <summary>
-    /// 绠�鍗曠姸鎬佺鐞嗗櫒
-    /// </summary>
-    internal class VisualStateManager
-    {
-        //缂撳瓨
-        private readonly Dictionary<VisualL3d, eVisualState> _cache = new();
-
-        /// <summary>
-        /// 鍒濆鍖�
-        /// </summary>
-        public void Initial(List<VisualL3d> allVisualList)
-        {
-            _cache.Clear();
-            allVisualList?.ForEach(x => _cache.Add(x, eVisualState.Normal));
-        }
-
-        /// <summary>
-        /// 璁剧疆
-        /// </summary>
-        public void SetState(VisualL3d visual, eVisualState state)
-        {
-            if (visual == null)
-            {
-                return;
-            }
-            _cache[visual] = state;
-        }
-
-        /// <summary>
-        /// 鍔犺浇鐘舵��
-        /// </summary>
-        public void LoadState(VisualL3d visual, eVisualState state)
-        {
-            var origin = GetState(visual);
-            _cache[visual] = origin | state;
-        }
-
-        /// <summary>
-        /// 鍗歌浇鐘舵��
-        /// </summary>
-        public void UnloadState(VisualL3d visual, eVisualState state)
-        {
-            var origin = GetState(visual);
-            _cache[visual] = origin ^ state;
-        }
-
-        /// <summary>
-        /// 鑾峰彇鐘舵��
-        /// </summary>
-        public eVisualState GetState(VisualL3d visual)
-        {
-            if (visual == null)
-            {
-                return eVisualState.Normal;
-            }
-            if (!_cache.ContainsKey(visual))
-            {
-                return eVisualState.Normal;
-            }
-            return _cache[visual];
-        }
-
-        /// <summary>
-        /// 鑾峰彇鏈夋晥鐘舵��
-        /// </summary>
-        public eVisualState GetEffectState(VisualL3d visual)
-        {
-            var state = GetState(visual);
-            if (state == eVisualState.None)
-            {
-                return eVisualState.Normal;
-            }
-            if ((state & eVisualState.Highlight) == eVisualState.Highlight)
-            {
-                return eVisualState.Highlight;
-            }
-            if ((state & eVisualState.Selection) == eVisualState.Selection)
-            {
-                return eVisualState.Selection;
-            }
-            if ((state & eVisualState.OverrideColor) == eVisualState.OverrideColor)
-            {
-                return eVisualState.OverrideColor;
-            }
-            return eVisualState.Normal;
-        }
-
-
-    }
-}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/02-helper/08-state/eVisualState.cs b/Yw.WpfUI.Hydro.L3d.Core/02-helper/08-state/eVisualState.cs
deleted file mode 100644
index 15af18f..0000000
--- a/Yw.WpfUI.Hydro.L3d.Core/02-helper/08-state/eVisualState.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-锘縩amespace Yw.WpfUI.Hydro
-{
-    /// <summary>
-    /// 鏋勪欢鐘舵��
-    /// </summary>
-    [Flags]
-    internal enum eVisualState
-    {
-        /// <summary>
-        /// 鏃�
-        /// </summary>
-        None = 0x00,
-
-        /// <summary>
-        /// 姝e父
-        /// </summary>
-        Normal = 0x01,
-
-        /// <summary>
-        /// 閫変腑
-        /// </summary>
-        Selection = 0x02,
-
-        /// <summary>
-        /// 楂樹寒
-        /// </summary>
-        Highlight = 0x04,
-
-        /// <summary>
-        /// 鐫�鑹�
-        /// </summary>
-        OverrideColor = 0x08
-    }
-}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/02-helper/09-view/SimpleViewManager.cs b/Yw.WpfUI.Hydro.L3d.Core/02-helper/09-view/SimpleViewManager.cs
deleted file mode 100644
index c5c235b..0000000
--- a/Yw.WpfUI.Hydro.L3d.Core/02-helper/09-view/SimpleViewManager.cs
+++ /dev/null
@@ -1,468 +0,0 @@
-锘縩amespace Yw.WpfUI.Hydro
-{
-    internal class SimpleViewManager
-    {
-        public SimpleViewManager(HelixViewport3D viewport)
-        {
-            _viewport = viewport;
-            _materialManager = new SimpleMaterialManager();
-            _geometryManager = new SimpleGeometryManager();
-            _highlightManager = new SimpleHighlightManager(viewport);
-            _highlightManager.StateChangedEvent += HighlightManager_StateChangedEvent;
-            _selectionManager = new SimpleSelectionManager(viewport);
-            _selectionManager.StateChangedEvent += SelectionManager_StateChangedEvent;
-            _selectionManager.SelectionChangedEvent += SelectionManager_SelectionChangedEvent;
-            _colorOverrideManager = new ColorOverrideManager();
-            _zoomManger = new ZoomManager(viewport);
-            _stateManager = new VisualStateManager();
-
-            _highlightColor = ConstParas.SimpleHighlightColor.ToMediaColor();
-            _highlightFactor = ConstParas.SimpleHighlightFactor;
-            _selectionColor = ConstParas.SimpleSelectionColor.ToMediaColor();
-            _selectionFactor = ConstParas.SimpleSelectionFactor;
-        }
-
-        #region 鍥哄畾璧勬簮
-
-        private readonly HelixViewport3D _viewport = null;
-        private readonly SimpleMaterialManager _materialManager = null;
-        private readonly SimpleGeometryManager _geometryManager = null;
-
-
-        private readonly VisualStateManager _stateManager = null;
-
-        private readonly Color _highlightColor;
-        private readonly double _highlightFactor;
-        private readonly Color _selectionColor;
-        private readonly double _selectionFactor;
-
-        #endregion
-
-        #region 绉佹湁瀛楁
-
-        private NetworkL3d _nw = null;
-        private Dictionary<string, VisualL3d> _allVisualL3dDict;
-        private Dictionary<VisualL3d, Visual3D> _allVisualModelDict;
-
-        #endregion
-
-        #region 鍒濆鍖�
-
-        /// <summary>
-        /// 鏄惁鍒濆鍖�
-        /// </summary>
-        public bool Initialized
-        {
-            get
-            {
-                if (_nw == null)
-                {
-                    return false;
-                }
-                if (_allVisualL3dDict == null)
-                {
-                    return false;
-                }
-                if (_allVisualModelDict == null)
-                {
-                    return false;
-                }
-                return true;
-            }
-        }
-
-        /// <summary>
-        /// 鍒濆鍖�
-        /// </summary>
-        public void Initial(NetworkL3d nw)
-        {
-            InitialNetwork(nw);
-            InitialViewport();
-            InitialManager();
-        }
-
-        //鍔犺浇绠$綉
-        private void InitialNetwork(NetworkL3d nw)
-        {
-            _nw = nw;
-            if (_nw == null)
-            {
-                return;
-            }
-            _allVisualL3dDict = _nw.Visuals.ToDictionary(x => x.Id);
-            _allVisualModelDict = new Dictionary<VisualL3d, Visual3D>();
-            _nw.Links.ForEach(x =>
-            {
-                var visual3d = CreateVisual3D(x);
-                _allVisualModelDict.Add(x, visual3d);
-            });
-            _nw.Nodes.ForEach(x =>
-            {
-                var visual3d = CreateVisual3D(x);
-                _allVisualModelDict.Add(x, visual3d);
-            });
-        }
-
-        //鍒濆鍖朧ieport
-        private void InitialViewport()
-        {
-            _viewport.Children.Clear();
-            _viewport.Children.Add(new DefaultLights());
-            _viewport.ViewCubeBackText = "鍚�";
-            _viewport.ViewCubeBottomText = "涓�";
-            _viewport.ViewCubeFrontText = "鍓�";
-            _viewport.ViewCubeLeftText = "宸�";
-            _viewport.ViewCubeRightText = "鍙�";
-            _viewport.ViewCubeTopText = "涓�";
-            //_viewport.CameraController.ZoomAroundMouseDownPoint = true;
-            //_viewport.CameraController.ZoomSensitivity = 1.1; // 璁剧疆缂╂斁鐏垫晱搴�
-            _allVisualModelDict?.Values.ToList().ForEach(x => _viewport.Children.Add(x));
-            _viewport.ZoomExtents();
-        }
-
-        //鍒濆鍖栫鐞嗗櫒
-        private void InitialManager()
-        {
-            _stateManager.Initial(_allVisualL3dDict?.Values.ToList());
-        }
-
-
-        #endregion
-
-        #region 楂樹寒
-
-        //楂樹寒绠$悊鍣�
-        private readonly SimpleHighlightManager _highlightManager = null;
-
-        /// <summary>
-        /// 楂樹寒鏄剧ず
-        /// </summary>
-        public void Highlight(Point pt)
-        {
-            if (!Initialized)
-            {
-                return;
-            }
-            _highlightManager.Highlight(pt);
-        }
-
-        //楂樹寒鐘舵�佹敼鍙樹簨浠�
-        private void HighlightManager_StateChangedEvent(Visual3D visual3d, eHighlightType highlightType)
-        {
-            if (visual3d == null)
-            {
-                return;
-            }
-            var visual = Visual3DProperties.GetTag(visual3d);
-            if (visual == null)
-            {
-                return;
-            }
-            switch (highlightType)
-            {
-                case eHighlightType.Load:
-                    {
-                        _stateManager.LoadState(visual, eVisualState.Highlight);
-                    }
-                    break;
-                case eHighlightType.Unload:
-                    {
-                        _stateManager.UnloadState(visual, eVisualState.Highlight);
-                    }
-                    break;
-                default: break;
-            }
-            UpdateVisual3D(visual, visual3d);
-        }
-
-        #endregion
-
-        #region 閫夋嫨
-
-        /// <summary>
-        /// 閫夋嫨鏀瑰彉浜嬩欢
-        /// </summary>
-        public event Action<List<VisualL3d>> SelectionChangedEvent;
-
-        //閫夋嫨绠$悊鍣�
-        private readonly SimpleSelectionManager _selectionManager = null;
-
-        /// <summary>
-        /// 澶勭悊鍗曚釜閫夋嫨
-        /// </summary>
-        public void HandleSingleSelection(Point pt)
-        {
-            if (!Initialized)
-            {
-                return;
-            }
-            _selectionManager.HandleSingle(pt);
-        }
-
-        //閫夋嫨鐘舵�佹敼鍙樹簨浠�
-        private void SelectionManager_StateChangedEvent(Visual3D visual3d, eSelectionType selectionType)
-        {
-            if (visual3d == null)
-            {
-                return;
-            }
-            var visual = Visual3DProperties.GetTag(visual3d);
-            if (visual == null)
-            {
-                return;
-            }
-            switch (selectionType)
-            {
-                case eSelectionType.Load:
-                    {
-                        _stateManager.LoadState(visual, eVisualState.Selection);
-                    }
-                    break;
-                case eSelectionType.Unload:
-                    {
-                        _stateManager.UnloadState(visual, eVisualState.Selection);
-                    }
-                    break;
-                default: break;
-            }
-            UpdateVisual3D(visual, visual3d);
-        }
-
-        //閫夋嫨鏀瑰彉浜嬩欢
-        private void SelectionManager_SelectionChangedEvent(List<Visual3D> visual3ds)
-        {
-            var visuals = visual3ds?.Select(x => Visual3DProperties.GetTag(x)).ToList();
-            this.SelectionChangedEvent?.Invoke(visuals);
-        }
-
-        #endregion
-
-        #region 缂╂斁
-
-        //缂╂斁绠$悊鍣�
-        private readonly ZoomManager _zoomManger = null;
-
-        public void ZoomToVisual(string Id)
-        {
-            if (!Initialized)
-            {
-                return;
-            }
-            var visual = _allVisualL3dDict[Id];
-            if (visual == null)
-            {
-                return;
-            }
-            var visual3d = _allVisualModelDict[visual];
-            if (visual3d == null)
-            {
-                return;
-            }
-            _zoomManger.ZoomToVisual(visual3d);
-        }
-
-        #endregion
-
-        #region 鐫�鑹�
-
-        //鏋勪欢鐫�鑹茬鐞嗗櫒
-        private readonly ColorOverrideManager _colorOverrideManager = null;
-
-        /// <summary>
-        /// 閫氳繃Id 瑕嗙洊棰滆壊
-        /// </summary>
-        public void OverrideColorById(string id, string htmlColor)
-        {
-            if (!Initialized)
-            {
-                return;
-            }
-            var visual = _allVisualL3dDict[id];
-            if (visual == null)
-            {
-                return;
-            }
-            _colorOverrideManager.SetColor(visual, htmlColor);
-            _stateManager.LoadState(visual, eVisualState.OverrideColor);
-            var visual3d = _allVisualModelDict[visual];
-            UpdateVisual3D(visual, visual3d);
-        }
-
-        /// <summary>
-        /// 閫氳繃 ids 瑕嗙洊棰滆壊
-        /// </summary>
-        public void OverrideColorByIds(List<string> ids, string htmlColor)
-        {
-            if (!Initialized)
-            {
-                return;
-            }
-            ids?.ForEach(x => OverrideColorById(x, htmlColor));
-        }
-
-        /// <summary>
-        /// 閫氳繃 id 鎭㈠棰滆壊
-        /// </summary>
-        public void RestoreColorById(string id)
-        {
-            if (!Initialized)
-            {
-                return;
-            }
-            var visual = _allVisualL3dDict[id];
-            if (visual == null)
-            {
-                return;
-            }
-            _colorOverrideManager.ClearColor(visual);
-            _stateManager.UnloadState(visual, eVisualState.OverrideColor);
-            var visual3d = _allVisualModelDict[visual];
-            UpdateVisual3D(visual, visual3d);
-        }
-
-        /// <summary>
-        /// 閫氳繃 ids 鎭㈠棰滆壊
-        /// </summary>
-        public void RestoreColorByIds(List<string> ids)
-        {
-            if (!Initialized)
-            {
-                return;
-            }
-            ids?.ForEach(x => RestoreColorById(x));
-        }
-
-        #endregion
-
-        #region 缁樺埗閫昏緫
-
-        //鏇存柊Visual3D
-        private void UpdateVisual3D(VisualL3d visual, Visual3D visual3d)
-        {
-            var state = _stateManager.GetEffectState(visual);
-            var model3d = (visual3d as ModelVisual3D).Content as GeometryModel3D;
-            model3d.Material = GetMaterial(visual, state);
-            model3d.Geometry = GetGeometry(visual, state);
-        }
-
-        //鍒涘缓Visual3D
-        private Visual3D CreateVisual3D(VisualL3d visual)
-        {
-            var visual3d = new ModelVisual3D()
-            {
-                Content = CreateModel3D(visual)
-            };
-            Visual3DProperties.SetTag(visual3d, visual);
-            return visual3d;
-        }
-
-        //鍒涘缓Model3D
-        private Model3D CreateModel3D(VisualL3d visual)
-        {
-            var state = _stateManager.GetEffectState(visual);
-
-            return new GeometryModel3D()
-            {
-                Geometry = GetGeometry(visual, state),
-                Material = GetMaterial(visual, state),
-            };
-        }
-
-        //鑾峰彇鏉愯川
-        private Material GetMaterial(VisualL3d visual, eVisualState state)
-        {
-            var color = GetVisual3DColor(visual, state);
-            return _materialManager.GetMaterial(color);
-        }
-
-        //鑾峰彇鍑犱綍浣�
-        private Geometry3D GetGeometry(VisualL3d visual, eVisualState state)
-        {
-            var size = GetVisual3DSize(visual, state);
-            var factor = GetVisual3DFactor(visual, state);
-            return _geometryManager.GetGeometry(visual, size, factor);
-        }
-
-        //鑾峰彇棰滆壊
-        private Color GetVisual3DColor(VisualL3d visual, eVisualState state)
-        {
-            Color color;
-            switch (state)
-            {
-                case eVisualState.Highlight:
-                    {
-                        color = _highlightColor;
-                    }
-                    break;
-                case eVisualState.Selection:
-                    {
-                        color = _selectionColor;
-                    }
-                    break;
-                case eVisualState.OverrideColor:
-                    {
-                        var cv = _colorOverrideManager.GetColor(visual);
-                        if (cv.HasValue)
-                        {
-                            color = cv.Value;
-                        }
-                    }
-                    break;
-                default:
-                    {
-                        color = visual.SimpleStyle.HtmlColor.ToMediaColor();
-                    }
-                    break;
-            }
-            return color;
-        }
-
-        //鑾峰彇灏哄
-        private double GetVisual3DSize(VisualL3d visual, eVisualState state)
-        {
-            if (visual is NodeL3d node)
-            {
-                return node.SimpleStyle.Radiu;
-            }
-            if (visual is LinkL3d link)
-            {
-                return link.SimpleStyle.Diameter;
-            }
-            return default;
-        }
-
-        //鑾峰彇鍥犲瓙
-        private double GetVisual3DFactor(VisualL3d visual, eVisualState state)
-        {
-            double factor = 1.0d;
-            switch (state)
-            {
-                case eVisualState.Highlight:
-                    {
-                        factor = _highlightFactor;
-                    }
-                    break;
-                case eVisualState.Selection:
-                    {
-                        factor = _selectionFactor;
-                    }
-                    break;
-                case eVisualState.OverrideColor:
-                    {
-
-                    }
-                    break;
-                default:
-                    {
-                        factor = 1.0d;
-                    }
-                    break;
-            }
-            return factor;
-        }
-
-        #endregion
-
-
-    }
-}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/02-settings/00-core/HydroL3dFileHelper.cs b/Yw.WpfUI.Hydro.L3d.Core/02-settings/00-core/HydroL3dFileHelper.cs
new file mode 100644
index 0000000..fb75624
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/02-settings/00-core/HydroL3dFileHelper.cs
@@ -0,0 +1,65 @@
+锘縩amespace Yw.Settings
+{
+    /// <summary>
+    /// 鏂囦欢杈呭姪绫�
+    /// </summary>
+    internal class HydroL3dFileHelper
+    {
+        /// <summary>
+        /// json鏂囦欢鍚嶇О
+        /// </summary>
+        internal static string JsonFileName
+        {
+            get
+            {
+                if (string.IsNullOrEmpty(_jsonFileName))
+                {
+                    _jsonFileName = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "paras_hydrol3d_settings.json");
+                }
+                return _jsonFileName;
+            }
+        }
+        private static string _jsonFileName = null;
+
+        /// <summary>
+        /// 鑾峰彇
+        /// </summary>
+        internal static HydroL3dParas Get()
+        {
+            if (_appparas == null)
+            {
+                lock (_locker)
+                {
+                    if (_appparas == null)
+                    {
+                        var json = File.ReadAllText(JsonFileName, Encoding.UTF8);
+                        _appparas = JsonHelper.Json2Object<HydroL3dParas>(json);
+                        if (_appparas == null)
+                        {
+                            _appparas = new HydroL3dParas();
+                        }
+                    }
+                }
+            }
+            return _appparas;
+        }
+        private static HydroL3dParas _appparas = null;
+        private static readonly object _locker = new object();
+
+        /// <summary>
+        /// 淇濆瓨
+        /// </summary>
+        /// <returns></returns>
+        internal static bool Save()
+        {
+            if (_appparas == null)
+            {
+                return default;
+            }
+            var json = JsonHelper.Object2FormatJson(_appparas);
+            File.WriteAllText(JsonFileName, json, Encoding.UTF8);
+            return true;
+        }
+
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/02-settings/00-core/HydroL3dParasHelper.cs b/Yw.WpfUI.Hydro.L3d.Core/02-settings/00-core/HydroL3dParasHelper.cs
new file mode 100644
index 0000000..7929210
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/02-settings/00-core/HydroL3dParasHelper.cs
@@ -0,0 +1,27 @@
+锘縩amespace Yw.Settings
+{
+    /// <summary>
+    /// 
+    /// </summary>
+    public class HydroL3dParasHelper
+    {
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public static Paras_HydroL3d HydroL3d
+        {
+            get { return HydroL3dFileHelper.Get().HydroL3d; }
+        }
+
+        /// <summary>
+        /// 淇濆瓨
+        /// </summary>
+        public static bool Save()
+        {
+            return HydroL3dFileHelper.Save();
+        }
+
+
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/00-core/HydroL3dParas.cs b/Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/00-core/HydroL3dParas.cs
new file mode 100644
index 0000000..6019b92
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/00-core/HydroL3dParas.cs
@@ -0,0 +1,13 @@
+锘縩amespace Yw.Settings
+{
+    /// <summary>
+    /// 
+    /// </summary>
+    internal class HydroL3dParas
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public Paras_HydroL3d HydroL3d { get; set; }
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/00-core/Paras_HydroL3d.cs b/Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/00-core/Paras_HydroL3d.cs
new file mode 100644
index 0000000..86db52e
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/00-core/Paras_HydroL3d.cs
@@ -0,0 +1,15 @@
+锘縩amespace Yw.Settings
+{
+    /// <summary>
+    /// 
+    /// </summary>
+    public class Paras_HydroL3d
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public Paras_HydroL3d_Logical Logical { get; set; }
+
+
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/00-core/Paras_HydroL3d_Line.cs b/Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/00-core/Paras_HydroL3d_Line.cs
new file mode 100644
index 0000000..67a7396
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/00-core/Paras_HydroL3d_Line.cs
@@ -0,0 +1,21 @@
+锘縩amespace Yw.Settings
+{
+    /// <summary>
+    /// 绾�
+    /// </summary>
+    public class Paras_HydroL3d_Line
+    {
+        /// <summary>
+        /// Html棰滆壊
+        /// </summary>
+        public string HtmlColor { get; set; }
+
+        /// <summary>
+        /// 鐩村緞
+        /// </summary>
+        public double Diameter { get; set; }
+
+
+
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/00-core/Paras_HydroL3d_Logical.cs b/Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/00-core/Paras_HydroL3d_Logical.cs
new file mode 100644
index 0000000..b159b67
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/00-core/Paras_HydroL3d_Logical.cs
@@ -0,0 +1,19 @@
+锘縩amespace Yw.Settings
+{
+    /// <summary>
+    /// 鎶借薄
+    /// </summary>
+    public class Paras_HydroL3d_Logical
+    {
+        /// <summary>
+        /// 鑺傜偣
+        /// </summary>
+        public Paras_HydroL3d_Logical_Node Node { get; set; }
+
+        /// <summary>
+        /// 绠℃
+        /// </summary>
+        public Paras_HydroL3d_Logical_Link Link { get; set; }
+
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/00-core/Paras_HydroL3d_Point.cs b/Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/00-core/Paras_HydroL3d_Point.cs
new file mode 100644
index 0000000..f682f82
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/00-core/Paras_HydroL3d_Point.cs
@@ -0,0 +1,20 @@
+锘縩amespace Yw.Settings
+{
+    /// <summary>
+    /// 鐐�
+    /// </summary>
+    public class Paras_HydroL3d_Point
+    {
+        /// <summary>
+        /// Html棰滆壊
+        /// </summary>
+        public string HtmlColor { get; set; }
+
+        /// <summary>
+        /// 鍗婂緞
+        /// </summary>
+        public double Radius { get; set; }
+
+
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/01-node/00-core/Paras_HydroL3d_Logical_Node.cs b/Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/01-node/00-core/Paras_HydroL3d_Logical_Node.cs
new file mode 100644
index 0000000..d2c211d
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/01-node/00-core/Paras_HydroL3d_Logical_Node.cs
@@ -0,0 +1,34 @@
+锘縩amespace Yw.Settings
+{
+    /// <summary>
+    /// 鎶借薄鑺傜偣
+    /// </summary>
+    public class Paras_HydroL3d_Logical_Node
+    {
+        /// <summary>
+        /// 姝e父
+        /// </summary>
+        public Paras_HydroL3d_Point Normal { get; set; }
+
+        /// <summary>
+        /// 楂樹寒
+        /// </summary>
+        public Paras_HydroL3d_Point Highlight { get; set; }
+
+        /// <summary>
+        /// 閫夋嫨
+        /// </summary>
+        public Paras_HydroL3d_Point Selection { get; set; }
+
+        /// <summary>
+        /// 鍚搁檮璺濈
+        /// </summary>
+        public double SnapDistance { get; set; }
+
+
+
+
+
+    }
+
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/02-link/00-core/Paras_HydroL3d_Logical_Link.cs b/Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/02-link/00-core/Paras_HydroL3d_Logical_Link.cs
new file mode 100644
index 0000000..de76daf
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/02-settings/01-paras/02-link/00-core/Paras_HydroL3d_Logical_Link.cs
@@ -0,0 +1,32 @@
+锘縩amespace Yw.Settings
+{
+    /// <summary>
+    /// 鎶借薄绠℃
+    /// </summary>
+    public class Paras_HydroL3d_Logical_Link
+    {
+        /// <summary>
+        /// 姝e父
+        /// </summary>
+        public Paras_HydroL3d_Line Normal { get; set; }
+
+        /// <summary>
+        /// 楂樹寒
+        /// </summary>
+        public Paras_HydroL3d_Line Highlight { get; set; }
+
+        /// <summary>
+        /// 閫夋嫨
+        /// </summary>
+        public Paras_HydroL3d_Line Selection { get; set; }
+
+
+
+
+
+
+
+
+    }
+
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/03-control/ViewerL3d.xaml.cs b/Yw.WpfUI.Hydro.L3d.Core/03-control/ViewerL3d.xaml.cs
deleted file mode 100644
index 5bd1de1..0000000
--- a/Yw.WpfUI.Hydro.L3d.Core/03-control/ViewerL3d.xaml.cs
+++ /dev/null
@@ -1,125 +0,0 @@
-锘縰sing System.Windows;
-using System.Windows.Controls;
-using System.Windows.Media;
-
-namespace Yw.WpfUI.Hydro
-{
-    /// <summary>
-    /// DrawerL3d.xaml 鐨勪氦浜掗�昏緫
-    /// </summary>
-    public partial class ViewerL3d : UserControl
-    {
-        public ViewerL3d()
-        {
-            InitializeComponent();
-        }
-
-        #region 浜嬩欢闆嗗悎
-
-        /// <summary>
-        /// 閫夋嫨鏀瑰彉浜嬩欢
-        /// </summary>
-        public event Action<List<VisualL3d>> SelectionChangedEvent;
-
-        #endregion
-
-        private SimpleViewManager _manager = null;
-
-        /// <summary>
-        /// 鍒濆鍖�
-        /// </summary>
-        public void Initial(NetworkL3d nw)
-        {
-            _manager = new SimpleViewManager(this.viewport);
-            _manager.Initial(nw);
-            _manager.SelectionChangedEvent += (List<VisualL3d> visuals) => this.SelectionChangedEvent?.Invoke(visuals);
-        }
-
-
-
-        //榧犳爣绉诲姩
-        private void viewport_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
-        {
-            _manager?.Highlight(e.GetPosition(this.viewport));
-        }
-
-        //榧犳爣婊氳疆婊氬姩
-        private void viewport_MouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
-        {
-
-        }
-
-        //榧犳爣鎸変笅
-        private void viewport_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
-        {
-
-        }
-
-        //榧犳爣鎶捣
-        private void viewport_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
-        {
-            _manager?.HandleSingleSelection(e.GetPosition(this.viewport));
-        }
-
-        #region 缂╂斁
-
-        /// <summary>
-        /// 缂╂斁鑷砎isual
-        /// </summary>
-        public void ZoomToVisual(string Id)
-        {
-
-        }
-
-        /// <summary>
-        /// 缂╂斁鑷砎isuals
-        /// </summary>
-        public void ZoomToVisuals(List<string> Ids)
-        {
-
-        }
-
-        #endregion
-
-        #region 閫夋嫨
-
-        /// <summary>
-        /// 閫夋嫨Visual
-        /// </summary>
-        public void SelectVisual(string Id)
-        {
-
-        }
-
-        /// <summary>
-        /// 閫夋嫨Visuals
-        /// </summary>
-        public void SelectVisuals(List<string> Ids)
-        {
-
-        }
-
-        #endregion
-
-        #region 缂╂斁骞朵笖閫夋嫨
-
-        /// <summary>
-        /// 缂╂斁骞朵笖閫夋嫨Visual
-        /// </summary>
-        public void ZoomAndSelectVisual(string Id)
-        {
-
-        }
-
-        /// <summary>
-        /// 缂╂斁骞朵笖閫夋嫨Visuals
-        /// </summary>
-        public void ZoomAndSelectVisuals(List<string> Ids)
-        {
-
-        }
-
-        #endregion
-
-    }
-}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/03-logical/00-core/LogicalCreateHelper.cs b/Yw.WpfUI.Hydro.L3d.Core/03-logical/00-core/LogicalCreateHelper.cs
new file mode 100644
index 0000000..477753b
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/00-core/LogicalCreateHelper.cs
@@ -0,0 +1,56 @@
+锘縩amespace Yw.WpfUI.Hydro
+{
+    /// <summary>
+    /// 鎶借薄鍒涘缓杈呭姪绫�
+    /// </summary>
+    internal class LogicalCreateHelper
+    {
+        /// <summary>
+        /// 鍒涘缓
+        /// </summary>
+        /// <param name="visuall3d"></param>
+        /// <param name="stateHelper"></param>
+        /// <param name="materialHelper"></param>
+        /// <param name="overrideColorHelper"></param>
+        /// <param name="overrideOpacityHelper"></param>
+        /// <param name="overrideVisibleHelper"></param>
+        /// <returns></returns>
+        public static LogicalVisual3D Create
+            (
+                VisualL3d visuall3d,
+                LogicalStateHelper stateHelper,
+                LogicalMaterialHelper materialHelper,
+                LogicalOverrideColorHelper overrideColorHelper,
+                LogicalOverrideOpacityHelper overrideOpacityHelper,
+                LogicalOverrideVisibleHelper overrideVisibleHelper
+            )
+        {
+            if (visuall3d == null)
+            {
+                return default;
+            }
+            if (visuall3d is JunctionL3d junctionl3d)
+            {
+                return new LogicalJunction3D(junctionl3d, stateHelper, materialHelper, overrideColorHelper, overrideOpacityHelper, overrideVisibleHelper);
+            }
+            if (visuall3d is SourceL3d sourcel3d)
+            {
+                return new LogicalSource3D(sourcel3d, stateHelper, materialHelper, overrideColorHelper, overrideOpacityHelper, overrideVisibleHelper);
+            }
+            if (visuall3d is PipeL3d pipel3d)
+            {
+                return new LogicalPipe3D(pipel3d, stateHelper, materialHelper, overrideColorHelper, overrideOpacityHelper, overrideVisibleHelper);
+            }
+            if (visuall3d is PumpL3d pumpl3d)
+            {
+                return new LogicalPump3D(pumpl3d, stateHelper, materialHelper, overrideColorHelper, overrideOpacityHelper, overrideVisibleHelper);
+            }
+            if (visuall3d is ValveL3d valvel3d)
+            {
+                return new LogicalValve3D(valvel3d, stateHelper, materialHelper, overrideColorHelper, overrideOpacityHelper, overrideVisibleHelper);
+            }
+            return default;
+        }
+
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/00-core/LogicalVisual3D.cs b/Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/00-core/LogicalVisual3D.cs
new file mode 100644
index 0000000..147812b
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/00-core/LogicalVisual3D.cs
@@ -0,0 +1,73 @@
+锘縩amespace Yw.WpfUI.Hydro
+{
+    /// <summary>
+    /// 鎶借薄3D鍙鍏冪礌
+    /// </summary>
+    internal abstract class LogicalVisual3D : MeshGeometryVisual3D
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public LogicalVisual3D() { }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public LogicalVisual3D
+            (
+                VisualL3d vmo,
+                LogicalStateHelper stateHelper,
+                LogicalMaterialHelper materialHelper,
+                LogicalOverrideColorHelper overrideColorHelper,
+                LogicalOverrideOpacityHelper overrideOpacityHelper,
+                LogicalOverrideVisibleHelper overrideVisibleHelper
+            )
+        {
+            this.Vmo = vmo;
+            _stateHelper = stateHelper;
+            _materialHelper = materialHelper;
+            _overrideColorHelper = overrideColorHelper;
+            _overrideOpacityHelper = overrideOpacityHelper;
+            _overrideVisibleHelper = overrideVisibleHelper;
+            UpdateVisual();
+        }
+
+        protected readonly LogicalStateHelper _stateHelper = null; //鐘舵�佽緟鍔╃被
+        protected readonly LogicalMaterialHelper _materialHelper = null; //鏉愯川杈呭姪绫�
+        protected readonly LogicalOverrideColorHelper _overrideColorHelper = null;//瑕嗙洊棰滆壊杈呭姪绫�
+        protected readonly LogicalOverrideOpacityHelper _overrideOpacityHelper = null;//瑕嗙洊閫忔槑搴﹁緟鍔╃被
+        protected readonly LogicalOverrideVisibleHelper _overrideVisibleHelper = null;//瑕嗙洊鍙鎬ц緟鍔╃被
+
+
+        /// <summary>
+        /// Vmo
+        /// </summary>
+        public VisualL3d Vmo
+        {
+            get { return _vmo; }
+            set { _vmo = value; }
+        }
+        protected VisualL3d _vmo = null;
+
+        /// <summary>
+        /// 鏇存柊鍙鍏冪礌
+        /// </summary>
+        public virtual void UpdateVisual()
+        {
+            this.UpdateGeometry();
+            this.UpdateMaterial();
+            this.UpdateVisibility();
+        }
+
+        //鏇存柊鏉愯川
+        protected abstract void UpdateMaterial();
+
+        //鏇存柊鍑犱綍鍥惧舰
+        protected abstract void UpdateGeometry();
+
+        //鏇存柊鍙鎬�
+        protected abstract void UpdateVisibility();
+
+
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/01-node/00-core/LogicalNode3D.cs b/Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/01-node/00-core/LogicalNode3D.cs
new file mode 100644
index 0000000..3ff63a9
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/01-node/00-core/LogicalNode3D.cs
@@ -0,0 +1,54 @@
+锘縩amespace Yw.WpfUI.Hydro
+{
+    /// <summary>
+    /// 鎶借薄3D鑺傜偣
+    /// </summary>
+    internal abstract class LogicalNode3D : LogicalVisual3D
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public LogicalNode3D() { }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public LogicalNode3D
+            (
+                NodeL3d vmo,
+                LogicalStateHelper stateHelper,
+                LogicalMaterialHelper materialHelper,
+                LogicalOverrideColorHelper overrideColorHelper,
+                LogicalOverrideOpacityHelper overrideOpacityHelper,
+                LogicalOverrideVisibleHelper overrideVisibleHelper
+            ) : base(vmo, stateHelper, materialHelper, overrideColorHelper, overrideOpacityHelper, overrideVisibleHelper)
+        {
+            this.Position = vmo.Position.ToPoint3D();
+        }
+
+        /// <summary>
+        /// Vmo
+        /// </summary>
+        public new NodeL3d Vmo
+        {
+            get { return _vmo as NodeL3d; }
+            set { _vmo = value; }
+        }
+
+        /// <summary>
+        /// 浣嶇疆
+        /// </summary>
+        public Point3D Position { get; set; }
+
+        /// <summary>
+        /// 鏇存柊鍙鍖栧厓绱�
+        /// </summary>
+        public override void UpdateVisual()
+        {
+            this.Position = this.Vmo.Position.ToPoint3D();
+            base.UpdateVisual();
+        }
+
+
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/01-node/01-junction/00-core/LogicalJunction3D.cs b/Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/01-node/01-junction/00-core/LogicalJunction3D.cs
new file mode 100644
index 0000000..ea4f225
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/01-node/01-junction/00-core/LogicalJunction3D.cs
@@ -0,0 +1,99 @@
+锘縩amespace Yw.WpfUI.Hydro
+{
+    /// <summary>
+    /// 鎶借薄3D杩炴帴鑺傜偣
+    /// </summary>
+    internal class LogicalJunction3D : LogicalNode3D
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public LogicalJunction3D() { }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public LogicalJunction3D
+            (
+                JunctionL3d vmo,
+                LogicalStateHelper stateHelper,
+                LogicalMaterialHelper materialHelper,
+                LogicalOverrideColorHelper overrideColorHelper,
+                LogicalOverrideOpacityHelper overrideOpacityHelper,
+                LogicalOverrideVisibleHelper overrideVisibleHelper
+            ) : base(vmo, stateHelper, materialHelper, overrideColorHelper, overrideOpacityHelper, overrideVisibleHelper)
+        {
+
+        }
+
+        /// <summary>
+        /// Vmo
+        /// </summary>
+        public new JunctionL3d Vmo
+        {
+            get { return _vmo as JunctionL3d; }
+            set { _vmo = value; }
+        }
+
+        //鏇存柊鏉愯川
+        protected override void UpdateMaterial()
+        {
+            var htmlColor = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Node.Normal.HtmlColor;
+            var opacity = 1.0d;
+            var state = _stateHelper.GetState(this.Vmo);
+            if (state.HasFlag(eLogicalState.Color))
+            {
+                htmlColor = _overrideColorHelper.GetColor(this.Vmo);
+            }
+            if (state.HasFlag(eLogicalState.Opacity))
+            {
+                opacity = _overrideOpacityHelper.GetOpacity(this.Vmo);
+            }
+            if (state.HasFlag(eLogicalState.Selection))
+            {
+                htmlColor = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Node.Selection.HtmlColor;
+            }
+            if (state.HasFlag(eLogicalState.Highlight))
+            {
+                htmlColor = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Node.Highlight.HtmlColor;
+            }
+            var material = _materialHelper.GetMaterial(htmlColor, opacity);
+            this.Material = material;
+        }
+
+        //鏇存柊鍙鎬�
+        protected override void UpdateVisibility()
+        {
+            bool visible = true;
+            var state = _stateHelper.GetState(this.Vmo);
+            if (state.HasFlag(eLogicalState.Visible))
+            {
+                visible = _overrideVisibleHelper.GetVisible(this.Vmo);
+            }
+            this.Visible = visible;
+        }
+
+        //鏇存柊鍑犱綍鍥惧舰
+        protected override void UpdateGeometry()
+        {
+            var radius = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Node.Normal.Radius;
+            var state = _stateHelper.GetState(this.Vmo);
+            if (state.HasFlag(eLogicalState.Selection))
+            {
+                radius = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Node.Selection.Radius;
+            }
+            if (state.HasFlag(eLogicalState.Highlight))
+            {
+                radius = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Node.Highlight.Radius;
+            }
+
+            var pt = this.Vmo.Position.ToPoint3D();
+            MeshBuilder builder = new MeshBuilder();
+            builder.AddSphere(pt, radius);
+            var geometry = builder.ToMesh();
+            this.MeshGeometry = geometry;
+        }
+
+
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/01-node/02-source/00-core/LogicalSource3D.cs b/Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/01-node/02-source/00-core/LogicalSource3D.cs
new file mode 100644
index 0000000..8a26800
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/01-node/02-source/00-core/LogicalSource3D.cs
@@ -0,0 +1,102 @@
+锘縩amespace Yw.WpfUI.Hydro
+{
+    /// <summary>
+    /// 鎶借薄3D姘存簮
+    /// </summary>
+    internal class LogicalSource3D : LogicalNode3D
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public LogicalSource3D() { }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public LogicalSource3D
+            (
+                SourceL3d vmo,
+                LogicalStateHelper stateHelper,
+                LogicalMaterialHelper materialHelper,
+                LogicalOverrideColorHelper overrideColorHelper,
+                LogicalOverrideOpacityHelper overrideOpacityHelper,
+                LogicalOverrideVisibleHelper overrideVisibleHelper
+            ) : base(vmo, stateHelper, materialHelper, overrideColorHelper, overrideOpacityHelper, overrideVisibleHelper)
+        {
+
+        }
+
+        /// <summary>
+        /// Vmo
+        /// </summary>
+        public new SourceL3d Vmo
+        {
+            get { return _vmo as SourceL3d; }
+            set { _vmo = value; }
+        }
+
+        //鏇存柊鏉愯川
+        protected override void UpdateMaterial()
+        {
+            var htmlColor = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Node.Normal.HtmlColor;
+            var opacity = 1.0d;
+            var state = _stateHelper.GetState(this.Vmo);
+            if (state.HasFlag(eLogicalState.Color))
+            {
+                htmlColor = _overrideColorHelper.GetColor(this.Vmo);
+            }
+            if (state.HasFlag(eLogicalState.Opacity))
+            {
+                opacity = _overrideOpacityHelper.GetOpacity(this.Vmo);
+            }
+            if (state.HasFlag(eLogicalState.Selection))
+            {
+                htmlColor = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Node.Selection.HtmlColor;
+            }
+            if (state.HasFlag(eLogicalState.Highlight))
+            {
+                htmlColor = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Node.Highlight.HtmlColor;
+            }
+            var material = _materialHelper.GetMaterial(htmlColor, opacity);
+            this.Material = material;
+        }
+
+        //鏇存柊鍙鎬�
+        protected override void UpdateVisibility()
+        {
+            bool visible = true;
+            var state = _stateHelper.GetState(this.Vmo);
+            if (state.HasFlag(eLogicalState.Visible))
+            {
+                visible = _overrideVisibleHelper.GetVisible(this.Vmo);
+            }
+            this.Visible = visible;
+        }
+
+        //鏇存柊鍑犱綍鍥惧舰
+        protected override void UpdateGeometry()
+        {
+            var radius = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Node.Normal.Radius;
+            var state = _stateHelper.GetState(this.Vmo);
+            if (state.HasFlag(eLogicalState.Selection))
+            {
+                radius = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Node.Selection.Radius;
+            }
+            if (state.HasFlag(eLogicalState.Highlight))
+            {
+                radius = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Node.Highlight.Radius;
+            }
+
+            var pt = this.Vmo.Position.ToPoint3D();
+            var x = radius * 4d;
+            var y = radius * 4d;
+            var z = radius * 2d;
+            var builder = new MeshBuilder();
+            builder.AddBox(pt, x, y, z);
+            var geometry = builder.ToMesh();
+            this.MeshGeometry = geometry;
+        }
+
+
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/02-link/00-core/LogicalLink3D.cs b/Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/02-link/00-core/LogicalLink3D.cs
new file mode 100644
index 0000000..e9aa787
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/02-link/00-core/LogicalLink3D.cs
@@ -0,0 +1,60 @@
+锘縩amespace Yw.WpfUI.Hydro
+{
+    /// <summary>
+    /// 鎶借薄3D绠℃
+    /// </summary>
+    internal abstract class LogicalLink3D : LogicalVisual3D
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public LogicalLink3D() { }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public LogicalLink3D
+            (
+                LinkL3d vmo,
+                LogicalStateHelper stateHelper,
+                LogicalMaterialHelper materialHelper,
+                LogicalOverrideColorHelper overrideColorHelper,
+                LogicalOverrideOpacityHelper overrideOpacityHelper,
+                LogicalOverrideVisibleHelper overrideVisibleHelper
+            ) : base(vmo, stateHelper, materialHelper, overrideColorHelper, overrideOpacityHelper, overrideVisibleHelper)
+        {
+            this.StartPosition = vmo.StartPosition.ToPoint3D();
+            this.EndPosition = vmo.EndPosition.ToPoint3D();
+        }
+
+        /// <summary>
+        /// Vmo
+        /// </summary>
+        public new LinkL3d Vmo
+        {
+            get { return _vmo as LinkL3d; }
+            set { _vmo = value; }
+        }
+
+        /// <summary>
+        /// 寮�濮嬩綅缃�
+        /// </summary>
+        public Point3D StartPosition { get; set; }
+
+        /// <summary>
+        /// 缁撴潫浣嶇疆
+        /// </summary>
+        public Point3D EndPosition { get; set; }
+
+        /// <summary>
+        /// 鏇存柊鍙鍖栧厓绱�
+        /// </summary>
+        public override void UpdateVisual()
+        {
+            this.StartPosition = this.Vmo.StartPosition.ToPoint3D();
+            this.EndPosition = this.Vmo.EndPosition.ToPoint3D();
+            base.UpdateVisual();
+        }
+
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/02-link/01-pipe/LogicalPipe3D.cs b/Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/02-link/01-pipe/LogicalPipe3D.cs
new file mode 100644
index 0000000..f656907
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/02-link/01-pipe/LogicalPipe3D.cs
@@ -0,0 +1,107 @@
+锘縩amespace Yw.WpfUI.Hydro
+{
+    /// <summary>
+    /// 鎶借薄3D绠¢亾
+    /// </summary>
+    internal class LogicalPipe3D : LogicalLink3D
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public LogicalPipe3D() { }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public LogicalPipe3D
+            (
+                PipeL3d vmo,
+                LogicalStateHelper stateHelper,
+                LogicalMaterialHelper materialHelper,
+                LogicalOverrideColorHelper overrideColorHelper,
+                LogicalOverrideOpacityHelper overrideOpacityHelper,
+                LogicalOverrideVisibleHelper overrideVisibleHelper
+            ) : base(vmo, stateHelper, materialHelper, overrideColorHelper, overrideOpacityHelper, overrideVisibleHelper)
+        {
+
+        }
+
+        /// <summary>
+        /// Vmo
+        /// </summary>
+        public new PipeL3d Vmo
+        {
+            get { return _vmo as PipeL3d; }
+            set { _vmo = value; }
+        }
+
+        //鏇存柊鏉愯川
+        protected override void UpdateMaterial()
+        {
+            var htmlColor = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Normal.HtmlColor;
+            var opacity = 1.0d;
+            var state = _stateHelper.GetState(this.Vmo);
+            if (state.HasFlag(eLogicalState.Color))
+            {
+                htmlColor = _overrideColorHelper.GetColor(this.Vmo);
+            }
+            if (state.HasFlag(eLogicalState.Opacity))
+            {
+                opacity = _overrideOpacityHelper.GetOpacity(this.Vmo);
+            }
+            if (state.HasFlag(eLogicalState.Selection))
+            {
+                htmlColor = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Selection.HtmlColor;
+            }
+            if (state.HasFlag(eLogicalState.Highlight))
+            {
+                htmlColor = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Highlight.HtmlColor;
+            }
+            var material = _materialHelper.GetMaterial(htmlColor, opacity);
+            this.Material = material;
+        }
+
+        //鏇存柊鍙鎬�
+        protected override void UpdateVisibility()
+        {
+            bool visible = true;
+            var state = _stateHelper.GetState(this.Vmo);
+            if (state.HasFlag(eLogicalState.Visible))
+            {
+                visible = _overrideVisibleHelper.GetVisible(this.Vmo);
+            }
+            this.Visible = visible;
+        }
+
+        //鏇存柊鍑犱綍鍥惧舰
+        protected override void UpdateGeometry()
+        {
+            var diameter = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Normal.Diameter;
+            var state = _stateHelper.GetState(this.Vmo);
+            if (state.HasFlag(eLogicalState.Selection))
+            {
+                diameter = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Selection.Diameter;
+            }
+            if (state.HasFlag(eLogicalState.Highlight))
+            {
+                diameter = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Highlight.Diameter;
+            }
+
+            var start = this.Vmo.StartPosition.ToPoint3D();
+            var end = this.Vmo.EndPosition.ToPoint3D();
+
+            MeshBuilder builder = new MeshBuilder();
+            builder.AddTube(
+                path: new[] { start, end },
+                diameter: diameter,  // 绾跨洿寰�(3D绌洪棿鍗曚綅)
+                thetaDiv: 8,    // 妯埅闈㈢粏鍒嗗害
+                false
+            );
+            var geometry = builder.ToMesh();
+            this.MeshGeometry = geometry;
+        }
+
+
+
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/02-link/02-pump/LogicalPump3D.cs b/Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/02-link/02-pump/LogicalPump3D.cs
new file mode 100644
index 0000000..908ba06
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/02-link/02-pump/LogicalPump3D.cs
@@ -0,0 +1,138 @@
+锘縩amespace Yw.WpfUI.Hydro
+{
+    /// <summary>
+    /// 鎶借薄3D姘存车
+    /// </summary>
+    internal class LogicalPump3D : LogicalLink3D
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public LogicalPump3D() { }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public LogicalPump3D
+            (
+                PumpL3d vmo,
+                LogicalStateHelper stateHelper,
+                LogicalMaterialHelper materialHelper,
+                LogicalOverrideColorHelper overrideColorHelper,
+                LogicalOverrideOpacityHelper overrideOpacityHelper,
+                LogicalOverrideVisibleHelper overrideVisibleHelper
+            ) : base(vmo, stateHelper, materialHelper, overrideColorHelper, overrideOpacityHelper, overrideVisibleHelper)
+        {
+
+        }
+
+        /// <summary>
+        /// Vmo
+        /// </summary>
+        public new PumpL3d Vmo
+        {
+            get { return _vmo as PumpL3d; }
+            set { _vmo = value; }
+        }
+
+        //鏇存柊鏉愯川
+        protected override void UpdateMaterial()
+        {
+            var htmlColor = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Normal.HtmlColor;
+            var opacity = 1.0d;
+            var state = _stateHelper.GetState(this.Vmo);
+            if (state.HasFlag(eLogicalState.Color))
+            {
+                htmlColor = _overrideColorHelper.GetColor(this.Vmo);
+            }
+            if (state.HasFlag(eLogicalState.Opacity))
+            {
+                opacity = _overrideOpacityHelper.GetOpacity(this.Vmo);
+            }
+            if (state.HasFlag(eLogicalState.Selection))
+            {
+                htmlColor = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Selection.HtmlColor;
+            }
+            if (state.HasFlag(eLogicalState.Highlight))
+            {
+                htmlColor = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Highlight.HtmlColor;
+            }
+            var material = _materialHelper.GetMaterial(htmlColor, opacity);
+            this.Material = material;
+        }
+
+        //鏇存柊鍙鎬�
+        protected override void UpdateVisibility()
+        {
+            bool visible = true;
+            var state = _stateHelper.GetState(this.Vmo);
+            if (state.HasFlag(eLogicalState.Visible))
+            {
+                visible = _overrideVisibleHelper.GetVisible(this.Vmo);
+            }
+            this.Visible = visible;
+        }
+
+        //鏇存柊鍑犱綍鍥惧舰
+        protected override void UpdateGeometry()
+        {
+            var diameter = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Normal.Diameter;
+            var state = _stateHelper.GetState(this.Vmo);
+            if (state.HasFlag(eLogicalState.Selection))
+            {
+                diameter = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Selection.Diameter;
+            }
+            if (state.HasFlag(eLogicalState.Highlight))
+            {
+                diameter = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Highlight.Diameter;
+            }
+
+            var sv = this.Vmo.StartPosition.ToVector3D();
+            var ev = this.Vmo.EndPosition.ToVector3D();
+            var center = (sv + ev) * 0.5d;
+            var direction = (ev - sv);
+            var length = direction.Length;
+            direction.Normalize();
+
+            //姘存车绠¢亾
+            MeshBuilder builder = new MeshBuilder();
+            builder.AddTube(
+                path: new[] { this.Vmo.StartPosition.ToPoint3D(), this.Vmo.EndPosition.ToPoint3D() },
+                diameter: diameter,  // 绾跨洿寰�(3D绌洪棿鍗曚綅)
+                thetaDiv: 8,    // 妯埅闈㈢粏鍒嗗害
+                false
+            );
+
+            // 姘存车涓讳綋锛堝渾鏌卞舰锛�
+            var pumpCenter = sv + direction * (length * 0.5d);
+            builder.AddCylinder(
+                p1: (pumpCenter - direction * (length * 0.3d)).ToPoint3D(),
+                p2: (pumpCenter + direction * (length * 0.3d)).ToPoint3D(),
+                diameter: diameter * 1.5d,
+                thetaDiv: 16);
+
+            double bladeWidth = diameter * 2d;
+            double bladeLength = length * 0.6d;
+
+            // 鍒涘缓涓や釜浜ゅ弶鐨勫彾鐗�
+            for (int i = 0; i < 2; i++)
+            {
+                var rotation = new RotateTransform3D(
+                    new AxisAngleRotation3D(direction, i * 90));
+
+                // 鍙剁墖1
+                var p1 = center + rotation.Transform(new Vector3D(-bladeLength / 2, -bladeWidth / 2, 0));
+                var p2 = center + rotation.Transform(new Vector3D(bladeLength / 2, -bladeWidth / 2, 0));
+                var p3 = center + rotation.Transform(new Vector3D(bladeLength / 2, bladeWidth / 2, 0));
+                var p4 = center + rotation.Transform(new Vector3D(-bladeLength / 2, bladeWidth / 2, 0));
+
+                builder.AddQuad(p1.ToPoint3D(), p2.ToPoint3D(), p3.ToPoint3D(), p4.ToPoint3D());
+            }
+
+            var geometry = builder.ToMesh();
+            this.MeshGeometry = geometry;
+        }
+
+
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/02-link/03-valve/LogicalValve3D.cs b/Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/02-link/03-valve/LogicalValve3D.cs
new file mode 100644
index 0000000..1bd7729
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/02-link/03-valve/LogicalValve3D.cs
@@ -0,0 +1,126 @@
+锘縰sing System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Yw.WpfUI.Hydro
+{
+    internal class LogicalValve3D : LogicalLink3D
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public LogicalValve3D() { }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public LogicalValve3D
+            (
+                ValveL3d vmo,
+                LogicalStateHelper stateHelper,
+                LogicalMaterialHelper materialHelper,
+                LogicalOverrideColorHelper overrideColorHelper,
+                LogicalOverrideOpacityHelper overrideOpacityHelper,
+                LogicalOverrideVisibleHelper overrideVisibleHelper
+            ) : base(vmo, stateHelper, materialHelper, overrideColorHelper, overrideOpacityHelper, overrideVisibleHelper)
+        {
+
+        }
+
+        /// <summary>
+        /// Vmo
+        /// </summary>
+        public new ValveL3d Vmo
+        {
+            get { return _vmo as ValveL3d; }
+            set { _vmo = value; }
+        }
+
+        //鏇存柊鏉愯川
+        protected override void UpdateMaterial()
+        {
+            var htmlColor = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Normal.HtmlColor;
+            var opacity = 1.0d;
+            var state = _stateHelper.GetState(this.Vmo);
+            if (state.HasFlag(eLogicalState.Color))
+            {
+                htmlColor = _overrideColorHelper.GetColor(this.Vmo);
+            }
+            if (state.HasFlag(eLogicalState.Opacity))
+            {
+                opacity = _overrideOpacityHelper.GetOpacity(this.Vmo);
+            }
+            if (state.HasFlag(eLogicalState.Selection))
+            {
+                htmlColor = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Selection.HtmlColor;
+            }
+            if (state.HasFlag(eLogicalState.Highlight))
+            {
+                htmlColor = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Highlight.HtmlColor;
+            }
+            var material = _materialHelper.GetMaterial(htmlColor, opacity);
+            this.Material = material;
+        }
+
+        //鏇存柊鍙鎬�
+        protected override void UpdateVisibility()
+        {
+            bool visible = true;
+            var state = _stateHelper.GetState(this.Vmo);
+            if (state.HasFlag(eLogicalState.Visible))
+            {
+                visible = _overrideVisibleHelper.GetVisible(this.Vmo);
+            }
+            this.Visible = visible;
+        }
+
+        //鏇存柊鍑犱綍鍥惧舰
+        protected override void UpdateGeometry()
+        {
+            var diameter = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Normal.Diameter;
+            var state = _stateHelper.GetState(this.Vmo);
+            if (state.HasFlag(eLogicalState.Selection))
+            {
+                diameter = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Selection.Diameter;
+            }
+            if (state.HasFlag(eLogicalState.Highlight))
+            {
+                diameter = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Highlight.Diameter;
+            }
+
+            var start = this.Vmo.StartPosition.ToPoint3D();
+            var end = this.Vmo.EndPosition.ToPoint3D();
+
+            var sv = start.ToVector3D();
+            var ev = end.ToVector3D();
+            var center = (sv + ev) * 0.5d;
+            var direction = (ev - sv);
+            var length = direction.Length;
+            direction.Normalize();
+            var size = diameter * 2d;
+            if (size > length)
+            {
+                size = length;
+            }
+
+            //闃�闂ㄧ閬�
+            var builder = new MeshBuilder();
+            builder.AddTube(
+                path: new[] { start, end },
+                diameter: diameter,  // 绾跨洿寰�(3D绌洪棿鍗曚綅)
+                thetaDiv: 8,    // 妯埅闈㈢粏鍒嗗害
+                false
+            );
+
+            builder.AddBox(center.ToPoint3D(), size, size, size);
+
+            var geometry = builder.ToMesh();
+            this.MeshGeometry = geometry;
+        }
+
+
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/03-logical/02-material/LogicalMaterialHelper.cs b/Yw.WpfUI.Hydro.L3d.Core/03-logical/02-material/LogicalMaterialHelper.cs
new file mode 100644
index 0000000..df07cc9
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/02-material/LogicalMaterialHelper.cs
@@ -0,0 +1,55 @@
+锘縩amespace Yw.WpfUI.Hydro
+{
+    /// <summary>
+    /// 鎶借薄鏉愯川杈呭姪绫�
+    /// </summary>
+    internal class LogicalMaterialHelper
+    {
+        //缂撳瓨
+        private readonly ConcurrentDictionary<Color, Material> _cache = new();
+
+        /// <summary>
+        /// 鑾峰彇绾壊鏉愯川
+        /// </summary>
+        public Material GetMaterial(Color color)
+        {
+            var material = _cache.GetOrAdd(color, CreateMaterial(color));
+            return material;
+        }
+
+        /// <summary>
+        /// 鑾峰彇绾壊鏉愯川
+        /// </summary>
+        public Material GetMaterial(Color color, double opacity)
+        {
+            var color1 = Color.FromArgb((byte)(opacity * 255.0), color.R, color.G, color.B);
+            return GetMaterial(color1);
+        }
+
+        /// <summary>
+        /// 鑾峰彇绾壊鏉愯川
+        /// </summary>
+        public Material GetMaterial(string htmlColor)
+        {
+            var color = htmlColor.ToMediaColor();
+            return GetMaterial(color);
+        }
+
+        /// <summary>
+        /// 鑾峰彇绾壊鏉愯川
+        /// </summary>
+        public Material GetMaterial(string htmlColor, double opacity)
+        {
+            var color = htmlColor.ToMediaColor();
+            return GetMaterial(color, opacity);
+        }
+
+        //鍒涘缓绾壊鏉愯川
+        private static Material CreateMaterial(Color color)
+        {
+            return MaterialHelper.CreateMaterial(color);
+        }
+
+
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/03-logical/03-state/LogicalStateExtensions.cs b/Yw.WpfUI.Hydro.L3d.Core/03-logical/03-state/LogicalStateExtensions.cs
new file mode 100644
index 0000000..446c133
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/03-state/LogicalStateExtensions.cs
@@ -0,0 +1,20 @@
+锘縩amespace Yw.WpfUI.Hydro
+{
+    /// <summary>
+    /// 鎶借薄鐘舵�佹嫇灞�
+    /// </summary>
+    internal static class LogicalStateExtensions
+    {
+        /// <summary>
+        /// 鏄惁鍖呭惈鐘舵��
+        /// </summary>
+        /// <param name="state">鐘舵��</param>
+        /// <param name="flag">鏍囧織</param>
+        /// <returns>鏄惁鍖呭惈鐘舵��</returns>
+        public static bool HasFlag(this eLogicalState state, eLogicalState flag)
+        {
+            return (state & flag) == flag;
+        }
+
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/03-logical/03-state/LogicalStateHelper.cs b/Yw.WpfUI.Hydro.L3d.Core/03-logical/03-state/LogicalStateHelper.cs
new file mode 100644
index 0000000..b8d394f
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/03-state/LogicalStateHelper.cs
@@ -0,0 +1,61 @@
+锘縩amespace Yw.WpfUI.Hydro
+{
+    /// <summary>
+    /// 鎶借薄鐘舵�佽緟鍔╃被
+    /// </summary>
+    internal class LogicalStateHelper
+    {
+        //缂撳瓨
+        private readonly Dictionary<VisualL3d, eLogicalState> _cache = new();
+
+        /// <summary>
+        /// 鑾峰彇鐘舵��
+        /// </summary>
+        public eLogicalState GetState(VisualL3d visual)
+        {
+            if (visual == null)
+            {
+                return eLogicalState.Normal;
+            }
+            if (!_cache.ContainsKey(visual))
+            {
+                return eLogicalState.Normal;
+            }
+            return _cache[visual];
+        }
+
+        /// <summary>
+        /// 璁剧疆鐘舵��
+        /// </summary>
+        public void SetState(VisualL3d visual, eLogicalState state)
+        {
+            if (visual == null)
+            {
+                return;
+            }
+            _cache[visual] = state;
+        }
+
+        /// <summary>
+        /// 鍔犺浇鐘舵��
+        /// </summary>
+        public void LoadState(VisualL3d visual, eLogicalState state)
+        {
+            var origin = GetState(visual);
+            _cache[visual] = origin | state;
+        }
+
+        /// <summary>
+        /// 鍗歌浇鐘舵��
+        /// </summary>
+        public void UnloadState(VisualL3d visual, eLogicalState state)
+        {
+            var origin = GetState(visual);
+            _cache[visual] = origin ^ state;
+        }
+
+
+
+
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/03-logical/03-state/eLogicalState.cs b/Yw.WpfUI.Hydro.L3d.Core/03-logical/03-state/eLogicalState.cs
new file mode 100644
index 0000000..cec01c8
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/03-state/eLogicalState.cs
@@ -0,0 +1,46 @@
+锘縩amespace Yw.WpfUI.Hydro
+{
+    /// <summary>
+    /// 鎶借薄鐘舵��
+    /// </summary>
+    [Flags]
+    internal enum eLogicalState
+    {
+        /// <summary>
+        /// 鏃�
+        /// </summary>
+        None = 0x00,
+
+        /// <summary>
+        /// 姝e父
+        /// </summary>
+        Normal = 0x01,
+
+        /// <summary>
+        /// 楂樹寒
+        /// </summary>
+        Highlight = 0x02,
+
+        /// <summary>
+        /// 閫変腑
+        /// </summary>
+        Selection = 0x04,
+
+        /// <summary>
+        /// 棰滆壊
+        /// </summary>
+        Color = 0x08,
+
+        /// <summary>
+        /// 閫忔槑搴�
+        /// </summary>
+        Opacity = 0x16,
+
+        /// <summary>
+        /// 鍙鎬�
+        /// </summary>
+        Visible = 0x32
+
+
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/02-helper/07-override/ColorOverrideManager.cs b/Yw.WpfUI.Hydro.L3d.Core/03-logical/04-override/LogicalOverrideColorHelper.cs
similarity index 75%
rename from Yw.WpfUI.Hydro.L3d.Core/02-helper/07-override/ColorOverrideManager.cs
rename to Yw.WpfUI.Hydro.L3d.Core/03-logical/04-override/LogicalOverrideColorHelper.cs
index 8d8024b..aefa895 100644
--- a/Yw.WpfUI.Hydro.L3d.Core/02-helper/07-override/ColorOverrideManager.cs
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/04-override/LogicalOverrideColorHelper.cs
@@ -1,16 +1,16 @@
 锘縩amespace Yw.WpfUI.Hydro
 {
     /// <summary>
-    /// 鏋勪欢鐫�鑹茬鐞嗗櫒
+    /// 鎶借薄瑕嗙洊棰滆壊杈呭姪绫�
     /// </summary>
-    internal class ColorOverrideManager
+    internal class LogicalOverrideColorHelper
     {
-        private readonly Dictionary<VisualL3d, Color> _cache = new();
+        private readonly Dictionary<VisualL3d, string> _cache = new();
 
         /// <summary>
         /// 鑾峰彇棰滆壊
         /// </summary>
-        public Color? GetColor(VisualL3d visual)
+        public string GetColor(VisualL3d visual)
         {
             if (!_cache.ContainsKey(visual))
             {
@@ -24,7 +24,7 @@
         /// </summary>
         public void SetColor(VisualL3d visual, string htmlColor)
         {
-            _cache[visual] = htmlColor.ToMediaColor();
+            _cache[visual] = htmlColor;
         }
 
         /// <summary>
@@ -32,8 +32,7 @@
         /// </summary>
         public void SetColor(List<VisualL3d> visuals, string htmlColor)
         {
-            var color = htmlColor.ToMediaColor();
-            visuals?.ForEach(x => _cache[x] = color);
+            visuals?.ForEach(x => _cache[x] = htmlColor);
         }
 
         /// <summary>
@@ -55,9 +54,6 @@
         {
             visuals?.ForEach(x => ClearColor(x));
         }
-
-
-
 
 
     }
diff --git a/Yw.WpfUI.Hydro.L3d.Core/03-logical/04-override/LogicalOverrideOpacityHelper.cs b/Yw.WpfUI.Hydro.L3d.Core/03-logical/04-override/LogicalOverrideOpacityHelper.cs
new file mode 100644
index 0000000..05727ee
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/04-override/LogicalOverrideOpacityHelper.cs
@@ -0,0 +1,65 @@
+锘縩amespace Yw.WpfUI.Hydro
+{
+    /// <summary>
+    /// 鎶借薄瑕嗙洊閫忔槑搴﹁緟鍔╃被
+    /// </summary>
+    internal class LogicalOverrideOpacityHelper
+    {
+        private readonly Dictionary<VisualL3d, double> _cache = new();
+
+        /// <summary>
+        /// 鑾峰彇閫忔槑搴�
+        /// </summary>
+        public double GetOpacity(VisualL3d visual)
+        {
+            if (visual == null)
+            {
+                return 1d;
+            }
+            if (!_cache.ContainsKey(visual))
+            {
+                return 1d;
+            }
+            return _cache[visual];
+        }
+
+        /// <summary>
+        /// 璁剧疆閫忔槑搴�
+        /// </summary>
+        public void SetOpacity(VisualL3d visual, double opacity)
+        {
+            _cache[visual] = opacity;
+        }
+
+        /// <summary>
+        /// 璁剧疆閫忔槑搴�
+        /// </summary>
+        public void SetOpacity(List<VisualL3d> visuals, double opacity)
+        {
+            visuals?.ForEach(x => _cache[x] = opacity);
+        }
+
+        /// <summary>
+        /// 娓呯悊閫忔槑搴�
+        /// </summary>
+        public void ClearOpacity(VisualL3d visual)
+        {
+            if (!_cache.ContainsKey(visual))
+            {
+                return;
+            }
+            _cache.Remove(visual);
+        }
+
+        /// <summary>
+        /// 娓呯悊閫忔槑搴�
+        /// </summary>
+        public void ClearOpacity(List<VisualL3d> visuals)
+        {
+            visuals?.ForEach(x => ClearOpacity(x));
+        }
+
+
+
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/03-logical/04-override/LogicalOverrideVisibleHelper.cs b/Yw.WpfUI.Hydro.L3d.Core/03-logical/04-override/LogicalOverrideVisibleHelper.cs
new file mode 100644
index 0000000..8baaa55
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/04-override/LogicalOverrideVisibleHelper.cs
@@ -0,0 +1,66 @@
+锘縩amespace Yw.WpfUI.Hydro
+{
+    /// <summary>
+    /// 鎶借薄瑕嗙洊鍙鎬ц緟鍔╃被
+    /// </summary>
+    internal class LogicalOverrideVisibleHelper
+    {
+        //缂撳瓨
+        private readonly Dictionary<VisualL3d, bool> _cache = new();
+
+        /// <summary>
+        /// 鑾峰彇鍙鎬�
+        /// </summary>
+        public bool GetVisible(VisualL3d visual)
+        {
+            if (visual == null)
+            {
+                return true;
+            }
+            if (!_cache.ContainsKey(visual))
+            {
+                return true;
+            }
+            return _cache[visual];
+        }
+
+        /// <summary>
+        /// 璁剧疆鍙鎬�
+        /// </summary>
+        public void SetVisible(VisualL3d visual, bool Visible)
+        {
+            _cache[visual] = Visible;
+        }
+
+        /// <summary>
+        /// 璁剧疆鍙鎬�
+        /// </summary>
+        public void SetVisible(List<VisualL3d> visuals, bool Visible)
+        {
+            visuals?.ForEach(x => _cache[x] = Visible);
+        }
+
+        /// <summary>
+        /// 娓呯悊鍙鎬�
+        /// </summary>
+        public void ClearVisible(VisualL3d visual)
+        {
+            if (!_cache.ContainsKey(visual))
+            {
+                return;
+            }
+            _cache.Remove(visual);
+        }
+
+        /// <summary>
+        /// 娓呯悊鍙鎬�
+        /// </summary>
+        public void ClearVisible(List<VisualL3d> visuals)
+        {
+            visuals?.ForEach(x => ClearVisible(x));
+        }
+
+
+
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/03-logical/05-highlight/LogicalHighlightHelper.cs b/Yw.WpfUI.Hydro.L3d.Core/03-logical/05-highlight/LogicalHighlightHelper.cs
new file mode 100644
index 0000000..1b0b429
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/05-highlight/LogicalHighlightHelper.cs
@@ -0,0 +1,60 @@
+锘縩amespace Yw.WpfUI.Hydro
+{
+    /// <summary>
+    /// 鎶借薄楂樹寒杈呭姪绫�
+    /// </summary>
+    internal class LogicalHighlightHelper
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public LogicalHighlightHelper(HelixViewport3D viewport)
+        {
+            _viewport = viewport;
+        }
+
+        /// <summary>
+        /// 鐘舵�佹敼鍙樹簨浠�
+        /// </summary>
+        public event Action<LogicalVisual3D, eLogicalHighlight> StateChangedEvent;
+
+        private readonly HelixViewport3D _viewport = null;//涓夌淮缁勪欢
+        private LogicalVisual3D _logicalVisual;//褰撳墠楂樹寒鐨刅isual
+
+
+        /// <summary>
+        /// 楂樹寒
+        /// </summary>
+        public void Highlight(Point pt)
+        {
+            var logicalVisual = _viewport.FindNearestVisual(pt) as LogicalVisual3D;
+            if (logicalVisual == null)
+            {
+                Reset();
+                return;
+            }
+            if (_logicalVisual == logicalVisual)
+            {
+                return;
+            }
+            Reset();
+            _logicalVisual = logicalVisual;
+            this.StateChangedEvent?.Invoke(_logicalVisual, eLogicalHighlight.Load);
+        }
+
+        //閲嶇疆
+        private void Reset()
+        {
+            if (_logicalVisual != null)
+            {
+                this.StateChangedEvent?.Invoke(_logicalVisual, eLogicalHighlight.Unload);
+                _logicalVisual = null;
+            }
+        }
+
+
+
+
+
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/02-helper/04-highlight/eHighlightType.cs b/Yw.WpfUI.Hydro.L3d.Core/03-logical/05-highlight/eLogicalHighlight.cs
similarity index 78%
rename from Yw.WpfUI.Hydro.L3d.Core/02-helper/04-highlight/eHighlightType.cs
rename to Yw.WpfUI.Hydro.L3d.Core/03-logical/05-highlight/eLogicalHighlight.cs
index 014c409..4ab81f1 100644
--- a/Yw.WpfUI.Hydro.L3d.Core/02-helper/04-highlight/eHighlightType.cs
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/05-highlight/eLogicalHighlight.cs
@@ -1,9 +1,9 @@
 锘縩amespace Yw.WpfUI.Hydro
 {
     /// <summary>
-    /// 楂樹寒绫诲瀷
+    /// 鎶借薄楂樹寒绫诲瀷
     /// </summary>
-    internal enum eHighlightType
+    internal enum eLogicalHighlight
     {
         /// <summary>
         /// 鍔犺浇
@@ -15,4 +15,6 @@
         /// </summary>
         Unload
     }
+
+
 }
diff --git a/Yw.WpfUI.Hydro.L3d.Core/02-helper/05-selection/SimpleSelectionManager.cs b/Yw.WpfUI.Hydro.L3d.Core/03-logical/06-selection/LogicalSelectionHelper.cs
similarity index 60%
rename from Yw.WpfUI.Hydro.L3d.Core/02-helper/05-selection/SimpleSelectionManager.cs
rename to Yw.WpfUI.Hydro.L3d.Core/03-logical/06-selection/LogicalSelectionHelper.cs
index c750a3e..8fcd622 100644
--- a/Yw.WpfUI.Hydro.L3d.Core/02-helper/05-selection/SimpleSelectionManager.cs
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/06-selection/LogicalSelectionHelper.cs
@@ -1,14 +1,14 @@
 锘縩amespace Yw.WpfUI.Hydro
 {
     /// <summary>
-    /// 閫夋嫨绠$悊鍣�
+    /// 鎶借薄閫夋嫨杈呭姪绫�
     /// </summary>
-    internal class SimpleSelectionManager
+    internal class LogicalSelectionHelper
     {
         /// <summary>
         /// 
         /// </summary>
-        public SimpleSelectionManager(HelixViewport3D viewport)
+        public LogicalSelectionHelper(HelixViewport3D viewport)
         {
             _viewport = viewport;
         }
@@ -16,37 +16,46 @@
         /// <summary>
         /// 閫夋嫨鏀瑰彉浜嬩欢
         /// </summary>
-        public event Action<List<Visual3D>> SelectionChangedEvent;
+        public event Action<List<LogicalVisual3D>> SelectionChangedEvent;
         /// <summary>
         /// 鐘舵�佹敼鍙樹簨浠�
         /// </summary>
-        public event Action<Visual3D, eSelectionType> StateChangedEvent;
+        public event Action<LogicalVisual3D, eLogicalSelection> StateChangedEvent;
 
-        private readonly HelixViewport3D _viewport;//鎺т欢
-        private readonly List<Visual3D> _selection = new();//閫夋嫨闆嗗悎
+        private readonly HelixViewport3D _viewport;//涓夌淮缁勪欢
+
+        /// <summary>
+        /// 閫夋嫨闆嗗悎
+        /// </summary>
+        public List<LogicalVisual3D> Selection
+        {
+            get { return _selection; }
+            private set { _selection = value; }
+        }
+        private List<LogicalVisual3D> _selection = new();
 
         #region 鍐呴儴瀹炵幇
 
         //娣诲姞閫夋嫨
-        private void AddToSelection(Visual3D visual)
+        private void AddToSelection(LogicalVisual3D visual)
         {
             if (_selection.Contains(visual))
             {
                 return;
             }
             _selection.Add(visual);
-            this.StateChangedEvent?.Invoke(visual, eSelectionType.Load);
+            this.StateChangedEvent?.Invoke(visual, eLogicalSelection.Load);
         }
 
         //浠庨�夋嫨涓Щ闄�
-        private void RemoveFromSelection(Visual3D visual)
+        private void RemoveFromSelection(LogicalVisual3D visual)
         {
             if (!_selection.Contains(visual))
             {
                 return;
             }
             _selection.Remove(visual);
-            this.StateChangedEvent?.Invoke(visual, eSelectionType.Unload);
+            this.StateChangedEvent?.Invoke(visual, eLogicalSelection.Unload);
         }
 
         //娓呯悊閫夋嫨
@@ -56,7 +65,7 @@
             {
                 return;
             }
-            _selection.ForEach(x => this.StateChangedEvent?.Invoke(x, eSelectionType.Unload));
+            _selection.ForEach(x => this.StateChangedEvent?.Invoke(x, eLogicalSelection.Unload));
             _selection.Clear();
         }
 
@@ -67,8 +76,8 @@
         /// </summary>
         public void HandleSingle(Point pt)
         {
-            var visual = _viewport.FindNearestVisual(pt);
-            if (visual == null)
+            var logicalVisual = _viewport.FindNearestVisual(pt) as LogicalVisual3D;
+            if (logicalVisual == null)
             {
                 if (_selection.Count > 0)
                 {
@@ -77,12 +86,12 @@
                 }
                 return;
             }
-            if (_selection.Count == 1 && _selection[0] == visual)
+            if (_selection.Count == 1 && _selection[0] == logicalVisual)
             {
                 return;
             }
             ClearSelection();
-            AddToSelection(visual);
+            AddToSelection(logicalVisual);
             this.SelectionChangedEvent?.Invoke(_selection);
         }
 
@@ -91,16 +100,16 @@
         /// </summary>
         public void HandleMulti(Point pt)
         {
-            var visual = _viewport.FindNearestVisual(pt);
-            if (visual == null)
+            var logicalVisual = _viewport.FindNearestVisual(pt) as LogicalVisual3D;
+            if (logicalVisual == null)
             {
                 return;
             }
-            if (_selection.Contains(visual))
+            if (_selection.Contains(logicalVisual))
             {
                 return;
             }
-            AddToSelection(visual);
+            AddToSelection(logicalVisual);
             this.SelectionChangedEvent?.Invoke(_selection);
         }
 
@@ -108,7 +117,7 @@
         /// 閫夋嫨Visual
         /// 涓嶈Е鍙戦�夋嫨鏀瑰彉浜嬩欢
         /// </summary>
-        public void SelectVisual(Visual3D visual)
+        public void SelectVisual(LogicalVisual3D visual)
         {
             ClearSelection();
             if (visual == null)
@@ -121,7 +130,7 @@
         /// <summary>
         /// 閫夋嫨Visuals
         /// </summary>
-        public void SelectVisuals(List<Visual3D> visuals)
+        public void SelectVisuals(List<LogicalVisual3D> visuals)
         {
             ClearSelection();
             if (visuals == null || visuals.Count < 1)
diff --git a/Yw.WpfUI.Hydro.L3d.Core/02-helper/04-highlight/eHighlightType.cs b/Yw.WpfUI.Hydro.L3d.Core/03-logical/06-selection/eLogicalSelection.cs
similarity index 78%
copy from Yw.WpfUI.Hydro.L3d.Core/02-helper/04-highlight/eHighlightType.cs
copy to Yw.WpfUI.Hydro.L3d.Core/03-logical/06-selection/eLogicalSelection.cs
index 014c409..52aef27 100644
--- a/Yw.WpfUI.Hydro.L3d.Core/02-helper/04-highlight/eHighlightType.cs
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/06-selection/eLogicalSelection.cs
@@ -1,9 +1,9 @@
 锘縩amespace Yw.WpfUI.Hydro
 {
     /// <summary>
-    /// 楂樹寒绫诲瀷
+    /// 鎶借薄閫夋嫨绫诲瀷
     /// </summary>
-    internal enum eHighlightType
+    internal enum eLogicalSelection
     {
         /// <summary>
         /// 鍔犺浇
@@ -15,4 +15,5 @@
         /// </summary>
         Unload
     }
+
 }
diff --git a/Yw.WpfUI.Hydro.L3d.Core/02-helper/06-zoom/ZoomManager.cs b/Yw.WpfUI.Hydro.L3d.Core/03-logical/07-zoom/LogicalZoomHelper.cs
similarity index 92%
rename from Yw.WpfUI.Hydro.L3d.Core/02-helper/06-zoom/ZoomManager.cs
rename to Yw.WpfUI.Hydro.L3d.Core/03-logical/07-zoom/LogicalZoomHelper.cs
index 48dc4f5..c654ba5 100644
--- a/Yw.WpfUI.Hydro.L3d.Core/02-helper/06-zoom/ZoomManager.cs
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/07-zoom/LogicalZoomHelper.cs
@@ -1,22 +1,19 @@
-锘縰sing System.Windows;
-using System.Windows.Media.Animation;
-
-namespace Yw.WpfUI.Hydro
+锘縩amespace Yw.WpfUI.Hydro
 {
     /// <summary>
-    /// 缂╂斁绠$悊鍣�
+    /// 鎶借薄缂╂斁杈呭姪绫�
     /// </summary>
-    internal class ZoomManager
+    internal class LogicalZoomHelper
     {
         /// <summary>
         /// 
         /// </summary>
-        public ZoomManager(HelixViewport3D viewport)
+        public LogicalZoomHelper(HelixViewport3D viewport)
         {
             _viewport = viewport;
         }
 
-        private readonly HelixViewport3D _viewport;
+        private readonly HelixViewport3D _viewport;//涓夌淮缁勪欢
         private readonly double _animationDuration = 0.5; // 鍔ㄧ敾鎸佺画鏃堕棿(绉�)
         private readonly double _zoomFactor = 1.2; // 缂╂斁鍥犲瓙(鍦ㄨ竟鐣屾澶栫暀浜涚┖闂�)
 
@@ -68,7 +65,7 @@
         /// <summary>
         /// 缂╂斁鑷砎isuals
         /// </summary>
-        public void ZoomToVisuals(List<ModelVisual3D> visuals)
+        public void ZoomToVisuals(List<Visual3D> visuals)
         {
             if (visuals == null || visuals.Count < 1)
             {
@@ -115,7 +112,7 @@
         /// <summary>
         /// 缂╂斁鑷砎isual(鏃犲姩鐢�)
         /// </summary>
-        public void ZoomDirectToVisual(ModelVisual3D visual)
+        public void ZoomDirectToVisual(Visual3D visual)
         {
             if (visual == null)
                 return;
@@ -128,7 +125,7 @@
         /// <summary>
         /// 缂╂斁鑷砎isuals(鏃犲姩鐢�)
         /// </summary>
-        public void ZoomDirectToVisuals(List<ModelVisual3D> visuals)
+        public void ZoomDirectToVisuals(List<Visual3D> visuals)
         {
             if (visuals == null || visuals.Count < 1)
             {
diff --git a/Yw.WpfUI.Hydro.L3d.Core/03-logical/08-manager/LogicalEditManager.cs b/Yw.WpfUI.Hydro.L3d.Core/03-logical/08-manager/LogicalEditManager.cs
new file mode 100644
index 0000000..b30479d
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/08-manager/LogicalEditManager.cs
@@ -0,0 +1,443 @@
+锘縩amespace Yw.WpfUI.Hydro
+{
+    /// <summary>
+    /// 鎶借薄缂栬緫绠$悊鍣�
+    /// </summary>
+    internal class LogicalEditManager : LogicalManager
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public LogicalEditManager(HelixViewport3D viewport) : base(viewport)
+        {
+
+        }
+
+        private eLogicalEditMode _logicalMode = eLogicalEditMode.None;//缂栬緫妯″紡
+        private VisualL3d _visual = null;//鍙鍖栧璞�
+
+
+        #region 娣诲姞鏂规硶
+
+        /// <summary>
+        /// 寮�濮嬫坊鍔犺繛鎺ヨ妭鐐�
+        /// </summary>
+        public void StartAddJunction()
+        {
+            _logicalMode = eLogicalEditMode.AddJunction;
+        }
+
+        /// <summary>
+        /// 寮�濮嬫坊鍔犳按搴�
+        /// </summary>
+        public void StartAddReservoir()
+        {
+            _logicalMode = eLogicalEditMode.AddReservoir;
+        }
+
+        /// <summary>
+        /// 寮�濮嬫坊鍔犳按姹�
+        /// </summary>
+        public void StartAddTank()
+        {
+            _logicalMode = eLogicalEditMode.AddTank;
+        }
+
+        /// <summary>
+        /// 寮�濮嬫坊鍔犺嚜鐢辩閬�
+        /// </summary>
+        public void StartAddPipe()
+        {
+            _logicalMode = eLogicalEditMode.AddPipe;
+        }
+
+        /// <summary>
+        /// 寮�濮嬫坊鍔犳按骞崇閬�
+        /// </summary>
+        public void StartAddHorizPipe()
+        {
+            _logicalMode = eLogicalEditMode.AddHorizPipe;
+        }
+
+        /// <summary>
+        /// 寮�濮嬫坊鍔犲瀭鐩寸閬�
+        /// </summary>
+        public void StartAddVertPipe()
+        {
+            _logicalMode = eLogicalEditMode.AddVertPipe;
+        }
+
+        /// <summary>
+        /// 寮�濮嬫坊鍔犳按娉�
+        /// </summary>
+        public void StartAddPump()
+        {
+            _logicalMode = eLogicalEditMode.AddPump;
+        }
+
+        /// <summary>
+        /// 寮�濮嬫坊鍔犻榾闂�
+        /// </summary>
+        public void StartAddValve()
+        {
+            _logicalMode = eLogicalEditMode.AddValve;
+        }
+
+        #endregion
+
+        #region 閲嶅啓浜嬩欢
+
+        //榧犳爣鎸変笅
+        protected override void OnMouseDown(MouseButtonEventArgs e)
+        {
+            if (!Initialized)
+            {
+                return;
+            }
+
+            switch (_logicalMode)
+            {
+                case eLogicalEditMode.AddJunction:
+                    {
+                        var pt = e.GetPosition(_viewport);
+                        var sp = _viewport.Viewport.UnProject(pt);
+                        if (sp.HasValue)
+                        {
+                            var visual = new JunctionL3d();
+                            visual.Id = Yw.Untity.UniqueHelper.CreateFromFirst("junction", _nw.Junctions.Select(x => x.Id).ToList());
+                            visual.Position = sp.Value.ToPointL3d();
+                            AddVisual(visual);
+                            _visual = visual;
+                        }
+                    }
+                    break;
+                case eLogicalEditMode.AddReservoir:
+                    {
+                        var pt = e.GetPosition(_viewport);
+                        var sp = _viewport.Viewport.UnProject(pt);
+                        if (sp.HasValue)
+                        {
+                            var visual = new ReservoirL3d();
+                            visual.Id = Yw.Untity.UniqueHelper.CreateFromFirst("reservoir", _nw.Reservoirs.Select(x => x.Id).ToList());
+                            visual.Position = sp.Value.ToPointL3d();
+                            AddVisual(visual);
+                            _visual = visual;
+                        }
+                    }
+                    break;
+                case eLogicalEditMode.AddTank:
+                    {
+                        var pt = e.GetPosition(_viewport);
+                        var sp = _viewport.Viewport.UnProject(pt);
+                        if (sp.HasValue)
+                        {
+                            var visual = new TankL3d();
+                            visual.Id = Yw.Untity.UniqueHelper.CreateFromFirst("tank", _nw.Reservoirs.Select(x => x.Id).ToList());
+                            visual.Position = sp.Value.ToPointL3d();
+                            AddVisual(visual);
+                            _visual = visual;
+                        }
+                    }
+                    break;
+                case eLogicalEditMode.AddPipe:
+                    {
+                        var pt = e.GetPosition(_viewport);
+                        var logicalNode = SnapNearestNode(pt);
+                        if (logicalNode != null)
+                        {
+                            var visual = new PipeL3d();
+                            visual.Id = Yw.Untity.UniqueHelper.CreateFromFirst("pipe", _nw.Pipes.Select(x => x.Id).ToList());
+                            visual.StartPosition = logicalNode.Position.ToPointL3d();
+                            visual.EndPosition = logicalNode.Position.ToPointL3d();
+                            AddVisual(visual);
+                            _visual = visual;
+                        }
+                    }
+                    break;
+                case eLogicalEditMode.AddPump:
+                    {
+                        var pt = e.GetPosition(_viewport);
+                        var logicalNode = SnapNearestNode(pt);
+                        if (logicalNode != null)
+                        {
+                            var visual = new PumpL3d();
+                            visual.Id = Yw.Untity.UniqueHelper.CreateFromFirst("pump", _nw.Pumps.Select(x => x.Id).ToList());
+                            visual.StartPosition = logicalNode.Position.ToPointL3d();
+                            visual.EndPosition = logicalNode.Position.ToPointL3d();
+                            AddVisual(visual);
+                            _visual = visual;
+                        }
+                    }
+                    break;
+                case eLogicalEditMode.AddValve:
+                    {
+                        var pt = e.GetPosition(_viewport);
+                        var logicalNode = SnapNearestNode(pt);
+                        if (logicalNode != null)
+                        {
+                            var visual = new ValveL3d();
+                            visual.Id = Yw.Untity.UniqueHelper.CreateFromFirst("valve", _nw.Pumps.Select(x => x.Id).ToList());
+                            visual.StartPosition = logicalNode.Position.ToPointL3d();
+                            visual.EndPosition = logicalNode.Position.ToPointL3d();
+                            AddVisual(visual);
+                            _visual = visual;
+                        }
+                    }
+                    break;
+                default:
+                    {
+                        base.OnMouseDown(e);
+                    }
+                    break;
+            }
+        }
+
+        //榧犳爣寮硅捣
+        protected override void OnMouseUp(MouseButtonEventArgs e)
+        {
+            if (!Initialized)
+            {
+                return;
+            }
+            switch (_logicalMode)
+            {
+                case eLogicalEditMode.AddJunction:
+                    {
+                        _logicalMode = eLogicalEditMode.None;
+                    }
+                    break;
+                case eLogicalEditMode.AddReservoir:
+                    {
+                        _logicalMode = eLogicalEditMode.None;
+                    }
+                    break;
+                case eLogicalEditMode.AddTank:
+                    {
+                        _logicalMode = eLogicalEditMode.None;
+                    }
+                    break;
+                case eLogicalEditMode.AddPipe:
+                    {
+                        var pt = e.GetPosition(_viewport);
+                        var logicalNode = SnapNearestNode(pt);
+                        if (logicalNode == null)
+                        {
+                            var sp = _viewport.Viewport.UnProject(pt);
+                            var junction = new JunctionL3d();
+                            junction.Id = Yw.Untity.UniqueHelper.CreateFromFirst("junction", _nw.Junctions.Select(x => x.Id).ToList());
+                            junction.Position = sp.Value.ToPointL3d();
+                            AddVisual(junction);
+                        }
+                        else
+                        {
+                            var end = logicalNode.Position.ToPointL3d();
+                            var pipe = _visual as PipeL3d;
+                            if (pipe != null)
+                            {
+                                pipe.EndPosition = end;
+                                UpdateVisual(pipe);
+                            }
+                        }
+                        _logicalMode = eLogicalEditMode.None;
+                    }
+                    break;
+                case eLogicalEditMode.AddHorizPipe:
+                    {
+                        _logicalMode = eLogicalEditMode.None;
+                    }
+                    break;
+                case eLogicalEditMode.AddVertPipe:
+                    {
+                        _logicalMode = eLogicalEditMode.None;
+                    }
+                    break;
+                case eLogicalEditMode.AddPump:
+                    {
+                        var pt = e.GetPosition(_viewport);
+                        var logicalNode = SnapNearestNode(pt);
+                        if (logicalNode == null)
+                        {
+                            var sp = _viewport.Viewport.UnProject(pt);
+                            var junction = new JunctionL3d();
+                            junction.Id = Yw.Untity.UniqueHelper.CreateFromFirst("junction", _nw.Junctions.Select(x => x.Id).ToList());
+                            junction.Position = sp.Value.ToPointL3d();
+                            AddVisual(junction);
+                        }
+                        else
+                        {
+                            var end = logicalNode.Position.ToPointL3d();
+                            var pump = _visual as PumpL3d;
+                            if (pump != null)
+                            {
+                                pump.EndPosition = end;
+                                UpdateVisual(pump);
+                            }
+                        }
+                        _logicalMode = eLogicalEditMode.None;
+                    }
+                    break;
+                case eLogicalEditMode.AddValve:
+                    {
+                        var pt = e.GetPosition(_viewport);
+                        var logicalNode = SnapNearestNode(pt);
+                        if (logicalNode == null)
+                        {
+                            var sp = _viewport.Viewport.UnProject(pt);
+                            var junction = new JunctionL3d();
+                            junction.Id = Yw.Untity.UniqueHelper.CreateFromFirst("junction", _nw.Junctions.Select(x => x.Id).ToList());
+                            junction.Position = sp.Value.ToPointL3d();
+                            AddVisual(junction);
+                        }
+                        else
+                        {
+                            var end = logicalNode.Position.ToPointL3d();
+                            var valve = _visual as ValveL3d;
+                            if (valve != null)
+                            {
+                                valve.EndPosition = end;
+                                UpdateVisual(valve);
+                            }
+                        }
+                        _logicalMode = eLogicalEditMode.None;
+                    }
+                    break;
+                default:
+                    {
+                        base.OnMouseUp(e);
+                    }
+                    break;
+            }
+        }
+
+        //榧犳爣绉诲姩
+        protected override void OnMouseMove(MouseEventArgs e)
+        {
+            if (!Initialized)
+            {
+                return;
+            }
+
+            switch (_logicalMode)
+            {
+                case eLogicalEditMode.AddJunction:
+                    {
+
+                    }
+                    break;
+                case eLogicalEditMode.AddPipe:
+                    {
+                        var pipe = _visual as PipeL3d;
+                        if (pipe != null)
+                        {
+                            var pt = e.GetPosition(_viewport);
+                            var sp = _viewport.Viewport.UnProject(pt);
+                            if (sp.HasValue)
+                            {
+                                pipe.EndPosition = sp.Value.ToPointL3d();
+                                UpdateVisual(_visual);
+                            }
+                        }
+                    }
+                    break;
+                case eLogicalEditMode.AddPump:
+                    {
+                        var pump = _visual as PumpL3d;
+                        if (pump != null)
+                        {
+                            var pt = e.GetPosition(_viewport);
+                            var sp = _viewport.Viewport.UnProject(pt);
+                            if (sp.HasValue)
+                            {
+                                pump.EndPosition = sp.Value.ToPointL3d();
+                                UpdateVisual(_visual);
+                            }
+                        }
+                    }
+                    break;
+                case eLogicalEditMode.AddValve:
+                    {
+                        var valve = _visual as ValveL3d;
+                        if (valve != null)
+                        {
+                            var pt = e.GetPosition(_viewport);
+                            var sp = _viewport.Viewport.UnProject(pt);
+                            if (sp.HasValue)
+                            {
+                                valve.EndPosition = sp.Value.ToPointL3d();
+                                UpdateVisual(_visual);
+                            }
+                        }
+                    }
+                    break;
+                default:
+                    {
+                        base.OnMouseMove(e);
+                    }
+                    break;
+            }
+        }
+
+        #endregion
+
+        //娣诲姞
+        private void AddVisual(VisualL3d visual)
+        {
+            if (!Initialized)
+            {
+                return;
+            }
+            _nw.Append(visual, out string msg);
+            _allVisualL3dDict.Add(visual.Id, visual);
+            var logicalVisual = LogicalCreateHelper.Create(visual, _stateHelper, _materialHelper, _overrideColorHelper, _overrideOpacityHelper, _overrideVisibleHelper);
+            if (logicalVisual != null)
+            {
+                _allVisualLogicalDict.Add(visual, logicalVisual);
+                _viewport.Children.Add(logicalVisual);
+            }
+        }
+
+        //鏇存柊
+        private void UpdateVisual(VisualL3d visual)
+        {
+            if (!Initialized)
+            {
+                return;
+            }
+            var logicalVisual = _allVisualLogicalDict[visual];
+            logicalVisual.UpdateVisual();
+        }
+
+        #region 杈呭姪鏂规硶
+
+
+        //鍚搁檮鏈�杩戣妭鐐�
+        private LogicalNode3D SnapNearestNode(Point pt)
+        {
+            if (!Initialized)
+            {
+                return default;
+            }
+            var logicalNode = _viewport.FindNearestVisual(pt) as LogicalNode3D;
+            if (logicalNode == null)
+            {
+                var sp = _viewport.Viewport.UnProject(pt);
+                if (sp.HasValue)
+                {
+                    var snapDistance = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Node.SnapDistance;
+                    logicalNode = _viewport.Children.OfType<LogicalNode3D>()
+                        .OrderBy(x => (x.Position - sp.Value).LengthSquared)
+                        .FirstOrDefault(x => (x.Position - sp.Value).Length < snapDistance);
+                }
+
+            }
+
+            return logicalNode;
+        }
+
+
+
+        #endregion
+
+
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/03-logical/08-manager/LogicalManager.cs b/Yw.WpfUI.Hydro.L3d.Core/03-logical/08-manager/LogicalManager.cs
new file mode 100644
index 0000000..22439e2
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/08-manager/LogicalManager.cs
@@ -0,0 +1,439 @@
+锘縰sing System.Windows.Controls;
+using System.Windows.Media.Media3D;
+
+namespace Yw.WpfUI.Hydro
+{
+    /// <summary>
+    /// 鎶借薄绠$悊鍣�
+    /// </summary>
+    internal class LogicalManager
+    {
+        public LogicalManager(HelixViewport3D viewport)
+        {
+            _viewport = viewport;
+            _stateHelper = new LogicalStateHelper();
+            _materialHelper = new LogicalMaterialHelper();
+            _overrideColorHelper = new LogicalOverrideColorHelper();
+            _overrideOpacityHelper = new LogicalOverrideOpacityHelper();
+            _overrideVisibleHelper = new LogicalOverrideVisibleHelper();
+            _highlightHelper = new LogicalHighlightHelper(_viewport);
+            _selectionHelper = new LogicalSelectionHelper(_viewport);
+            _zoomHelper = new LogicalZoomHelper(_viewport);
+        }
+
+        #region 浜嬩欢闆嗗悎
+
+        /// <summary>
+        /// 閫夋嫨鏀瑰彉浜嬩欢
+        /// </summary>
+        public event Action<List<VisualL3d>> SelectionChangedEvent;
+
+        #endregion
+
+        #region 鍥哄畾璧勬簮
+
+        protected readonly HelixViewport3D _viewport = null;//涓夌淮缁勪欢
+        protected readonly LogicalStateHelper _stateHelper = null;//鐘舵�佽緟鍔╃被
+        protected readonly LogicalMaterialHelper _materialHelper = null;//鏉愯川杈呭姪绫�
+        protected readonly LogicalOverrideColorHelper _overrideColorHelper = null;//瑕嗙洊棰滆壊杈呭姪绫�
+        protected readonly LogicalOverrideOpacityHelper _overrideOpacityHelper = null;//瑕嗙洊閫忔槑搴﹁緟鍔╃被
+        protected readonly LogicalOverrideVisibleHelper _overrideVisibleHelper = null;//瑕嗙洊鍙鎬ц緟鍔╃被
+        protected readonly LogicalHighlightHelper _highlightHelper = null;//楂樹寒杈呭姪绫�
+        protected readonly LogicalSelectionHelper _selectionHelper = null;//閫夋嫨杈呭姪绫�
+        protected readonly LogicalZoomHelper _zoomHelper = null;//缂╂斁杈呭姪绫�
+
+        #endregion
+
+        #region 绉佹湁瀛楁
+
+        protected NetworkL3d _nw = null;
+        protected Dictionary<string, VisualL3d> _allVisualL3dDict;
+        protected Dictionary<VisualL3d, LogicalVisual3D> _allVisualLogicalDict;
+
+        #endregion
+
+        #region 鍒ゆ柇瀛楁
+
+        /// <summary>
+        /// 鏄惁鍚敤缂╂斁
+        /// </summary>
+        public virtual bool IsZoomEnabled
+        {
+            get { return _viewport.IsZoomEnabled; }
+            set { _viewport.IsZoomEnabled = value; }
+        }
+
+        /// <summary>
+        /// 鏄惁鍚敤骞崇Щ
+        /// </summary>
+        public virtual bool IsPanEnabled
+        {
+            get { return _viewport.IsPanEnabled; }
+            set { _viewport.IsPanEnabled = value; }
+        }
+
+        /// <summary>
+        /// 鏄惁鍚敤鏃嬭浆
+        /// </summary>
+        public virtual bool IsRotationEnabled
+        {
+            get { return _viewport.IsRotationEnabled; }
+            set { _viewport.IsRotationEnabled = value; }
+        }
+
+        /// <summary>
+        /// 鏄惁鍚敤楂樹寒
+        /// </summary>
+        public virtual bool IsHighlightEnabled
+        {
+            get { return _isHighlightEnabled; }
+            set { _isHighlightEnabled = value; }
+        }
+        protected bool _isHighlightEnabled = true;
+
+        /// <summary>
+        /// 鏄惁鍚敤閫夋嫨
+        /// </summary>
+        public virtual bool IsSelectionEnabled
+        {
+            get => _isSelectionEnabled;
+            set => _isSelectionEnabled = value;
+        }
+        protected bool _isSelectionEnabled = true;
+
+        /// <summary>
+        /// 鏄惁鍚敤缂╂斁閫傚簲
+        /// </summary>
+        public virtual bool IsZoomExtentsEnabled
+        {
+            get => _isZoomExtentsEnabled;
+            set => _isZoomExtentsEnabled = value;
+        }
+        protected bool _isZoomExtentsEnabled = true;
+
+        #endregion
+
+        #region 鍒濆鍖�
+
+        /// <summary>
+        /// 鏄惁鍒濆鍖�
+        /// </summary>
+        public virtual bool Initialized
+        {
+            get
+            {
+                if (_nw == null)
+                {
+                    return false;
+                }
+                if (_allVisualL3dDict == null)
+                {
+                    return false;
+                }
+                if (_allVisualLogicalDict == null)
+                {
+                    return false;
+                }
+                return true;
+            }
+        }
+
+        /// <summary>
+        /// 鍒濆鍖�
+        /// </summary>
+        public virtual void Initial(NetworkL3d nw)
+        {
+            _nw = nw;
+            InitialNetwork();
+            InitialViewport();
+            RegisterEvents();
+        }
+
+        //鍔犺浇绠$綉
+        protected virtual void InitialNetwork()
+        {
+            if (_nw == null)
+            {
+                return;
+            }
+            _allVisualL3dDict = _nw.Visuals.ToDictionary(keySelector: x => x.Id);
+            _allVisualLogicalDict = new Dictionary<VisualL3d, LogicalVisual3D>();
+            _nw.Visuals?.ForEach(x =>
+            {
+                var logicalVisual = LogicalCreateHelper.Create(x, _stateHelper, _materialHelper, _overrideColorHelper, _overrideOpacityHelper, _overrideVisibleHelper);
+                if (logicalVisual != null)
+                {
+                    _allVisualLogicalDict.Add(x, logicalVisual);
+                }
+            });
+        }
+
+        //鍒濆鍖朧ieport
+        protected virtual void InitialViewport()
+        {
+            InitialViewportInput();
+            InitialViewportCube();
+            InitialViewportData();
+        }
+
+        //鍒濆鍖朧iewport绔嬫柟浣�
+        protected virtual void InitialViewportCube()
+        {
+            if (_viewport == null)
+            {
+                return;
+            }
+            _viewport.ViewCubeBackText = "鍚�";
+            _viewport.ViewCubeBottomText = "涓�";
+            _viewport.ViewCubeFrontText = "鍓�";
+            _viewport.ViewCubeLeftText = "宸�";
+            _viewport.ViewCubeRightText = "鍙�";
+            _viewport.ViewCubeTopText = "涓�";
+        }
+
+        //鍒濆鍖朧iewport浜や簰
+        protected virtual void InitialViewportInput()
+        {
+            if (_viewport == null)
+            {
+                return;
+            }
+            //褰撳墠鎿嶄綔涓嶅仛浠讳綍澶勭悊锛屾槸涓轰簡閬垮厤榧犳爣鎿嶄綔鍐茬獊
+        }
+
+        //鍒濆鍖朧iewport鏁版嵁
+        protected virtual void InitialViewportData()
+        {
+            if (_viewport == null)
+            {
+                return;
+            }
+            _viewport.Children.Clear();
+            _viewport.Children.Add(new DefaultLights());
+            _allVisualLogicalDict?.Values.ToList().ForEach(x => _viewport.Children.Add(x));
+            _viewport.ZoomExtents();
+        }
+
+
+        #endregion
+
+        #region 浜嬩欢娉ㄥ唽
+
+        //娉ㄥ唽浜嬩欢
+        protected virtual void RegisterEvents()
+        {
+            RegisterViewportEvents();
+            RegisterOperationEvents();
+        }
+
+        #region Viewport
+
+        //娉ㄥ唽浜嬩欢
+        protected virtual void RegisterViewportEvents()
+        {
+            if (_viewport == null)
+            {
+                return;
+            }
+            _viewport.MouseDown += Viewport_MouseDown;
+            _viewport.MouseUp += Viewport_MouseUp;
+            _viewport.MouseMove += Viewport_MouseMove;
+            _viewport.MouseWheel += Viewport_MouseWheel;
+            _viewport.MouseDoubleClick += Viewport_MouseDoubleClick;
+            _viewport.MouseLeftButtonDown += Viewport_MouseLeftButtonDown;
+            _viewport.PreviewMouseDown += _viewport_PreviewMouseDown;
+        }
+
+        private void _viewport_PreviewMouseDown(object sender, MouseButtonEventArgs e)
+        {
+            OnPreviewMouseDown(e);
+        }
+
+        //榧犳爣鎸変笅
+        private void Viewport_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
+        {
+            OnMouseDown(e);
+        }
+
+        //榧犳爣寮硅捣
+        private void Viewport_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
+        {
+            OnMouseUp(e);
+        }
+
+        //榧犳爣绉诲姩
+        private void Viewport_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
+        {
+            OnMouseMove(e);
+        }
+
+        //榧犳爣婊氳疆
+        private void Viewport_MouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
+        {
+            OnMouseWheel(e);
+        }
+
+        //榧犳爣鍙屽嚮
+        private void Viewport_MouseDoubleClick(object sender, MouseButtonEventArgs e)
+        {
+            OnMouseDoubleClick(e);
+        }
+
+        //榧犳爣宸﹂敭鎸変笅
+        private void Viewport_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
+        {
+            OnMouseLeftButtonDown(e);
+        }
+
+        //澶勭悊榧犳爣鎸変笅浜嬩欢
+        protected virtual void OnMouseDown(System.Windows.Input.MouseButtonEventArgs e)
+        {
+
+        }
+
+        //澶勭悊榧犳爣寮硅捣浜嬩欢
+        protected virtual void OnMouseUp(System.Windows.Input.MouseButtonEventArgs e)
+        {
+            if (!Initialized)
+            {
+                return;
+            }
+            if (this.IsSelectionEnabled)
+            {
+                _selectionHelper.HandleSingle(e.GetPosition(_viewport));
+            }
+        }
+
+        //澶勭悊榧犳爣绉诲姩浜嬩欢
+        protected virtual void OnMouseMove(System.Windows.Input.MouseEventArgs e)
+        {
+            if (!Initialized)
+            {
+                return;
+            }
+            if (this.IsHighlightEnabled)
+            {
+                _highlightHelper.Highlight(e.GetPosition(_viewport));
+            }
+        }
+
+        //澶勭悊榧犳爣婊氳疆浜嬩欢
+        protected virtual void OnMouseWheel(System.Windows.Input.MouseWheelEventArgs e)
+        {
+
+        }
+
+        //澶勭悊榧犳爣鍙屽嚮浜嬩欢
+        protected virtual void OnMouseDoubleClick(System.Windows.Input.MouseButtonEventArgs e)
+        {
+            if (!Initialized)
+            {
+                return;
+            }
+            if (this.IsZoomExtentsEnabled)
+            {
+                _viewport.ZoomExtents();
+            }
+        }
+
+        //澶勭悊榧犳爣
+        protected virtual void OnMouseLeftButtonDown(MouseButtonEventArgs e)
+        {
+
+        }
+
+        protected virtual void OnPreviewMouseDown(MouseButtonEventArgs e)
+        {
+
+        }
+
+        #endregion
+
+        #region Operation
+
+        //娉ㄥ唽鎿嶄綔浜嬩欢
+        protected virtual void RegisterOperationEvents()
+        {
+            if (_highlightHelper != null)
+            {
+                _highlightHelper.StateChangedEvent += HighlightHelper_StateChangedEvent;
+            }
+            if (_selectionHelper != null)
+            {
+                _selectionHelper.StateChangedEvent += SelectionHelper_StateChangedEvent;
+                _selectionHelper.SelectionChangedEvent += SelectionHelper_SelectionChangedEvent;
+            }
+        }
+
+        //楂樹寒鐘舵�佹敼鍙樹簨浠�
+        private void HighlightHelper_StateChangedEvent(LogicalVisual3D logicalVisual, eLogicalHighlight highlightType)
+        {
+            if (logicalVisual == null)
+            {
+                return;
+            }
+            switch (highlightType)
+            {
+                case eLogicalHighlight.Load:
+                    {
+                        _stateHelper.LoadState(logicalVisual.Vmo, eLogicalState.Highlight);
+                    }
+                    break;
+                case eLogicalHighlight.Unload:
+                    {
+                        _stateHelper.UnloadState(logicalVisual.Vmo, eLogicalState.Highlight);
+                    }
+                    break;
+                default: break;
+            }
+            logicalVisual.UpdateVisual();
+        }
+
+        //閫夋嫨鐘舵�佹敼鍙樹簨浠�
+        private void SelectionHelper_StateChangedEvent(LogicalVisual3D logicalVisual, eLogicalSelection selectionType)
+        {
+            if (logicalVisual == null)
+            {
+                return;
+            }
+            switch (selectionType)
+            {
+                case eLogicalSelection.Load:
+                    {
+                        _stateHelper.LoadState(logicalVisual.Vmo, eLogicalState.Selection);
+                    }
+                    break;
+                case eLogicalSelection.Unload:
+                    {
+                        _stateHelper.UnloadState(logicalVisual.Vmo, eLogicalState.Selection);
+                    }
+                    break;
+                default: break;
+            }
+            logicalVisual.UpdateVisual();
+        }
+
+        //閫夋嫨鏀瑰彉浜嬩欢
+        private void SelectionHelper_SelectionChangedEvent(List<LogicalVisual3D> obj)
+        {
+            var visuals = obj?.Select(x => x.Vmo).ToList();
+            this.SelectionChangedEvent?.Invoke(visuals);
+        }
+
+
+        #endregion
+
+        #endregion
+
+
+
+
+
+
+
+
+
+
+
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/03-logical/08-manager/LogicalViewManager.cs b/Yw.WpfUI.Hydro.L3d.Core/03-logical/08-manager/LogicalViewManager.cs
new file mode 100644
index 0000000..1e7a64f
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/08-manager/LogicalViewManager.cs
@@ -0,0 +1,30 @@
+锘縩amespace Yw.WpfUI.Hydro
+{
+    /// <summary>
+    /// 鎶借薄瑙嗗浘绠$悊鍣�
+    /// </summary>
+    internal class LogicalViewManager : LogicalManager
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public LogicalViewManager(HelixViewport3D viewport) : base(viewport)
+        {
+
+        }
+
+        protected override void InitialViewportInput()
+        {
+            if (_viewport == null)
+            {
+                return;
+            }
+            _viewport.RotateGesture.MouseAction = MouseAction.LeftClick;
+            _viewport.RotateGesture.Modifiers = ModifierKeys.None;
+            _viewport.PanGesture.MouseAction = MouseAction.RightClick;
+            _viewport.PanGesture.Modifiers = ModifierKeys.None;
+            base.InitialViewportInput();
+        }
+
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/03-logical/08-manager/eLogicalEditMode.cs b/Yw.WpfUI.Hydro.L3d.Core/03-logical/08-manager/eLogicalEditMode.cs
new file mode 100644
index 0000000..43e440d
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/08-manager/eLogicalEditMode.cs
@@ -0,0 +1,20 @@
+锘縩amespace Yw.WpfUI.Hydro
+{
+    /// <summary>
+    /// 鎶借薄缂栬緫妯″紡
+    /// </summary>
+    internal enum eLogicalEditMode
+    {
+        None,
+        AddJunction,
+        AddReservoir,
+        AddTank,
+        AddPipe,
+        AddHorizPipe,
+        AddVertPipe,
+        AddPump,
+        AddValve,
+    }
+
+
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/03-control/ViewerL3d.xaml b/Yw.WpfUI.Hydro.L3d.Core/03-logical/09-control/LogicalEditerL3d.xaml
similarity index 76%
rename from Yw.WpfUI.Hydro.L3d.Core/03-control/ViewerL3d.xaml
rename to Yw.WpfUI.Hydro.L3d.Core/03-logical/09-control/LogicalEditerL3d.xaml
index 156c3d2..fcd1eb8 100644
--- a/Yw.WpfUI.Hydro.L3d.Core/03-control/ViewerL3d.xaml
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/09-control/LogicalEditerL3d.xaml
@@ -1,5 +1,5 @@
 锘�<UserControl
-    x:Class="Yw.WpfUI.Hydro.ViewerL3d"
+    x:Class="Yw.WpfUI.Hydro.LogicalEditerL3d"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
@@ -12,10 +12,6 @@
     <Grid>
         <hx:HelixViewport3D
             x:Name="viewport"
-            MouseDown="viewport_MouseDown"
-            MouseMove="viewport_MouseMove"
-            MouseUp="viewport_MouseUp"
-            MouseWheel="viewport_MouseWheel"
             ShowCoordinateSystem="True"
             ZoomExtentsWhenLoaded="True">
             <hx:DefaultLights />
diff --git a/Yw.WpfUI.Hydro.L3d.Core/03-logical/09-control/LogicalEditerL3d.xaml.cs b/Yw.WpfUI.Hydro.L3d.Core/03-logical/09-control/LogicalEditerL3d.xaml.cs
new file mode 100644
index 0000000..a731026
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/09-control/LogicalEditerL3d.xaml.cs
@@ -0,0 +1,85 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Yw.WpfUI.Hydro
+{
+    /// <summary>
+    /// LogicalEditerL3d.xaml 鐨勪氦浜掗�昏緫
+    /// </summary>
+    public partial class LogicalEditerL3d : UserControl
+    {
+        public LogicalEditerL3d()
+        {
+            InitializeComponent();
+        }
+
+        #region 浜嬩欢闆嗗悎
+
+        /// <summary>
+        /// 閫夋嫨鏀瑰彉浜嬩欢
+        /// </summary>
+        public event Action<List<VisualL3d>> SelectionChangedEvent;
+
+        #endregion
+
+        #region 绉佹湁瀛楁
+
+        private LogicalEditManager _manager = null;//绠$悊鍣�
+
+        #endregion
+
+        /// <summary>
+        /// 鍒濆鍖�
+        /// </summary>
+        public void Initial(NetworkL3d nw)
+        {
+            _manager = new LogicalEditManager(this.viewport);
+            _manager.Initial(nw);
+            _manager.SelectionChangedEvent += (List<VisualL3d> visuals) => this.SelectionChangedEvent?.Invoke(visuals);
+        }
+
+
+        public void StartAddJunction()
+        {
+            _manager.StartAddJunction();
+        }
+
+        public void StartAddReservoir()
+        {
+            _manager.StartAddReservoir();
+        }
+
+        public void StartAddTank()
+        {
+            _manager.StartAddTank();
+        }
+
+        public void StartAddPipe()
+        {
+            _manager.StartAddPipe();
+        }
+
+        public void StartAddPump()
+        {
+            _manager.StartAddPump();
+        }
+
+        public void StartAddValve()
+        {
+            _manager.StartAddValve();
+        }
+
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/03-control/ViewerL3d.xaml b/Yw.WpfUI.Hydro.L3d.Core/03-logical/09-control/LogicalViewerL3d.xaml
similarity index 76%
copy from Yw.WpfUI.Hydro.L3d.Core/03-control/ViewerL3d.xaml
copy to Yw.WpfUI.Hydro.L3d.Core/03-logical/09-control/LogicalViewerL3d.xaml
index 156c3d2..55ca919 100644
--- a/Yw.WpfUI.Hydro.L3d.Core/03-control/ViewerL3d.xaml
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/09-control/LogicalViewerL3d.xaml
@@ -1,5 +1,5 @@
 锘�<UserControl
-    x:Class="Yw.WpfUI.Hydro.ViewerL3d"
+    x:Class="Yw.WpfUI.Hydro.LogicalViewerL3d"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
@@ -12,10 +12,6 @@
     <Grid>
         <hx:HelixViewport3D
             x:Name="viewport"
-            MouseDown="viewport_MouseDown"
-            MouseMove="viewport_MouseMove"
-            MouseUp="viewport_MouseUp"
-            MouseWheel="viewport_MouseWheel"
             ShowCoordinateSystem="True"
             ZoomExtentsWhenLoaded="True">
             <hx:DefaultLights />
diff --git a/Yw.WpfUI.Hydro.L3d.Core/03-logical/09-control/LogicalViewerL3d.xaml.cs b/Yw.WpfUI.Hydro.L3d.Core/03-logical/09-control/LogicalViewerL3d.xaml.cs
new file mode 100644
index 0000000..282ec8f
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/03-logical/09-control/LogicalViewerL3d.xaml.cs
@@ -0,0 +1,54 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Yw.WpfUI.Hydro
+{
+    /// <summary>
+    /// LogicalViewerL3d.xaml 鐨勪氦浜掗�昏緫
+    /// </summary>
+    public partial class LogicalViewerL3d : UserControl
+    {
+        public LogicalViewerL3d()
+        {
+            InitializeComponent();
+        }
+
+        #region 浜嬩欢闆嗗悎
+
+        /// <summary>
+        /// 閫夋嫨鏀瑰彉浜嬩欢
+        /// </summary>
+        public event Action<List<VisualL3d>> SelectionChangedEvent;
+
+        #endregion
+
+        #region 绉佹湁瀛楁
+
+        private LogicalViewManager _manager = null;//绠$悊鍣�
+
+        #endregion
+
+        /// <summary>
+        /// 鍒濆鍖�
+        /// </summary>
+        public void Initial(NetworkL3d nw)
+        {
+            _manager = new LogicalViewManager(this.viewport);
+            _manager.Initial(nw);
+            _manager.SelectionChangedEvent += (List<VisualL3d> visuals) => this.SelectionChangedEvent?.Invoke(visuals);
+        }
+
+    }
+}
diff --git a/Yw.WpfUI.Hydro.L3d.Core/GlobalUsings.cs b/Yw.WpfUI.Hydro.L3d.Core/GlobalUsings.cs
index 7b2d6d1..7a204a3 100644
--- a/Yw.WpfUI.Hydro.L3d.Core/GlobalUsings.cs
+++ b/Yw.WpfUI.Hydro.L3d.Core/GlobalUsings.cs
@@ -1,6 +1,9 @@
 锘縢lobal using System.Windows.Media.Media3D;
 global using System.Windows.Media;
+global using System.Windows.Media.Animation;
 global using System.Windows;
 global using HelixToolkit.Wpf;
 global using System.Collections.Concurrent;
-global using System.Text;
\ No newline at end of file
+global using System.Text;
+global using System.IO;
+global using System.Windows.Input;
\ No newline at end of file
diff --git a/Yw.WpfUI.Hydro.L3d.Core/Yw.WpfUI.Hydro.L3d.Core.csproj b/Yw.WpfUI.Hydro.L3d.Core/Yw.WpfUI.Hydro.L3d.Core.csproj
index 058e4a8..2e388e4 100644
--- a/Yw.WpfUI.Hydro.L3d.Core/Yw.WpfUI.Hydro.L3d.Core.csproj
+++ b/Yw.WpfUI.Hydro.L3d.Core/Yw.WpfUI.Hydro.L3d.Core.csproj
@@ -11,7 +11,32 @@
 	</PropertyGroup>
 
 	<ItemGroup>
+		<None Remove="paras_hydrol3d_settings.json" />
+	</ItemGroup>
+
+	<ItemGroup>
+		<Content Include="paras_hydrol3d_settings.json">
+			<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+		</Content>
+	</ItemGroup>
+
+	<ItemGroup>
 		<PackageReference Include="HelixToolkit.Core.Wpf" Version="2.26.0" />
+		<PackageReference Include="Yw.Newtonsoft.Core" Version="3.0.0" />
+		<PackageReference Include="Yw.Untity.Core" Version="3.0.6" />
+	</ItemGroup>
+
+	<ItemGroup>
+		<Folder Include="03-logical\01-visual\01-node\01-junction\01-coupling\" />
+		<Folder Include="03-logical\01-visual\01-node\02-source\01-reservoir\" />
+		<Folder Include="03-logical\01-visual\01-node\02-source\02-tank\" />
+		<Folder Include="02-settings\01-paras\01-node\01-junction\" />
+		<Folder Include="02-settings\01-paras\01-node\02-source\01-reservoir\" />
+		<Folder Include="02-settings\01-paras\01-node\02-source\02-tank\" />
+		<Folder Include="02-settings\01-paras\01-node\02-source\00-core\" />
+		<Folder Include="02-settings\01-paras\02-link\01-pipe\" />
+		<Folder Include="02-settings\01-paras\02-link\02-pump\" />
+		<Folder Include="02-settings\01-paras\02-link\03-valve\" />
 	</ItemGroup>
 
 </Project>
diff --git a/Yw.WpfUI.Hydro.L3d.Core/Yw.WpfUI.Hydro.L3d.Core.csproj.user b/Yw.WpfUI.Hydro.L3d.Core/Yw.WpfUI.Hydro.L3d.Core.csproj.user
index 0023786..59851aa 100644
--- a/Yw.WpfUI.Hydro.L3d.Core/Yw.WpfUI.Hydro.L3d.Core.csproj.user
+++ b/Yw.WpfUI.Hydro.L3d.Core/Yw.WpfUI.Hydro.L3d.Core.csproj.user
@@ -3,4 +3,20 @@
   <PropertyGroup>
     <_LastSelectedProfileId>D:\WorkData\Module\Epanet\Yw.WpfUI.Hydro.L3d.Core\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId>
   </PropertyGroup>
+  <ItemGroup>
+    <Compile Update="03-logical\09-control\LogicalEditerL3d.xaml.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Update="03-logical\09-control\LogicalViewerL3d.xaml.cs">
+      <SubType>Code</SubType>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <Page Update="03-logical\09-control\LogicalEditerL3d.xaml">
+      <SubType>Designer</SubType>
+    </Page>
+    <Page Update="03-logical\09-control\LogicalViewerL3d.xaml">
+      <SubType>Designer</SubType>
+    </Page>
+  </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/Yw.WpfUI.Hydro.L3d.Core/paras_hydrol3d_settings.json b/Yw.WpfUI.Hydro.L3d.Core/paras_hydrol3d_settings.json
new file mode 100644
index 0000000..b3066e6
--- /dev/null
+++ b/Yw.WpfUI.Hydro.L3d.Core/paras_hydrol3d_settings.json
@@ -0,0 +1,40 @@
+{
+    "$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json",
+
+
+    "HydroL3d": {
+        "Logical": {
+            "Node": {
+                "Normal": {
+                    "HtmlColor": "#0000FF",
+                    "Radius": 0.3
+                },
+                "Highlight": {
+                    "HtmlColor": "#FF0000",
+                    "Radius": 0.5
+                },
+                "Selection": {
+                    "HtmlColor": "#FF0000",
+                    "Radius": 0.4
+                },
+                "SnapDistance": 0.2
+            },
+            "Link": {
+                "Normal": {
+                    "HtmlColor": "#0000FF",
+                    "Diameter": 0.5
+                },
+                "Highlight": {
+                    "HtmlColor": "#FF0000",
+                    "Diameter": 0.8
+                },
+                "Selection": {
+                    "HtmlColor": "#FF0000",
+                    "Diameter": 0.6
+                }
+            }
+        }
+    }
+
+
+}
diff --git a/Yw.WpfUI.Test.Core/MainWindow.xaml b/Yw.WpfUI.Test.Core/MainWindow.xaml
index 8084ce1..1306702 100644
--- a/Yw.WpfUI.Test.Core/MainWindow.xaml
+++ b/Yw.WpfUI.Test.Core/MainWindow.xaml
@@ -11,12 +11,72 @@
     Height="800"
     mc:Ignorable="d">
     <Grid>
-        <!--<hx:HelixViewport3D
-            x:Name="viewport"
-            ShowCoordinateSystem="True"
-            ZoomExtentsWhenLoaded="True">
-            <hx:DefaultLights />
-        </hx:HelixViewport3D>-->
-        <local:ViewerL3d Name="viewer" />
+        <Grid.RowDefinitions>
+            <RowDefinition Height="Auto" />
+            <RowDefinition Height="*" />
+        </Grid.RowDefinitions>
+        <!--  宸ュ叿鏍�  -->
+        <ToolBar
+            Grid.Row="0"
+            Margin="0"
+            Padding="0">
+            <RadioButton
+                x:Name="rbAddJunction"
+                Margin="5"
+                Checked="AddJunction_Click"
+                Content="鉃� 鑺傜偣"
+                GroupName="Add"
+                ToolTip="娣诲姞杩炴帴鑺傜偣 (N)" />
+            <RadioButton
+                x:Name="rbAddReservoir"
+                Margin="5"
+                Checked="AddReservoir_Click"
+                Content="鉃� 姘村簱"
+                GroupName="Add"
+                ToolTip="娣诲姞姘村簱 (R)" />
+            <RadioButton
+                x:Name="rbAddTank"
+                Margin="5"
+                Checked="AddTank_Click"
+                Content="鉃� 姘存睜"
+                GroupName="Add"
+                ToolTip="娣诲姞姘存睜 (T)" />
+            <RadioButton
+                x:Name="rbAddPipe"
+                Margin="5"
+                Checked="AddPipe_Click"
+                Content="鉃� 鑷敱绠�"
+                GroupName="Add"
+                ToolTip="鑷敱绠$嚎" />
+            <RadioButton
+                x:Name="rbAddHorizPipe"
+                Margin="5"
+                Checked="AddHorizPipe_Click"
+                Content="鉃� 姘村钩绠�"
+                GroupName="Add"
+                ToolTip="姘村钩绠$嚎 (H)" />
+            <RadioButton
+                x:Name="rbVertPipe"
+                Margin="5"
+                Checked="AddVertPipe_Click"
+                Content="猬� 鍨傜洿绠�"
+                GroupName="Add"
+                ToolTip="鍨傜洿绠$嚎 (V)" />
+            <RadioButton
+                x:Name="rbAddPump"
+                Margin="5"
+                Checked="AddPump_Click"
+                Content="鉃� 姘存车"
+                GroupName="Add"
+                ToolTip="姘存车 (P)" />
+            <RadioButton
+                x:Name="rbAddValve"
+                Margin="5"
+                Checked="AddValve_Click"
+                Content="鉃� 闃�闂�"
+                GroupName="Add"
+                ToolTip="闃�闂� (V)" />
+        </ToolBar>
+        <local:LogicalEditerL3d Name="editer" Grid.Row="1" />
     </Grid>
 </Window>
diff --git a/Yw.WpfUI.Test.Core/MainWindow.xaml.cs b/Yw.WpfUI.Test.Core/MainWindow.xaml.cs
index 2b89d9d..00740dd 100644
--- a/Yw.WpfUI.Test.Core/MainWindow.xaml.cs
+++ b/Yw.WpfUI.Test.Core/MainWindow.xaml.cs
@@ -22,7 +22,7 @@
         {
             var nw = LoadEpaNetwork();
             var nw3d = Get3dNetwork(nw);
-            this.viewer.Initial(nw3d);
+            this.editer.Initial(nw3d);
             //BuildSimpleNetwork(this.viewport,nw3d.Nodes,nw3d.Links);
         }
 
@@ -129,8 +129,45 @@
 
         }
 
+        private void AddJunction_Click(object sender, RoutedEventArgs e)
+        {
+            this.editer.StartAddJunction();
+        }
 
+        private void AddReservoir_Click(object sender, RoutedEventArgs e)
+        {
+            this.editer.StartAddReservoir();
+        }
 
+        private void AddTank_Click(object sender, RoutedEventArgs e)
+        {
+            this.editer.StartAddTank();
+        }
+
+        private void AddPipe_Click(object sender, RoutedEventArgs e)
+        {
+            this.editer.StartAddPipe();
+        }
+
+        private void AddHorizPipe_Click(object sender, RoutedEventArgs e)
+        {
+
+        }
+
+        private void AddVertPipe_Click(object sender, RoutedEventArgs e)
+        {
+
+        }
+
+        private void AddPump_Click(object sender, RoutedEventArgs e)
+        {
+            this.editer.StartAddPump();
+        }
+
+        private void AddValve_Click(object sender, RoutedEventArgs e)
+        {
+            this.editer.StartAddValve();
+        }
     }
 
 

--
Gitblit v1.9.3