lixiaojun
2025-04-18 28ba54f194f1301c45aa30b44cd7b612855b8963
改变光源,管理器修改
已删除1个文件
已修改20个文件
已添加4个文件
1582 ■■■■■ 文件已修改
Yw.WpfUI.Hydro.L3d.Core/00-core/CatalogL3d.cs 67 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Yw.WpfUI.Hydro.L3d.Core/00-core/CatalogL3dExtensions.cs 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Yw.WpfUI.Hydro.L3d.Core/00-core/ConstParas.cs 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Yw.WpfUI.Hydro.L3d.Core/01-network/00-core/NetworkL3d_Append.cs 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Yw.WpfUI.Hydro.L3d.Core/01-network/00-core/NetworkL3d_Method.cs 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Yw.WpfUI.Hydro.L3d.Core/01-network/04-link/00-core/LinkL3d.cs 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Yw.WpfUI.Hydro.L3d.Core/03-logical/00-core/LogicalCreateHelper.cs 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Yw.WpfUI.Hydro.L3d.Core/03-logical/00-core/LogicalLineTransformHelper.cs 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/00-core/LogicalVisual3D.cs 53 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/01-node/00-core/LogicalNode3D.cs 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/01-node/01-junction/00-core/LogicalJunction3D.cs 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/01-node/02-source/00-core/LogicalSource3D.cs 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/01-node/02-source/01-reservoir/LogicalReservoir3D.cs 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/01-node/02-source/02-tank/LogicalTank3D.cs 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/02-link/00-core/LogicalLink3D.cs 65 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/02-link/01-pipe/LogicalPipe3D.cs 38 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/02-link/02-pump/LogicalPump3D.cs 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/02-link/03-valve/LogicalValve3D.cs 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Yw.WpfUI.Hydro.L3d.Core/03-logical/02-state/eLogicalState.cs 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Yw.WpfUI.Hydro.L3d.Core/03-logical/08-manager/LogicalEditManager.cs 683 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Yw.WpfUI.Hydro.L3d.Core/03-logical/08-manager/LogicalManager.cs 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Yw.WpfUI.Hydro.L3d.Core/03-logical/08-manager/eLogicalEditMode.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Yw.WpfUI.Hydro.L3d.Core/Yw.WpfUI.Hydro.L3d.Core.csproj 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Yw.WpfUI.Hydro.L3d.Core/paras_hydrol3d_settings.json 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Yw.WpfUI.Test.Core/MainWindow.xaml.cs 42 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Yw.WpfUI.Hydro.L3d.Core/00-core/CatalogL3d.cs
@@ -8,157 +8,162 @@
        /// <summary>
        /// ç»„ä»¶
        /// </summary>
        public const string Parter = "Parter";
        public const string Parter = "parter";
        /// <summary>
        /// å¯è§ç»„ä»¶
        /// </summary>
        public const string Visual = "Visual";
        public const string Visual = "visual";
        /// <summary>
        /// èŠ‚ç‚¹
        /// </summary>
        public const string Node = "Node";
        public const string Node = "node";
        /// <summary>
        /// æ°´æº
        /// </summary>
        public const string Source = "source";
        /// <summary>
        /// æ°´åº“
        /// </summary>
        public const string Reservoir = "Reservoir";
        public const string Reservoir = "reservoir";
        /// <summary>
        /// æ°´æ± 
        /// </summary>
        public const string Tank = "Tank";
        public const string Tank = "tank";
        /// <summary>
        /// æ°´ç®±
        /// </summary>
        public const string Waterbox = "Waterbox";
        public const string Waterbox = "waterbox";
        /// <summary>
        /// è¿žæŽ¥èŠ‚ç‚¹
        /// </summary>
        public const string Junction = "Junction";
        public const string Junction = "junction";
        /// <summary>
        /// è¿žæŽ¥ä»¶
        /// </summary>
        public const string Coupling = "Coupling";
        public const string Coupling = "coupling";
        /// <summary>
        /// é—·å¤´
        /// </summary>
        public const string Blunthead = "Blunthead";
        public const string Blunthead = "blunthead";
        /// <summary>
        /// å¼¯å¤´
        /// </summary>
        public const string Elbow = "Elbow";
        public const string Elbow = "elbow";
        /// <summary>
        /// ä¸‰é€š
        /// </summary>
        public const string Threelink = "Threelink";
        public const string Threelink = "threelink";
        /// <summary>
        /// å››é€š
        /// </summary>
        public const string Fourlink = "Fourlink";
        public const string Fourlink = "fourlink";
        /// <summary>
        /// æ‰©æ•£å™¨
        /// </summary>
        public const string Emitter = "Emitter";
        public const string Emitter = "emitter";
        /// <summary>
        /// å–·å¤´
        /// </summary>
        public const string Nozzle = "Nozzle";
        public const string Nozzle = "zozzle";
        /// <summary>
        /// æ¶ˆç«æ “
        /// </summary>
        public const string Hydrant = "Hydrant";
        public const string Hydrant = "hydrant";
        /// <summary>
        /// æ°´è¡¨
        /// </summary>
        public const string Meter = "Meter";
        public const string Meter = "meter";
        /// <summary>
        /// ä»ªè¡¨
        /// </summary>
        public const string Instrument = "Instrument";
        public const string Instrument = "instrument";
        /// <summary>
        /// æµé‡è®¡
        /// </summary>
        public const string Flowmeter = "Flowmeter";
        public const string Flowmeter = "flowmeter";
        /// <summary>
        /// åŽ‹åŠ›è¡¨
        /// </summary>
        public const string Pressmeter = "Pressmeter";
        public const string Pressmeter = "pressmeter";
        /// <summary>
        /// ç®¡æ®µ
        /// </summary>
        public const string Link = "Link";
        public const string Link = "link";
        /// <summary>
        /// ç®¡é“
        /// </summary>
        public const string Pipe = "Pipe";
        public const string Pipe = "pipe";
        /// <summary>
        /// è¿‡æ¸¡ä»¶(变径管)
        /// </summary>
        public const string Translation = "Translation";
        public const string Translation = "translation";
        /// <summary>
        /// æ°´æ³µ
        /// </summary>
        public const string Pump = "Pump";
        public const string Pump = "pump";
        /// <summary>
        /// é˜€é—¨
        /// </summary>
        public const string Valve = "Valve";
        public const string Valve = "valve";
        /// <summary>
        /// æ°´åŠ›é˜»ä»¶
        /// </summary>
        public const string Resistance = "Resistance";
        public const string Resistance = "resistance";
        /// <summary>
        /// æ¢çƒ­å™¨
        /// </summary>
        public const string Exchanger = "Exchanger";
        public const string Exchanger = "exchanger";
        /// <summary>
        /// åŽ‹ç¼©æœº
        /// </summary>
        public const string Compressor = "Compressor";
        public const string Compressor = "compressor";
        /// <summary>
        /// æ“ä½œ
        /// </summary>
        public const string Operation = "Operation";
        public const string Operation = "operation";
        /// <summary>
        /// æ›²çº¿
        /// </summary>
        public const string Curve = "Curve";
        public const string Curve = "curve";
        /// <summary>
        /// æ¨¡å¼
        /// </summary>
        public const string Pattern = "Pattern";
        public const string Pattern = "pattern";
        /// <summary>
        /// è§„则
        /// </summary>
        public const string Rule = "Rule";
        public const string Rule = "rule";
    }
}
Yw.WpfUI.Hydro.L3d.Core/00-core/CatalogL3dExtensions.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,59 @@
namespace Yw.WpfUI.Hydro
{
    /// <summary>
    /// åˆ†ç±»æ‰©å±•
    /// </summary>
    internal static class CatalogL3dExtensions
    {
        /// <summary>
        /// èŽ·å–åˆ†ç±»åç§°
        /// </summary>
        public static string GetCatalogName(this string code)
        {
            var caser = code?.Trim()?.ToLower();
            if (string.IsNullOrEmpty(caser))
            {
                return string.Empty;
            }
            var name = string.Empty;
            switch (caser)
            {
                case CatalogL3d.Parter: name = "组件"; break;
                case CatalogL3d.Visual: name = "可视组件"; break;
                case CatalogL3d.Node: name = "节点"; break;
                case CatalogL3d.Junction: name = "连接节点"; break;
                case CatalogL3d.Coupling: name = "连接件"; break;
                case CatalogL3d.Blunthead: name = "闷头"; break;
                case CatalogL3d.Elbow: name = "弯头"; break;
                case CatalogL3d.Threelink: name = "三通"; break;
                case CatalogL3d.Fourlink: name = "四通"; break;
                case CatalogL3d.Meter: name = "水表"; break;
                case CatalogL3d.Instrument: name = "仪表"; break;
                case CatalogL3d.Flowmeter: name = "流量计"; break;
                case CatalogL3d.Pressmeter: name = "压力表"; break;
                case CatalogL3d.Emitter: name = "扩散器"; break;
                case CatalogL3d.Nozzle: name = "喷头"; break;
                case CatalogL3d.Hydrant: name = "消火栓"; break;
                case CatalogL3d.Source: name = "水源"; break;
                case CatalogL3d.Reservoir: name = "水库"; break;
                case CatalogL3d.Tank: name = "æ°´æ± "; break;
                case CatalogL3d.Waterbox: name = "æ°´ç®±"; break;
                case CatalogL3d.Link: name = "管段"; break;
                case CatalogL3d.Pipe: name = "管道"; break;
                case CatalogL3d.Translation: name = "过渡件"; break;
                case CatalogL3d.Pump: name = "æ°´æ³µ"; break;
                case CatalogL3d.Valve: name = "阀门"; break;
                case CatalogL3d.Resistance: name = "阻件"; break;
                case CatalogL3d.Exchanger: name = "换热器"; break;
                case CatalogL3d.Compressor: name = "压缩机"; break;
                case CatalogL3d.Curve: name = "曲线"; break;
                case CatalogL3d.Pattern: name = "模式"; break;
                case CatalogL3d.Rule: name = "规则"; break;
                default: break;
            }
            return name;
        }
    }
}
Yw.WpfUI.Hydro.L3d.Core/00-core/ConstParas.cs
ÎļþÒÑɾ³ý
Yw.WpfUI.Hydro.L3d.Core/01-network/00-core/NetworkL3d_Append.cs
@@ -5,6 +5,7 @@
    /// </summary>
    public partial class NetworkL3d
    {
        /// <summary>
        /// æ·»åŠ ç»„ä»¶
        /// </summary>
@@ -196,5 +197,7 @@
    }
}
Yw.WpfUI.Hydro.L3d.Core/01-network/00-core/NetworkL3d_Method.cs
@@ -9,16 +9,51 @@
        /// <summary>
        /// åˆ¤æ–­æ˜¯å¦å­˜åœ¨
        /// </summary>
        public bool IsExist(string id)
        internal bool IsExist(string id)
        {
            return _parters.Exists(x => x.Id == id);
        }
        /// <summary>
        /// åˆ¤æ–­æ˜¯å¦å­˜åœ¨
        /// </summary>
        internal bool IsExist(ParterL3d parter)
        {
            if (parter == null)
            {
                return false;
            }
            return _parters.Contains(parter);
        }
        /// <summary>
        /// ç§»é™¤
        /// </summary>
        internal bool Remove(ParterL3d parter)
        {
            return _parters.Remove(parter);
        }
        /// <summary>
        /// åˆ›å»ºId
        /// </summary>
        internal string CreateId(string catalog)
        {
            var ids = this.Parters.Select(x => x.Id).Distinct().ToList();
            var id = Yw.Untity.UniqueHelper.CreateFromFirst(catalog, ids);
            return id;
        }
        /// <summary>
        /// åˆ›å»ºåç§°
        /// </summary>
        internal string CreateName(string catalog)
        {
            var names = this.Parters.Select(x => x.Name).Distinct().ToList();
            var catalogName = catalog.GetCatalogName();
            var name = Yw.Untity.UniqueHelper.CreateFromFirst(catalogName, names);
            return name;
        }
Yw.WpfUI.Hydro.L3d.Core/01-network/04-link/00-core/LinkL3d.cs
@@ -18,8 +18,8 @@
        /// </summary>
        public LinkL3d(LinkL3d rhs) : base(rhs)
        {
            this.StartPosition = new PointL3d(rhs.StartPosition);
            this.EndPosition = new PointL3d(rhs.EndPosition);
            this.StartNode = rhs.StartNode;
            this.EndNode = rhs.EndNode;
        }
        /// <summary>
@@ -32,23 +32,27 @@
        /// </summary>
        public NodeL3d EndNode { get; set; }
        /// <summary>
        /// ä¸Šæ¸¸ä½ç½®
        /// </summary>
        public PointL3d StartPosition { get; set; }
        /// <summary>
        /// ä¸‹æ¸¸ä½ç½®
        /// </summary>
        public PointL3d EndPosition { get; set; }
        /// <summary>
        /// èŽ·å–ä½ç½®
        /// </summary>
        public override List<PointL3d> GetPositions()
        {
            return new List<PointL3d>() { this.StartPosition, this.EndPosition };
            var list = new List<PointL3d>();
            if (this.StartNode != null)
            {
                if (this.StartNode.Position != null)
                {
                    list.Add(this.StartNode.Position);
                }
            }
            if (this.EndNode != null)
            {
                if (this.EndNode.Position != null)
                {
                    list.Add(this.EndNode.Position);
                }
            }
            return list;
        }
Yw.WpfUI.Hydro.L3d.Core/03-logical/00-core/LogicalCreateHelper.cs
@@ -8,7 +8,7 @@
        /// <summary>
        /// åˆ›å»º
        /// </summary>
        /// <param name="visuall3d"></param>
        /// <param name="visual"></param>
        /// <param name="stateHelper"></param>
        /// <param name="materialHelper"></param>
        /// <param name="overrideColorHelper"></param>
@@ -17,7 +17,7 @@
        /// <returns></returns>
        public static LogicalVisual3D Create
            (
                VisualL3d visuall3d,
                VisualL3d visual,
                LogicalStateHelper stateHelper,
                LogicalMaterialHelper materialHelper,
                LogicalOverrideColorHelper overrideColorHelper,
@@ -25,27 +25,31 @@
                LogicalOverrideVisibleHelper overrideVisibleHelper
            )
        {
            if (visuall3d == null)
            if (visual == null)
            {
                return default;
            }
            if (visuall3d is JunctionL3d junctionl3d)
            if (visual is JunctionL3d junction)
            {
                return new LogicalJunction3D(junctionl3d, stateHelper, materialHelper, overrideColorHelper, overrideOpacityHelper, overrideVisibleHelper);
                return new LogicalJunction3D(junction, stateHelper, materialHelper, overrideColorHelper, overrideOpacityHelper, overrideVisibleHelper);
            }
            if (visuall3d is SourceL3d sourcel3d)
            if (visual is ReservoirL3d reservoir)
            {
                return new LogicalSource3D(sourcel3d, stateHelper, materialHelper, overrideColorHelper, overrideOpacityHelper, overrideVisibleHelper);
                return new LogicalReservoir3D(reservoir, stateHelper, materialHelper, overrideColorHelper, overrideOpacityHelper, overrideVisibleHelper);
            }
            if (visuall3d is PipeL3d pipel3d)
            if (visual is TankL3d tank)
            {
                return new LogicalTank3D(tank, stateHelper, materialHelper, overrideColorHelper, overrideOpacityHelper, overrideVisibleHelper);
            }
            if (visual is PipeL3d pipel3d)
            {
                return new LogicalPipe3D(pipel3d, stateHelper, materialHelper, overrideColorHelper, overrideOpacityHelper, overrideVisibleHelper);
            }
            if (visuall3d is PumpL3d pumpl3d)
            if (visual is PumpL3d pumpl3d)
            {
                return new LogicalPump3D(pumpl3d, stateHelper, materialHelper, overrideColorHelper, overrideOpacityHelper, overrideVisibleHelper);
            }
            if (visuall3d is ValveL3d valvel3d)
            if (visual is ValveL3d valvel3d)
            {
                return new LogicalValve3D(valvel3d, stateHelper, materialHelper, overrideColorHelper, overrideOpacityHelper, overrideVisibleHelper);
            }
Yw.WpfUI.Hydro.L3d.Core/03-logical/00-core/LogicalLineTransformHelper.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,121 @@
namespace Yw.WpfUI.Hydro
{
    /// <summary>
    /// æŠ½è±¡çº¿è½¬æ¢è¾…助类
    /// </summary>
    internal class LogicalLineTransformHelper
    {
        /// <summary>
        ///
        /// </summary>
        public LogicalLineTransformHelper(Point3D start, Point3D end)
        {
            this.StartPoint = start;
            this.EndPoint = end;
            this.Direction = end - start;
            this.Length = this.Direction.Length;
            this.Direction.Normalize();
            this.Perpendicular = Math.Abs(Direction.X) > 0.9
                ? Vector3D.CrossProduct(Direction, new Vector3D(0, 1, 0))
                : Vector3D.CrossProduct(Direction, new Vector3D(1, 0, 0));
            this.Perpendicular.Normalize();
        }
        /// <summary>
        /// å¼€å§‹ç‚¹
        /// </summary>
        public Point3D StartPoint { get; }
        /// <summary>
        /// ç»“束点
        /// </summary>
        public Point3D EndPoint { get; }
        /// <summary>
        /// é•¿åº¦
        /// </summary>
        public double Length { get; }
        /// <summary>
        /// æ–¹å‘
        /// </summary>
        public Vector3D Direction { get; }
        /// <summary>
        /// åž‚线
        /// </summary>
        public Vector3D Perpendicular { get; }
        /// <summary>
        /// å°†å±€éƒ¨åæ ‡è½¬æ¢ä¸ºä¸–界坐标
        /// </summary>
        public Point3D LocalToWorld(Point3D local)
        {
            // è®¡ç®—中点作为局部坐标系原点
            Point3D center = this.StartPoint + (this.EndPoint - this.StartPoint) * 0.5;
            // åˆ›å»ºå˜æ¢çŸ©é˜µ
            var transform = new Matrix3D();
            // æ—‹è½¬ä»ŽZ轴到实际方向
            var axis = Vector3D.CrossProduct(new Vector3D(0, 0, 1), this.Direction);
            double angle = Vector3D.AngleBetween(new Vector3D(0, 0, 1), this.Direction);
            transform.Rotate(new Quaternion(axis, angle));
            // å¹³ç§»
            transform.Translate(new Vector3D(center.X, center.Y, center.Z));
            return transform.Transform(local);
        }
        /// <summary>
        /// å°†ä¸–界坐标转换为局部坐标
        /// </summary>
        public Point3D WorldToLocal(Point3D world)
        {
            Point3D center = this.StartPoint + (this.EndPoint - this.StartPoint) * 0.5;
            var transform = new Matrix3D();
            transform.Translate(new Vector3D(-center.X, -center.Y, -center.Z));
            var axis = Vector3D.CrossProduct(new Vector3D(0, 0, 1), Direction);
            double angle = -Vector3D.AngleBetween(new Vector3D(0, 0, 1), Direction);
            transform.Rotate(new Quaternion(axis, angle));
            return transform.Transform(world);
        }
        /// <summary>
        /// è®¡ç®—矩阵
        /// </summary>
        public Matrix3D CalculateMatrix()
        {
            // è®¡ç®—中点
            var center = this.StartPoint + (this.EndPoint - this.StartPoint) * 0.5;
            // è®¡ç®—旋转轴和角度(从Z轴旋转到实际方向)
            var axis = Vector3D.CrossProduct(new Vector3D(0, 0, 1), this.Direction);
            double angle = Vector3D.AngleBetween(new Vector3D(0, 0, 1), this.Direction);
            // åˆ›å»ºå˜æ¢çŸ©é˜µ
            var transform = new Matrix3D();
            transform.Rotate(new Quaternion(axis, angle));
            transform.Translate(new Vector3D(center.X, center.Y, center.Z));
            return transform;
        }
        /// <summary>
        /// è®¡ç®—转换
        /// </summary>
        public Transform3D CalculateTransform()
        {
            var matrix = CalculateMatrix();
            return new MatrixTransform3D(matrix);
        }
    }
}
Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/00-core/LogicalVisual3D.cs
@@ -38,7 +38,6 @@
        protected readonly LogicalOverrideOpacityHelper _overrideOpacityHelper = null;//覆盖透明度辅助类
        protected readonly LogicalOverrideVisibleHelper _overrideVisibleHelper = null;//覆盖可见性辅助类
        /// <summary>
        /// Vmo
        /// </summary>
@@ -51,22 +50,62 @@
        /// <summary>
        /// æ›´æ–°å¯è§å…ƒç´ 
        /// åŒ…含位置、材质、几何图形和可见性
        /// </summary>
        public virtual void UpdateVisual()
        {
            this.UpdatePositions();
            this.UpdateGeometry();
            this.UpdateMaterial();
            this.UpdateTransform();
            this.UpdateVisibility();
        }
        //更新材质
        protected abstract void UpdateMaterial();
        /// <summary>
        /// æ›´æ–°ä½ç½®
        /// </summary>
        public abstract void UpdatePositions();
        //更新几何图形
        protected abstract void UpdateGeometry();
        /// <summary>
        /// æ›´æ–°æè´¨
        /// </summary>
        public abstract void UpdateMaterial();
        //更新可见性
        protected abstract void UpdateVisibility();
        /// <summary>
        /// æ›´æ–°å‡ ä½•图形
        /// </summary>
        public abstract void UpdateGeometry();
        /// <summary>
        /// æ›´æ–°å˜æ¢çŸ©é˜µ
        /// </summary>
        public abstract void UpdateTransform();
        /// <summary>
        /// æ›´æ–°å¯è§æ€§
        /// </summary>
        public virtual void UpdateVisibility()
        {
            bool visible = true;
            var state = _stateHelper.GetState(this.Vmo);
            if (state.HasFlag(eLogicalState.Visible))
            {
                visible = _overrideVisibleHelper.GetVisible(this.Vmo);
            }
            this.Visible = visible;
        }
        /// <summary>
        /// éªŒè¯
        /// </summary>
        public virtual bool Verify()
        {
            if (this.Vmo == null)
            {
                return false;
            }
            return true;
        }
    }
Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/01-node/00-core/LogicalNode3D.cs
@@ -23,7 +23,7 @@
                LogicalOverrideVisibleHelper overrideVisibleHelper
            ) : base(vmo, stateHelper, materialHelper, overrideColorHelper, overrideOpacityHelper, overrideVisibleHelper)
        {
            this.Position = vmo.Position.ToPoint3D();
        }
        /// <summary>
@@ -41,12 +41,33 @@
        public Point3D Position { get; set; }
        /// <summary>
        /// æ›´æ–°å¯è§†åŒ–元素
        /// æ›´æ–°ä½ç½®
        /// </summary>
        public override void UpdateVisual()
        public override void UpdatePositions()
        {
            this.Position = this.Vmo.Position.ToPoint3D();
            base.UpdateVisual();
            if (this.Vmo != null)
            {
                if (this.Vmo.Position != null)
                {
                    this.Position = this.Vmo.Position.ToPoint3D();
                }
            }
        }
        /// <summary>
        /// éªŒè¯
        /// </summary>
        public override bool Verify()
        {
            if (this.Vmo == null)
            {
                return false;
            }
            if (this.Vmo.Position == null)
            {
                return false;
            }
            return base.Verify();
        }
Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/01-node/01-junction/00-core/LogicalJunction3D.cs
@@ -35,8 +35,10 @@
            set { _vmo = value; }
        }
        //更新材质
        protected override void UpdateMaterial()
        /// <summary>
        /// æ›´æ–°æè´¨
        /// </summary>
        public override void UpdateMaterial()
        {
            var htmlColor = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Node.Normal.HtmlColor;
            var opacity = 1.0d;
@@ -61,20 +63,10 @@
            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()
        /// <summary>
        /// æ›´æ–°å‡ ä½•图形
        /// </summary>
        public override void UpdateGeometry()
        {
            var radius = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Node.Normal.Radius;
            var state = _stateHelper.GetState(this.Vmo);
@@ -94,6 +86,14 @@
            this.MeshGeometry = geometry;
        }
        /// <summary>
        /// æ›´æ–°å˜æ¢çŸ©é˜µ
        /// </summary>
        public override void UpdateTransform()
        {
        }
    }
}
Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/01-node/02-source/00-core/LogicalSource3D.cs
@@ -35,8 +35,10 @@
            set { _vmo = value; }
        }
        //更新材质
        protected override void UpdateMaterial()
        /// <summary>
        /// æ›´æ–°æè´¨
        /// </summary>
        public override void UpdateMaterial()
        {
            var htmlColor = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Node.Normal.HtmlColor;
            var opacity = 1.0d;
@@ -61,20 +63,10 @@
            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()
        /// <summary>
        /// æ›´æ–°å‡ ä½•图形
        /// </summary>
        public override void UpdateGeometry()
        {
            var radius = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Node.Normal.Radius;
            var state = _stateHelper.GetState(this.Vmo);
@@ -97,6 +89,13 @@
            this.MeshGeometry = geometry;
        }
        /// <summary>
        /// æ›´æ–°å˜æ¢çŸ©é˜µ
        /// </summary>
        public override void UpdateTransform()
        {
        }
    }
}
Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/01-node/02-source/01-reservoir/LogicalReservoir3D.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,41 @@
namespace Yw.WpfUI.Hydro
{
    internal class LogicalReservoir3D : LogicalSource3D
    {
        /// <summary>
        ///
        /// </summary>
        public LogicalReservoir3D() { }
        /// <summary>
        ///
        /// </summary>
        public LogicalReservoir3D
            (
                ReservoirL3d vmo,
                LogicalStateHelper stateHelper,
                LogicalMaterialHelper materialHelper,
                LogicalOverrideColorHelper overrideColorHelper,
                LogicalOverrideOpacityHelper overrideOpacityHelper,
                LogicalOverrideVisibleHelper overrideVisibleHelper
            ) : base(vmo, stateHelper, materialHelper, overrideColorHelper, overrideOpacityHelper, overrideVisibleHelper)
        {
        }
        /// <summary>
        /// Vmo
        /// </summary>
        public new ReservoirL3d Vmo
        {
            get { return _vmo as ReservoirL3d; }
            set { _vmo = value; }
        }
    }
}
Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/01-node/02-source/02-tank/LogicalTank3D.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,40 @@
namespace Yw.WpfUI.Hydro
{
    /// <summary>
    ///
    /// </summary>
    internal class LogicalTank3D : LogicalSource3D
    {
        /// <summary>
        ///
        /// </summary>
        public LogicalTank3D() { }
        /// <summary>
        ///
        /// </summary>
        public LogicalTank3D
            (
                TankL3d vmo,
                LogicalStateHelper stateHelper,
                LogicalMaterialHelper materialHelper,
                LogicalOverrideColorHelper overrideColorHelper,
                LogicalOverrideOpacityHelper overrideOpacityHelper,
                LogicalOverrideVisibleHelper overrideVisibleHelper
            ) : base(vmo, stateHelper, materialHelper, overrideColorHelper, overrideOpacityHelper, overrideVisibleHelper)
        {
        }
        /// <summary>
        /// Vmo
        /// </summary>
        public new TankL3d Vmo
        {
            get { return _vmo as TankL3d; }
            set { _vmo = value; }
        }
    }
}
Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/02-link/00-core/LogicalLink3D.cs
@@ -23,8 +23,7 @@
                LogicalOverrideVisibleHelper overrideVisibleHelper
            ) : base(vmo, stateHelper, materialHelper, overrideColorHelper, overrideOpacityHelper, overrideVisibleHelper)
        {
            this.StartPosition = vmo.StartPosition.ToPoint3D();
            this.EndPosition = vmo.EndPosition.ToPoint3D();
        }
        /// <summary>
@@ -47,14 +46,66 @@
        public Point3D EndPosition { get; set; }
        /// <summary>
        /// æ›´æ–°å¯è§†åŒ–元素
        /// æ›´æ–°ä½ç½®ä¿¡æ¯
        /// </summary>
        public override void UpdateVisual()
        public override void UpdatePositions()
        {
            this.StartPosition = this.Vmo.StartPosition.ToPoint3D();
            this.EndPosition = this.Vmo.EndPosition.ToPoint3D();
            base.UpdateVisual();
            if (this.Vmo != null)
            {
                if (this.Vmo.StartNode != null)
                {
                    if (this.Vmo.StartNode.Position != null)
                    {
                        this.StartPosition = this.Vmo.StartNode.Position.ToPoint3D();
                    }
                }
                if (this.Vmo.EndNode != null)
                {
                    if (this.Vmo.EndNode.Position != null)
                    {
                        this.EndPosition = this.Vmo.EndNode.Position.ToPoint3D();
                    }
                }
            }
        }
        /// <summary>
        /// éªŒè¯
        /// </summary>
        public override bool Verify()
        {
            if (this.Vmo == null)
            {
                return false;
            }
            if (this.Vmo.StartNode == null)
            {
                return false;
            }
            if (this.Vmo.StartNode.Position == null)
            {
                return false;
            }
            if (this.Vmo.EndNode == null)
            {
                return false;
            }
            if (this.Vmo.EndNode.Position == null)
            {
                return false;
            }
            var snapDistance = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Node.SnapDistance;
            var length = (this.EndPosition - this.StartPosition).Length;
            if (length < snapDistance)
            {
                return false;
            }
            return base.Verify();
        }
    }
}
Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/02-link/01-pipe/LogicalPipe3D.cs
@@ -35,8 +35,10 @@
            set { _vmo = value; }
        }
        //更新材质
        protected override void UpdateMaterial()
        /// <summary>
        /// æ›´æ–°æè´¨
        /// </summary>
        public override void UpdateMaterial()
        {
            var htmlColor = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Normal.HtmlColor;
            var opacity = 1.0d;
@@ -61,20 +63,10 @@
            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()
        /// <summary>
        /// æ›´æ–°å‡ ä½•图形
        /// </summary>
        public override void UpdateGeometry()
        {
            var diameter = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Normal.Diameter;
            var state = _stateHelper.GetState(this.Vmo);
@@ -87,12 +79,9 @@
                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 },
                path: new[] { this.StartPosition, this.EndPosition },
                diameter: diameter,  // çº¿ç›´å¾„(3D空间单位)
                thetaDiv: 8,    // æ¨ªæˆªé¢ç»†åˆ†åº¦
                false
@@ -101,6 +90,15 @@
            this.MeshGeometry = geometry;
        }
        /// <summary>
        /// æ›´æ–°å˜æ¢çŸ©é˜µ
        /// </summary>
        public override void UpdateTransform()
        {
        }
    }
Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/02-link/02-pump/LogicalPump3D.cs
@@ -1,4 +1,6 @@
namespace Yw.WpfUI.Hydro
using System.Net;
namespace Yw.WpfUI.Hydro
{
    /// <summary>
    /// æŠ½è±¡3Dæ°´æ³µ
@@ -35,8 +37,10 @@
            set { _vmo = value; }
        }
        //更新材质
        protected override void UpdateMaterial()
        /// <summary>
        /// æ›´æ–°æè´¨
        /// </summary>
        public override void UpdateMaterial()
        {
            var htmlColor = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Normal.HtmlColor;
            var opacity = 1.0d;
@@ -61,20 +65,10 @@
            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()
        /// <summary>
        /// æ›´æ–°å‡ ä½•图形
        /// </summary>
        public override void UpdateGeometry()
        {
            var diameter = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Normal.Diameter;
            var state = _stateHelper.GetState(this.Vmo);
@@ -87,8 +81,8 @@
                diameter = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Highlight.Diameter;
            }
            var sv = this.Vmo.StartPosition.ToVector3D();
            var ev = this.Vmo.EndPosition.ToVector3D();
            var sv = this.StartPosition.ToVector3D();
            var ev = this.EndPosition.ToVector3D();
            var center = (sv + ev) * 0.5d;
            var direction = (ev - sv);
            var length = direction.Length;
@@ -97,7 +91,7 @@
            //水泵管道
            MeshBuilder builder = new MeshBuilder();
            builder.AddTube(
                path: new[] { this.Vmo.StartPosition.ToPoint3D(), this.Vmo.EndPosition.ToPoint3D() },
                path: new[] { this.StartPosition, this.EndPosition },
                diameter: diameter,  // çº¿ç›´å¾„(3D空间单位)
                thetaDiv: 8,    // æ¨ªæˆªé¢ç»†åˆ†åº¦
                false
@@ -111,28 +105,21 @@
                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;
        }
        /// <summary>
        /// æ›´æ–°å˜æ¢çŸ©é˜µ
        /// </summary>
        public override void UpdateTransform()
        {
        }
    }
}
Yw.WpfUI.Hydro.L3d.Core/03-logical/01-visual/02-link/03-valve/LogicalValve3D.cs
@@ -1,11 +1,4 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Yw.WpfUI.Hydro
namespace Yw.WpfUI.Hydro
{
    internal class LogicalValve3D : LogicalLink3D
    {
@@ -39,8 +32,10 @@
            set { _vmo = value; }
        }
        //更新材质
        protected override void UpdateMaterial()
        /// <summary>
        /// æ›´æ–°æè´¨
        /// </summary>
        public override void UpdateMaterial()
        {
            var htmlColor = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Normal.HtmlColor;
            var opacity = 1.0d;
@@ -65,20 +60,10 @@
            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()
        /// <summary>
        /// æ›´æ–°å‡ ä½•图形
        /// </summary>
        public override void UpdateGeometry()
        {
            var diameter = Yw.Settings.HydroL3dParasHelper.HydroL3d.Logical.Link.Normal.Diameter;
            var state = _stateHelper.GetState(this.Vmo);
@@ -91,25 +76,22 @@
                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 sv = this.StartPosition.ToVector3D();
            var ev = this.EndPosition.ToVector3D();
            var center = (sv + ev) * 0.5d;
            var direction = (ev - sv);
            var length = direction.Length;
            direction.Normalize();
            var size = diameter * 2d;
            if (size > length)
            var size = diameter * 1.5d;
            if (size > length * 0.7)
            {
                size = length;
                size = length * 0.7;
            }
            //阀门管道
            var builder = new MeshBuilder();
            builder.AddTube(
                path: new[] { start, end },
                path: new[] { this.StartPosition, this.EndPosition },
                diameter: diameter,  // çº¿ç›´å¾„(3D空间单位)
                thetaDiv: 8,    // æ¨ªæˆªé¢ç»†åˆ†åº¦
                false
@@ -121,6 +103,16 @@
            this.MeshGeometry = geometry;
        }
        /// <summary>
        /// æ›´æ–°å˜æ¢çŸ©é˜µ
        /// </summary>
        public override void UpdateTransform()
        {
        }
    }
}
Yw.WpfUI.Hydro.L3d.Core/03-logical/02-state/eLogicalState.cs
@@ -39,7 +39,19 @@
        /// <summary>
        /// å¯è§æ€§
        /// </summary>
        Visible = 0x32
        Visible = 0x32,
        /// <summary>
        /// å¢žåŠ 
        /// </summary>
        Add = 0x64,
        /// <summary>
        /// ç¼–辑
        /// </summary>
        Edit = 0x128,
    }
