diff --git a/App.xaml b/App.xaml index 4b8a7f4..d3aa98f 100644 --- a/App.xaml +++ b/App.xaml @@ -28,6 +28,8 @@ + + + /// Converter that converts boolean values to Visibility, with inverse logic + /// (true -> Collapsed, false -> Visible) + /// + public class InverseBooleanToVisibilityConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is bool boolValue) + { + return boolValue ? Visibility.Collapsed : Visibility.Visible; + } + + return Visibility.Visible; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is Visibility visibility) + { + return visibility == Visibility.Collapsed; + } + + return false; + } + } +} diff --git a/Converters/SubtractConverter.cs b/Converters/SubtractConverter.cs new file mode 100644 index 0000000..cbf636a --- /dev/null +++ b/Converters/SubtractConverter.cs @@ -0,0 +1,54 @@ +using System; +using System.Globalization; +using System.Windows.Data; + +namespace CtrEditor.Converters +{ + /// + /// Converter that subtracts a parameter value from the input value + /// Useful for calculations like width - margin, etc. + /// + public class SubtractConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + try + { + if (value != null && parameter != null) + { + var inputValue = System.Convert.ToDouble(value); + var subtractValue = System.Convert.ToDouble(parameter); + + var result = inputValue - subtractValue; + return Math.Max(0, result); // Ensure result is not negative + } + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine($"SubtractConverter.Convert: Exception - {ex.Message}"); + } + + return 0.0; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + try + { + if (value != null && parameter != null) + { + var inputValue = System.Convert.ToDouble(value); + var addValue = System.Convert.ToDouble(parameter); + + return inputValue + addValue; + } + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine($"SubtractConverter.ConvertBack: Exception - {ex.Message}"); + } + + return 0.0; + } + } +} diff --git a/CtrEditor.csproj b/CtrEditor.csproj index c2c428d..bed0220 100644 --- a/CtrEditor.csproj +++ b/CtrEditor.csproj @@ -37,6 +37,7 @@ + diff --git a/ObjetosSim/HydraulicComponents/osHydTank.cs b/ObjetosSim/HydraulicComponents/osHydTank.cs index 0c60084..0ca2f01 100644 --- a/ObjetosSim/HydraulicComponents/osHydTank.cs +++ b/ObjetosSim/HydraulicComponents/osHydTank.cs @@ -84,6 +84,43 @@ namespace CtrEditor.ObjetosSim [property: Name("Color")] private Brush colorButton_oculto = Brushes.LightBlue; + // Three-section tank properties + [ObservableProperty] + [property: Category("🏭 Configuración Tanque")] + [property: Description("Habilitar sistema de tres secciones")] + [property: Name("Tres Secciones")] + private bool enableThreeSection = false; + + [ObservableProperty] + [property: Category("🏭 Configuración Tanque")] + [property: Description("Altura de la sección de mezcla (m)")] + [property: Name("Altura Mezcla")] + private double mixingSectionHeight = 0.20; + + [ObservableProperty] + [property: Category("📊 Niveles")] + [property: Description("Nivel secundario en metros")] + [property: Name("Nivel Secundario")] + private double secondaryLevelM = 0.0; + + [ObservableProperty] + [property: Category("📊 Niveles")] + [property: Description("Nivel primario en metros")] + [property: Name("Nivel Primario")] + private double primaryLevelM = 0.0; + + [ObservableProperty] + [property: Category("📊 Porcentajes")] + [property: Description("Porcentaje de llenado sección secundaria")] + [property: Name("% Secundario")] + private double secondaryPercentage = 0.0; + + [ObservableProperty] + [property: Category("📊 Porcentajes")] + [property: Description("Porcentaje de llenado sección primaria")] + [property: Name("% Primario")] + private double primaryPercentage = 0.0; + // Constructor @@ -112,7 +149,15 @@ namespace CtrEditor.ObjetosSim SafeUpdateTankPressure(); // Inicializar estado de mezcla - UpdateMixingState(); // Debug: Confirmar que el constructor se ejecuta + UpdateMixingState(); + + // Inicializar sistema de tres secciones + if (EnableThreeSection) + { + ConfigureThreeSectionLevels(); + } + + // 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}"); } catch (Exception ex) @@ -1095,6 +1140,12 @@ namespace CtrEditor.ObjetosSim // Actualizar volúmenes de fluidos según el estado de mezcla UpdateFluidVolumesFromFlow(volumeChangeL); + // Actualizar sistema de tres secciones si está habilitado + if (EnableThreeSection) + { + UpdateThreeSectionLevels(); + } + // Debug para verificar cambios if (VerboseLogging() && Math.Abs(volumeChangeL) > 0.1) { @@ -1326,6 +1377,127 @@ namespace CtrEditor.ObjetosSim + // Three-Section Tank Methods + + /// + /// Obtiene la altura total del tanque + /// + private double GetHeightFromVolume() + { + return Tamano * 100; // Convertir tamaño a píxeles/altura + } + + /// + /// Configura los niveles para el sistema de tres secciones + /// + public void ConfigureThreeSectionLevels() + { + if (!EnableThreeSection) return; + + try + { + lock (_levelLock) + { + var totalHeight = GetHeightFromVolume(); + var mixingHeight = MixingSectionHeight; + + // Validar que la altura de mezcla no sea mayor que la altura total + if (mixingHeight > totalHeight) + { + mixingHeight = totalHeight * 0.3; // Máximo 30% de la altura total + MixingSectionHeight = mixingHeight; + } + + // Calcular niveles basados en la altura actual del líquido + var currentLevel = CurrentLevelM; + + if (currentLevel <= mixingHeight) + { + // Solo sección de mezcla + SecondaryLevelM = 0.0; + PrimaryLevelM = currentLevel; + } + else + { + // Mezcla completa + nivel adicional + SecondaryLevelM = currentLevel - mixingHeight; + PrimaryLevelM = mixingHeight; + } + + UpdateThreeSectionPercentages(); + } + } + catch (Exception ex) + { + Debug.WriteLine($"Error configurando niveles de tres secciones: {ex.Message}"); + } + } + + /// + /// Actualiza los porcentajes de llenado para cada sección + /// + public void UpdateThreeSectionPercentages() + { + if (!EnableThreeSection) return; + + try + { + lock (_levelLock) + { + var totalHeight = GetHeightFromVolume(); + var mixingHeight = MixingSectionHeight; + var secondaryHeight = totalHeight - mixingHeight; + + // Calcular porcentajes + if (mixingHeight > 0) + { + PrimaryPercentage = (PrimaryLevelM / mixingHeight) * 100.0; + PrimaryPercentage = Math.Min(100.0, Math.Max(0.0, PrimaryPercentage)); + } + else + { + PrimaryPercentage = 0.0; + } + + if (secondaryHeight > 0) + { + SecondaryPercentage = (SecondaryLevelM / secondaryHeight) * 100.0; + SecondaryPercentage = Math.Min(100.0, Math.Max(0.0, SecondaryPercentage)); + } + else + { + SecondaryPercentage = 0.0; + } + } + } + catch (Exception ex) + { + Debug.WriteLine($"Error actualizando porcentajes de tres secciones: {ex.Message}"); + } + } + + /// + /// Actualiza los niveles basados en el nivel total actual + /// + public void UpdateThreeSectionLevels() + { + if (!EnableThreeSection) return; + + try + { + lock (_levelLock) + { + ConfigureThreeSectionLevels(); + } + } + catch (Exception ex) + { + Debug.WriteLine($"Error actualizando niveles de tres secciones: {ex.Message}"); + } + } + + + // Serialization Support /// diff --git a/ObjetosSim/HydraulicComponents/ucHydTank.xaml b/ObjetosSim/HydraulicComponents/ucHydTank.xaml index 1ceee4e..e70729d 100644 --- a/ObjetosSim/HydraulicComponents/ucHydTank.xaml +++ b/ObjetosSim/HydraulicComponents/ucHydTank.xaml @@ -22,201 +22,315 @@ - + + Height="{Binding Tamano, Converter={StaticResource MeterToPixelConverter}, ConverterParameter=1.4}"> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + FontSize="10" /> - - + + + + + + + + MaxWidth="60"/> - - + - - + + + - - + + - + - - - + + + - - + + - - - + + + - - + + - + - + + Foreground="White" FontSize="8" FontWeight="SemiBold" Margin="2,0,0,0"/> + - + - + + Foreground="White" FontSize="8" FontWeight="SemiBold" Margin="2,0,0,0"/> + - + - + + Foreground="White" FontSize="8" FontWeight="SemiBold" Margin="2,0,0,0"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - -