### Aqui se mantiene la memoria de evolucion de las distintas decisiones que fueron tomadas y porque

BEPU.cs : SimulationManagerBEPU gestor de la simulacion con el motor BEPUphysics y punto de creacion y modificacion de los objetos dentro del mundo que se derivan des simBase

simBase : Clase base que da un marco a el resto de los objetos
simBarrera : Simula una fotocelula con un espejo usando RayCast
simBotella : Simula una botella que puede transitar por los transportes simTransporte o simCurve
simCurve : Simula una curva o arco de curva de transporte
simDescarte : Permite la eliminacion localizada de botellas en un punto del mundo
simGuia : Es un box con el que las botellas pueden colisionar y cambiar de direccion.
simTransporte : Es un box por donde las botellas pueden desplazarse usando un truco de aplicar la Velocity.Linear pero sin integrar esta velocidad para que no se mueva el objeto transporte. 

* Se usaron esferas en vez de cilindros para mejorar la eficiencia. En el Debug3D si se usan cilindros. **Revertido**: Se ha vuelto a usar `Cylinder` para las `simBotella` ya que el nuevo sistema de fricción debería prevenir la rotación indeseada que ocurría con los `LinearAxisMotor`.

* Se reemplazó el sistema de `LinearAxisMotor` que actuaba sobre las `simBotella` por un sistema basado en fricción. Los transportes (`simTransporte` y `simCurve`) ahora son cuerpos cinemáticos que no se mueven de su sitio. Para lograr que arrastren a las botellas, se les asigna una velocidad (`Velocity.Linear` o `Velocity.Angular`) justo antes de que el solver se ejecute (en `OnSubstepStarted`) y se les quita justo después (en `OnSubstepEnded`). Esto permite que los cuerpos cinemáticos transmitan su velocidad a través de la fricción durante la simulación, pero evita que el `PoseIntegrator` los desplace de su posición original, ya que su velocidad es cero cuando se integra la pose.

* Para aumentar la estabilidad de las `simBotella` y evitar que roten descontroladamente sobre su eje Z al ser arrastradas, se implementó un callback `IntegrateVelocity` personalizado. Este callback identifica las botellas durante la integración y les aplica un amortiguamiento angular (`AngularDamping`) adicional solo en el eje Z. Se descartó la idea inicial de modificar dinámicamente la masa de las botellas dentro de este callback, ya que la arquitectura de BEPUphysics no permite cambiar la masa o la inercia de un cuerpo durante la fase de integración de velocidad.

* Originalmente se habia puesto todos los objetos en awaken para poder usar las colisiones constantemente incluso con objetos en modo sleep para que los simBarrera puedan detectar las colisiones. Ahora que se usar RayCast podemos dejar que las simBotellas se duerman

* La unica clase que se ha terminado de refactorizar respecto a el cambio de coordenadas es simBarrera y ucPhotocell. El concepto es poder separar usando metodos de SimulationManagerBEPU y estructuras como BarreraData la conversion de coordenadas de WPF a coordenadas BEPU. Para esto se usa CoordinateConverter que permite bidireccionalmente convertir las coordenadas pero esto solo se debe usar en SimulationManagerBEPU las clases derivadas de osBase solo deben manejar coordenadas WPF, mientras que las clases dervadas de simBase solo deben almacenar y usar coordenadas BEPU. La z tambien es algo que se debe transferir a SimulationManagerBEPU ya que los objetos simBase deberian recibir tambien sus coordenadas de Z desde SimulationManagerBEPU y ser SimulationManagerBEPU el que gestione las Z.

* Se ha implementado un sistema para evitar que las botellas (`simBotella`) "floten" o se eleven de manera irreal por la acumulación de presión en la simulación. Cada botella ahora registra si está en contacto con un transporte y almacena la última coordenada Z válida durante dicho contacto. Si la botella deja de tener contacto con transportes por varios frames consecutivos, se incrementa un contador de "presión". Al superar un umbral, el sistema reestablece la posición Z de la botella a su última altura conocida, previniendo la flotación. Este contador de presión se decrementa rápidamente al volver a hacer contacto con un transporte.