Yw.WpfUI.Hydro.L3d.Core/03-logical/08-manager/LogicalEditManager.cs
@@ -1,6 +1,4 @@
using HelixToolkit.Wpf;
namespace Yw.WpfUI.Hydro
namespace Yw.WpfUI.Hydro
{
    /// <summary>
    /// æŠ½è±¡ç¼–辑管理器
@@ -16,7 +14,8 @@
        }
        private eLogicalEditMode _logicalMode = eLogicalEditMode.None;//编辑模式
        private VisualL3d _visual = null;//可视化对象
        private LogicalVisual3D _addLogicalVisual;//添加抽象对象
        private LogicalVisual3D _editLogicalVisual;//编辑抽象对象
        #region æ·»åŠ æ–¹æ³•
@@ -87,6 +86,18 @@
        #endregion
        #region ç¼–辑方法
        /// <summary>
        /// å¼€å§‹ç¼–辑
        /// </summary>
        public void StartEdit()
        {
            _logicalMode = eLogicalEditMode.Edit;
        }
        #endregion
        #region é‡å†™äº‹ä»¶
        //鼠标按下
@@ -96,7 +107,7 @@
            {
                return;
            }
            _addLogicalVisual = null;
            switch (_logicalMode)
            {
                case eLogicalEditMode.AddJunction:
@@ -105,11 +116,15 @@
                        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;
                            var junction = new JunctionL3d();
                            junction.Id = _nw.CreateId(CatalogL3d.Junction);
                            junction.Catalog = CatalogL3d.Junction;
                            junction.Name = _nw.CreateName(CatalogL3d.Junction);
                            junction.Position = sp.Value.ToPointL3d();
                            var logicalJunction = CreateLogicalVisual(junction);
                            logicalJunction.UpdateVisual();
                            AddLogicalVisual(logicalJunction);
                            _addLogicalVisual = logicalJunction;
                        }
                    }
                    break;
@@ -119,11 +134,15 @@
                        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;
                            var reservoir = new ReservoirL3d();
                            reservoir.Id = _nw.CreateId(CatalogL3d.Reservoir);
                            reservoir.Catalog = CatalogL3d.Reservoir;
                            reservoir.Name = _nw.CreateName(CatalogL3d.Reservoir);
                            reservoir.Position = sp.Value.ToPointL3d();
                            var logicalReservoir = CreateLogicalVisual(reservoir);
                            logicalReservoir.UpdateVisual();
                            AddLogicalVisual(logicalReservoir);
                            _addLogicalVisual = logicalReservoir;
                        }
                    }
                    break;
@@ -133,11 +152,15 @@
                        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;
                            var tank = new TankL3d();
                            tank.Id = _nw.CreateId(CatalogL3d.Tank);
                            tank.Catalog = CatalogL3d.Tank;
                            tank.Name = _nw.CreateName(CatalogL3d.Tank);
                            tank.Position = sp.Value.ToPointL3d();
                            var logicalTank = CreateLogicalVisual(tank);
                            logicalTank.UpdateVisual();
                            AddLogicalVisual(logicalTank);
                            _addLogicalVisual = logicalTank;
                        }
                    }
                    break;
@@ -147,12 +170,16 @@
                        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;
                            var pipe = new PipeL3d();
                            pipe.Id = _nw.CreateId(CatalogL3d.Pipe);
                            pipe.Catalog = CatalogL3d.Pipe;
                            pipe.Name = _nw.CreateName(CatalogL3d.Pipe);
                            pipe.StartNode = logicalNode.Vmo;
                            var logicalPipe = CreateLogicalVisual(pipe) as LogicalPipe3D;
                            logicalPipe.EndPosition = logicalNode.Position;
                            logicalPipe.UpdateVisual();
                            AddLogicalVisual(logicalPipe);
                            _addLogicalVisual = logicalPipe;
                        }
                    }
                    break;
@@ -162,12 +189,16 @@
                        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;
                            var pipe = new PipeL3d();
                            pipe.Id = _nw.CreateId(CatalogL3d.Pipe);
                            pipe.Catalog = CatalogL3d.Pipe;
                            pipe.Name = _nw.CreateName(CatalogL3d.Pipe);
                            pipe.StartNode = logicalNode.Vmo;
                            var logicalPipe = CreateLogicalVisual(pipe) as LogicalPipe3D;
                            logicalPipe.EndPosition = logicalNode.Position;
                            logicalPipe.UpdateVisual();
                            AddLogicalVisual(logicalPipe);
                            _addLogicalVisual = logicalPipe;
                        }
                    }
                    break;
@@ -177,12 +208,16 @@
                        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;
                            var pipe = new PipeL3d();
                            pipe.Id = _nw.CreateId(CatalogL3d.Pipe);
                            pipe.Catalog = CatalogL3d.Pipe;
                            pipe.Name = _nw.CreateName(CatalogL3d.Pipe);
                            pipe.StartNode = logicalNode.Vmo;
                            var logicalPipe = CreateLogicalVisual(pipe) as LogicalPipe3D;
                            logicalPipe.EndPosition = logicalNode.Position;
                            logicalPipe.UpdateVisual();
                            AddLogicalVisual(logicalPipe);
                            _addLogicalVisual = logicalPipe;
                        }
                    }
                    break;
