791 lines
25 KiB
C#
791 lines
25 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Windows.Media;
|
|
using CtrEditor.HydraulicSimulator;
|
|
using CtrEditor.ObjetosSim;
|
|
using CtrEditor.FuncionesBase;
|
|
using HydraulicSimulator.Models;
|
|
using Newtonsoft.Json;
|
|
using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using LibS7Adv;
|
|
|
|
namespace CtrEditor.ObjetosSim.HydraulicComponents
|
|
{
|
|
/// <summary>
|
|
/// Tanque hidráulico con gestión dinámica de nivel y presión configurable
|
|
/// </summary>
|
|
public partial class osHydTank : osBase, IHydraulicComponent, IHydraulicFlowReceiver, IHydraulicPressureReceiver, IosBase
|
|
{
|
|
public static string NombreCategoria() => "Componentes Hidráulicos";
|
|
|
|
public static string NombreClase() => "Tanque Hidráulico";
|
|
|
|
// Private Fields
|
|
|
|
private double _tankPressure = 101325.0; // Pa (1 atm por defecto)
|
|
private double _currentLevel = 1.0; // m
|
|
private double _maxLevel = 2.0; // m
|
|
private double _minLevel = 0.1; // m
|
|
private double _crossSectionalArea = 1.0; // m²
|
|
private double _currentVolume = 1.0; // m³
|
|
private double _maxVolume = 2.0; // m³
|
|
private double _inletFlow = 0.0; // m³/s
|
|
private double _outletFlow = 0.0; // m³/s
|
|
private double _currentPressure = 101325.0; // Pa
|
|
private bool _isFixedPressure = true;
|
|
private HydraulicTankType _tankType = HydraulicTankType.Intermediate;
|
|
private string _connectedInletPipe = "";
|
|
private string _connectedOutletPipe = "";
|
|
private double _lastUpdateTime = 0.0;
|
|
private readonly object _levelLock = new object();
|
|
private PropertyChangedEventHandler? inletPropertyChangedHandler;
|
|
private PropertyChangedEventHandler? outletPropertyChangedHandler;
|
|
|
|
|
|
// Enums
|
|
public enum HydraulicTankType
|
|
{
|
|
[Description("Tanque de succión (inicio del sistema)")]
|
|
Suction,
|
|
[Description("Tanque intermedio (buffer)")]
|
|
Intermediate,
|
|
[Description("Tanque de almacenamiento")]
|
|
Storage,
|
|
[Description("Tanque de proceso")]
|
|
Process
|
|
}
|
|
|
|
|
|
// 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 del tanque")]
|
|
[property: Name("Tamaño")]
|
|
public float tamano;
|
|
|
|
// Propiedades visuales específicas del tanque
|
|
[ObservableProperty]
|
|
[property: Category("🎨 Apariencia")]
|
|
[property: Description("Color visual del tanque")]
|
|
[property: Name("Color")]
|
|
private Brush colorButton_oculto = Brushes.LightBlue;
|
|
|
|
|
|
|
|
// Constructor
|
|
public osHydTank()
|
|
{
|
|
Nombre = "Tanque Hidráulico";
|
|
Tamano = 1.0f; // Usar un tamaño mayor para mayor visibilidad
|
|
// Inicializar dimensiones usando las propiedades de osBase
|
|
Ancho = 0.30f;
|
|
Alto = 0.40f;
|
|
Angulo = 0f;
|
|
// Asegurar que el movimiento esté habilitado
|
|
Lock_movement = false;
|
|
// Inicializar posición por defecto
|
|
ImageSource_oculta = ImageFromPath("/imagenes/tank.png");
|
|
_currentVolume = _currentLevel * _crossSectionalArea;
|
|
_maxVolume = _maxLevel * _crossSectionalArea;
|
|
IsVisFilter = true; // Asegurar que el componente hidráulico sea visible en filtros
|
|
UpdateTankPressure();
|
|
|
|
// Debug: Confirmar que el constructor se ejecuta
|
|
Debug.WriteLine($"osHydTank Constructor: Nombre='{Nombre}', Tamaño={Tamano}, ZIndex={zIndex_fromFrames}, IsVisFilter={IsVisFilter}, Lock_movement={Lock_movement}");
|
|
}
|
|
|
|
|
|
// Constructor y Métodos Base
|
|
|
|
private string nombre = NombreClase();
|
|
|
|
[Category("🏷️ Identificación")]
|
|
[Description("Nombre identificativo del objeto")]
|
|
[Name("Nombre")]
|
|
public override string Nombre
|
|
{
|
|
get => nombre;
|
|
set => SetProperty(ref nombre, value);
|
|
}
|
|
|
|
public override void OnResize(float Delta_Width, float Delta_Height)
|
|
{
|
|
Tamano += Delta_Width + Delta_Height;
|
|
}
|
|
|
|
public override void UpdateGeometryStart()
|
|
{
|
|
// Los objetos hidráulicos se registran automáticamente
|
|
// cuando inicia la simulación a través de las interfaces
|
|
}
|
|
|
|
public override void UpdateGeometryStep()
|
|
{
|
|
// Los objetos hidráulicos actualizan sus resultados
|
|
// a través de ApplyHydraulicResults()
|
|
}
|
|
|
|
public override void UpdateControl(int elapsedMilliseconds)
|
|
{
|
|
// Actualizar el color según el estado del tanque
|
|
var percentage = FillPercentage;
|
|
if (percentage < 20)
|
|
ColorButton_oculto = Brushes.Red;
|
|
else if (percentage < 50)
|
|
ColorButton_oculto = Brushes.Orange;
|
|
else if (percentage < 80)
|
|
ColorButton_oculto = Brushes.Yellow;
|
|
else
|
|
ColorButton_oculto = Brushes.LightBlue;
|
|
}
|
|
|
|
|
|
|
|
// Properties - Configuration
|
|
|
|
[Category("🏗️ Configuración del Tanque")]
|
|
[DisplayName("Tipo de tanque")]
|
|
[Description("Función del tanque en el sistema hidráulico")]
|
|
public HydraulicTankType TankType
|
|
{
|
|
get => _tankType;
|
|
set
|
|
{
|
|
if (SetProperty(ref _tankType, value))
|
|
{
|
|
UpdateTankConfiguration();
|
|
InvalidateHydraulicNetwork();
|
|
}
|
|
}
|
|
}
|
|
|
|
[Category("🏗️ Configuración del Tanque")]
|
|
[DisplayName("Área sección transversal")]
|
|
[Description("Área de la sección transversal del tanque (m²)")]
|
|
public double CrossSectionalArea
|
|
{
|
|
get => _crossSectionalArea;
|
|
set
|
|
{
|
|
if (SetProperty(ref _crossSectionalArea, Math.Max(0.1, value)))
|
|
{
|
|
UpdateVolumeCalculations();
|
|
InvalidateHydraulicNetwork();
|
|
}
|
|
}
|
|
}
|
|
|
|
[Category("🏗️ Configuración del Tanque")]
|
|
[DisplayName("Nivel máximo")]
|
|
[Description("Nivel máximo permitido en el tanque (m)")]
|
|
public double MaxLevel
|
|
{
|
|
get => _maxLevel;
|
|
set
|
|
{
|
|
if (SetProperty(ref _maxLevel, Math.Max(0.2, value)))
|
|
{
|
|
if (_currentLevel > _maxLevel)
|
|
CurrentLevel = _maxLevel;
|
|
UpdateVolumeCalculations();
|
|
}
|
|
}
|
|
}
|
|
|
|
[Category("🏗️ Configuración del Tanque")]
|
|
[DisplayName("Nivel mínimo")]
|
|
[Description("Nivel mínimo permitido en el tanque (m)")]
|
|
public double MinLevel
|
|
{
|
|
get => _minLevel;
|
|
set
|
|
{
|
|
if (SetProperty(ref _minLevel, Math.Max(0.0, Math.Min(value, _maxLevel - 0.1))))
|
|
{
|
|
if (_currentLevel < _minLevel)
|
|
CurrentLevel = _minLevel;
|
|
UpdateVolumeCalculations();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Properties - Pressure
|
|
|
|
[Category("🔧 Sistema de Presión")]
|
|
[DisplayName("Presión fija")]
|
|
[Description("Si está habilitado, la presión se mantiene constante")]
|
|
public bool IsFixedPressure
|
|
{
|
|
get => _isFixedPressure;
|
|
set
|
|
{
|
|
if (SetProperty(ref _isFixedPressure, value))
|
|
{
|
|
UpdateTankPressure();
|
|
InvalidateHydraulicNetwork();
|
|
}
|
|
}
|
|
}
|
|
|
|
[Category("🔧 Sistema de Presión")]
|
|
[DisplayName("Presión del tanque")]
|
|
[Description("Presión mantenida en el tanque (Pa). En sistemas reales controlada por PID")]
|
|
public double TankPressure
|
|
{
|
|
get => _tankPressure;
|
|
set
|
|
{
|
|
if (SetProperty(ref _tankPressure, Math.Max(0, value)))
|
|
{
|
|
UpdateTankPressure();
|
|
InvalidateHydraulicNetwork();
|
|
}
|
|
}
|
|
}
|
|
|
|
[Category("🔧 Sistema de Presión")]
|
|
[DisplayName("Presión (bar)")]
|
|
[Description("Presión del tanque en bar")]
|
|
[JsonIgnore]
|
|
public double TankPressureBar
|
|
{
|
|
get => TankPressure / 100000.0;
|
|
set => TankPressure = value * 100000.0;
|
|
}
|
|
|
|
|
|
|
|
// Properties - Current State
|
|
|
|
[Category("📊 Estado Actual")]
|
|
[DisplayName("Nivel actual")]
|
|
[Description("Nivel actual de líquido en el tanque (m)")]
|
|
[JsonIgnore]
|
|
public double CurrentLevel
|
|
{
|
|
get => _currentLevel;
|
|
private set
|
|
{
|
|
lock (_levelLock)
|
|
{
|
|
var clampedLevel = Math.Max(_minLevel, Math.Min(_maxLevel, value));
|
|
if (SetProperty(ref _currentLevel, clampedLevel))
|
|
{
|
|
UpdateVolumeCalculations();
|
|
OnPropertyChanged(nameof(FillPercentage));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
[Category("📊 Estado Actual")]
|
|
[DisplayName("Volumen actual")]
|
|
[Description("Volumen actual de líquido en el tanque (m³)")]
|
|
[JsonIgnore]
|
|
public double CurrentVolume
|
|
{
|
|
get => _currentVolume;
|
|
private set => SetProperty(ref _currentVolume, value);
|
|
}
|
|
|
|
[Category("📊 Estado Actual")]
|
|
[DisplayName("Volumen máximo")]
|
|
[Description("Volumen máximo del tanque (m³)")]
|
|
[JsonIgnore]
|
|
public double MaxVolume
|
|
{
|
|
get => _maxVolume;
|
|
private set => SetProperty(ref _maxVolume, value);
|
|
}
|
|
|
|
[Category("📊 Estado Actual")]
|
|
[DisplayName("Porcentaje llenado")]
|
|
[Description("Porcentaje de llenado del tanque")]
|
|
[JsonIgnore]
|
|
public double FillPercentage => (_currentLevel - _minLevel) / (_maxLevel - _minLevel) * 100.0;
|
|
|
|
[Category("📊 Estado Actual")]
|
|
[DisplayName("Flujo entrada")]
|
|
[Description("Flujo de entrada actual (m³/s)")]
|
|
[JsonIgnore]
|
|
public double InletFlow
|
|
{
|
|
get => _inletFlow;
|
|
private set => SetProperty(ref _inletFlow, value);
|
|
}
|
|
|
|
[Category("📊 Estado Actual")]
|
|
[DisplayName("Flujo salida")]
|
|
[Description("Flujo de salida actual (m³/s)")]
|
|
[JsonIgnore]
|
|
public double OutletFlow
|
|
{
|
|
get => _outletFlow;
|
|
private set => SetProperty(ref _outletFlow, value);
|
|
}
|
|
|
|
[Category("📊 Estado Actual")]
|
|
[DisplayName("Balance flujo")]
|
|
[Description("Balance de flujo (entrada - salida) (m³/s)")]
|
|
[JsonIgnore]
|
|
public double FlowBalance => InletFlow - OutletFlow;
|
|
|
|
[Category("📊 Estado Actual")]
|
|
[DisplayName("Presión actual")]
|
|
[Description("Presión actual en el tanque (Pa)")]
|
|
[JsonIgnore]
|
|
public double CurrentPressure
|
|
{
|
|
get => _currentPressure;
|
|
private set => SetProperty(ref _currentPressure, value);
|
|
}
|
|
|
|
[Category("📊 Estado Actual")]
|
|
[DisplayName("Presión actual (bar)")]
|
|
[Description("Presión actual en bar")]
|
|
[JsonIgnore]
|
|
public double CurrentPressureBar => CurrentPressure / 100000.0;
|
|
|
|
|
|
|
|
// Properties - Connections
|
|
|
|
[Category("🔗 Conexiones")]
|
|
[DisplayName("Tubería entrada")]
|
|
[Description("Nombre de la tubería conectada a la entrada")]
|
|
public string ConnectedInletPipe
|
|
{
|
|
get => _connectedInletPipe;
|
|
set
|
|
{
|
|
if (SetProperty(ref _connectedInletPipe, value ?? ""))
|
|
{
|
|
ManageInletConnection();
|
|
InvalidateHydraulicNetwork();
|
|
}
|
|
}
|
|
}
|
|
|
|
[Category("🔗 Conexiones")]
|
|
[DisplayName("Tubería salida")]
|
|
[Description("Nombre de la tubería conectada a la salida")]
|
|
public string ConnectedOutletPipe
|
|
{
|
|
get => _connectedOutletPipe;
|
|
set
|
|
{
|
|
if (SetProperty(ref _connectedOutletPipe, value ?? ""))
|
|
{
|
|
ManageOutletConnection();
|
|
InvalidateHydraulicNetwork();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// IHydraulicComponent Implementation
|
|
|
|
[JsonIgnore]
|
|
public bool HasHydraulicComponents => true;
|
|
|
|
public List<HydraulicNodeDefinition> GetHydraulicNodes()
|
|
{
|
|
var nodes = new List<HydraulicNodeDefinition>();
|
|
|
|
// El tanque siempre es un nodo de presión fija si está configurado así
|
|
if (IsFixedPressure)
|
|
{
|
|
nodes.Add(new HydraulicNodeDefinition(Nombre, true, TankPressure, GetTankDescription()));
|
|
Debug.WriteLine($"Tanque {Nombre}: Nodo de presión fija creado - {TankPressure:F0} Pa ({TankPressureBar:F2} bar)");
|
|
}
|
|
else
|
|
{
|
|
nodes.Add(new HydraulicNodeDefinition(Nombre, false, null, GetTankDescription()));
|
|
Debug.WriteLine($"Tanque {Nombre}: Nodo de presión libre creado");
|
|
}
|
|
|
|
return nodes;
|
|
}
|
|
|
|
public List<HydraulicElementDefinition> GetHydraulicElements()
|
|
{
|
|
// Los tanques no generan elementos hidráulicos, solo nodos
|
|
return new List<HydraulicElementDefinition>();
|
|
}
|
|
|
|
public void UpdateHydraulicProperties()
|
|
{
|
|
// Actualizar propiedades antes de la simulación
|
|
UpdateTankPressure();
|
|
UpdateVolumeCalculations();
|
|
}
|
|
|
|
public void ApplyHydraulicResults(Dictionary<string, double> flows, Dictionary<string, double> pressures)
|
|
{
|
|
var deltaTime = GetDeltaTime();
|
|
|
|
// Obtener flujos conectados
|
|
UpdateFlowsFromConnectedPipes(flows);
|
|
|
|
// Actualizar presión
|
|
if (pressures.ContainsKey(Nombre))
|
|
{
|
|
CurrentPressure = pressures[Nombre];
|
|
}
|
|
|
|
// Actualizar nivel basado en balance de flujo
|
|
UpdateLevelFromFlowBalance(deltaTime);
|
|
|
|
if (VerboseLogging())
|
|
{
|
|
Debug.WriteLine($"Tanque {Nombre}: Nivel={CurrentLevel:F2}m ({FillPercentage:F1}%), " +
|
|
$"Flujo_entrada={InletFlow:F6}m³/s, Flujo_salida={OutletFlow:F6}m³/s, " +
|
|
$"Balance={FlowBalance:F6}m³/s, Presión={CurrentPressure:F0}Pa");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// UI Properties
|
|
|
|
/// <summary>
|
|
/// Color del nivel de líquido
|
|
/// </summary>
|
|
[JsonIgnore]
|
|
public SolidColorBrush LevelColor
|
|
{
|
|
get
|
|
{
|
|
var percentage = FillPercentage;
|
|
if (percentage < 20) return new SolidColorBrush(Colors.Red);
|
|
if (percentage < 50) return new SolidColorBrush(Colors.Orange);
|
|
if (percentage < 80) return new SolidColorBrush(Colors.Yellow);
|
|
return new SolidColorBrush(Colors.LightBlue);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Color del borde del nivel de líquido
|
|
/// </summary>
|
|
[JsonIgnore]
|
|
public SolidColorBrush LevelBorderColor
|
|
{
|
|
get
|
|
{
|
|
var percentage = FillPercentage;
|
|
if (percentage < 20) return new SolidColorBrush(Colors.DarkRed);
|
|
if (percentage < 50) return new SolidColorBrush(Colors.DarkOrange);
|
|
if (percentage < 80) return new SolidColorBrush(Colors.DarkGoldenrod);
|
|
return new SolidColorBrush(Colors.DarkBlue);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Indica si hay conexión de entrada
|
|
/// </summary>
|
|
[JsonIgnore]
|
|
public bool HasInletConnection => !string.IsNullOrEmpty(ConnectedInletPipe);
|
|
|
|
/// <summary>
|
|
/// Indica si hay conexión de salida
|
|
/// </summary>
|
|
[JsonIgnore]
|
|
public bool HasOutletConnection => !string.IsNullOrEmpty(ConnectedOutletPipe);
|
|
|
|
/// <summary>
|
|
/// Indicador del tipo de tanque
|
|
/// </summary>
|
|
[JsonIgnore]
|
|
public string TankTypeIndicator
|
|
{
|
|
get
|
|
{
|
|
return TankType switch
|
|
{
|
|
HydraulicTankType.Suction => "S",
|
|
HydraulicTankType.Intermediate => "I",
|
|
HydraulicTankType.Storage => "A",
|
|
HydraulicTankType.Process => "P",
|
|
_ => "T"
|
|
};
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Balance de flujo en L/min
|
|
/// </summary>
|
|
[JsonIgnore]
|
|
public double FlowBalanceLMin => FlowBalance * 60000; // m³/s a L/min
|
|
|
|
/// <summary>
|
|
/// Color del balance de flujo
|
|
/// </summary>
|
|
[JsonIgnore]
|
|
public SolidColorBrush FlowBalanceColor
|
|
{
|
|
get
|
|
{
|
|
var balance = FlowBalance;
|
|
if (Math.Abs(balance) < 0.0001) return new SolidColorBrush(Colors.Gray);
|
|
return balance > 0 ? new SolidColorBrush(Colors.Green) : new SolidColorBrush(Colors.Red);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Posición Y de la línea de nivel medio (50%)
|
|
/// </summary>
|
|
[JsonIgnore]
|
|
public double MidLevelY
|
|
{
|
|
get
|
|
{
|
|
var tankHeight = Tamano * 100; // Convertir a píxeles aproximados
|
|
return tankHeight * 0.5; // 50% de altura
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Posición Y de la línea de nivel mínimo
|
|
/// </summary>
|
|
[JsonIgnore]
|
|
public double MinLevelY
|
|
{
|
|
get
|
|
{
|
|
var tankHeight = Tamano * 100; // Convertir a píxeles aproximados
|
|
var minPercentage = (MinLevel - MinLevel) / (MaxLevel - MinLevel) * 100;
|
|
return tankHeight - (tankHeight * (minPercentage + 10) / 100); // 10% del nivel mínimo
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Private Methods
|
|
|
|
private string GetTankDescription()
|
|
{
|
|
return TankType switch
|
|
{
|
|
HydraulicTankType.Suction => "Tanque de succión",
|
|
HydraulicTankType.Intermediate => "Tanque intermedio",
|
|
HydraulicTankType.Storage => "Tanque de almacenamiento",
|
|
HydraulicTankType.Process => "Tanque de proceso",
|
|
_ => "Tanque hidráulico"
|
|
};
|
|
}
|
|
|
|
private void UpdateTankConfiguration()
|
|
{
|
|
// Configuración automática según el tipo de tanque
|
|
switch (TankType)
|
|
{
|
|
case HydraulicTankType.Suction:
|
|
// Tanques de succión típicamente a presión atmosférica
|
|
if (TankPressure < 50000) // Si no se ha configurado manualmente
|
|
TankPressure = 101325.0; // 1 atm
|
|
IsFixedPressure = true;
|
|
break;
|
|
|
|
case HydraulicTankType.Intermediate:
|
|
case HydraulicTankType.Storage:
|
|
case HydraulicTankType.Process:
|
|
// Estos pueden tener presión variable o fija según el proceso
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void UpdateVolumeCalculations()
|
|
{
|
|
CurrentVolume = CurrentLevel * CrossSectionalArea;
|
|
MaxVolume = MaxLevel * CrossSectionalArea;
|
|
}
|
|
|
|
private void UpdateTankPressure()
|
|
{
|
|
if (IsFixedPressure)
|
|
{
|
|
CurrentPressure = TankPressure;
|
|
}
|
|
}
|
|
|
|
private void UpdateFlowsFromConnectedPipes(Dictionary<string, double> flows)
|
|
{
|
|
InletFlow = 0.0;
|
|
OutletFlow = 0.0;
|
|
|
|
// Buscar flujos en las ramas conectadas
|
|
foreach (var flow in flows)
|
|
{
|
|
if (flow.Key.Contains(Nombre))
|
|
{
|
|
// Determinar si es flujo de entrada o salida según la dirección
|
|
if (flow.Key.EndsWith($" -> {Nombre}"))
|
|
{
|
|
InletFlow += Math.Max(0, flow.Value); // Solo flujos positivos hacia el tanque
|
|
}
|
|
else if (flow.Key.StartsWith($"{Nombre} -> "))
|
|
{
|
|
OutletFlow += Math.Max(0, flow.Value); // Solo flujos positivos desde el tanque
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void UpdateLevelFromFlowBalance(double deltaTime)
|
|
{
|
|
if (deltaTime <= 0) return;
|
|
|
|
// Balance de masa: cambio_volumen = (flujo_entrada - flujo_salida) * tiempo
|
|
var volumeChange = FlowBalance * deltaTime;
|
|
var levelChange = volumeChange / CrossSectionalArea;
|
|
|
|
// Actualizar nivel con límites
|
|
CurrentLevel = Math.Max(MinLevel, Math.Min(MaxLevel, CurrentLevel + levelChange));
|
|
}
|
|
|
|
private double GetDeltaTime()
|
|
{
|
|
var currentTime = Environment.TickCount64 / 1000.0; // segundos
|
|
var deltaTime = _lastUpdateTime > 0 ? currentTime - _lastUpdateTime : 0.0;
|
|
_lastUpdateTime = currentTime;
|
|
|
|
// Limitar delta time para evitar saltos grandes
|
|
return Math.Min(deltaTime, 0.1); // máximo 100ms
|
|
}
|
|
|
|
private bool VerboseLogging()
|
|
{
|
|
return _mainViewModel?.hydraulicSimulationManager?.VerboseOutput ?? false;
|
|
}
|
|
|
|
private void ManageInletConnection()
|
|
{
|
|
// Gestionar conexión de entrada
|
|
// Implementar lógica de conexión específica si es necesario
|
|
}
|
|
|
|
private void ManageOutletConnection()
|
|
{
|
|
// Gestionar conexión de salida
|
|
// Implementar lógica de conexión específica si es necesario
|
|
}
|
|
|
|
private void InvalidateHydraulicNetwork()
|
|
{
|
|
_mainViewModel?.hydraulicSimulationManager?.InvalidateNetwork();
|
|
}
|
|
|
|
|
|
|
|
// IHydraulicFlowReceiver Implementation
|
|
|
|
public void SetFlow(double flow)
|
|
{
|
|
// Este método puede ser llamado por tuberías conectadas
|
|
// La lógica de flujo se maneja en ApplyHydraulicResults
|
|
}
|
|
|
|
public double GetFlow()
|
|
{
|
|
return FlowBalance;
|
|
}
|
|
|
|
|
|
|
|
// IHydraulicPressureReceiver Implementation
|
|
|
|
public void SetPressure(double pressure)
|
|
{
|
|
if (!IsFixedPressure)
|
|
{
|
|
CurrentPressure = pressure;
|
|
}
|
|
}
|
|
|
|
public double GetPressure()
|
|
{
|
|
return CurrentPressure;
|
|
}
|
|
|
|
|
|
|
|
// ZIndex Implementation
|
|
|
|
public int zIndex_fromFrames { get; set; } = 2;
|
|
|
|
public ZIndexEnum ZIndex_Base()
|
|
{
|
|
return ZIndexEnum.Estaticos;
|
|
}
|
|
|
|
|
|
|
|
// IosBase Implementation
|
|
|
|
public void Start()
|
|
{
|
|
// Inicialización del tanque para la simulación
|
|
UpdateVolumeCalculations();
|
|
UpdateTankPressure();
|
|
}
|
|
|
|
public void Inicializar(int valorInicial)
|
|
{
|
|
// Inicialización con valor inicial
|
|
UpdateVolumeCalculations();
|
|
UpdateTankPressure();
|
|
}
|
|
|
|
public void Disposing()
|
|
{
|
|
// Desconectar event handlers si existen
|
|
if (inletPropertyChangedHandler != null)
|
|
{
|
|
// Aquí se desconectarían los handlers cuando se implementen las conexiones
|
|
// Similar a como lo hace osHydDischargeTank
|
|
}
|
|
|
|
if (outletPropertyChangedHandler != null)
|
|
{
|
|
// Desconectar outlet handler cuando se implemente
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// osBase Overrides
|
|
|
|
public override void ucLoaded()
|
|
{
|
|
// Inicialización cuando se carga el UserControl
|
|
UpdateVolumeCalculations();
|
|
UpdateTankPressure();
|
|
|
|
// Debug: Confirmar que el UserControl se está cargando
|
|
Debug.WriteLine($"osHydTank.ucLoaded(): Tanque '{Nombre}' cargado - Tamaño: {Tamano}, ZIndex: {zIndex_fromFrames}");
|
|
}
|
|
|
|
public override void ucUnLoaded()
|
|
{
|
|
// Los tanques hidráulicos no tienen geometría que limpiar
|
|
}
|
|
|
|
|
|
}
|
|
}
|