* Cuando una botella (`simBotella`) entra en contacto con un transporte de frenado (`simTransporte` con `isBrake = true`), su posición se ajusta automáticamente para centrarla en el eje longitudinal del transporte. Esto se realiza una única vez, en el primer contacto, para asegurar un acoplamiento suave y predecible. La posición de la botella se proyecta sobre la línea central del transporte y su velocidad lateral se anula, evitando que la botella se desvíe mientras frena y se alinea con el flujo de salida.

* Se ha implementado un indicador visual simple para mostrar cuando los transportes (`simTransporte`) están en movimiento. El sistema detecta automáticamente si un transporte tiene velocidad (`Speed > 0.001`) y cambia su color a verde brillante. Los transportes detenidos se muestran en verde normal. Esta funcionalidad se integra en el sistema de materiales del `BEPUVisualization3DManager` y se actualiza automáticamente cuando cambia el estado del transporte, proporcionando una retroalimentación visual inmediata del estado de operación.

* Se ha implementado un sistema de animaciones automáticas usando StoryBoard de WPF para los transportes en movimiento. Los transportes activos muestran una animación continua que combina: (1) rotación sutil muy lenta alrededor del eje Z (20 segundos por vuelta completa) y (2) pulsación cíclica del color del material (1.5 segundos por ciclo). Las animaciones se crean y destruyen automáticamente según el estado del transporte, sin necesidad de actualización manual en cada frame. El sistema gestiona las animaciones activas en un diccionario y las limpia correctamente cuando se eliminan objetos. Se resolvió el problema de `InvalidOperationException` al animar brushes inmutables creando una función `CreateAnimatableMaterial` que genera materiales específicamente diseñados para ser animados sin estar "frozen", proporcionando una experiencia visual fluida y eficiente.

* Se ha mejorado el sistema de guías curvas (`ucTransporteCurvaGuias`) para incluir apertura en cono en los extremos de entrada y salida. Se agregó el parámetro `AnguloAperturaGuias` (por defecto 5 grados) que permite configurar la apertura modificando los radios de las guías en los puntos extremos. En lugar de cambiar ángulos, se reduce el radio de la guía superior (externa) y se aumenta el radio de la guía inferior (interna) en los segmentos inicial y final, creando naturalmente la apertura en cono. La modificación del radio se calcula usando `Math.Sin(anguloApertura)` para obtener el desplazamiento apropiado. Esta apertura facilita la entrada y salida de botellas del transporte curvo, reduciendo atascos y mejorando el flujo de materiales manteniendo la continuidad geométrica de las guías.

* Se ha implementado un sistema de fricción dinámica que simula el comportamiento de fricción estática vs dinámica para contactos botella-transporte y botella-curva. El sistema calcula el deslizamiento relativo entre la botella y la superficie del transporte: cuando el deslizamiento es bajo (< 0.05 m/s), se aplica fricción estática alta para un arrastre efectivo; cuando el deslizamiento es alto, se aplica fricción dinámica menor para permitir un deslizamiento suave. Para curvas, se calcula la velocidad de superficie usando el producto vectorial (v = ω × r). Para contactos botella-botella, se usa detección de profundidad de penetración para aplicar materiales ultra-suaves cuando hay alta presión, previniendo acumulaciones explosivas. Este enfoque proactivo reemplaza el sistema reactivo de `PressureBuildup` y proporciona un comportamiento más físicamente realista y estable en acumulaciones de botellas.

* Se ha reemplazado el sistema `ProcessPressureSystem` por un nuevo sistema de calibración visual `HighSlippery` que permite ajustar las fricciones de cada componente. Cada botella tiene una propiedad `HighSlippery` (rango 0-9) con sistema de heatup/cooldown que se incrementa durante deslizamiento y se decrementa durante adherencia. El valor se muestra como número en el centro de cada botella para calibración visual. Los `SpringSettings` se mantienen >= 30 para evitar compresiones irreales. El sistema permite calibrar las tasas de heatup/cooldown específicas para transportes (0.2/0.1) y curvas (0.15/0.08), y el umbral de cambio estático/dinámico (HighSlippery > 3). Este sistema elimina el problema del cooldown que reactivaba prematuramente la fricción estática.