@@ -192,12 +227,16 @@
                        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;
                            var pump = new PumpL3d();
                            pump.Id = _nw.CreateId(CatalogL3d.Pump);
                            pump.Catalog = CatalogL3d.Pump;
                            pump.Name = _nw.CreateName(CatalogL3d.Pump);
                            pump.StartNode = logicalNode.Vmo;
                            var logicalPump = CreateLogicalVisual(pump) as LogicalPump3D;
                            logicalPump.EndPosition = logicalNode.Position;
                            logicalPump.UpdateVisual();
                            AddLogicalVisual(logicalPump);
                            _addLogicalVisual = logicalPump;
                        }
                    }
                    break;
@@ -207,170 +246,22 @@
                        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;
                            var valve = new ValveL3d();
                            valve.Id = _nw.CreateId(CatalogL3d.Valve);
                            valve.Catalog = CatalogL3d.Valve;
                            valve.Name = _nw.CreateName(CatalogL3d.Valve);
                            valve.StartNode = logicalNode.Vmo;
                            var logicalValve = CreateLogicalVisual(valve) as LogicalValve3D;
                            logicalValve.EndPosition = logicalNode.Position;
                            logicalValve.UpdateVisual();
                            AddLogicalVisual(logicalValve);
                            _addLogicalVisual = logicalValve;
                        }
                    }
                    break;
                default:
                    {
                        base.OnMouseDown(e);
                    }
                    break;
            }
        }
        //鼠标弹起
        protected override void OnMouseUp(MouseButtonEventArgs e)
        {
            if (!Initialized)
            {
                return;
            }
            switch (_logicalMode)
            {
                case eLogicalEditMode.AddJunction:
                    {
                        _visual = null;
                        _logicalMode = eLogicalEditMode.None;
                    }
                    break;
                case eLogicalEditMode.AddReservoir:
                    {
                        _visual = null;
                        _logicalMode = eLogicalEditMode.None;
                    }
                    break;
                case eLogicalEditMode.AddTank:
                    {
                        _visual = null;
                        _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);
                            }
                        }
                        _visual = null;
                        _logicalMode = eLogicalEditMode.None;
                    }
                    break;
                case eLogicalEditMode.AddHorizPipe:
                    {
                        var pipe = _visual as PipeL3d;
                        if (pipe != null)
                        {
                            var end = pipe.EndPosition.ToPoint3D();
                            var logicalNode = SnapNearestNode(end);
                            if (logicalNode == null)
                            {
                                var junction = new JunctionL3d();
                                junction.Id = Yw.Untity.UniqueHelper.CreateFromFirst("junction", _nw.Junctions.Select(x => x.Id).ToList());
                                junction.Position = end.ToPointL3d();
                                AddVisual(junction);
                            }
                        }
                        _visual = null;
                        _logicalMode = eLogicalEditMode.None;
                    }
                    break;
                case eLogicalEditMode.AddVertPipe:
                    {
                        var pipe = _visual as PipeL3d;
                        if (pipe != null)
                        {
                            var end = pipe.EndPosition.ToPoint3D();
                            LogicalNode3D logicalNode = SnapNearestNode(end);
                            if (logicalNode == null)
                            {
                                var junction = new JunctionL3d();
                                junction.Id = Yw.Untity.UniqueHelper.CreateFromFirst("junction", _nw.Junctions.Select(x => x.Id).ToList());
                                junction.Position = end.ToPointL3d();
                                AddVisual(junction);
                            }
                        }
                        _visual = null;
                        _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);
                            }
                        }
                        _visual = null;
                        _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);
                            }
                        }
                        _visual = null;
                        _logicalMode = eLogicalEditMode.None;
                    }
                    break;
                default:
                    {
                        base.OnMouseUp(e);
                    }
                    break;
            }
@@ -388,21 +279,61 @@
            {
                case eLogicalEditMode.AddJunction:
                    {
                    }
                    break;
                case eLogicalEditMode.AddPipe:
                    {
                        base.OnMouseMove(e);
                        var pipe = _visual as PipeL3d;
                        if (pipe != null)
                        var logicalJunction = _addLogicalVisual as LogicalJunction3D;
                        if (logicalJunction != null)
                        {
                            var pt = e.GetPosition(_viewport);
                            var sp = _viewport.Viewport.UnProject(pt);
                            if (sp.HasValue)
                            {
                                pipe.EndPosition = sp.Value.ToPointL3d();
                                UpdateVisual(_visual);
                                logicalJunction.Vmo.Position = sp.Value.ToPointL3d();
                                logicalJunction.UpdateVisual();
                            }
                        }
                    }
                    break;
                case eLogicalEditMode.AddReservoir:
                    {
                        var logicalReservoir = _addLogicalVisual as LogicalSource3D;
                        if (logicalReservoir != null)
                        {
                            var pt = e.GetPosition(_viewport);
                            var sp = _viewport.Viewport.UnProject(pt);
                            if (sp.HasValue)
                            {
                                logicalReservoir.Vmo.Position = sp.Value.ToPointL3d();
                                logicalReservoir.UpdateVisual();
                            }
                        }
                    }
                    break;
                case eLogicalEditMode.AddTank:
                    {
                        var logicalTank = _addLogicalVisual as LogicalTank3D;
                        if (logicalTank != null)
                        {
                            var pt = e.GetPosition(_viewport);
                            var sp = _viewport.Viewport.UnProject(pt);
                            if (sp.HasValue)
                            {
                                logicalTank.Vmo.Position = sp.Value.ToPointL3d();
                                logicalTank.UpdateVisual();
                            }
                        }
                    }
                    break;
                case eLogicalEditMode.AddPipe:
                    {
                        base.OnMouseMove(e);
                        var logicalPipe = _addLogicalVisual as LogicalPipe3D;
                        if (logicalPipe != null)
                        {
                            var pt = e.GetPosition(_viewport);
                            var sp = _viewport.Viewport.UnProject(pt);
                            if (sp.HasValue)
                            {
                                logicalPipe.EndPosition = sp.Value;
                                logicalPipe.UpdateVisual();
                            }
                        }
                    }
@@ -410,15 +341,15 @@
                case eLogicalEditMode.AddHorizPipe:
                    {
                        base.OnMouseMove(e);
                        var pipe = _visual as PipeL3d;
                        if (pipe != null)
                        var logicalPipe = _addLogicalVisual as LogicalPipe3D;
                        if (logicalPipe != null)
                        {
                            var pt = e.GetPosition(_viewport);
                            var sp = _viewport.Viewport.UnProject(pt);
                            if (sp.HasValue)
                            {
                                pipe.EndPosition = new PointL3d(sp.Value.X, sp.Value.Y, pipe.StartPosition.Z);
                                UpdateVisual(_visual);
                                logicalPipe.EndPosition = new Point3D(sp.Value.X, sp.Value.Y, logicalPipe.StartPosition.Z);
                                logicalPipe.UpdateVisual();
                            }
                        }
                    }
@@ -426,15 +357,15 @@
                case eLogicalEditMode.AddVertPipe:
                    {
                        base.OnMouseMove(e);
                        var pipe = _visual as PipeL3d;
                        if (pipe != null)
                        var logicalPipe = _addLogicalVisual as LogicalPipe3D;
                        if (logicalPipe != null)
                        {
                            var pt = e.GetPosition(_viewport);
                            var sp = _viewport.Viewport.UnProject(pt);
                            if (sp.HasValue)
                            {
                                pipe.EndPosition = new PointL3d(pipe.StartPosition.X, pipe.StartPosition.Y, sp.Value.Z);
                                UpdateVisual(_visual);
                                logicalPipe.EndPosition = new Point3D(logicalPipe.StartPosition.X, logicalPipe.StartPosition.Y, sp.Value.Z);
                                logicalPipe.UpdateVisual();
                            }
                        }
                    }
@@ -442,15 +373,15 @@
                case eLogicalEditMode.AddPump:
                    {
                        base.OnMouseMove(e);
                        var pump = _visual as PumpL3d;
                        if (pump != null)
                        var logicalPump = _addLogicalVisual as LogicalPump3D;
                        if (logicalPump != null)
                        {
                            var pt = e.GetPosition(_viewport);
                            var sp = _viewport.Viewport.UnProject(pt);
                            if (sp.HasValue)
                            {
                                pump.EndPosition = sp.Value.ToPointL3d();
                                UpdateVisual(_visual);
                                logicalPump.EndPosition = sp.Value;
                                logicalPump.UpdateVisual();
                            }
                        }
                    }
@@ -458,15 +389,15 @@
                case eLogicalEditMode.AddValve:
                    {
                        base.OnMouseMove(e);
                        var valve = _visual as ValveL3d;
                        if (valve != null)
                        var logicalValve = _addLogicalVisual as LogicalValve3D;
                        if (logicalValve != null)
                        {
                            var pt = e.GetPosition(_viewport);
                            var sp = _viewport.Viewport.UnProject(pt);
                            if (sp.HasValue)
                            {
                                valve.EndPosition = sp.Value.ToPointL3d();
                                UpdateVisual(_visual);
                                logicalValve.EndPosition = sp.Value;
                                logicalValve.UpdateVisual();
                            }
                        }
                    }
@@ -479,38 +410,310 @@
            }
        }
        #endregion
        //添加
        private void AddVisual(VisualL3d visual)
        //鼠标弹起
        protected override void OnMouseUp(MouseButtonEventArgs e)
        {
            if (!Initialized)
            {
                return;
            }
            _nw.Append(visual, out string msg);
            _allVisualL3dDict.Add(visual.Id, visual);
            switch (_logicalMode)
            {
                case eLogicalEditMode.AddJunction:
                    {
                        var logicalJunction = _addLogicalVisual as LogicalJunction3D;
                        if (logicalJunction != null)
                        {
                            if (!logicalJunction.Verify())
                            {
                                RemoveLogicalVisual(logicalJunction);
                            }
                            _addLogicalVisual = null;
                            _logicalMode = eLogicalEditMode.None;
                        }
                    }
                    break;
                case eLogicalEditMode.AddReservoir:
                    {
                        var logicalReservoir = _addLogicalVisual as LogicalReservoir3D;
                        if (logicalReservoir != null)
                        {
                            if (!logicalReservoir.Verify())
                            {
                                RemoveLogicalVisual(logicalReservoir);
                            }
                            _addLogicalVisual = null;
                            _logicalMode = eLogicalEditMode.None;
                        }
                    }
                    break;
                case eLogicalEditMode.AddTank:
                    {
                        var logicalTank = _addLogicalVisual as LogicalTank3D;
                        if (logicalTank != null)
                        {
                            if (!logicalTank.Verify())
                            {
                                RemoveLogicalVisual(logicalTank);
                            }
                            _addLogicalVisual = null;
                            _logicalMode = eLogicalEditMode.None;
                        }
                    }
                    break;
                case eLogicalEditMode.AddPipe:
                    {
                        var logicalPipe = _addLogicalVisual as LogicalPipe3D;
                        if (logicalPipe != null)
                        {
                            var pt = e.GetPosition(_viewport);
                            var logicalNode = SnapNearestNode(pt);
                            if (logicalNode == null)
                            {
                                var sp = _viewport.Viewport.UnProject(pt);
                                var junction = new JunctionL3d();
                                junction.Id = _nw.CreateId(CatalogL3d.Junction);
                                junction.Catalog = CatalogL3d.Junction;
                                junction.Name = _nw.CreateName(CatalogL3d.Junction);
                                junction.Position = sp.Value.ToPointL3d();
                                var logicalVisual = CreateLogicalVisual(junction);
                                AddLogicalVisual(logicalVisual);
                                logicalPipe.Vmo.EndNode = junction;
                            }
                            else
                            {
                                logicalPipe.Vmo.EndNode = logicalNode.Vmo;
                            }
                            logicalPipe.UpdateVisual();
                            if (!logicalPipe.Verify())
                            {
                                RemoveLogicalVisual(logicalPipe);
                            }
                            _addLogicalVisual = null;
                            _logicalMode = eLogicalEditMode.None;
                        }
                    }
                    break;
                case eLogicalEditMode.AddHorizPipe:
                    {
                        var logicalPipe = _addLogicalVisual as LogicalPipe3D;
                        if (logicalPipe != null)
                        {
                            var end = logicalPipe.EndPosition;
                            var logicalNode = SnapNearestNode(end);
                            if (logicalNode == null)
                            {
                                var junction = new JunctionL3d();
                                junction.Id = _nw.CreateId(CatalogL3d.Junction);
                                junction.Catalog = CatalogL3d.Junction;
                                junction.Name = _nw.CreateName(CatalogL3d.Junction);
                                junction.Position = end.ToPointL3d();
                                var logicalJunction = CreateLogicalVisual(junction);
                                AddLogicalVisual(logicalJunction);
                                logicalPipe.Vmo.EndNode = junction;
                            }
                            else
                            {
                                logicalPipe.Vmo.EndNode = logicalNode.Vmo;
                            }
                            logicalPipe.UpdateVisual();
                            if (!logicalPipe.Verify())
                            {
                                RemoveLogicalVisual(logicalPipe);
                            }
                            _addLogicalVisual = null;
                            _logicalMode = eLogicalEditMode.None;
                        }
                    }
                    break;
                case eLogicalEditMode.AddVertPipe:
                    {
                        var logicalPipe = _addLogicalVisual as LogicalPipe3D;
                        if (logicalPipe != null)
                        {
                            var end = logicalPipe.EndPosition;
                            var logicalNode = SnapNearestNode(end);
                            if (logicalNode == null)
                            {
                                var junction = new JunctionL3d();
                                junction.Id = _nw.CreateId(CatalogL3d.Junction);
                                junction.Catalog = CatalogL3d.Junction;
                                junction.Name = _nw.CreateName(CatalogL3d.Junction);
                                junction.Position = end.ToPointL3d();
                                var logicalJunction = CreateLogicalVisual(junction);
                                AddLogicalVisual(logicalJunction);
                                logicalPipe.Vmo.EndNode = junction;
                            }
                            else
                            {
                                logicalPipe.Vmo.EndNode = logicalNode.Vmo;
                            }
                            logicalPipe.UpdateVisual();
                            if (!logicalPipe.Verify())
                            {
                                RemoveLogicalVisual(logicalPipe);
                            }
                            _addLogicalVisual = null;
                            _logicalMode = eLogicalEditMode.None;
                        }
                    }
                    break;
                case eLogicalEditMode.AddPump:
                    {
                        var logicalPump = _addLogicalVisual as LogicalPump3D;
                        if (logicalPump != null)
                        {
                            var pt = e.GetPosition(_viewport);
                            var logicalNode = SnapNearestNode(pt);
                            if (logicalNode == null)
                            {
                                var sp = _viewport.Viewport.UnProject(pt);
                                var junction = new JunctionL3d();
                                junction.Id = _nw.CreateId(CatalogL3d.Junction);
                                junction.Catalog = CatalogL3d.Junction;
                                junction.Name = _nw.CreateName(CatalogL3d.Junction);
                                junction.Position = sp.Value.ToPointL3d();
                                var logicalVisual = CreateLogicalVisual(junction);
                                AddLogicalVisual(logicalVisual);
                                logicalPump.Vmo.EndNode = junction;
                            }
                            else
                            {
                                logicalPump.Vmo.EndNode = logicalNode.Vmo;
                            }
                            logicalPump.UpdateVisual();
                            if (!logicalPump.Verify())
                            {
                                RemoveLogicalVisual(logicalPump);
                            }
                            _addLogicalVisual = null;
                            _logicalMode = eLogicalEditMode.None;
                        }
                    }
                    break;
                case eLogicalEditMode.AddValve:
                    {
                        var logicalValve = _addLogicalVisual as LogicalValve3D;
                        if (logicalValve != null)
                        {
                            var pt = e.GetPosition(_viewport);
                            var logicalNode = SnapNearestNode(pt);
                            if (logicalNode == null)
                            {
                                var sp = _viewport.Viewport.UnProject(pt);
                                var junction = new JunctionL3d();
                                junction.Id = _nw.CreateId(CatalogL3d.Junction);
                                junction.Catalog = CatalogL3d.Junction;
                                junction.Name = _nw.CreateName(CatalogL3d.Junction);
                                junction.Position = sp.Value.ToPointL3d();
                                var logicalVisual = CreateLogicalVisual(junction);
                                AddLogicalVisual(logicalVisual);
                                logicalValve.Vmo.EndNode = junction;
                            }
                            else
                            {
                                logicalValve.Vmo.EndNode = logicalNode.Vmo;
                            }
                            logicalValve.UpdateVisual();
                            if (!logicalValve.Verify())
                            {
                                RemoveLogicalVisual(logicalValve);
                            }
                            _addLogicalVisual = null;
                            _logicalMode = eLogicalEditMode.None;
                        }
                    }
                    break;
                default:
                    {
                        base.OnMouseUp(e);
                    }
                    break;
            }
        }
        #endregion
        #region æž„件方法
        //创建抽象可见元素
        private LogicalVisual3D CreateLogicalVisual(VisualL3d visual)
        {
            var logicalVisual = LogicalCreateHelper.Create(visual, _stateHelper, _materialHelper, _overrideColorHelper, _overrideOpacityHelper, _overrideVisibleHelper);
            if (logicalVisual != null)
            return logicalVisual;
        }
        //添加抽象可见元素
        private void AddLogicalVisual(LogicalVisual3D logicalVisual)
        {
            if (!Initialized)
            {
                return;
            }
            if (logicalVisual == null)
            {
                return;
            }
            if (logicalVisual.Vmo == null)
            {
                return;
            }
            var visual = logicalVisual.Vmo;
            if (!_nw.IsExist(visual))
            {
                _nw.Append(visual, out _);
            }
            if (!_allVisualL3dDict.ContainsKey(visual.Id))
            {
                _allVisualL3dDict.Add(visual.Id, visual);
            }
            if (!_allVisualLogicalDict.ContainsKey(visual))
            {
                _allVisualLogicalDict.Add(visual, logicalVisual);
            }
            if (!_viewport.Children.Contains(logicalVisual))
            {
                _viewport.Children.Add(logicalVisual);
            }
        }
        //更新
        private void UpdateVisual(VisualL3d visual)
        //移除抽象可见元素
        private void RemoveLogicalVisual(LogicalVisual3D logicalVisual)
        {
            if (!Initialized)
            {
                return;
            }
            var logicalVisual = _allVisualLogicalDict[visual];
            logicalVisual.UpdateVisual();
            if (logicalVisual == null)
            {
                return;
            }
            if (logicalVisual.Vmo == null)
            {
                return;
            }
            var visual = logicalVisual.Vmo;
            if (_nw.IsExist(visual))
            {
                _nw.Remove(visual);
            }
            if (_allVisualL3dDict.ContainsKey(visual.Id))
            {
                _allVisualL3dDict.Remove(visual.Id);
            }
            if (_allVisualLogicalDict.ContainsKey(visual))
            {
                _allVisualLogicalDict.Remove(visual);
            }
            if (_viewport.Children.Contains(logicalVisual))
            {
                _viewport.Children.Remove(logicalVisual);
            }
        }
        #region è¾…助方法
        #endregion
        #region è¾…助方法
        //吸附最近节点
        private LogicalNode3D SnapNearestNode(Point pt)
