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"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-