# Sistema de Limitación de Fuerzas para Contactos Múltiples Simultáneos (ELIMINADO)

## Problema Identificado
Durante la simulación de "trenes largos" de botellas que impactan simultáneamente, se generaban fuerzas armónicas irreales que no ocurren en la vida real. Aunque tengas 50 botellas empujando, la fuerza máxima está limitada por la resistencia de los materiales.

## Solución Inicial Implementada (OBSOLETA)

### 1. Sistema de Tracking de Densidad de Contactos
- **Discretización espacial**: El espacio se dividía en regiones de 0.5m x 0.5m x 0.5m
- **Contador por región**: Se contaba el número de contactos simultáneos en cada región
- **Límite de contactos**: Máximo 10 contactos antes de aplicar limitación de fuerzas

### 2. Factor de Escala Dinámico
```csharp
// Sin limitación hasta 10 contactos
if (contactCount <= 10) return 1.0f;

// Reducción progresiva: 5% por cada contacto extra
var scaleFactor = 1.0f - (excessContacts * 0.05f);
return Math.Max(scaleFactor, 0.3f); // Mínimo 30% de fuerza original
```

### 3. Aplicación Integral
- **SpringSettings**: Se escalaban proporcionalmente (frecuencia reducida)
- **MaximumRecoveryVelocity**: Se reducía proporcionalmente
- **Todos los tipos de contacto**: Botella-botella, botella-transporte, botella-curva, etc.

## Razón para la Eliminación
Este sistema se **eliminó completamente** porque:
- Era un enfoque indirecto modificando parámetros de material
- El nuevo sistema de **intervención post-solver** es más efectivo
- La cancelación directa de velocidades Z es más elegante y simple
- Reducía la complejidad del código sin comprometer la funcionalidad

# Sistema de Intervención Post-Solver para Control de Velocidades Z

## Problema Identificado
El sistema anterior de limitación de fuerzas pre-solver no controlaba directamente las velocidades Z excesivas generadas por el solver de BEPU. Las botellas seguían elevándose debido a fuerzas de separación acumuladas que se aplicaban después de las restricciones iniciales. Además, el sistema de `forceScale` para contactos múltiples era un enfoque indirecto que no atacaba la causa raíz del problema.

## Solución Implementada

### 1. Enfoque Post-Solver como "Fusible de Energía"
- **Timing crítico**: Intervención en `OnSubstepEnded` - después del solver, antes de la integración de posición
- **Fusible de energía**: Elimina velocidades Z excesivas sin interferir con el comportamiento normal del solver
- **Preservación de física**: Permite al solver trabajar con fuerzas realistas, interviniendo solo cuando es necesario

### 2. Control de Velocidades Z Granular
```csharp
// Límites configurables
const float maxUpwardVelocity = 0.15f;    // Anti-elevación
const float maxDownwardVelocity = 2.0f;   // Anti-hundimiento
const float zDampingFactor = 0.7f;        // Amortiguamiento suave

// Intervención directa en velocidades
if (velocity.Linear.Z > maxUpwardVelocity) {
    velocity.Linear.Z = maxUpwardVelocity;
}
```

### 3. Corrección de Posición Extrema
- **Detección de altura excesiva**: Si la botella está muy por encima del nivel normal
- **Corrección suave**: Aplicar velocidad correctiva hacia abajo (máximo 0.5 m/s)
- **Cálculo proporcional**: Velocidad correctiva basada en la altura excesiva

## Simplificación del Sistema

### 1. Eliminación de `ApplyZForceLimitation`
- **Antes**: Limitación pre-solver que interfería con el comportamiento normal
- **Ahora**: Intervención post-solver más directa y efectiva