Yw.WpfUI.Hydro.L3d.Core/03-logical/08-manager/LogicalManager.cs
@@ -1,6 +1,4 @@
using System.Net;
namespace Yw.WpfUI.Hydro
namespace Yw.WpfUI.Hydro
{
    /// <summary>
    /// æŠ½è±¡ç®¡ç†å™¨
@@ -214,7 +212,7 @@
                return;
            }
            _viewport.Children.Clear();
            _viewport.Children.Add(new DefaultLights());
            _viewport.Children.Add(new SunLight());
            _allVisualLogicalDict?.Values.ToList().ForEach(x => _viewport.Children.Add(x));
            _viewport.ZoomExtents();
        }
Yw.WpfUI.Hydro.L3d.Core/03-logical/08-manager/eLogicalEditMode.cs
@@ -14,6 +14,7 @@
        AddVertPipe,
        AddPump,
        AddValve,
        Edit,
    }
Yw.WpfUI.Hydro.L3d.Core/Yw.WpfUI.Hydro.L3d.Core.csproj
@@ -28,8 +28,6 @@
    <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\" />
Yw.WpfUI.Hydro.L3d.Core/paras_hydrol3d_settings.json
@@ -6,15 +6,15 @@
        "Logical": {
            "Node": {
                "Normal": {
                    "HtmlColor": "#e1300a",
                    "HtmlColor": "#FF0000",
                    "Radius": 0.3
                },
                "Highlight": {
                    "HtmlColor": "#FF0000",
                    "HtmlColor": "#32CD32",
                    "Radius": 0.5
                },
                "Selection": {
                    "HtmlColor": "#FF0000",
                    "HtmlColor": "#FF1493",
                    "Radius": 0.4
                },
                "SnapDistance": 0.2
@@ -25,11 +25,11 @@
                    "Diameter": 0.5
                },
                "Highlight": {
                    "HtmlColor": "#FF0000",
                    "HtmlColor": "#32CD32",
                    "Diameter": 0.8
                },
                "Selection": {
                    "HtmlColor": "#FF0000",
                    "HtmlColor": "#FF1493",
                    "Diameter": 0.6
                }
            }
Yw.WpfUI.Test.Core/MainWindow.xaml.cs
@@ -69,18 +69,8 @@
                var pipe3d = new PipeL3d();
                pipe3d.Id = pipe.Id;
                pipe3d.Name = pipe.Name;
                pipe3d.StartPosition = new PointL3d()
                {
                    X = (float)pipe.StartNode.Position.X,
                    Y = (float)pipe.StartNode.Position.Y,
                    Z = (float)pipe.StartNode.GetElev()
                };
                pipe3d.EndPosition = new PointL3d()
                {
                    X = (float)pipe.EndNode.Position.X,
                    Y = (float)pipe.EndNode.Position.Y,
                    Z = (float)pipe.EndNode.GetElev()
                };
                pipe3d.StartNode = nw3d.Nodes.Find(x => x.Id == pipe.StartNodeId);
                pipe3d.EndNode = nw3d.Nodes.Find(x => x.Id == pipe.EndNodeId);
                nw3d.Append(pipe3d, out msg);
            }
@@ -89,18 +79,8 @@
                var pump3d = new PumpL3d();
                pump3d.Id = pump.Id;
                pump3d.Name = pump.Name;
                pump3d.StartPosition = new PointL3d()
                {
                    X = (float)pump.StartNode.Position.X,
                    Y = (float)pump.StartNode.Position.Y,
                    Z = (float)pump.StartNode.GetElev()
                };
                pump3d.EndPosition = new PointL3d()
                {
                    X = (float)pump.EndNode.Position.X,
                    Y = (float)pump.EndNode.Position.Y,
                    Z = (float)pump.EndNode.GetElev()
                };
                pump3d.StartNode = nw3d.Nodes.Find(x => x.Id == pump.StartNodeId);
                pump3d.EndNode = nw3d.Nodes.Find(x => x.Id == pump.EndNodeId);
                nw3d.Append(pump3d, out msg);
            }
@@ -109,18 +89,8 @@
                var valve3d = new ValveL3d();
                valve3d.Id = valve.Id;
                valve3d.Name = valve.Name;
                valve3d.StartPosition = new PointL3d()
                {
                    X = (float)valve.StartNode.Position.X,
                    Y = (float)valve.StartNode.Position.Y,
                    Z = (float)valve.StartNode.GetElev()
                };
                valve3d.EndPosition = new PointL3d()
                {
                    X = (float)valve.EndNode.Position.X,
                    Y = (float)valve.EndNode.Position.Y,
                    Z = (float)valve.EndNode.GetElev()
                };
                valve3d.StartNode = nw3d.Nodes.Find(x => x.Id == valve.StartNodeId);
                valve3d.EndNode = nw3d.Nodes.Find(x => x.Id == valve.EndNodeId);
                nw3d.Append(valve3d, out msg);
            }