using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Windows.Media;
using CtrEditor.HydraulicSimulator;
using CtrEditor.HydraulicSimulator.TSNet.Components;
using CtrEditor.ObjetosSim;
using CtrEditor.FuncionesBase;
using HydraulicSimulator.Models;
using Newtonsoft.Json;
using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
using CommunityToolkit.Mvvm.ComponentModel;
namespace CtrEditor.ObjetosSim
{
///
/// Bomba hidráulica que implementa las interfaces del simulador hidráulico
///
public partial class osHydPump : osBase, IHydraulicComponent, IHydraulicFlowReceiver, IHydraulicPressureReceiver, IosBase
{
public static string NombreCategoria() => "Componentes Hidráulicos";
public static string NombreClase()
{
return "Bomba Hidráulica";
}
// TSNet Integration
[JsonIgnore]
public TSNetPumpAdapter TSNetAdapter { get; private set; }
// 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 _maxFlow = 0.01; // m³/s (36 m³/h)
private double _speedRatio = 1.0;
private bool _isRunning = true;
private int _pumpDirection = 1;
private double _currentFlow = 0.0;
private double _currentPressure = 0.0;
// Propiedades visuales específicas de la bomba
[ObservableProperty]
[property: Category("🎨 Apariencia")]
[property: Description("Color visual de la bomba")]
[property: Name("Color")]
private Brush colorButton_oculto = Brushes.Blue;
[Category("🔧 Bomba Hidráulica")]
[DisplayName("Cabeza de bomba")]
[Description("Cabeza de la bomba a caudal cero (m)")]
public double PumpHead
{
get => _pumpHead;
set
{
if (SetProperty(ref _pumpHead, Math.Max(0, value)))
{
InvalidateHydraulicNetwork();
}
}
}
[Category("🔧 Bomba Hidráulica")]
[DisplayName("Caudal máximo")]
[Description("Caudal máximo de la bomba (m³/s)")]
public double MaxFlow
{
get => _maxFlow;
set
{
// Si el valor es mayor a 1, asumir que está en m³/h y convertir a m³/s
double valueInM3s = value > 1.0 ? value / 3600.0 : value;
if (SetProperty(ref _maxFlow, Math.Max(0.0001, valueInM3s)))
{
InvalidateHydraulicNetwork();
Debug.WriteLine($"Bomba {Nombre}: MaxFlow establecido a {_maxFlow:F6} m³/s ({_maxFlow * 3600:F2} m³/h)");
}
}
}
[Category("🔧 Bomba Hidráulica")]
[DisplayName("Velocidad relativa")]
[Description("Velocidad relativa de la bomba (0.0 a 1.0)")]
public double SpeedRatio
{
get => _speedRatio;
set
{
SetProperty(ref _speedRatio, Math.Max(0.0, Math.Min(1.0, value)));
}
}
[Category("🔧 Bomba Hidráulica")]
[DisplayName("Funcionando")]
[Description("Indica si la bomba está encendida")]
public bool IsRunning
{
get => _isRunning;
set
{
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")]
[DisplayName("Dirección")]
[Description("Dirección de la bomba (+1 o -1)")]
[ItemsSource(typeof(PumpDirectionItemsSource))]
public int PumpDirection
{
get => _pumpDirection;
set
{
if (SetProperty(ref _pumpDirection, value == -1 ? -1 : 1))
{
InvalidateHydraulicNetwork();
}
}
}
[Category("📊 Estado Actual")]
[DisplayName("Caudal actual")]
[Description("Caudal actual de la bomba (m³/s)")]
[JsonIgnore]
public double CurrentFlow
{
get => _currentFlow;
private set => SetProperty(ref _currentFlow, value);
}
[Category("📊 Estado Actual")]
[DisplayName("Presión actual")]
[Description("Presión actual en la bomba (bar)")]
[JsonIgnore]
public double CurrentPressure
{
get => _currentPressure;
private set => SetProperty(ref _currentPressure, value);
}
[Category("📊 Estado Actual")]
[DisplayName("Presión (Pa)")]
[Description("Presión actual en Pascal")]
[JsonIgnore]
public double CurrentPressurePa => CurrentPressure * 100000.0;
[Category("📊 Estado Actual")]
[DisplayName("Presión (bar)")]
[Description("Presión actual en la bomba (bar)")]
[JsonIgnore]
public double CurrentPressureBar => CurrentPressure; // Ya está en bar internamente
[Category("📊 Estado Actual")]
[DisplayName("Caudal (L/min)")]
[Description("Caudal actual en L/min")]
[JsonIgnore]
public double CurrentFlowLMin => CurrentFlow * 60000.0; // m³/s a L/min
[Category("📊 Estado Actual")]
[DisplayName("Tiene Flujo")]
[Description("Indica si hay flujo en la bomba")]
[JsonIgnore]
public bool HasFlow => Math.Abs(CurrentFlow) > 1e-6;
[Category("📊 Estado Actual")]
[DisplayName("Estado")]
[Description("Estado actual de la bomba")]
[JsonIgnore]
public string PumpStatus
{
get
{
if (!IsRunning) return "Bomba detenida";
if (HasFlow) return "✅ Bombeando";
return "⚠️ Sin flujo";
}
}
[Category("📊 Estado Actual")]
[DisplayName("Estado Detallado")]
[Description("Información detallada del estado operacional")]
[JsonIgnore]
public string DetailedStatus
{
get
{
var flow = CurrentFlowLMin;
var pressure = CurrentPressureBar;
return $"Flujo: {flow:F1} L/min | Presión: {pressure:F1} bar | {PumpStatus}";
}
}
// Propiedades de fluido actual
private FluidProperties _currentFluid = new FluidProperties(FluidType.Air);
[Category("🧪 Fluido Actual")]
[DisplayName("Tipo de fluido")]
[Description("Tipo de fluido que está bombeando")]
[ReadOnly(true)]
public FluidType CurrentFluidType => _currentFluid.Type;
[Category("🧪 Fluido Actual")]
[DisplayName("Descripción")]
[Description("Descripción del fluido que se está bombeando")]
[ReadOnly(true)]
public string CurrentFluidDescription => _currentFluid.Description;
[Category("📊 Estado Actual")]
[DisplayName("Factor Viscosidad")]
[Description("Factor de eficiencia debido a la viscosidad del fluido")]
[ReadOnly(true)]
public double ViscosityEffect
{
get
{
// Factor basado en viscosidad del fluido vs agua
var waterViscosity = 0.001; // Pa·s
var currentViscosity = _currentFluid.Viscosity;
return Math.Max(0.1, Math.Min(1.0, waterViscosity / currentViscosity));
}
}
[Category("📊 Estado Actual")]
[DisplayName("Flujo Efectivo (L/min)")]
[Description("Flujo real ajustado por viscosidad")]
[ReadOnly(true)]
public double EffectiveFlowLMin => CurrentFlowLMin * ViscosityEffect;
[Category("📊 Estado Actual")]
[DisplayName("Temperatura (°C)")]
[Description("Temperatura del fluido bombeado")]
[ReadOnly(true)]
public double FluidTemperature => _currentFluid.Temperature;
[Category("📊 Estado Actual")]
[DisplayName("Densidad (kg/L)")]
[Description("Densidad del fluido bombeado")]
[ReadOnly(true)]
public double FluidDensity => _currentFluid.Density;
[Category("📊 Estado Actual")]
[DisplayName("Brix (%)")]
[Description("Concentración en grados Brix (para jarabes)")]
[ReadOnly(true)]
public double FluidBrix => _currentFluid.Brix;
[Category("📊 Estado Actual")]
[DisplayName("Concentración (%)")]
[Description("Concentración en porcentaje (para químicos)")]
[ReadOnly(true)]
public double FluidConcentration => _currentFluid.Concentration;
[Category("📊 Estado Actual")]
[DisplayName("Viscosidad (cP)")]
[Description("Viscosidad dinámica en centipoise")]
[ReadOnly(true)]
public double FluidViscosity => _currentFluid.Viscosity;
[Category("📊 Estado Actual")]
[DisplayName("Descripción del Fluido")]
[Description("Descripción completa del fluido")]
[ReadOnly(true)]
public string FluidDescription => _currentFluid.Description;
// 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 osHydPump()
{
Nombre = "Bomba Hidráulica";
Tamano = 0.30f;
// Inicializar dimensiones usando las propiedades de osBase
Ancho = 0.15f;
Alto = 0.10f;
Angulo = 0f;
// Asegurar que el movimiento esté habilitado
Lock_movement = false;
ImageSource_oculta = ImageFromPath("/imagenes/pump_stop.png");
// No inicializar TSNet Adapter aquí - se creará cuando se registre con TSNetSimulationManager
// TSNetAdapter = new TSNetPumpAdapter(this);
}
public override void UpdateGeometryStart()
{
// En el nuevo sistema unificado, el HydraulicSimulationManager se encarga
// de registrar automáticamente los objetos que implementan IHydraulicComponent
// No necesitamos crear objetos simHydraulic* separados
}
public override void UpdateGeometryStep()
{
// Los objetos hidráulicos actualizan sus resultados
// a través de ApplyHydraulicResults() desde HydraulicSimulationManager
}
// Método para actualizar fluido desde tanque de succión
public void UpdateFluidFromSuction()
{
if (_mainViewModel?.ObjetosSimulables == null) return;
try
{
// Solo actualizar fluido si hay flujo
if (HasFlow)
{
// Buscar el componente conectado en la succión
var suctionComponent = FindSuctionComponent();
if (suctionComponent is osHydTank tank)
{
var sourceFluid = tank.CurrentOutputFluid;
if (sourceFluid != null)
{
_currentFluid = sourceFluid.Clone();
OnPropertyChanged(nameof(CurrentFluidType));
OnPropertyChanged(nameof(CurrentFluidDescription));
OnPropertyChanged(nameof(ViscosityEffect));
OnPropertyChanged(nameof(EffectiveFlowLMin));
OnPropertyChanged(nameof(FluidTemperature));
OnPropertyChanged(nameof(FluidDensity));
// Actualizar color de la bomba según el fluido
UpdatePumpColorFromFluid();
}
}
}
else
{
// Si no hay flujo, mantener aire como fluido
if (_currentFluid.Type != FluidType.Air)
{
_currentFluid = new FluidProperties(FluidType.Air);
OnPropertyChanged(nameof(CurrentFluidType));
OnPropertyChanged(nameof(CurrentFluidDescription));
UpdatePumpColorFromFluid();
}
}
}
catch (Exception ex)
{
// Mantener fluido por defecto en caso de error
System.Diagnostics.Debug.WriteLine($"Error updating pump fluid: {ex.Message}");
}
}
private void UpdatePumpColorFromFluid()
{
if (!IsRunning)
{
ColorButton_oculto = Brushes.Gray;
return;
}
// Color basado solo en si hay flujo o no
if (HasFlow)
{
// Si hay flujo, usar color del fluido o verde por defecto
try
{
var fluidColorHex = _currentFluid.Color;
var fluidColor = (Color)System.Windows.Media.ColorConverter.ConvertFromString(fluidColorHex);
ColorButton_oculto = new SolidColorBrush(fluidColor);
}
catch
{
ColorButton_oculto = Brushes.Green; // Color por defecto si hay flujo
}
}
else
{
ColorButton_oculto = Brushes.Yellow; // Sin flujo (standby o sin succión)
}
}
private IHydraulicComponent FindSuctionComponent()
{
// Buscar tuberías conectadas a esta bomba
var connectedPipes = _mainViewModel.ObjetosSimulables
.OfType()
.Where(pipe => pipe.Id_ComponenteA == Nombre || pipe.Id_ComponenteB == Nombre)
.ToList();
foreach (var pipe in connectedPipes)
{
// La succión es donde el flujo viene HACIA la bomba
string suctionComponentName = null;
if (pipe.Id_ComponenteB == Nombre && pipe.CurrentFlow >= 0)
{
// Flujo de A hacia B (hacia esta bomba)
suctionComponentName = pipe.Id_ComponenteA;
}
else if (pipe.Id_ComponenteA == Nombre && pipe.CurrentFlow < 0)
{
// Flujo de B hacia A (hacia esta bomba)
suctionComponentName = pipe.Id_ComponenteB;
}
if (!string.IsNullOrEmpty(suctionComponentName))
{
return _mainViewModel.ObjetosSimulables
.OfType()
.FirstOrDefault(c => c is osBase osb && osb.Nombre == suctionComponentName);
}
}
return null;
}
public override void UpdateControl(int elapsedMilliseconds)
{
// En el nuevo sistema TSNet, los valores provienen exclusivamente de TSNet
// No realizamos cálculos internos - solo actualizamos propiedades de UI
try
{
// Los resultados de TSNet ya están aplicados en ApplyHydraulicResults()
// Solo actualizamos propiedades derivadas y visuales
// Actualizar propiedades del fluido basado en si hay flujo
UpdateFluidFromSuction();
// Actualizar propiedades de UI calculadas
OnPropertyChanged(nameof(CurrentFlowLMin));
OnPropertyChanged(nameof(EffectiveFlowLMin));
OnPropertyChanged(nameof(HasFlow));
OnPropertyChanged(nameof(PumpStatus));
OnPropertyChanged(nameof(DetailedStatus));
OnPropertyChanged(nameof(ViscosityEffect));
// Actualizar color visual basado en estado
UpdatePumpColorFromFluid();
// Debug periódico cada 5 segundos
if (Environment.TickCount % 5000 < elapsedMilliseconds)
{
Debug.WriteLine($"Pump {Nombre}: Flow={CurrentFlowLMin:F1}L/min, Pressure={CurrentPressureBar:F2}bar, Status={PumpStatus}");
}
}
catch (Exception ex)
{
Debug.WriteLine($"Error in Pump {Nombre} UpdateControl: {ex.Message}");
}
}
public override void ucLoaded()
{
// En el nuevo sistema unificado, no necesitamos crear objetos separados
base.ucLoaded();
// No reinicializar TSNet Adapter aquí - se creará cuando se registre con TSNetSimulationManager
// if (TSNetAdapter == null)
// {
// TSNetAdapter = new TSNetPumpAdapter(this);
// Debug.WriteLine($"Pump {Nombre}: TSNetAdapter inicializado en ucLoaded");
// }
UpdatePumpImage();
}
public override void ucUnLoaded()
{
// En el nuevo sistema unificado, el HydraulicSimulationManager
// maneja automáticamente el registro/desregistro de objetos
base.ucUnLoaded();
}
// IHydraulicComponent Implementation
[JsonIgnore]
public bool HasHydraulicComponents => true;
public List GetHydraulicNodes()
{
var nodes = new List();
// Las bombas no crean nodos propios - deben estar conectadas a otros componentes para funcionar
if (!HasConnectedComponents())
{
Debug.WriteLine($"Bomba {Nombre}: Sin componentes conectados - no puede funcionar");
}
else
{
//Debug.WriteLine($"Bomba {Nombre}: Conectada a otros componentes - lista para operar");
}
return nodes;
}
public List GetHydraulicElements()
{
var elements = new List();
// Solo crear elementos si la bomba está conectada a otros componentes
if (!HasConnectedComponents())
{
Debug.WriteLine($"Bomba {Nombre}: Sin conexiones - no se puede crear elemento hidráulico");
return elements;
}
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));
// Obtener los nombres de nodos correctos basados en las conexiones
var (inletNode, outletNode) = GetConnectedNodeNames();
// Verificar que tenemos nodos válidos
if (string.IsNullOrEmpty(inletNode) || string.IsNullOrEmpty(outletNode))
{
Debug.WriteLine($"Bomba {Nombre}: Nodos de conexión inválidos - inlet: '{inletNode}', outlet: '{outletNode}'");
return elements;
}
// Crear bomba estándar - el solver manejará las limitaciones de flujo
var pump = new PumpHQ(
h0: PumpHead,
q0: MaxFlow,
speedRel: effectiveSpeed,
direction: PumpDirection
);
// Asignar nombres de nodos
pump.InletNodeName = inletNode;
pump.OutletNodeName = outletNode;
var pumpElement = new HydraulicElementDefinition(
$"{Nombre}_Pump",
inletNode,
outletNode,
pump,
$"Bomba {Nombre}"
);
elements.Add(pumpElement);
Debug.WriteLine($"Bomba {Nombre}: Creando elemento hidráulico - H0={PumpHead}m, Q0={MaxFlow:F6}m³/s ({MaxFlow*3600:F2}m³/h), Velocidad={effectiveSpeed:F2}, Dirección={PumpDirection}");
Debug.WriteLine($"Bomba {Nombre}: Conectando {inletNode} -> {outletNode}");
}
return elements;
}
public void UpdateHydraulicProperties()
{
// Validaciones simples antes de la simulación
if (!IsRunning)
{
SpeedRatio = 0.0;
}
if (SpeedRatio < 0.0) SpeedRatio = 0.0;
if (SpeedRatio > 1.0) SpeedRatio = 1.0;
// El solver se encarga del resto - NPSH, limitaciones de flujo, etc.
}
public void ApplyHydraulicResults(Dictionary flows, Dictionary pressures)
{
try
{
// Aplicar resultados a través del TSNet Adapter
if (TSNetAdapter?.Results != null)
{
// Buscar resultados para esta bomba usando el NodeId del adapter
string pumpElementName = $"{Nombre}_Pump";
// Actualizar flujo desde TSNet
if (flows.ContainsKey(pumpElementName))
{
var flowM3s = flows[pumpElementName];
CurrentFlow = flowM3s;
TSNetAdapter.Results.CalculatedFlowM3s = flowM3s;
Debug.WriteLine($"Pump {Nombre}: TSNet Flow={flowM3s:F6} m³/s ({CurrentFlowLMin:F2} L/min)");
}
else
{
// Intentar con NodeId del adapter
if (flows.ContainsKey(TSNetAdapter.NodeId))
{
var flowM3s = flows[TSNetAdapter.NodeId];
CurrentFlow = flowM3s;
TSNetAdapter.Results.CalculatedFlowM3s = flowM3s;
}
else
{
CurrentFlow = 0.0;
TSNetAdapter.Results.CalculatedFlowM3s = 0.0;
}
}
// Actualizar presión desde TSNet
var (inletNode, outletNode) = GetConnectedNodeNames();
if (!string.IsNullOrEmpty(outletNode) && pressures.ContainsKey(outletNode))
{
var pressurePa = pressures[outletNode];
CurrentPressure = pressurePa / 100000.0; // Convertir Pa a bar
TSNetAdapter.Results.OutletPressureBar = CurrentPressure;
Debug.WriteLine($"Pump {Nombre}: TSNet Pressure={pressurePa:F0} Pa = {CurrentPressure:F3} bar");
}
else if (!string.IsNullOrEmpty(inletNode) && pressures.ContainsKey(inletNode))
{
var pressurePa = pressures[inletNode];
CurrentPressure = pressurePa / 100000.0;
TSNetAdapter.Results.InletPressureBar = CurrentPressure;
}
// Actualizar estado del adapter
TSNetAdapter.Results.IsOperating = IsRunning;
TSNetAdapter.Results.CalculatedEfficiency = CurrentFlow * SpeedRatio;
TSNetAdapter.Results.Timestamp = DateTime.Now;
TSNetAdapter.Results.OperationalStatus = $"Flow: {CurrentFlowLMin:F1}L/min, Pressure: {CurrentPressureBar:F2}bar";
// Actualizar el fluido desde el tanque de succión si hay flujo
if (HasFlow)
{
UpdateFluidFromSuction();
}
}
// Notificar cambios para UI
OnPropertyChanged(nameof(CurrentFlow));
OnPropertyChanged(nameof(CurrentFlowLMin));
OnPropertyChanged(nameof(CurrentPressure));
OnPropertyChanged(nameof(HasFlow));
OnPropertyChanged(nameof(PumpStatus));
OnPropertyChanged(nameof(DetailedStatus));
// Debug periódico
if (Environment.TickCount % 2000 < 50) // Cada ~2 segundos
{
Debug.WriteLine($"Pump {Nombre}: Flow={CurrentFlowLMin:F1}L/min, Pressure={CurrentPressureBar:F2}bar, Running={IsRunning}");
}
}
catch (Exception ex)
{
Debug.WriteLine($"Error en Pump {Nombre} ApplyHydraulicResults: {ex.Message}");
}
}
// IHydraulicFlowReceiver Implementation
public void SetFlow(double flow)
{
CurrentFlow = flow;
}
public double GetFlow()
{
return CurrentFlow;
}
// IHydraulicPressureReceiver Implementation
public void SetPressure(double pressure)
{
CurrentPressure = pressure;
}
public double GetPressure()
{
return CurrentPressure;
}
// Helper Methods
///
/// Verifica si la bomba tiene componentes conectados a través de tuberías
///
private bool HasConnectedComponents()
{
if (_mainViewModel == null) return false;
// Buscar tuberías que conecten esta bomba con otros componentes
var myId = Id.Value.ToString();
var connectedPipes = _mainViewModel.ObjetosSimulables
.OfType()
.Where(pipe => pipe.Id_ComponenteA == myId || pipe.Id_ComponenteB == myId)
.ToList();
return connectedPipes.Any();
}
///
/// Obtiene los nombres de nodos correctos para la bomba basándose en las conexiones
///
private (string inletNode, string outletNode) GetConnectedNodeNames()
{
if (_mainViewModel == null)
return (string.Empty, string.Empty);
string inletNode = string.Empty;
string outletNode = string.Empty;
// Buscar tuberías conectadas a esta bomba
var myId = Id.Value.ToString();
var connectedPipes = _mainViewModel.ObjetosSimulables
.OfType()
.Where(pipe => pipe.Id_ComponenteA == myId || pipe.Id_ComponenteB == myId)
.ToList();
foreach (var pipe in connectedPipes)
{
if (pipe.Id_ComponenteB == myId && !string.IsNullOrEmpty(pipe.Id_ComponenteA))
{
// Esta bomba es el destino, el componente A es la fuente (inlet)
inletNode = ResolveComponentIdToNodeName(pipe.Id_ComponenteA);
//Debug.WriteLine($"Bomba {Nombre}: Nodo inlet identificado como '{inletNode}'");
}
else if (pipe.Id_ComponenteA == myId && !string.IsNullOrEmpty(pipe.Id_ComponenteB))
{
// Esta bomba es la fuente, el componente B es el destino (outlet)
outletNode = ResolveComponentIdToNodeName(pipe.Id_ComponenteB);
//Debug.WriteLine($"Bomba {Nombre}: Nodo outlet identificado como '{outletNode}'");
}
}
return (inletNode, outletNode);
}
///
/// Resuelve un ID de componente al nombre de nodo hidráulico correspondiente
///
private string ResolveComponentIdToNodeName(string componentId)
{
if (string.IsNullOrEmpty(componentId) || _mainViewModel == null)
return string.Empty;
// Buscar el componente por ID
var component = _mainViewModel.ObjetosSimulables
.FirstOrDefault(obj => obj.Id.Value.ToString() == componentId);
if (component == null)
return string.Empty;
// Para tanques, el nombre del nodo es el nombre del tanque
if (component is osHydTank tank)
{
return tank.Nombre;
}
// Para tuberías, necesitamos encontrar el nodo terminal correcto
if (component is osHydPipe pipe)
{
// Las tuberías no crean nodos - necesitamos seguir la conexión hasta encontrar un tanque
// Esto es más complejo, por ahora retornamos el nombre de la tubería como fallback
// pero deberíamos implementar una lógica para seguir las conexiones
return pipe.Nombre;
}
// Para otros tipos de componentes hidráulicos
if (component is IHydraulicComponent hydComponent)
{
return component.Nombre;
}
return string.Empty;
}
private void InvalidateHydraulicNetwork()
{
_mainViewModel?.hydraulicSimulationManager?.InvalidateNetwork();
}
}
///
/// Proveedor de items para la dirección de la bomba
///
public class PumpDirectionItemsSource : IItemsSource
{
public Xceed.Wpf.Toolkit.PropertyGrid.Attributes.ItemCollection GetValues()
{
var items = new Xceed.Wpf.Toolkit.PropertyGrid.Attributes.ItemCollection();
items.Add(1, "Adelante (+1)");
items.Add(-1, "Atrás (-1)");
return items;
}
}
}