### 2. Simplificación de `IntegrateVelocity`
- **Antes**: Control complejo de velocidades Z durante la integración
- **Ahora**: Solo control angular básico (anti-vuelco) y damping en Z
- **Beneficio**: Menor interferencia con la física normal de BEPU

## Beneficios del Enfoque Post-Solver
- **Más efectivo**: Intervención después de que el solver haya calculado todas las fuerzas
- **Menos interferencia**: Permite comportamiento físico normal hasta el punto de intervención
- **Más directo**: Control directo de velocidades en lugar de modificar parámetros de material
- **Más predecible**: Comportamiento determinista independiente de las configuraciones del solver
- **Mantenimiento de rigidez**: Las fuerzas normales en XY permanecen intactas
- **Solución integral**: Resuelve tanto el problema de elevación como el de contactos múltiples simultáneos
- **Código más simple**: Elimina la complejidad del sistema de tracking de densidad de contactos

# Sistema Hidráulico Integrado con HydraulicSimulationManager

## Arquitectura del Sistema Hidráulico

Se ha implementado un sistema de simulación hidráulica completo que funciona en paralelo con la simulación física BEPU. El sistema está basado en el `HydraulicSimulationManager` que actúa como puente entre los objetos gráficos derivados de `osBase` y el motor de simulación hidráulica.

### Componentes Principales

#### HydraulicSimulationManager
- **Función**: Gestiona el ciclo de vida y la comunicación entre objetos hidráulicos y el solver
- **Integración**: Se ejecuta en paralelo con BEPU en el timer loop principal de MainViewModel
- **Responsabilidades**: 
  - Registro automático de objetos que implementan `IHydraulicComponent`
  - Construcción dinámica de la red hidráulica
  - Aplicación de resultados a los objetos tras cada iteración del solver

#### Interfaces Hidráulicas
- **IHydraulicComponent**: Interfaz base para todos los objetos hidráulicos
- **IHydraulicPump**: Para bombas con curvas H-Q
- **IHydraulicPipe**: Para tuberías con pérdidas por fricción
- **IHydraulicTank**: Para tanques con cálculo de nivel dinámico
- **IHydraulicValve**: Para válvulas con coeficiente Kv

## Mejoras Implementadas en Objetos Hidráulicos

### 1. Sistema de Conexiones Mejorado en osHydPipe

**Problema Original**: El sistema de conexiones era limitado y no seguía el patrón establecido en otros objetos del sistema.

**Solución Implementada**:
```csharp
// Antes - Sistema limitado
[ObservableProperty] string id_InletComponent = "";
[ObservableProperty] string id_OutletComponent = "";

// Después - Patrón consistente
[ItemsSource(typeof(osBaseItemsSource<IHydraulicComponent>))]
[ObservableProperty] string id_ComponenteA = "";

[ItemsSource(typeof(osBaseItemsSource<IHydraulicComponent>))]
[ObservableProperty] string id_ComponenteB = "";
```

**Beneficios**:
- **Filtrado automático**: Solo muestra objetos que implementan `IHydraulicComponent` en el PropertyGrid
- **Consistencia**: Sigue el mismo patrón usado en `ucTransporteGuias` con `Motor`
- **Mantenimiento automático**: PropertyChangedHandlers mantienen sincronizados los nombres
- **Validación**: Solo crea elementos hidráulicos cuando ambos componentes están conectados

### 2. Lógica de Nodos Corregida

**Problema Original**: Las tuberías intentaban crear sus propios nodos, generando duplicación y conflictos.

**Solución Implementada**:
```csharp
// Las tuberías no crean nodos propios
public List<HydraulicNodeDefinition> GetHydraulicNodes()
{
    // Los nodos son creados por los componentes conectados (tanques, bombas, etc.)
    return new List<HydraulicNodeDefinition>();
}

// Solo conectan nodos existentes
public List<HydraulicElementDefinition> GetHydraulicElements()
{
    if (!string.IsNullOrEmpty(Id_ComponenteA) && !string.IsNullOrEmpty(Id_ComponenteB))
    {
        var pipeElement = new Pipe(Length, Diameter, Roughness);
        // Conecta directamente usando nombres de componentes como nodos
        return new List<HydraulicElementDefinition> {
            new HydraulicElementDefinition($"{Nombre}_Pipe", Id_ComponenteA, Id_ComponenteB, pipeElement)
        };
    }
    return new List<HydraulicElementDefinition>();
}
```

