Add unit test for hydraulic component type assignability
- Created a new test class TestItemsSource in test_osBaseItemsSource.cs. - Implemented TestTypeAssignability method to verify that osHydPipe, osHydDischargeTank, and osHydPump correctly implement the IHydraulicComponent interface. - Added console output to display results of type checks and comparisons.
This commit is contained in:
parent
42c9ab9449
commit
de4193dee3
|
@ -74,6 +74,9 @@
|
||||||
<None Remove="imagenes\gear.png" />
|
<None Remove="imagenes\gear.png" />
|
||||||
<None Remove="imagenes\motorNegro.png" />
|
<None Remove="imagenes\motorNegro.png" />
|
||||||
<None Remove="imagenes\motorVerde.png" />
|
<None Remove="imagenes\motorVerde.png" />
|
||||||
|
<None Remove="imagenes\pump.png" />
|
||||||
|
<None Remove="imagenes\pump_run.png" />
|
||||||
|
<None Remove="imagenes\pump_stop.png" />
|
||||||
<None Remove="Images\base.png" />
|
<None Remove="Images\base.png" />
|
||||||
<None Remove="motor2.png" />
|
<None Remove="motor2.png" />
|
||||||
<None Remove="tank.png" />
|
<None Remove="tank.png" />
|
||||||
|
@ -150,6 +153,8 @@
|
||||||
<Resource Include="imagenes\gear.png" />
|
<Resource Include="imagenes\gear.png" />
|
||||||
<Resource Include="imagenes\motorNegro.png" />
|
<Resource Include="imagenes\motorNegro.png" />
|
||||||
<Resource Include="imagenes\motorVerde.png" />
|
<Resource Include="imagenes\motorVerde.png" />
|
||||||
|
<Resource Include="imagenes\pump_run.png" />
|
||||||
|
<Resource Include="imagenes\pump_stop.png" />
|
||||||
<Resource Include="imagenes\tank.png" />
|
<Resource Include="imagenes\tank.png" />
|
||||||
<EmbeddedResource Include="Images\base.png" />
|
<EmbeddedResource Include="Images\base.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -169,21 +169,80 @@ namespace CtrEditor.ObjetosSim.HydraulicComponents
|
||||||
// Solo crear elemento si ambos componentes están conectados
|
// Solo crear elemento si ambos componentes están conectados
|
||||||
if (!string.IsNullOrEmpty(Id_ComponenteA) && !string.IsNullOrEmpty(Id_ComponenteB))
|
if (!string.IsNullOrEmpty(Id_ComponenteA) && !string.IsNullOrEmpty(Id_ComponenteB))
|
||||||
{
|
{
|
||||||
// Crear el elemento Pipe según la documentación
|
// Obtener los nombres de nodos correctos para cada componente
|
||||||
var pipeElement = new Pipe(Length, Diameter, Roughness);
|
string fromNodeName = GetNodeNameForComponent(Id_ComponenteA, true); // true = es el nodo origen
|
||||||
|
string toNodeName = GetNodeNameForComponent(Id_ComponenteB, false); // false = es el nodo destino
|
||||||
|
|
||||||
elements.Add(new HydraulicElementDefinition(
|
if (!string.IsNullOrEmpty(fromNodeName) && !string.IsNullOrEmpty(toNodeName))
|
||||||
name: $"{Nombre}_Pipe",
|
{
|
||||||
fromNode: Id_ComponenteA, // Usar el nombre del componente A como nodo origen
|
// Crear el elemento Pipe según la documentación
|
||||||
toNode: Id_ComponenteB, // Usar el nombre del componente B como nodo destino
|
var pipeElement = new Pipe(Length, Diameter, Roughness);
|
||||||
element: pipeElement,
|
|
||||||
description: $"Tubería {Nombre} - L:{Length:F2}m, D:{Diameter*1000:F0}mm ({Id_ComponenteA} → {Id_ComponenteB})"
|
elements.Add(new HydraulicElementDefinition(
|
||||||
));
|
name: $"{Nombre}_Pipe",
|
||||||
|
fromNode: fromNodeName,
|
||||||
|
toNode: toNodeName,
|
||||||
|
element: pipeElement,
|
||||||
|
description: $"Tubería {Nombre} - L:{Length:F2}m, D:{Diameter*1000:F0}mm ({fromNodeName} → {toNodeName})"
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return elements;
|
return elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Obtiene el nombre del nodo correcto para un componente dado
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="componentName">Nombre del componente</param>
|
||||||
|
/// <param name="isSource">True si es el nodo origen de la tubería, False si es destino</param>
|
||||||
|
/// <returns>Nombre del nodo o string vacío si no se encuentra</returns>
|
||||||
|
private string GetNodeNameForComponent(string componentName, bool isSource)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(componentName) || _mainViewModel == null)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
// Buscar el componente hidráulico
|
||||||
|
var component = _mainViewModel.ObjetosSimulables
|
||||||
|
.FirstOrDefault(s => s is IHydraulicComponent comp &&
|
||||||
|
((osBase)comp).Nombre == componentName) as IHydraulicComponent;
|
||||||
|
|
||||||
|
if (component == null)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
// Obtener los nodos que crea este componente
|
||||||
|
var nodes = component.GetHydraulicNodes();
|
||||||
|
if (nodes == null || !nodes.Any())
|
||||||
|
return "";
|
||||||
|
|
||||||
|
// Determinar qué nodo usar según el tipo de componente
|
||||||
|
var componentType = component.GetType();
|
||||||
|
|
||||||
|
// Para tanques: siempre usar su único nodo
|
||||||
|
if (componentType.Name.Contains("Tank"))
|
||||||
|
{
|
||||||
|
return nodes.FirstOrDefault()?.Name ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Para bombas: usar nodo de entrada o salida según corresponda
|
||||||
|
if (componentType.Name.Contains("Pump"))
|
||||||
|
{
|
||||||
|
if (isSource)
|
||||||
|
{
|
||||||
|
// Si la tubería sale desde este componente, usar el nodo de salida de la bomba
|
||||||
|
return nodes.FirstOrDefault(n => n.Name.EndsWith("_Out"))?.Name ?? "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Si la tubería llega a este componente, usar el nodo de entrada de la bomba
|
||||||
|
return nodes.FirstOrDefault(n => n.Name.EndsWith("_In"))?.Name ?? "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Para otros tipos de componentes, usar el primer nodo disponible
|
||||||
|
return nodes.FirstOrDefault()?.Name ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
public void UpdateHydraulicProperties()
|
public void UpdateHydraulicProperties()
|
||||||
{
|
{
|
||||||
// Actualizar propiedades antes de la simulación si es necesario
|
// Actualizar propiedades antes de la simulación si es necesario
|
||||||
|
@ -195,18 +254,25 @@ namespace CtrEditor.ObjetosSim.HydraulicComponents
|
||||||
// Solo procesar si ambos componentes están conectados
|
// Solo procesar si ambos componentes están conectados
|
||||||
if (!string.IsNullOrEmpty(Id_ComponenteA) && !string.IsNullOrEmpty(Id_ComponenteB))
|
if (!string.IsNullOrEmpty(Id_ComponenteA) && !string.IsNullOrEmpty(Id_ComponenteB))
|
||||||
{
|
{
|
||||||
string branchKey = $"{Id_ComponenteA}->{Id_ComponenteB}";
|
// Obtener los nombres de nodos correctos
|
||||||
|
string fromNodeName = GetNodeNameForComponent(Id_ComponenteA, true);
|
||||||
|
string toNodeName = GetNodeNameForComponent(Id_ComponenteB, false);
|
||||||
|
|
||||||
if (flows.TryGetValue(branchKey, out double flow))
|
if (!string.IsNullOrEmpty(fromNodeName) && !string.IsNullOrEmpty(toNodeName))
|
||||||
{
|
{
|
||||||
CurrentFlow = flow;
|
string branchKey = $"{fromNodeName}->{toNodeName}";
|
||||||
}
|
|
||||||
|
if (flows.TryGetValue(branchKey, out double flow))
|
||||||
// Calcular pérdida de presión entre nodos
|
{
|
||||||
if (pressures.TryGetValue(Id_ComponenteA, out double pressureA) &&
|
CurrentFlow = flow;
|
||||||
pressures.TryGetValue(Id_ComponenteB, out double pressureB))
|
}
|
||||||
{
|
|
||||||
PressureDrop = pressureA - pressureB;
|
// Calcular pérdida de presión entre nodos
|
||||||
|
if (pressures.TryGetValue(fromNodeName, out double pressureA) &&
|
||||||
|
pressures.TryGetValue(toNodeName, out double pressureB))
|
||||||
|
{
|
||||||
|
PressureDrop = pressureA - pressureB;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,33 @@ namespace CtrEditor.ObjetosSim.HydraulicComponents
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class osHydPump : osBase, IHydraulicPump, IosBase
|
public partial class osHydPump : osBase, IHydraulicPump, IosBase
|
||||||
{
|
{
|
||||||
#region Properties
|
public static string NombreCategoria() => "Hidraulico";
|
||||||
|
|
||||||
|
public static string NombreClase()
|
||||||
|
{
|
||||||
|
return "Bomba Hidráulica";
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
[property: JsonIgnore]
|
||||||
|
[property: Category("Apariencia")]
|
||||||
|
[property: Description("Imagen visual")]
|
||||||
|
[property: Name("Imagen")]
|
||||||
|
public ImageSource imageSource_oculta;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
[property: Category("🎨 Apariencia")]
|
||||||
|
[property: Description("Tamaño visual de la bomba")]
|
||||||
|
[property: Name("Tamaño")]
|
||||||
|
public float tamano;
|
||||||
|
|
||||||
|
public override void OnResize(float Delta_Width, float Delta_Height)
|
||||||
|
{
|
||||||
|
Tamano += Delta_Width + Delta_Height;
|
||||||
|
}
|
||||||
|
|
||||||
private double _pumpHead = 50.0; // metros
|
private double _pumpHead = 50.0; // metros
|
||||||
private double _maxFlow = 0.01; // m³/s (36 m³/h)
|
private double _maxFlow = 0.01; // m³/s (36 m³/h)
|
||||||
private double _speedRatio = 1.0;
|
private double _speedRatio = 1.0;
|
||||||
|
@ -103,9 +128,20 @@ namespace CtrEditor.ObjetosSim.HydraulicComponents
|
||||||
get => _isRunning;
|
get => _isRunning;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
SetProperty(ref _isRunning, value);
|
if (SetProperty(ref _isRunning, value))
|
||||||
|
{
|
||||||
|
UpdatePumpImage();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdatePumpImage()
|
||||||
|
{
|
||||||
|
if (IsRunning)
|
||||||
|
ImageSource_oculta = ImageFromPath("/imagenes/pump_run.png");
|
||||||
|
else
|
||||||
|
ImageSource_oculta = ImageFromPath("/imagenes/pump_stop.png");
|
||||||
|
}
|
||||||
|
|
||||||
[Category("🔧 Bomba Hidráulica")]
|
[Category("🔧 Bomba Hidráulica")]
|
||||||
[DisplayName("Dirección")]
|
[DisplayName("Dirección")]
|
||||||
|
@ -175,15 +211,11 @@ namespace CtrEditor.ObjetosSim.HydraulicComponents
|
||||||
// Los objetos hidráulicos no necesitan actualizar geometría física
|
// Los objetos hidráulicos no necesitan actualizar geometría física
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnResize(float Delta_Width, float Delta_Height)
|
|
||||||
{
|
|
||||||
Ancho += Delta_Width;
|
|
||||||
Alto += Delta_Height;
|
|
||||||
}
|
|
||||||
|
|
||||||
public osHydPump()
|
public osHydPump()
|
||||||
{
|
{
|
||||||
Nombre = "Bomba Hidráulica";
|
Nombre = "Bomba Hidráulica";
|
||||||
|
Tamano = 0.30f;
|
||||||
|
ImageSource_oculta = ImageFromPath("/imagenes/pump_stop.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void UpdateGeometryStart()
|
public override void UpdateGeometryStart()
|
||||||
|
@ -211,6 +243,7 @@ namespace CtrEditor.ObjetosSim.HydraulicComponents
|
||||||
{
|
{
|
||||||
// Los objetos hidráulicos no necesitan geometría física
|
// Los objetos hidráulicos no necesitan geometría física
|
||||||
base.ucLoaded();
|
base.ucLoaded();
|
||||||
|
UpdatePumpImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ucUnLoaded()
|
public override void ucUnLoaded()
|
||||||
|
@ -242,11 +275,17 @@ namespace CtrEditor.ObjetosSim.HydraulicComponents
|
||||||
|
|
||||||
if (HasHydraulicComponents)
|
if (HasHydraulicComponents)
|
||||||
{
|
{
|
||||||
|
// Calcular velocidad efectiva basada en el estado de la bomba
|
||||||
|
double effectiveSpeed = IsRunning ? SpeedRatio : 0.0;
|
||||||
|
|
||||||
|
// Asegurar que la velocidad esté en rango válido
|
||||||
|
effectiveSpeed = Math.Max(0.0, Math.Min(1.0, effectiveSpeed));
|
||||||
|
|
||||||
// Crear bomba con parámetros actuales
|
// Crear bomba con parámetros actuales
|
||||||
var pump = new PumpHQ(
|
var pump = new PumpHQ(
|
||||||
h0: PumpHead,
|
h0: PumpHead,
|
||||||
q0: MaxFlow,
|
q0: MaxFlow,
|
||||||
speedRel: IsRunning ? SpeedRatio : 0.0, // Si no está funcionando, velocidad = 0
|
speedRel: effectiveSpeed,
|
||||||
direction: PumpDirection
|
direction: PumpDirection
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -259,6 +298,8 @@ namespace CtrEditor.ObjetosSim.HydraulicComponents
|
||||||
);
|
);
|
||||||
|
|
||||||
elements.Add(pumpElement);
|
elements.Add(pumpElement);
|
||||||
|
|
||||||
|
Debug.WriteLine($"Bomba {Nombre}: Creando elemento hidráulico - H0={PumpHead}m, Q0={MaxFlow}m³/s, Velocidad={effectiveSpeed:F2}, Dirección={PumpDirection}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return elements;
|
return elements;
|
||||||
|
@ -288,16 +329,25 @@ namespace CtrEditor.ObjetosSim.HydraulicComponents
|
||||||
if (flows.ContainsKey(pumpBranchName))
|
if (flows.ContainsKey(pumpBranchName))
|
||||||
{
|
{
|
||||||
CurrentFlow = flows[pumpBranchName];
|
CurrentFlow = flows[pumpBranchName];
|
||||||
|
Debug.WriteLine($"Bomba {Nombre}: Aplicando caudal={CurrentFlow:F6} m³/s ({CurrentFlowLMin:F2} L/min)");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pressures.ContainsKey(inletNodeName))
|
if (pressures.ContainsKey(inletNodeName))
|
||||||
{
|
{
|
||||||
CurrentPressure = pressures[inletNodeName];
|
CurrentPressure = pressures[inletNodeName];
|
||||||
|
Debug.WriteLine($"Bomba {Nombre}: Presión entrada={CurrentPressure:F2} Pa ({CurrentPressureBar:F2} bar)");
|
||||||
}
|
}
|
||||||
else if (pressures.ContainsKey(outletNodeName))
|
else if (pressures.ContainsKey(outletNodeName))
|
||||||
{
|
{
|
||||||
CurrentPressure = pressures[outletNodeName];
|
CurrentPressure = pressures[outletNodeName];
|
||||||
|
Debug.WriteLine($"Bomba {Nombre}: Presión salida={CurrentPressure:F2} Pa ({CurrentPressureBar:F2} bar)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disparar PropertyChanged para actualizar el UI
|
||||||
|
OnPropertyChanged(nameof(CurrentFlow));
|
||||||
|
OnPropertyChanged(nameof(CurrentFlowLMin));
|
||||||
|
OnPropertyChanged(nameof(CurrentPressure));
|
||||||
|
OnPropertyChanged(nameof(CurrentPressureBar));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -345,13 +395,6 @@ namespace CtrEditor.ObjetosSim.HydraulicComponents
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Static Interface Implementation
|
|
||||||
|
|
||||||
public static string NombreClase() => "Bomba Hidráulica";
|
|
||||||
public static string NombreCategoria() => "Componentes Hidráulicos";
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -3,77 +3,39 @@
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
xmlns:local="clr-namespace:CtrEditor.ObjetosSim"
|
||||||
xmlns:vm="clr-namespace:CtrEditor.ObjetosSim.HydraulicComponents"
|
xmlns:vm="clr-namespace:CtrEditor.ObjetosSim.HydraulicComponents"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
|
|
||||||
<UserControl.DataContext>
|
<UserControl.DataContext>
|
||||||
<vm:osHydPump Ancho="0.15" Alto="0.10"/>
|
<vm:osHydPump ImageSource_oculta="/imagenes/pump_run.png" />
|
||||||
</UserControl.DataContext>
|
</UserControl.DataContext>
|
||||||
|
|
||||||
<Canvas RenderTransformOrigin="0,0">
|
<Grid RenderTransformOrigin="0,0">
|
||||||
<Canvas.RenderTransform>
|
<Grid.RenderTransform>
|
||||||
<TransformGroup>
|
<TransformGroup>
|
||||||
<ScaleTransform />
|
<RotateTransform Angle="{Binding Angulo}"/>
|
||||||
<SkewTransform />
|
|
||||||
<RotateTransform Angle="{Binding Angulo}" />
|
|
||||||
<TranslateTransform />
|
|
||||||
</TransformGroup>
|
</TransformGroup>
|
||||||
</Canvas.RenderTransform>
|
</Grid.RenderTransform>
|
||||||
|
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<!-- Fondo de la bomba -->
|
<!-- Imagen de la bomba -->
|
||||||
<Ellipse x:Name="PumpBackground"
|
<Image Grid.Row="0" Source="{Binding ImageSource_oculta}"
|
||||||
Width="{Binding Ancho, Converter={StaticResource MeterToPixelConverter}}"
|
Width="{Binding Tamano, Converter={StaticResource MeterToPixelConverter}}"
|
||||||
Height="{Binding Alto, Converter={StaticResource MeterToPixelConverter}}"
|
Height="{Binding Tamano, Converter={StaticResource MeterToPixelConverter}}"
|
||||||
Fill="{Binding ColorButton_oculto}"
|
Stretch="Uniform"/>
|
||||||
Stroke="DarkSlateGray"
|
|
||||||
StrokeThickness="2"/>
|
<!-- Panel de información con presión y caudal -->
|
||||||
<!-- Indicador de dirección con tamaño proporcional -->
|
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center">
|
||||||
<Polygon x:Name="DirectionArrow"
|
<TextBlock Text="{Binding CurrentPressureBar, StringFormat='{}{0:F1} bar'}"
|
||||||
Fill="DarkBlue"
|
Foreground="White" Background="Blue" Padding="2" Margin="1" FontSize="8"/>
|
||||||
Points="0.5,0.3 0.8,0.5 0.5,0.7"
|
<TextBlock Text="{Binding CurrentFlowLMin, StringFormat='{}{0:F1} L/min'}"
|
||||||
RenderTransformOrigin="0.5,0.5">
|
Foreground="White" Background="Green" Padding="2" Margin="1" FontSize="8"/>
|
||||||
<Polygon.RenderTransform>
|
</StackPanel>
|
||||||
<ScaleTransform ScaleX="{Binding Ancho, Converter={StaticResource MeterToPixelConverter}}"
|
</Grid>
|
||||||
ScaleY="{Binding Alto, Converter={StaticResource MeterToPixelConverter}}"/>
|
|
||||||
</Polygon.RenderTransform>
|
</UserControl>
|
||||||
</Polygon>
|
|
||||||
|
|
||||||
<!-- Texto de identificación con Viewbox para escalado -->
|
|
||||||
<Viewbox Width="{Binding Ancho, Converter={StaticResource MeterToPixelConverter}}"
|
|
||||||
Height="{Binding Alto, Converter={StaticResource MeterToPixelConverter}}"
|
|
||||||
Stretch="Uniform">
|
|
||||||
<Label Content="{Binding Nombre}"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
FontWeight="Bold"
|
|
||||||
FontSize="18"
|
|
||||||
Opacity="0.9"
|
|
||||||
Foreground="White"/>
|
|
||||||
</Viewbox>
|
|
||||||
|
|
||||||
<!-- Indicador de estado (LED) con posición proporcional -->
|
|
||||||
<Ellipse x:Name="StatusLED"
|
|
||||||
Width="8"
|
|
||||||
Height="8"
|
|
||||||
Fill="{Binding IsRunning, Converter={StaticResource BoolToColorConverter}}"
|
|
||||||
Canvas.Right="5"
|
|
||||||
Canvas.Top="5"/>
|
|
||||||
|
|
||||||
<!-- Conexiones de entrada y salida con posiciones proporcionales -->
|
|
||||||
<Rectangle x:Name="InletConnection"
|
|
||||||
Width="10"
|
|
||||||
Height="4"
|
|
||||||
Fill="Green"
|
|
||||||
Canvas.Left="-5"
|
|
||||||
Canvas.Top="{Binding Alto, Converter={StaticResource MeterToPixelConverter}, ConverterParameter=0.5}"/>
|
|
||||||
|
|
||||||
<Rectangle x:Name="OutletConnection"
|
|
||||||
Width="10"
|
|
||||||
Height="4"
|
|
||||||
Fill="Red"
|
|
||||||
Canvas.Right="-5"
|
|
||||||
Canvas.Top="{Binding Alto, Converter={StaticResource MeterToPixelConverter}, ConverterParameter=0.5}"/>
|
|
||||||
|
|
||||||
</Canvas>
|
|
||||||
</UserControl>
|
|
|
@ -3,7 +3,6 @@ using System.Diagnostics;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using System.Windows.Media.Animation;
|
|
||||||
using CtrEditor.ObjetosSim;
|
using CtrEditor.ObjetosSim;
|
||||||
using CtrEditor.FuncionesBase;
|
using CtrEditor.FuncionesBase;
|
||||||
|
|
||||||
|
@ -17,7 +16,6 @@ namespace CtrEditor.ObjetosSim.HydraulicComponents
|
||||||
public osBase? Datos { get; set; }
|
public osBase? Datos { get; set; }
|
||||||
public int zIndex_fromFrames { get; set; } = 0;
|
public int zIndex_fromFrames { get; set; } = 0;
|
||||||
|
|
||||||
private Storyboard? _rotationAnimation;
|
|
||||||
private bool _isHighlighted = false;
|
private bool _isHighlighted = false;
|
||||||
|
|
||||||
public ucHydPump()
|
public ucHydPump()
|
||||||
|
@ -25,13 +23,11 @@ namespace CtrEditor.ObjetosSim.HydraulicComponents
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
this.Loaded += OnLoaded;
|
this.Loaded += OnLoaded;
|
||||||
this.Unloaded += OnUnloaded;
|
this.Unloaded += OnUnloaded;
|
||||||
DataContextChanged += OnDataContextChanged;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnLoaded(object sender, RoutedEventArgs e)
|
private void OnLoaded(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
Datos?.ucLoaded();
|
Datos?.ucLoaded();
|
||||||
UpdateVisualState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnUnloaded(object sender, RoutedEventArgs e)
|
private void OnUnloaded(object sender, RoutedEventArgs e)
|
||||||
|
@ -39,155 +35,12 @@ namespace CtrEditor.ObjetosSim.HydraulicComponents
|
||||||
Datos?.ucUnLoaded();
|
Datos?.ucUnLoaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
|
|
||||||
{
|
|
||||||
if (DataContext is osHydPump pump)
|
|
||||||
{
|
|
||||||
Datos = pump;
|
|
||||||
pump.PropertyChanged += OnPumpPropertyChanged;
|
|
||||||
UpdateVisualState();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnPumpPropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
|
||||||
{
|
|
||||||
if (e.PropertyName == nameof(osHydPump.IsRunning) ||
|
|
||||||
e.PropertyName == nameof(osHydPump.SpeedRatio) ||
|
|
||||||
e.PropertyName == nameof(osHydPump.PumpDirection) ||
|
|
||||||
e.PropertyName == nameof(osHydPump.CurrentFlow) ||
|
|
||||||
e.PropertyName == nameof(osHydPump.CurrentPressure))
|
|
||||||
{
|
|
||||||
UpdateVisualState();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Actualiza el estado visual de la bomba
|
|
||||||
/// </summary>
|
|
||||||
private void UpdateVisualState()
|
|
||||||
{
|
|
||||||
if (Datos is not osHydPump pump) return;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Dispatcher.BeginInvoke(() =>
|
|
||||||
{
|
|
||||||
UpdateStatusLED(pump);
|
|
||||||
UpdateRotationAnimation(pump);
|
|
||||||
UpdateDirectionArrow(pump);
|
|
||||||
UpdateStatusInfo(pump);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Debug.WriteLine($"Error updating pump visual state: {ex.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Actualiza el LED de estado
|
|
||||||
/// </summary>
|
|
||||||
private void UpdateStatusLED(osHydPump pump)
|
|
||||||
{
|
|
||||||
if (pump.IsRunning && pump.SpeedRatio > 0)
|
|
||||||
{
|
|
||||||
StatusLED.Fill = new SolidColorBrush(Colors.LimeGreen);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
StatusLED.Fill = new SolidColorBrush(Colors.Red);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Actualiza la animación de rotación
|
|
||||||
/// </summary>
|
|
||||||
private void UpdateRotationAnimation(osHydPump pump)
|
|
||||||
{
|
|
||||||
_rotationAnimation?.Stop();
|
|
||||||
|
|
||||||
if (pump.IsRunning && pump.SpeedRatio > 0)
|
|
||||||
{
|
|
||||||
// Crear animación de rotación
|
|
||||||
var rotateTransform = new RotateTransform();
|
|
||||||
PumpBackground.RenderTransform = rotateTransform;
|
|
||||||
PumpBackground.RenderTransformOrigin = new Point(0.5, 0.5);
|
|
||||||
|
|
||||||
var animation = new DoubleAnimation
|
|
||||||
{
|
|
||||||
From = 0,
|
|
||||||
To = 360,
|
|
||||||
Duration = TimeSpan.FromSeconds(2.0 / pump.SpeedRatio), // Más rápido con mayor velocidad
|
|
||||||
RepeatBehavior = RepeatBehavior.Forever
|
|
||||||
};
|
|
||||||
|
|
||||||
_rotationAnimation = new Storyboard();
|
|
||||||
Storyboard.SetTarget(animation, rotateTransform);
|
|
||||||
Storyboard.SetTargetProperty(animation, new PropertyPath(RotateTransform.AngleProperty));
|
|
||||||
_rotationAnimation.Children.Add(animation);
|
|
||||||
_rotationAnimation.Begin();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PumpBackground.RenderTransform = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Actualiza la flecha de dirección
|
|
||||||
/// </summary>
|
|
||||||
private void UpdateDirectionArrow(osHydPump pump)
|
|
||||||
{
|
|
||||||
if (pump.PumpDirection == -1)
|
|
||||||
{
|
|
||||||
// Cambiar el color de la flecha para indicar dirección inversa
|
|
||||||
DirectionArrow.Fill = new SolidColorBrush(Colors.Orange);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DirectionArrow.Fill = new SolidColorBrush(Colors.DarkBlue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Actualiza la información de estado
|
|
||||||
/// </summary>
|
|
||||||
private void UpdateStatusInfo(osHydPump pump)
|
|
||||||
{
|
|
||||||
// La información de estado se mostrará a través de la etiqueta principal
|
|
||||||
// El StatusLED ya está configurado para mostrar el estado IsRunning
|
|
||||||
}
|
|
||||||
|
|
||||||
#region IDataContainer Implementation
|
#region IDataContainer Implementation
|
||||||
|
|
||||||
public void Highlight(bool state)
|
public void Highlight(bool state)
|
||||||
{
|
{
|
||||||
_isHighlighted = state;
|
_isHighlighted = state;
|
||||||
|
// Aquí se podría agregar lógica de resaltado si fuera necesario
|
||||||
if (state)
|
|
||||||
{
|
|
||||||
PumpBackground.Stroke = new SolidColorBrush(Colors.Yellow);
|
|
||||||
PumpBackground.StrokeThickness = 3;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PumpBackground.Stroke = new SolidColorBrush(Colors.DarkSlateGray);
|
|
||||||
PumpBackground.StrokeThickness = 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
protected override void OnMouseEnter(System.Windows.Input.MouseEventArgs e)
|
|
||||||
{
|
|
||||||
base.OnMouseEnter(e);
|
|
||||||
// No hay elementos adicionales para mostrar en la implementación actual
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnMouseLeave(System.Windows.Input.MouseEventArgs e)
|
|
||||||
{
|
|
||||||
base.OnMouseLeave(e);
|
|
||||||
// No hay elementos adicionales para ocultar en la implementación actual
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ZIndexEnum ZIndex_Base()
|
public ZIndexEnum ZIndex_Base()
|
||||||
|
@ -195,9 +48,6 @@ namespace CtrEditor.ObjetosSim.HydraulicComponents
|
||||||
return ZIndexEnum.Estaticos;
|
return ZIndexEnum.Estaticos;
|
||||||
}
|
}
|
||||||
|
|
||||||
~ucHydPump()
|
#endregion
|
||||||
{
|
|
||||||
_rotationAnimation?.Stop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1919,9 +1919,30 @@ namespace CtrEditor.ObjetosSim
|
||||||
items.Add("");
|
items.Add("");
|
||||||
foreach (var obj in objetosSimulables)
|
foreach (var obj in objetosSimulables)
|
||||||
{
|
{
|
||||||
if (obj.GetType() == typeof(T))
|
try
|
||||||
{
|
{
|
||||||
items.Add(obj.Nombre);
|
// Verificar si el tipo T es una interfaz
|
||||||
|
if (typeof(T).IsInterface)
|
||||||
|
{
|
||||||
|
// Para interfaces, verificar si el objeto implementa la interfaz
|
||||||
|
if (typeof(T).IsAssignableFrom(obj.GetType()))
|
||||||
|
{
|
||||||
|
items.Add(obj.Nombre);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Para clases concretas, usar comparación directa de tipos
|
||||||
|
if (obj.GetType() == typeof(T))
|
||||||
|
{
|
||||||
|
items.Add(obj.Nombre);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// Log the exception but continue processing other objects
|
||||||
|
System.Diagnostics.Debug.WriteLine($"Error checking type compatibility for {obj?.GetType()?.Name}: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
|
@ -0,0 +1,32 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using CtrEditor.ObjetosSim;
|
||||||
|
using CtrEditor.ObjetosSim.HydraulicComponents;
|
||||||
|
using CtrEditor.HydraulicSimulator;
|
||||||
|
|
||||||
|
// Este archivo es solo para verificar que la corrección funciona
|
||||||
|
// Se puede eliminar después de confirmar que todo funciona bien
|
||||||
|
|
||||||
|
namespace CtrEditor.Test
|
||||||
|
{
|
||||||
|
class TestItemsSource
|
||||||
|
{
|
||||||
|
static void TestTypeAssignability()
|
||||||
|
{
|
||||||
|
// Crear instancias de objetos hidráulicos
|
||||||
|
var pipe = new osHydPipe();
|
||||||
|
var tank = new osHydDischargeTank();
|
||||||
|
var pump = new osHydPump();
|
||||||
|
|
||||||
|
// Probar la corrección - debería ser true para todos
|
||||||
|
Console.WriteLine($"osHydPipe implements IHydraulicComponent: {typeof(IHydraulicComponent).IsAssignableFrom(pipe.GetType())}");
|
||||||
|
Console.WriteLine($"osHydDischargeTank implements IHydraulicComponent: {typeof(IHydraulicComponent).IsAssignableFrom(tank.GetType())}");
|
||||||
|
Console.WriteLine($"osHydPump implements IHydraulicComponent: {typeof(IHydraulicComponent).IsAssignableFrom(pump.GetType())}");
|
||||||
|
|
||||||
|
// La comparación anterior que fallaba
|
||||||
|
Console.WriteLine($"osHydPipe.GetType() == typeof(IHydraulicComponent): {pipe.GetType() == typeof(IHydraulicComponent)}");
|
||||||
|
Console.WriteLine($"osHydDischargeTank.GetType() == typeof(IHydraulicComponent): {tank.GetType() == typeof(IHydraulicComponent)}");
|
||||||
|
Console.WriteLine($"osHydPump.GetType() == typeof(IHydraulicComponent): {pump.GetType() == typeof(IHydraulicComponent)}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue