|
@@ -16,12 +16,7 @@ namespace YZWater.Avalonia.Controls;
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
|
/// 通用污水提升泵站 2.5D 工艺总览控件(等轴测投影)。
|
|
/// 通用污水提升泵站 2.5D 工艺总览控件(等轴测投影)。
|
|
|
-///
|
|
|
|
|
-/// <para>支持两种模式:</para>
|
|
|
|
|
-/// <list type="bullet">
|
|
|
|
|
-/// <item><b>动态模式</b>:设置 <see cref="Profile"/> 后,根据项目档案自动布局渲染</item>
|
|
|
|
|
-/// <item><b>兼容模式</b>:使用旧版硬编码属性,保持向后兼容</item>
|
|
|
|
|
-/// </list>
|
|
|
|
|
|
|
+/// 根据项目档案 (Profile) + 模拟量/数字量字典自动布局渲染。
|
|
|
/// </summary>
|
|
/// </summary>
|
|
|
public class PumpStation3DControl : Control
|
|
public class PumpStation3DControl : Control
|
|
|
{
|
|
{
|
|
@@ -63,56 +58,6 @@ public class PumpStation3DControl : Control
|
|
|
set => SetValue(DeviceClickedCommandProperty, value);
|
|
set => SetValue(DeviceClickedCommandProperty, value);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // ═══ 旧版硬编码属性 ═══
|
|
|
|
|
-
|
|
|
|
|
- public static readonly StyledProperty<double> Tank1LevelProperty = AvaloniaProperty.Register<PumpStation3DControl, double>(nameof(Tank1Level));
|
|
|
|
|
- public static readonly StyledProperty<double> Tank2LevelProperty = AvaloniaProperty.Register<PumpStation3DControl, double>(nameof(Tank2Level));
|
|
|
|
|
- public static readonly StyledProperty<double> Tank3LevelProperty = AvaloniaProperty.Register<PumpStation3DControl, double>(nameof(Tank3Level));
|
|
|
|
|
- public static readonly StyledProperty<double> Tank4LevelProperty = AvaloniaProperty.Register<PumpStation3DControl, double>(nameof(Tank4Level));
|
|
|
|
|
- public static readonly StyledProperty<double> InflowRateProperty = AvaloniaProperty.Register<PumpStation3DControl, double>(nameof(InflowRate));
|
|
|
|
|
- public static readonly StyledProperty<double> OutflowRateProperty = AvaloniaProperty.Register<PumpStation3DControl, double>(nameof(OutflowRate));
|
|
|
|
|
- public static readonly StyledProperty<bool> Pump1RunningProperty = AvaloniaProperty.Register<PumpStation3DControl, bool>(nameof(Pump1Running));
|
|
|
|
|
- public static readonly StyledProperty<bool> Pump2RunningProperty = AvaloniaProperty.Register<PumpStation3DControl, bool>(nameof(Pump2Running));
|
|
|
|
|
- public static readonly StyledProperty<bool> Pump3RunningProperty = AvaloniaProperty.Register<PumpStation3DControl, bool>(nameof(Pump3Running));
|
|
|
|
|
- public static readonly StyledProperty<bool> Pump4RunningProperty = AvaloniaProperty.Register<PumpStation3DControl, bool>(nameof(Pump4Running));
|
|
|
|
|
- public static readonly StyledProperty<bool> Pump5RunningProperty = AvaloniaProperty.Register<PumpStation3DControl, bool>(nameof(Pump5Running));
|
|
|
|
|
- public static readonly StyledProperty<bool> Fan1RunningProperty = AvaloniaProperty.Register<PumpStation3DControl, bool>(nameof(Fan1Running));
|
|
|
|
|
- public static readonly StyledProperty<bool> Fan2RunningProperty = AvaloniaProperty.Register<PumpStation3DControl, bool>(nameof(Fan2Running));
|
|
|
|
|
- public static readonly StyledProperty<ValveStatus> Valve1StatusProperty = AvaloniaProperty.Register<PumpStation3DControl, ValveStatus>(nameof(Valve1Status));
|
|
|
|
|
- public static readonly StyledProperty<ValveStatus> Valve2StatusProperty = AvaloniaProperty.Register<PumpStation3DControl, ValveStatus>(nameof(Valve2Status));
|
|
|
|
|
- public static readonly StyledProperty<ValveStatus> Valve3StatusProperty = AvaloniaProperty.Register<PumpStation3DControl, ValveStatus>(nameof(Valve3Status));
|
|
|
|
|
- public static readonly StyledProperty<ValveStatus> Valve4StatusProperty = AvaloniaProperty.Register<PumpStation3DControl, ValveStatus>(nameof(Valve4Status));
|
|
|
|
|
- public static readonly StyledProperty<bool> IsInflowRunningProperty = AvaloniaProperty.Register<PumpStation3DControl, bool>(nameof(IsInflowRunning));
|
|
|
|
|
- public static readonly StyledProperty<bool> IsOutflowRunningProperty = AvaloniaProperty.Register<PumpStation3DControl, bool>(nameof(IsOutflowRunning));
|
|
|
|
|
- public static readonly StyledProperty<bool> HasAlarmProperty = AvaloniaProperty.Register<PumpStation3DControl, bool>(nameof(HasAlarm));
|
|
|
|
|
- public static readonly StyledProperty<int> AlarmCountProperty = AvaloniaProperty.Register<PumpStation3DControl, int>(nameof(AlarmCount));
|
|
|
|
|
- public static readonly StyledProperty<int> RunningDeviceCountProperty = AvaloniaProperty.Register<PumpStation3DControl, int>(nameof(RunningDeviceCount));
|
|
|
|
|
- public static readonly StyledProperty<double> EfficiencyProperty = AvaloniaProperty.Register<PumpStation3DControl, double>(nameof(Efficiency));
|
|
|
|
|
-
|
|
|
|
|
- public double Tank1Level { get => GetValue(Tank1LevelProperty); set => SetValue(Tank1LevelProperty, value); }
|
|
|
|
|
- public double Tank2Level { get => GetValue(Tank2LevelProperty); set => SetValue(Tank2LevelProperty, value); }
|
|
|
|
|
- public double Tank3Level { get => GetValue(Tank3LevelProperty); set => SetValue(Tank3LevelProperty, value); }
|
|
|
|
|
- public double Tank4Level { get => GetValue(Tank4LevelProperty); set => SetValue(Tank4LevelProperty, value); }
|
|
|
|
|
- public double InflowRate { get => GetValue(InflowRateProperty); set => SetValue(InflowRateProperty, value); }
|
|
|
|
|
- public double OutflowRate { get => GetValue(OutflowRateProperty); set => SetValue(OutflowRateProperty, value); }
|
|
|
|
|
- public bool Pump1Running { get => GetValue(Pump1RunningProperty); set => SetValue(Pump1RunningProperty, value); }
|
|
|
|
|
- public bool Pump2Running { get => GetValue(Pump2RunningProperty); set => SetValue(Pump2RunningProperty, value); }
|
|
|
|
|
- public bool Pump3Running { get => GetValue(Pump3RunningProperty); set => SetValue(Pump3RunningProperty, value); }
|
|
|
|
|
- public bool Pump4Running { get => GetValue(Pump4RunningProperty); set => SetValue(Pump4RunningProperty, value); }
|
|
|
|
|
- public bool Pump5Running { get => GetValue(Pump5RunningProperty); set => SetValue(Pump5RunningProperty, value); }
|
|
|
|
|
- public bool Fan1Running { get => GetValue(Fan1RunningProperty); set => SetValue(Fan1RunningProperty, value); }
|
|
|
|
|
- public bool Fan2Running { get => GetValue(Fan2RunningProperty); set => SetValue(Fan2RunningProperty, value); }
|
|
|
|
|
- public ValveStatus Valve1Status { get => GetValue(Valve1StatusProperty); set => SetValue(Valve1StatusProperty, value); }
|
|
|
|
|
- public ValveStatus Valve2Status { get => GetValue(Valve2StatusProperty); set => SetValue(Valve2StatusProperty, value); }
|
|
|
|
|
- public ValveStatus Valve3Status { get => GetValue(Valve3StatusProperty); set => SetValue(Valve3StatusProperty, value); }
|
|
|
|
|
- public ValveStatus Valve4Status { get => GetValue(Valve4StatusProperty); set => SetValue(Valve4StatusProperty, value); }
|
|
|
|
|
- public bool IsInflowRunning { get => GetValue(IsInflowRunningProperty); set => SetValue(IsInflowRunningProperty, value); }
|
|
|
|
|
- public bool IsOutflowRunning { get => GetValue(IsOutflowRunningProperty); set => SetValue(IsOutflowRunningProperty, value); }
|
|
|
|
|
- public bool HasAlarm { get => GetValue(HasAlarmProperty); set => SetValue(HasAlarmProperty, value); }
|
|
|
|
|
- public int AlarmCount { get => GetValue(AlarmCountProperty); set => SetValue(AlarmCountProperty, value); }
|
|
|
|
|
- public int RunningDeviceCount { get => GetValue(RunningDeviceCountProperty); set => SetValue(RunningDeviceCountProperty, value); }
|
|
|
|
|
- public double Efficiency { get => GetValue(EfficiencyProperty); set => SetValue(EfficiencyProperty, value); }
|
|
|
|
|
-
|
|
|
|
|
// ═══ 动画 & 布局 ═══
|
|
// ═══ 动画 & 布局 ═══
|
|
|
|
|
|
|
|
private double _phase;
|
|
private double _phase;
|
|
@@ -122,20 +67,11 @@ public class PumpStation3DControl : Control
|
|
|
private LayoutResult? _cachedLayout;
|
|
private LayoutResult? _cachedLayout;
|
|
|
private Size _lastCanvasSize;
|
|
private Size _lastCanvasSize;
|
|
|
|
|
|
|
|
- private static readonly SolidColorBrush FlowDotBrush3D = new(Color.FromRgb(3, 169, 244));
|
|
|
|
|
private static readonly SolidColorBrush PumpBodyBrush = new(Color.FromRgb(31, 41, 55));
|
|
private static readonly SolidColorBrush PumpBodyBrush = new(Color.FromRgb(31, 41, 55));
|
|
|
|
|
|
|
|
static PumpStation3DControl()
|
|
static PumpStation3DControl()
|
|
|
{
|
|
{
|
|
|
- AffectsRender<PumpStation3DControl>(
|
|
|
|
|
- Tank1LevelProperty, Tank2LevelProperty, Tank3LevelProperty, Tank4LevelProperty,
|
|
|
|
|
- InflowRateProperty, OutflowRateProperty,
|
|
|
|
|
- Pump1RunningProperty, Pump2RunningProperty, Pump3RunningProperty, Pump4RunningProperty, Pump5RunningProperty,
|
|
|
|
|
- Fan1RunningProperty, Fan2RunningProperty,
|
|
|
|
|
- Valve1StatusProperty, Valve2StatusProperty, Valve3StatusProperty, Valve4StatusProperty,
|
|
|
|
|
- IsInflowRunningProperty, IsOutflowRunningProperty, HasAlarmProperty, AlarmCountProperty,
|
|
|
|
|
- RunningDeviceCountProperty, EfficiencyProperty,
|
|
|
|
|
- ProfileProperty, AnalogValuesProperty, DigitalValuesProperty);
|
|
|
|
|
|
|
+ AffectsRender<PumpStation3DControl>(ProfileProperty, AnalogValuesProperty, DigitalValuesProperty);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
|
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
|
@@ -161,8 +97,7 @@ public class PumpStation3DControl : Control
|
|
|
ThemeHelper.ThemeChanged += OnThemeChanged;
|
|
ThemeHelper.ThemeChanged += OnThemeChanged;
|
|
|
_timer = DispatcherTimer.Run(() =>
|
|
_timer = DispatcherTimer.Run(() =>
|
|
|
{
|
|
{
|
|
|
- var needsAnim = IsDynamicMode ? HasDynamicAnimation : HasLegacyAnimation;
|
|
|
|
|
- if (needsAnim)
|
|
|
|
|
|
|
+ if (HasDynamicAnimation)
|
|
|
{
|
|
{
|
|
|
_phase = (_phase + 1) % 120;
|
|
_phase = (_phase + 1) % 120;
|
|
|
_faultFlash = (_faultFlash + 0.025) % 1.0;
|
|
_faultFlash = (_faultFlash + 0.025) % 1.0;
|
|
@@ -182,19 +117,11 @@ public class PumpStation3DControl : Control
|
|
|
|
|
|
|
|
private void OnThemeChanged() { _cachedLayout = null; InvalidateVisual(); }
|
|
private void OnThemeChanged() { _cachedLayout = null; InvalidateVisual(); }
|
|
|
|
|
|
|
|
- // ═══ 模式判断 ═══
|
|
|
|
|
-
|
|
|
|
|
- public bool IsDynamicMode => Profile != null;
|
|
|
|
|
|
|
+ // ═══ 动画判断 ═══
|
|
|
|
|
|
|
|
private bool HasDynamicAnimation =>
|
|
private bool HasDynamicAnimation =>
|
|
|
_cachedLayout?.Devices.Any(d => d.DeviceType == "Pump" && GetDigitalValue($"{d.DeviceId}.Run")) == true;
|
|
_cachedLayout?.Devices.Any(d => d.DeviceType == "Pump" && GetDigitalValue($"{d.DeviceId}.Run")) == true;
|
|
|
|
|
|
|
|
- private bool HasLegacyAnimation =>
|
|
|
|
|
- AnyPumpRunning || Fan1Running || Fan2Running || IsInflowRunning || IsOutflowRunning;
|
|
|
|
|
-
|
|
|
|
|
- private bool AnyPumpRunning =>
|
|
|
|
|
- Pump1Running || Pump2Running || Pump3Running || Pump4Running || Pump5Running;
|
|
|
|
|
-
|
|
|
|
|
// ═══ 值读取 ═══
|
|
// ═══ 值读取 ═══
|
|
|
|
|
|
|
|
private float GetAnalogValue(string key) =>
|
|
private float GetAnalogValue(string key) =>
|
|
@@ -212,14 +139,11 @@ public class PumpStation3DControl : Control
|
|
|
if (bounds.Width < 120 || bounds.Height < 120) return;
|
|
if (bounds.Width < 120 || bounds.Height < 120) return;
|
|
|
context.DrawRectangle(ThemeHelper.PanelBg, null, bounds);
|
|
context.DrawRectangle(ThemeHelper.PanelBg, null, bounds);
|
|
|
|
|
|
|
|
- if (IsDynamicMode)
|
|
|
|
|
- RenderDynamic(context, bounds);
|
|
|
|
|
- else
|
|
|
|
|
- RenderLegacy(context, bounds);
|
|
|
|
|
|
|
+ RenderDynamic(context, bounds);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// ════════════════════════════════════════════════════════
|
|
// ════════════════════════════════════════════════════════
|
|
|
- // 动态模式
|
|
|
|
|
|
|
+ // 渲染
|
|
|
// ════════════════════════════════════════════════════════
|
|
// ════════════════════════════════════════════════════════
|
|
|
|
|
|
|
|
private void RenderDynamic(DrawingContext context, Rect bounds)
|
|
private void RenderDynamic(DrawingContext context, Rect bounds)
|
|
@@ -260,7 +184,6 @@ public class PumpStation3DControl : Control
|
|
|
switch (device.DeviceType)
|
|
switch (device.DeviceType)
|
|
|
{
|
|
{
|
|
|
case "Tank":
|
|
case "Tank":
|
|
|
- var level = (double)GetAnalogValue($"{device.DeviceId}.Level");
|
|
|
|
|
DrawDynamicTank3D(context, origin, scale, cx, cy, device);
|
|
DrawDynamicTank3D(context, origin, scale, cx, cy, device);
|
|
|
break;
|
|
break;
|
|
|
case "Pump":
|
|
case "Pump":
|
|
@@ -294,7 +217,7 @@ public class PumpStation3DControl : Control
|
|
|
DrawText(context, profile.Description, hudP.Position + new Point(12 * scale, 28 * scale), 10 * scale, ThemeHelper.TextTertiary, FontWeight.Bold);
|
|
DrawText(context, profile.Description, hudP.Position + new Point(12 * scale, 28 * scale), 10 * scale, ThemeHelper.TextTertiary, FontWeight.Bold);
|
|
|
|
|
|
|
|
// 报警边框
|
|
// 报警边框
|
|
|
- if (GetDigitalValue("Alarm.Active") || HasAlarm)
|
|
|
|
|
|
|
+ if (GetDigitalValue("Alarm.Active"))
|
|
|
context.DrawRectangle(null, new Pen(ThemeHelper.Danger, 2), scene, 4);
|
|
context.DrawRectangle(null, new Pen(ThemeHelper.Danger, 2), scene, 4);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -405,49 +328,12 @@ public class PumpStation3DControl : Control
|
|
|
DrawText(context, device.DeviceId, c + new Point(-10 * scale, s + 3 * scale), 10 * scale, ThemeHelper.TextSecondary, FontWeight.Bold);
|
|
DrawText(context, device.DeviceId, c + new Point(-10 * scale, s + 3 * scale), 10 * scale, ThemeHelper.TextSecondary, FontWeight.Bold);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // ════════════════════════════════════════════════════════
|
|
|
|
|
- // 兼容模式(旧版硬编码)
|
|
|
|
|
- // ════════════════════════════════════════════════════════
|
|
|
|
|
-
|
|
|
|
|
- private void RenderLegacy(DrawingContext context, Rect bounds)
|
|
|
|
|
- {
|
|
|
|
|
- var scene = new Rect(bounds.X + 22, bounds.Y + 16, Math.Max(0, bounds.Width - 44), Math.Max(0, bounds.Height - 32));
|
|
|
|
|
- var scale = Math.Min(scene.Width / 960.0, scene.Height / 540.0);
|
|
|
|
|
- var origin = new Point(scene.Center.X - 132 * scale, scene.Y + scene.Height * 0.10);
|
|
|
|
|
-
|
|
|
|
|
- DrawFloor(context, origin, scale);
|
|
|
|
|
-
|
|
|
|
|
- DrawChannel(context, origin, scale, new Point(40, 188), "进水渠道", Tank1Level);
|
|
|
|
|
- DrawWetWell(context, origin, scale, new Point(255, 145), Tank2Level);
|
|
|
|
|
- DrawValveChamber(context, origin, scale, new Point(520, 172), Tank4Level);
|
|
|
|
|
- DrawCabinet(context, origin, scale, new Point(430, 64));
|
|
|
|
|
-
|
|
|
|
|
- DrawPipe(context, origin, scale, new Point(32, 244), new Point(258, 244), IsInflowRunning, 20);
|
|
|
|
|
- DrawPipe(context, origin, scale, new Point(300, 132), new Point(620, 132), IsOutflowRunning || AnyPumpRunning, 122);
|
|
|
|
|
- DrawPipe(context, origin, scale, new Point(620, 132), new Point(720, 132), IsOutflowRunning, 122);
|
|
|
|
|
-
|
|
|
|
|
- DrawRiser(context, origin, scale, new Point(322, 228), "P1", Pump1Running);
|
|
|
|
|
- DrawRiser(context, origin, scale, new Point(382, 228), "P2", Pump2Running);
|
|
|
|
|
- DrawRiser(context, origin, scale, new Point(442, 228), "P3", Pump3Running);
|
|
|
|
|
- DrawRiser(context, origin, scale, new Point(352, 292), "P4", Pump4Running);
|
|
|
|
|
- DrawRiser(context, origin, scale, new Point(412, 292), "P5", Pump5Running);
|
|
|
|
|
-
|
|
|
|
|
- DrawValve(context, origin, scale, new Point(550, 132), "V1", Valve2Status);
|
|
|
|
|
- DrawValve(context, origin, scale, new Point(610, 132), "V2", Valve3Status);
|
|
|
|
|
- DrawValve(context, origin, scale, new Point(670, 132), "V3", Valve4Status);
|
|
|
|
|
- DrawFlowMeter(context, origin, scale, new Point(116, 218), "进水", InflowRate, IsInflowRunning);
|
|
|
|
|
- DrawFlowMeter(context, origin, scale, new Point(748, 112), "出水", OutflowRate, IsOutflowRunning);
|
|
|
|
|
- DrawFan(context, origin, scale, new Point(490, 300), "F1", Fan1Running);
|
|
|
|
|
- DrawFan(context, origin, scale, new Point(550, 300), "F2", Fan2Running);
|
|
|
|
|
- DrawHud(context, scene, scale);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
// ═══ 点击事件 ═══
|
|
// ═══ 点击事件 ═══
|
|
|
|
|
|
|
|
protected override void OnPointerPressed(PointerPressedEventArgs e)
|
|
protected override void OnPointerPressed(PointerPressedEventArgs e)
|
|
|
{
|
|
{
|
|
|
base.OnPointerPressed(e);
|
|
base.OnPointerPressed(e);
|
|
|
- if (!IsDynamicMode || _cachedLayout == null) return;
|
|
|
|
|
|
|
+ if (_cachedLayout == null) return;
|
|
|
|
|
|
|
|
var pos = e.GetPosition(this);
|
|
var pos = e.GetPosition(this);
|
|
|
// 反向映射到设计坐标
|
|
// 反向映射到设计坐标
|
|
@@ -472,7 +358,7 @@ public class PumpStation3DControl : Control
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // ═══ 等轴测投影 & 绘制辅助(保留原有逻辑)═══
|
|
|
|
|
|
|
+ // ═══ 等轴测投影 & 绘制辅助 ═══
|
|
|
|
|
|
|
|
private Point Iso(Point p, double z, Point origin, double scale) =>
|
|
private Point Iso(Point p, double z, Point origin, double scale) =>
|
|
|
new(origin.X + (p.X - p.Y) * 0.78 * scale, origin.Y + (p.X + p.Y) * 0.38 * scale - z * scale);
|
|
new(origin.X + (p.X - p.Y) * 0.78 * scale, origin.Y + (p.X + p.Y) * 0.38 * scale - z * scale);
|
|
@@ -489,75 +375,6 @@ public class PumpStation3DControl : Control
|
|
|
context.DrawLine(gridPen, Iso(new Point(0, y), 0, origin, scale), Iso(new Point(875, y), 0, origin, scale));
|
|
context.DrawLine(gridPen, Iso(new Point(0, y), 0, origin, scale), Iso(new Point(875, y), 0, origin, scale));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private void DrawChannel(DrawingContext context, Point origin, double scale, Point p, string name, double level)
|
|
|
|
|
- {
|
|
|
|
|
- DrawBox(context, origin, scale, p, 180, 112, 44, StructureColor, ThemeHelper.Border);
|
|
|
|
|
- DrawBox(context, origin, scale, new Point(p.X + 10, p.Y + 10), 160, 92, Math.Max(8, 34 * Math.Clamp(level, 0, 100) / 100), GetColor(ThemeHelper.Success), null, 0.66);
|
|
|
|
|
- var gridPen = new Pen(ThemeHelper.TextTertiary, Math.Max(1, scale));
|
|
|
|
|
- for (var x = p.X + 128; x < p.X + 168; x += 8)
|
|
|
|
|
- context.DrawLine(gridPen, Iso(new Point(x, p.Y + 20), 46, origin, scale), Iso(new Point(x, p.Y + 92), 46, origin, scale));
|
|
|
|
|
- DrawText(context, name, Iso(new Point(p.X + 25, p.Y + 14), 62, origin, scale), 12 * scale, ThemeHelper.TextPrimary, FontWeight.Bold);
|
|
|
|
|
- DrawText(context, "粗格栅", Iso(new Point(p.X + 146, p.Y + 64), 57, origin, scale), 10 * scale, ThemeHelper.TextSecondary, FontWeight.Bold);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private void DrawWetWell(DrawingContext context, Point origin, double scale, Point p, double level)
|
|
|
|
|
- {
|
|
|
|
|
- const double width = 255, depth = 214, wallHeight = 82;
|
|
|
|
|
- DrawCutawayWellWalls(context, origin, scale, p, width, depth, wallHeight);
|
|
|
|
|
- var waterHeight = 14 + 74 * Math.Clamp(level, 0, 100) / 100;
|
|
|
|
|
- var water = new[]
|
|
|
|
|
- {
|
|
|
|
|
- Iso(new Point(p.X + 16, p.Y + 16), waterHeight, origin, scale),
|
|
|
|
|
- Iso(new Point(p.X + width - 16, p.Y + 16), waterHeight, origin, scale),
|
|
|
|
|
- Iso(new Point(p.X + width - 16, p.Y + depth - 16), waterHeight, origin, scale),
|
|
|
|
|
- Iso(new Point(p.X + 16, p.Y + depth - 16), waterHeight, origin, scale)
|
|
|
|
|
- };
|
|
|
|
|
- context.DrawGeometry(new SolidColorBrush(GetColor(ThemeHelper.Info), 0.60), new Pen(ThemeHelper.Info, Math.Max(1, scale)), Polygon(water));
|
|
|
|
|
- var title = Iso(new Point(p.X + 70, p.Y + 14), wallHeight + 26, origin, scale);
|
|
|
|
|
- DrawText(context, "集水湿井", title, 14 * scale, ThemeHelper.TextPrimary, FontWeight.Bold);
|
|
|
|
|
- DrawText(context, $"液位 {level:F1}%", title + new Point(0, 15 * scale), 10 * scale, ThemeHelper.Info, FontWeight.Bold);
|
|
|
|
|
- DrawText(context, "潜水泵组 (3 用 2 备)", Iso(new Point(p.X + 55, p.Y + depth - 18), waterHeight + 6, origin, scale), 10 * scale, ThemeHelper.TextSecondary, FontWeight.Bold);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private void DrawCutawayWellWalls(DrawingContext context, Point origin, double scale, Point p, double width, double depth, double height)
|
|
|
|
|
- {
|
|
|
|
|
- var wallBrush = new SolidColorBrush(StructureColor, 0.96);
|
|
|
|
|
- var rearWall = new[] { Iso(p, 0, origin, scale), Iso(new Point(p.X + width, p.Y), 0, origin, scale), Iso(new Point(p.X + width, p.Y), height, origin, scale), Iso(p, height, origin, scale) };
|
|
|
|
|
- var sideWall = new[] { Iso(new Point(p.X + width, p.Y), 0, origin, scale), Iso(new Point(p.X + width, p.Y + depth), 0, origin, scale), Iso(new Point(p.X + width, p.Y + depth), height, origin, scale), Iso(new Point(p.X + width, p.Y), height, origin, scale) };
|
|
|
|
|
- context.DrawGeometry(wallBrush, new Pen(ThemeHelper.Border, Math.Max(1, scale)), Polygon(rearWall));
|
|
|
|
|
- context.DrawGeometry(new SolidColorBrush(Darken(StructureColor, 0.82), 0.98), new Pen(ThemeHelper.Border, Math.Max(1, scale)), Polygon(sideWall));
|
|
|
|
|
- var rimPen = new Pen(ThemeHelper.TextSecondary, Math.Max(1.2, 1.5 * scale));
|
|
|
|
|
- context.DrawLine(rimPen, Iso(p, height, origin, scale), Iso(new Point(p.X + width, p.Y), height, origin, scale));
|
|
|
|
|
- context.DrawLine(rimPen, Iso(new Point(p.X + width, p.Y), height, origin, scale), Iso(new Point(p.X + width, p.Y + depth), height, origin, scale));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private void DrawValveChamber(DrawingContext context, Point origin, double scale, Point p, double level)
|
|
|
|
|
- {
|
|
|
|
|
- DrawBox(context, origin, scale, p, 168, 145, 58, StructureColor, ThemeHelper.Border);
|
|
|
|
|
- DrawBox(context, origin, scale, new Point(p.X + 12, p.Y + 12), 144, 121, Math.Max(6, 22 * Math.Clamp(level, 0, 100) / 100), GetColor(ThemeHelper.Success), null, 0.48);
|
|
|
|
|
- DrawText(context, "阀门井", Iso(new Point(p.X + 55, p.Y + 12), 76, origin, scale), 12 * scale, ThemeHelper.TextPrimary, FontWeight.Bold);
|
|
|
|
|
- DrawText(context, "止回阀 / 闸阀", Iso(new Point(p.X + 35, p.Y + 124), 67, origin, scale), 10 * scale, ThemeHelper.TextSecondary, FontWeight.Bold);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private void DrawCabinet(DrawingContext context, Point origin, double scale, Point p)
|
|
|
|
|
- {
|
|
|
|
|
- DrawBox(context, origin, scale, p, 150, 82, 84, StructureColor, ThemeHelper.Border);
|
|
|
|
|
- DrawText(context, "电控柜 / 变频柜", Iso(new Point(p.X + 20, p.Y + 22), 102, origin, scale), 11 * scale, ThemeHelper.TextPrimary, FontWeight.Bold);
|
|
|
|
|
- DrawText(context, "干区", Iso(new Point(p.X + 48, p.Y + 70), 95, origin, scale), 10 * scale, ThemeHelper.TextSecondary, FontWeight.Bold);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private void DrawRiser(DrawingContext context, Point origin, double scale, Point p, string label, bool running)
|
|
|
|
|
- {
|
|
|
|
|
- var basePoint = Iso(p, 20, origin, scale);
|
|
|
|
|
- var topPoint = Iso(p, 122, origin, scale);
|
|
|
|
|
- var status = running ? ThemeHelper.Success : ThemeHelper.TextDisabled;
|
|
|
|
|
- context.DrawLine(new Pen(new SolidColorBrush(Darken(StructureColor, 0.70)), 12 * scale), basePoint, topPoint);
|
|
|
|
|
- context.DrawLine(new Pen(status, 4 * scale), basePoint, topPoint);
|
|
|
|
|
- var headerTap = new Point(p.X, 132);
|
|
|
|
|
- DrawPipe(context, origin, scale, p, headerTap, running, 122);
|
|
|
|
|
- DrawPump(context, origin, scale, p, label, running);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
private void DrawBox(DrawingContext context, Point origin, double scale, Point p, double w, double d, double h, Color color, IBrush? stroke, double opacity = 1)
|
|
private void DrawBox(DrawingContext context, Point origin, double scale, Point p, double w, double d, double h, Color color, IBrush? stroke, double opacity = 1)
|
|
|
{
|
|
{
|
|
|
var top = new[] { Iso(p, h, origin, scale), Iso(new Point(p.X + w, p.Y), h, origin, scale), Iso(new Point(p.X + w, p.Y + d), h, origin, scale), Iso(new Point(p.X, p.Y + d), h, origin, scale) };
|
|
var top = new[] { Iso(p, h, origin, scale), Iso(new Point(p.X + w, p.Y), h, origin, scale), Iso(new Point(p.X + w, p.Y + d), h, origin, scale), Iso(new Point(p.X, p.Y + d), h, origin, scale) };
|
|
@@ -582,72 +399,8 @@ public class PumpStation3DControl : Control
|
|
|
{
|
|
{
|
|
|
var t = ((_phase / 120.0) + i / 9.0) % 1.0;
|
|
var t = ((_phase / 120.0) + i / 9.0) % 1.0;
|
|
|
var pt = new Point(a.X + (b.X - a.X) * t, a.Y + (b.Y - a.Y) * t);
|
|
var pt = new Point(a.X + (b.X - a.X) * t, a.Y + (b.Y - a.Y) * t);
|
|
|
- context.DrawEllipse(FlowDotBrush3D, null, new Rect(pt.X - 4 * scale, pt.Y - 4 * scale, 8 * scale, 8 * scale));
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private void DrawPump(DrawingContext context, Point origin, double scale, Point p, string label, bool running)
|
|
|
|
|
- {
|
|
|
|
|
- var c = Iso(p, 30, origin, scale);
|
|
|
|
|
- var status = running ? GetColor(ThemeHelper.Success) : GetColor(ThemeHelper.TextDisabled);
|
|
|
|
|
- var radius = 15 * scale;
|
|
|
|
|
- var body = new Rect(c.X - radius, c.Y - radius * 1.4, radius * 2, radius * 2.25);
|
|
|
|
|
- context.DrawRectangle(new SolidColorBrush(Darken(StructureColor, 0.78)), new Pen(new SolidColorBrush(status), Math.Max(1, 1.4 * scale)), body, radius * 0.42);
|
|
|
|
|
- context.DrawEllipse(new SolidColorBrush(Lighten(StructureColor, 0.12)), new Pen(new SolidColorBrush(status), Math.Max(1, scale)), new Rect(c.X - radius, c.Y - radius * 1.7, radius * 2, radius * 0.78));
|
|
|
|
|
- context.DrawEllipse(new SolidColorBrush(status), null, new Rect(c.X - 3 * scale, c.Y - radius * 0.55, 6 * scale, 6 * scale));
|
|
|
|
|
- DrawText(context, label, c + new Point(-9 * scale, radius * 1.3), 10 * scale, ThemeHelper.TextPrimary, FontWeight.Bold);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private void DrawFan(DrawingContext context, Point origin, double scale, Point p, string label, bool running)
|
|
|
|
|
- {
|
|
|
|
|
- var c = Iso(p, 34, origin, scale);
|
|
|
|
|
- var r = 24 * scale;
|
|
|
|
|
- var status = running ? GetColor(ThemeHelper.Info) : GetColor(ThemeHelper.TextDisabled);
|
|
|
|
|
- context.DrawEllipse(PumpBodyBrush, new Pen(new SolidColorBrush(status), 1.5 * scale), new Rect(c.X - r, c.Y - r, r * 2, r * 2));
|
|
|
|
|
- for (var i = 0; i < 5; i++)
|
|
|
|
|
- {
|
|
|
|
|
- var a = (_phase * 7 + i * 72) * Math.PI / 180.0;
|
|
|
|
|
- context.DrawLine(new Pen(new SolidColorBrush(status, running ? 0.9 : 0.45), 5 * scale), c, new Point(c.X + Math.Cos(a) * r * 0.7, c.Y + Math.Sin(a) * r * 0.7));
|
|
|
|
|
|
|
+ context.DrawEllipse(new SolidColorBrush(Color.FromRgb(3, 169, 244)), null, new Rect(pt.X - 4 * scale, pt.Y - 4 * scale, 8 * scale, 8 * scale));
|
|
|
}
|
|
}
|
|
|
- context.DrawEllipse(new SolidColorBrush(status), null, new Rect(c.X - 5 * scale, c.Y - 5 * scale, 10 * scale, 10 * scale));
|
|
|
|
|
- DrawText(context, label, c + new Point(-10 * scale, r + 5 * scale), 11 * scale, ThemeHelper.TextPrimary, FontWeight.Bold);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private void DrawValve(DrawingContext context, Point origin, double scale, Point p, string label, ValveStatus status)
|
|
|
|
|
- {
|
|
|
|
|
- var c = Iso(p, 42, origin, scale);
|
|
|
|
|
- var color = status switch
|
|
|
|
|
- {
|
|
|
|
|
- ValveStatus.Open => GetColor(ThemeHelper.Success),
|
|
|
|
|
- ValveStatus.Closed => GetColor(ThemeHelper.Warning),
|
|
|
|
|
- _ => GetColor(ThemeHelper.TextDisabled)
|
|
|
|
|
- };
|
|
|
|
|
- var s = 18 * scale;
|
|
|
|
|
- var points = new[] { c + new Point(0, -s), c + new Point(s, 0), c + new Point(0, s), c + new Point(-s, 0) };
|
|
|
|
|
- context.DrawGeometry(new SolidColorBrush(color, 0.85), new Pen(ThemeHelper.Border, 1), Polygon(points));
|
|
|
|
|
- context.DrawLine(new Pen(ThemeHelper.TextPrimary, 2 * scale), c + new Point(-s * 0.55, 0), c + new Point(s * 0.55, 0));
|
|
|
|
|
- DrawText(context, label, c + new Point(-10 * scale, s + 3 * scale), 10 * scale, ThemeHelper.TextSecondary, FontWeight.Bold);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private void DrawFlowMeter(DrawingContext context, Point origin, double scale, Point p, string label, double value, bool active)
|
|
|
|
|
- {
|
|
|
|
|
- var c = Iso(p, 52, origin, scale);
|
|
|
|
|
- var color = active ? GetColor(ThemeHelper.Success) : GetColor(ThemeHelper.TextDisabled);
|
|
|
|
|
- var rect = new Rect(c.X - 34 * scale, c.Y - 18 * scale, 68 * scale, 36 * scale);
|
|
|
|
|
- context.DrawRectangle(new SolidColorBrush(GetColor(ThemeHelper.SurfaceBg), 0.95), new Pen(new SolidColorBrush(color), 1.2 * scale), rect, 4 * scale);
|
|
|
|
|
- DrawText(context, label, rect.Position + new Point(8 * scale, 3 * scale), 10 * scale, ThemeHelper.TextTertiary, FontWeight.Bold);
|
|
|
|
|
- DrawText(context, $"{value:F1}", rect.Position + new Point(28 * scale, 16 * scale), 12 * scale, new SolidColorBrush(color), FontWeight.Bold);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private void DrawHud(DrawingContext context, Rect scene, double scale)
|
|
|
|
|
- {
|
|
|
|
|
- var panel = new Rect(scene.X + 10, scene.Y + 10, 218 * scale, 78 * scale);
|
|
|
|
|
- context.DrawRectangle(new SolidColorBrush(GetColor(ThemeHelper.SurfaceBg), 0.9), new Pen(ThemeHelper.Border, 1), panel, 4 * scale);
|
|
|
|
|
- DrawText(context, "通用泵站 3D 总览", panel.Position + new Point(12 * scale, 8 * scale), 13 * scale, ThemeHelper.TextPrimary, FontWeight.Bold);
|
|
|
|
|
- DrawText(context, "进水渠 -> 集水井 -> 泵组 -> 出水总管", panel.Position + new Point(12 * scale, 30 * scale), 10 * scale, ThemeHelper.TextTertiary, FontWeight.Bold);
|
|
|
|
|
- DrawText(context, $"RUN {RunningDeviceCount} EFF {Efficiency:F0}% ALM {AlarmCount}", panel.Position + new Point(12 * scale, 50 * scale), 11 * scale, HasAlarm ? ThemeHelper.Danger : ThemeHelper.Success, FontWeight.Bold);
|
|
|
|
|
- if (HasAlarm)
|
|
|
|
|
- context.DrawRectangle(null, new Pen(ThemeHelper.Danger, 2), scene, 4);
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// ═══ 通用辅助 ═══
|
|
// ═══ 通用辅助 ═══
|