### 3. Integración Completa con ItemsSource

**En osHydDischargeTank**:
```csharp
[Category("🔗 Conexiones")]
[Name("Componente Entrada")]
[ItemsSource(typeof(osBaseItemsSource<IHydraulicComponent>))]
[ObservableProperty] string id_InletComponent = "";
```

## Flujo de Simulación Hidráulica

### 1. Registro Automático
- Los objetos que implementan `IHydraulicComponent` se registran automáticamente en `HydraulicSimulationManager`
- El sistema detecta cuando hay cambios y marca la red para reconstrucción (`_networkNeedsRebuild = true`)

### 2. Construcción de Red
- **BuildNodesFromObjects()**: Crea nodos basándose en las definiciones de cada objeto
- **BuildBranchesFromObjects()**: Crea elementos (tuberías, bombas, válvulas) que conectan los nodos
- La red resultante es compatible con el solver `HydraulicNetwork.Solve()`

### 3. Resolución y Aplicación
- **UpdateObjectProperties()**: Actualiza propiedades antes del solver (apertura de válvulas, velocidad de bombas, etc.)
- **Network.Solve()**: Resuelve el sistema de ecuaciones usando el algoritmo iterativo
- **ApplyResultsToObjects()**: Aplica caudales y presiones calculados a cada objeto

## Patrón de Conexión Establecido

El sistema establecido para conexiones sigue este patrón consistente:

```csharp
// 1. Propiedad string con ItemsSource filtrado
[ItemsSource(typeof(osBaseItemsSource<IInterfaceEspecifica>))]
[ObservableProperty] string id_ComponenteConectado = "";

// 2. Referencia privada al objeto real
[JsonIgnore] private IInterfaceEspecifica ComponenteConectado = null;

// 3. PropertyChangedHandler para mantener sincronización
[JsonIgnore] private PropertyChangedEventHandler componentePropertyChangedHandler;

// 4. Método OnChanged que maneja la conexión
partial void OnId_ComponenteConectadoChanged(string value)
{
    // Desconectar anterior si existe
    if (ComponenteConectado != null && componentePropertyChangedHandler != null)
        ((INotifyPropertyChanged)ComponenteConectado).PropertyChanged -= componentePropertyChangedHandler;

    // Buscar y conectar nuevo componente
    if (_mainViewModel != null && !string.IsNullOrEmpty(value))
    {
        ComponenteConectado = (IInterfaceEspecifica)_mainViewModel.ObjetosSimulables
            .FirstOrDefault(s => s is IInterfaceEspecifica comp && 
                           ((osBase)comp).Nombre == value);
        
        // Establecer handler para sincronización de nombres
        if (ComponenteConectado != null)
        {
            componentePropertyChangedHandler = (sender, e) =>
            {
                if (e.PropertyName == nameof(osBase.Nombre))
                    Id_ComponenteConectado = ((osBase)sender).Nombre;
            };
            ((INotifyPropertyChanged)ComponenteConectado).PropertyChanged += componentePropertyChangedHandler;
        }
    }
}
```

## Beneficios del Sistema Integrado

- **Doble simulación**: Simulación física (BEPU) y hidráulica funcionan en paralelo sin interferencia
- **Interfaces unificadas**: Todos los objetos hidráulicos implementan interfaces consistentes
- **Red dinámica**: La red hidráulica se reconstruye automáticamente cuando cambian las conexiones
- **Resultados bidireccionales**: Los resultados hidráulicos pueden influir en la simulación física y viceversa
- **Patrón consistente**: Todas las conexiones siguen el mismo patrón establecido
- **Mantenimiento automático**: Los nombres y referencias se mantienen sincronizados automáticamente

